【V4L2】 v4l2框架分析之v4l2_fh

一、v4l2_fh简介

相关源码文件:

  • /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()函数时设置,如下代码:

【V4L2】 v4l2框架分析之v4l2_fh_第1张图片

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_operationopenrelease的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

你可能感兴趣的:(小生聊【嵌入式linux】,小生聊【linux,kernel】,c语言,linux,v4l2_fh,v4l2,linux内核)