文章目录
- 一、V4L2简介
- 二、v4l2驱动关键组件
- (一)video_device结构体
- v4l2操作方法结构体
- v4l2的ioctl操作方法结构体
- (二)v4l2_device结构体
一、V4L2简介
V4L2,即Video for Linux two,是Linux内核中用于视频设备驱动的框架。
它提供了一套统一的接口规范给用户空间的应用程序,使其能够访问和控制视频设备。
v4l2设备本质是字符设备驱动,当调用cdev的fops时,就会回调到v4l2的操作方法结构体,即v4l2_file_operations。
当调用ioctl函数时,会回调到v4l2的操作方法结构体,然后再回调到ioctl操作方法结构体,即v4l2_ioctl_ops。
首先,需要分配并初始化video_device结构体,
然后,设置其成员变量,如设备名、文件操作函数集、ioctl操作函数集等,注意必须填充v4l2_dev->name成员
最后,调用video_register_device函数将video_device结构体注册到系统中,创建一个对应的设备文件(如/dev/videoX)。
二、v4l2驱动关键组件
video_device:表示一个字符设备,包含cdev和v4l2_device等成员v4l2_device:表示一个v4l2设备实例,内部通过链表管理从属所有子设备。
(一)video_device结构体
V4L2驱动框架中表示视频设备的核心结构体。
它包含了设备的各种属性和操作函数,如字符设备名、操作函数集以及ioctl操作函数集。
//该结构体用于创建和管理v4l2设备节点
struct video_device
{const struct v4l2_file_operations *fops; //v4l2_file_operations操作方法结构体struct device dev; //视频设备结构体devicestruct cdev *cdev; //字符设备struct v4l2_device *v4l2_dev; //v4l2_device父类struct device *dev_parent; //device结构体的父类/* 设备信息 */char name[32]; //视频设备名enum vfl_devnode_type vfl_type; //v4l设备类型int minor; //次设备号u16 num; //视频设备节点号 unsigned long flags; //视频设备标志位/* 回调函数 */void (*release)(struct video_device *vdev); //视频设备注销的回调函数const struct v4l2_ioctl_ops *ioctl_ops; //v4l2的ioctl回调函数struct mutex *lock; //序列化操作锁
};
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);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操作方法结构体
struct v4l2_ioctl_ops {//查询是否是摄像头设备int (*vidioc_querycap)(struct file *file, void *fh, struct v4l2_capability *cap); //列举摄像头支持的数据格式int (*vidioc_enum_fmt_vid_cap)(struct file *file, void *fh, struct v4l2_fmtdesc *f);//获取当前设置的数据格式int (*vidioc_g_fmt_vid_cap)(struct file *file, void *fh, struct v4l2_format *f); //尝试设置数据格式到摄像头 int (*vidioc_try_fmt_vid_cap)(struct file *file, void *fh, struct v4l2_format *f);//设置数据格式给摄像头int (*vidioc_s_fmt_vid_cap)(struct file *file, void *fh, struct v4l2_format *f);//申请内存int (*vidioc_reqbufs)(struct file *file, void *fh, struct v4l2_requestbuffers *b);//查询内存int (*vidioc_querybuf)(struct file *file, void *fh, struct v4l2_buffer *b);//将申请的内存放入到队列尾int (*vidioc_qbuf)(struct file *file, void *fh, struct v4l2_buffer *b);//将内存从队列头取出int (*vidioc_dqbuf)(struct file *file, void *fh, struct v4l2_buffer *b); //开启摄像头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);
(二)v4l2_device结构体
表示一个V4L2设备,通常作为管理所有子设备的根节点。
它包含了指向子设备的指针数组,以及用于管理子设备的各种函数。
通过v4l2_device_register函数,可以将v4l2_device结构体注册到系统中。
v4l2_dev继承于device,描述摄像头设备,所有的子设备由链表连接
//v4l2设备驱动的主结构体
struct v4l2_device {struct device *dev; //指向struct device的指针struct media_device *mdev; //指向struct media_device的指针,可能为NULLstruct list_head subdevs; //已注册的子设备,以链表形式管理spinlock_t lock; //自旋锁char name[V4L2_DEVICE_NAME_SIZE]; //v4l2的设备名void (*release)(struct v4l2_device *v4l2_dev); //当引用计数降为0时调用的释放函数
};
--------------------
//以链表形式保存每一个v4l2设备的子设备
struct list_head {struct list_head *next, *prev;
};