0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

看看Linux为相机提供的驱动框架

冬至配饺子 来源:嵌入式软件开发交流 作者:年轻的 2022-08-07 16:03 次阅读

前言

前面我们了解了一些相机的基础知识《相机基础知识》。下面来看看Linux为相机提供的驱动框架。

V4L2简介

V4L2 (Video Linux Two),是为支持Linux内核设计的驱动框架驱动框架。为应用设置的操作接口层(ioctl),是在提供更广泛的时候它的设备,它们只有在原件上,才是真正的视频设备,所以它们才是真正的摄像头设计。

V4L2框架

poYBAGLvcXOAU-5_AACaFZ8UYXM697.png

在应用层,可以在 /dev 显示设备节点,程序打开设备设备进行我们的设备目录发现应用程序0、视频画面。video1、video2...这些设备节点是在核心层注册。

v4l2-dev.c) 起承上启下的作用,它会为每一个核心层注册中的设备设置一个统一的 v4l2_fops ,这些统一驱动的接口最终将调用到驱动的 video_device 的 fops 。

重要结构体

视频设备

视频设备

//表示一个视频设备

struct video_device {

#if defined(CONFIG_MEDIA_CONTROLLER);

struct media_entity entity;

struct media_intf_devnode *intf_devnode;

struct media_pipeline pipe;

#endif;

const struct v4l2_file_operations *fops; //文件操作接口(dev/videoX)

u32 device_caps; //设备功能,用于v4l2_capabilities(应用层定义的结构体)

struct device dev;

struct cdev *cdev; //字符设备

struct v4l2_device *v4l2_dev; //V4L2设备

struct device *dev_parent;

struct v4l2_ctrl_handler *ctrl_handler; //设备节点对应的控制句柄

struct vb2_queue *queue;

struct v4l2_prio_state *prio;

char name[32]; //Video设备名称

enum vfl_devnode_type vfl_type; //V4L设备类型

enum vfl_devnode_direction vfl_dir; //V4L 接收者/发送者/m2m

int minor; //子设备号,主设备为81

u16 num;

unsigned long flags;

int index;

spinlock_t fh_lock;

struct list_head fh_list;

int dev_debug;

v4l2_std_id tvnorms;

void (*release)(struct video_device *vdev); //video_device release()回调

const struct v4l2_ioctl_ops *ioctl_ops; //IOCTL回调

unsigned long valid_ioctls[BITS_TO_LONGS(BASE_VIDIOC_PRIVATE)];

struct mutex *lock;

};

v4l2_device

struct v4l2_device {

struct device *dev;

struct media_device *mdev;

struct list_head subdevs; //用于追踪已注册的subdev

spinlock_t lock;

char name[V4L2_DEVICE_NAME_SIZE]; //设备名

void (*notify)(struct v4l2_subdev *sd, unsigned int notification, void *arg);

struct v4l2_ctrl_handler *ctrl_handler; //控制句柄

struct v4l2_prio_state prio; //设备的优先状态

struct kref ref; //引用

void (*release)(struct v4l2_device *v4l2_dev);//引用计数为0后调用

};

嵌入到video_device中,表示一个v4l2设备实例。

v4l2_subdev

struct v4l2_subdev {

#if defined(CONFIG_MEDIA_CONTROLLER);

struct media_entity entity;

#endif;

struct list_head list; //subdev列表

struct module *owner;

bool owner_v4l2_dev;

u32 flags;

struct v4l2_device *v4l2_dev; //依附的v4l2_device

const struct v4l2_subdev_ops *ops; //subdev操作函数

const struct v4l2_subdev_internal_ops *internal_ops;

struct v4l2_ctrl_handler *ctrl_handler; //控制句柄

char name[V4L2_SUBDEV_NAME_SIZE]; //subdev名称

u32 grp_id;

void *dev_priv;

void *host_priv;

struct video_device *devnode;

struct device *dev;

struct fwnode_handle *fwnode;

struct list_head async_list;

struct v4l2_async_subdev *asd;

struct v4l2_async_notifier *notifier;

struct v4l2_async_notifier *subdev_notifier;

struct v4l2_subdev_platform_data *pdata;//subdev平台数据

};

依附在一个v4l2_device下面,并表示一个v4l2设备的子设备,v4l2_device下可以有多个sub_device。

v4l2_fh

struct v4l2_fh {

struct list_head list; //文件句柄列表

struct video_device *vdev; //依附的video_device

struct v4l2_ctrl_handler *ctrl_handler;

enum v4l2_priority prio; //文件句柄的优先级

wait_queue_head_t wait;

struct mutex subscribe_lock;

struct list_head subscribed; //订阅的事件列表

struct list_head available; //可用的事件

unsigned int navailable; //可用的事件数

u32 sequence;

struct v4l2_m2m_ctx *m2m_ctx;

};

追踪的文件句柄用于

v4l2_device和v4l2_subdev的关系:

subdev 的设计目的是为了多路复用,就是控制使用一个v4l2_device可以挂接多个v4l2_subdev。这样的多路复用就是一个摄像头来多个摄像头。手机和后置摄像头。

