相关源码文件:
/drivers/media/v4l2-fh.c
/drivers/media/v4l2-fh.h
在V4L2中,struct v4l2_fh
结构用于保存V4L2框架中使用的文件句柄(File Handle)的数据,即每个打开的视频设备都会对应一个struct v4l2_fh
结构体,该结构体包含了与该设备相关的各种信息,例如该设备的控制器、缓冲区、状态等等。通过struct v4l2_fh
,V4L2子系统能够跟踪设备文件的打开和关闭,并管理与句柄相关的状态和控制操作。
在新的驱动程序设计中必须使用struct v4l2_fh
,因为它可以用来实现优先级处理。该结构定义如下:
struct v4l2_fh {
struct list_head list; //file 处理列表
struct video_device *vdev; //指向video_device结构体的指针
struct v4l2_ctrl_handler *ctrl_handler; //指向结构体v4l2_ctrl_handler的指针
enum v4l2_priority prio; //文件处理程序的优先级,由enum v4l2_priority定义
/* Events */
wait_queue_head_t wait; //事件等待队列
struct list_head subscribed; //已订阅事件链表
struct list_head available; //等待退出队列的事件链表
unsigned int navailable; //可用列表中可用事件的数量
u32 sequence; //事件序列号
#if IS_ENABLED(CONFIG_V4L2_MEM2MEM_DEV)
struct v4l2_m2m_ctx *m2m_ctx; //指向结构体v4l2_m2m_ctx的指针
#endif
};
在V4L2框架中,通过检测v4l2_fh
结构中的video_device->flags
是否是V4L2_FL_USES_V4L2_FH
位来判断驱动程序是否使用v4l2_fh作为它的file->private_data
指针。该flags会在调用v4l2_fh_init()
函数时设置,如下代码:
struct v4l2_fh
被分配为驱动程序自己的文件句柄结构的一部分,并且驱动程序在open()函数中会将file->private_data
设置为文件句柄。
在多数情况下,struct v4l2_fh
将被嵌入到更大的结构中。这时候应该调用:
v4l2_fh_init() 和 v4l2_fh_add()
v4l2_fh_del() 和 v4l2_fh_exit()
注:驱动程序可以使用
container_of
宏来提取自己的文件句柄结构。
例如下列代码:
struct my_fh {
int blah;
struct v4l2_fh fh;
};
...
int my_open(struct file *file)
{
struct my_fh *my_fh;
struct video_device *vfd;
int ret;
...
my_fh = kzalloc(sizeof(*my_fh), GFP_KERNEL);
...
v4l2_fh_init(&my_fh->fh, vfd);
...
file->private_data = &my_fh->fh;
v4l2_fh_add(&my_fh->fh);
return 0;
}
int my_release(struct file *file)
{
struct v4l2_fh *fh = file->private_data;
//从子级元素(v4l2_fh)中提取父级包含元素(my_fh)
struct my_fh *my_fh = container_of(fh, struct my_fh, fh);
...
v4l2_fh_del(&my_fh->fh);
v4l2_fh_exit(&my_fh->fh);
kfree(my_fh);
return 0;
}
struct v4l2_fh
的常用API接口(1)初始化文件句柄:
v4l2_fh_init (fh, vdev)
该函数必须在驱动程序的
v4l2_file_operations->open()
处理程序中执行。
(2)将v4l2_fh
添加到video_device
的文件处理列表:
v4l2_fh_add (fh)
注:该函数必须在文件句柄完全初始化后调用。
(3)解除与video_device的文件句柄的关联:
v4l2_fh_del (fh)
(4)取消初始化的文件句柄:
v4l2_fh_exit (fh)
在取消初始化后,可以释放v4l2_fh内存。
如果struct v4l2_fh
没有嵌入到更大的结构中,可以使用下列助手函数:
v4l2_fh_open (struct file *filp)
分配一个struct v4l2_fh
,对其进行初始化并将其添加到与struct file
相关联的struct video_device
中。
v4l2_fh_release (struct file *filp)
该函数从struct file
相关联的struct video_device
中删除v4l2_fh
,取消初始化的v4l2_fh
并释放。
上述两个函数可以插入到v4l2_file_operation
的open
和release
的ops中。
当第一个文件句柄打开和最后一个文件句柄关闭时,在驱动程序中可添加两个助手函数来检查v4l2_fh
结构是否是关联该设备节点唯一打开的文件句柄:
v4l2_fh_is_singular (fh)
检查该文件句柄是否是唯一打开的文件句柄,如果是则返回1,否则返回0。
v4l2_fh_is_singular_file (struct file *filp)
该函数与v4l2_fh_is_singular()
一样,但是该函数使用filp->private_data
调用v4l2_fh_is_singular
。