在V4L2驱动中,使用v4l2_device来表示摄像头摄像头(ISP)。使用v4l2_subdev来表示具体的某个摄像头(Sensor)。

v4l2_file_operations

//V4L2设备操作函数

struct v4l2_file_operations {

struct module *owner;

ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);

ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);

__poll_t (*poll) (struct file *, struct poll_table_struct *);

long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);

#ifdef CONFIG_COMPAT;

long (*compat_ioctl32) (struct file *, unsigned int, unsigned long);

#endif;

unsigned long (*get_unmapped_area) (struct file *, unsigned long, unsigned long, unsigned long, unsigned long);

int (*mmap) (struct file *, struct vm_area_struct *);

int (*open) (struct file *);

int (*release) (struct file *);

};

v4l2_ioctl_ops

//IOCTL操作函数

struct v4l2_ioctl_ops {

......

int (*vidioc_overlay)(struct file *file, void *fh, unsigned int i);

int (*vidioc_g_fbuf)(struct file *file, void *fh, struct v4l2_framebuffer *a);

int (*vidioc_s_fbuf)(struct file *file, void *fh, const struct v4l2_framebuffer *a);

int (*vidioc_streamon)(struct file *file, void *fh, enum v4l2_buf_type i);

int (*vidioc_streamoff)(struct file *file, void *fh, enum v4l2_buf_type i);

......

int (*vidioc_enum_framesizes)(struct file *file, void *fh, struct v4l2_frmsizeenum *fsize);

int (*vidioc_enum_frameintervals)(struct file *file, void *fh, struct v4l2_frmivalenum *fival);

int (*vidioc_s_dv_timings)(struct file *file, void *fh, struct v4l2_dv_timings *timings);

int (*vidioc_g_dv_timings)(struct file *file, void *fh, struct v4l2_dv_timings *timings);

int (*vidioc_query_dv_timings)(struct file *file, void *fh, struct v4l2_dv_timings *timings);

int (*vidioc_enum_dv_timings)(struct file *file, void *fh, struct v4l2_enum_dv_timings *timings);

int (*vidioc_dv_timings_cap)(struct file *file, void *fh, struct v4l2_dv_timings_cap *cap);

int (*vidioc_g_edid)(struct file *file, void *fh, struct v4l2_edid *edid);

int (*vidioc_s_edid)(struct file *file, void *fh, struct v4l2_edid *edid);

int (*vidioc_subscribe_event)(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub);

int (*vidioc_unsubscribe_event)(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub);

long (*vidioc_default)(struct file *file, void *fh, bool valid_prio, unsigned int cmd, void *arg);

};

v4l2_subdev_ops

//subdev操作函数

struct v4l2_subdev_ops {

const struct v4l2_subdev_core_ops *core; //subdev核心操作回调

const struct v4l2_subdev_tuner_ops *tuner; //radio模式打开v4l设备时的操作回调

const struct v4l2_subdev_audio_ops *audio; //音频相关设置回调

const struct v4l2_subdev_video_ops *video; //video模式打开v4l设备时的操作回调

const struct v4l2_subdev_vbi_ops *vbi; //通过vbi设备节点以video模式打开v4l设备时的操作回调

const struct v4l2_subdev_ir_ops *ir; //IR(红外)设备操作函数

const struct v4l2_subdev_sensor_ops *sensor; //sensor操作函数

const struct v4l2_subdev_pad_ops *pad; //pad操作函数

};

v4l22,所以多部分可以轻松地根据实际设备的需要实现的设备。

上面的_ioctl_ops中实现的部分ioctl最终到v4l2_dev_ops中的调用子函数。

API函数

//注册/注销video_device

int video_register_device(struct video_device *vdev, enum vfl_devnode_type type, int nr)

void video_unregister_device(struct video_device *vdev)

//分配/释放video_device

struct video_device * __must_check video_device_alloc(void);

void video_device_release(struct video_device *vdev)

//注册/注销v4l2_device

int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev)

void v4l2_device_unregister(struct v4l2_device *v4l2_dev)

//注册/注销v4l2_subdev(关联v4l2_device和v4l2_subdev)

int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev, struct v4l2_subdev *sd)

void v4l2_device_unregister_subdev(struct v4l2_subdev *sd)

//初始化v4l2_subdev

void v4l2_subdev_init(struct v4l2_subdev *sd, const struct v4l2_subdev_ops *ops);

/********************************I2C subdev*************************************/

//初始化v4l2_subdev, 该subdev是I2C设备

void v4l2_i2c_subdev_init(struct v4l2_subdev *sd, struct i2c_client *client,

const struct v4l2_subdev_ops *ops)

/*******************************SPI subdev************************************************/

//初始化v4l2_subdev, 该subdev是SPI设备

void v4l2_spi_subdev_init(struct v4l2_subdev *sd, struct spi_device *spi,

const struct v4l2_subdev_ops *ops)



审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Linux
    +关注

    关注

    87

    文章

    10981

    浏览量

    206687
  • 摄像头
    +关注

    关注

    59

    文章

    4599

    浏览量

    92833
  • LINUX内核
    +关注

    关注

    1

    文章

    311

    浏览量

    21386
收藏 人收藏

    评论

    相关推荐

    linux驱动框架

    驱动程序的框架有了大致的了解,感觉花了这么长的时间值得,以后的框架就能了解了。明天独立写再次编写led驱动程序。Led驱动程序代码(firs
    发表于 03-20 12:44

    linux驱动框架是什么

    编写linux驱动先看一下驱动框架是什么样子的。驱动编写和应用层编写有什么区别呢?
    发表于 07-26 08:14

    Linux下的UART驱动框架详解

    Linux下的UART驱动框架
    发表于 12-22 07:18

    Linux 驱动 = 软件框架 + 硬件操作

      Linux 驱动 = 软件框架 + 硬件操作  驱动程序依赖于 Linux 内核,你开发板
    发表于 12-17 07:11

    OpenHarmony相机用户态驱动框架

    Linux采用的开源协议具有传染性[1],导致Android HAL[2]成为了手机厂商们竞争的重要战场。随着OpenHarmony 3.1[3]的发布,相机模块也逐渐完善起来,目前提供了基础预览和拍照的能力
    发表于 04-20 17:09

    想要驾驭Linux驱动开发,必须深刻理解Linux总线设备驱动框架

    想要驾驭Linux驱动开发,必须深刻理解Linux总线设备驱动框架。之所以会形成这样的框架,主要
    的头像 发表于 03-22 11:08 1w次阅读
    想要驾驭<b class='flag-5'>Linux</b><b class='flag-5'>驱动</b>开发,必须深刻理解<b class='flag-5'>Linux</b>总线设备<b class='flag-5'>驱动</b><b class='flag-5'>框架</b>

    Linux DMA Engine框架的介绍

    此会话描述如何从设备驱动程序在Linux中使用DMA。 这包括内存分配,缓存控制和DMA设备控制。 详细介绍了Linux DMA Engine框架
    的头像 发表于 11-23 06:29 5878次阅读

    需要了解Linux V4L2的驱动架构

    video4linux2(V4L2)是Linux内核中关于视频设备的中间驱动层,向上为Linux应用程序访问视频设备提供了通用接口,向下为
    发表于 04-28 17:29 906次阅读
    需要了解<b class='flag-5'>Linux</b> V4L2的<b class='flag-5'>驱动</b>架构

    你对Linux总线设备驱动框架是否了解

    Linux的设备驱动模型,或者说,Linux的设备驱动框架,都是同一个意思。应该这样理解,(Linux
    发表于 05-05 15:13 596次阅读

    如何使用Linux内核实现USB驱动程序框架

    Linux内核提供了完整的USB驱动程序框架。USB总线采用树形结构,在一条总线上只能有唯一的主机设备。 Linux内核从主机和设备两个角度
    发表于 11-06 17:59 19次下载
    如何使用<b class='flag-5'>Linux</b>内核实现USB<b class='flag-5'>驱动</b>程序<b class='flag-5'>框架</b>

    嵌入式Linux驱动开发从基础到框架

    想讲好嵌入式Linux驱动开发并不容易,各位业界大神最基础的字符驱动到中断并发再到驱动框架、应用层调用。但是总觉得业界写的书都是点到为止,
    发表于 11-01 16:58 13次下载
    嵌入式<b class='flag-5'>Linux</b><b class='flag-5'>驱动</b>开发从基础到<b class='flag-5'>框架</b>

    Linux内核中视频设备驱动框架V4L2X详解

    V4L2(Video for Linux 2):Linux内核中关于视频设备驱动框架,对上向应用层提供统一的接口,对下支持各类复杂硬件的灵
    的头像 发表于 05-30 16:18 5126次阅读

    Linux的PWM驱动框架及实现方法

    本文主要讲述了Linux的PWM驱动框架、实现方法、驱动添加方法和调试方法。
    的头像 发表于 05-14 15:24 1001次阅读
    <b class='flag-5'>Linux</b>的PWM<b class='flag-5'>驱动</b><b class='flag-5'>框架</b>及实现方法

    Linux驱动分析之RTC框架

    Linux内核启动时,它会从RTC中读取时间与日期,作为基准值。然后通过软件来维护系统时间和日期。Linux系统中提供了RTC核心层,对于驱动开发者而言,操作起来就变得很简单了。我们
    的头像 发表于 05-26 15:12 767次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>驱动</b>分析之RTC<b class='flag-5'>框架</b>

    Linux Regmap 驱动框架

    层,regmap 向驱动编写人员提供的 API 接口,驱动编写人员使用这些API 接口来操作具体的芯片设备,也是驱动编写人员重点要掌握的。 2、regmap 结构体
    的头像 发表于 07-06 17:29 725次阅读
    <b class='flag-5'>Linux</b> Regmap <b class='flag-5'>驱动</b><b class='flag-5'>框架</b>