第三期摄像头之第一章 USB摄像头驱动之第1.1节_摄像头驱动_V4L2框架分析

转载笔记:
https://blog.csdn.net/qingkongyeyue/article/details/53447331
https://hceng.cn/2018/03/08/Linux摄像头驱动1——vivid/

V4L2(Video for Linux two)是Linux内核中关于视频设备的内核驱动框架,为上层访问底层的视频设备提供了统一的接口。

1.摄像头驱动程序框架
摄像头驱动程序属于字符设备驱动程序。它的框架就是字符设备驱动程序框架。(回顾)
在这里插入图片描述
解释:
(1)当我们装载一个驱动程序的时候内核会自动去调用它的入口函数,入口函数会调用register_chrdev()(或者用<1>分配cdev;<2>设置cdev,cdev结构体的某一项就等于file_operation;<3>cdev_add()代替register_chrdev(),在“第25课第1节_字符设备驱动程序概念纠正之另一种写法”中有讲解)。卸载驱动程序的时候内核会自动调用出口函数,出口函数会调用unregister_chrdev()。
(2)怎么写分层驱动?
①分配某结构体(是什么结构体需要具体驱动具体分析:对于LCD来说,是fb_info结构体;对于本章的视频驱动是video_device);
②设置这个结构体;
③注册这个结构体;
④硬件相关操作。
2.V4L2框架分析
UVC – USB video class是USB视频捕获设备定义的协议标准
在这里插入图片描述
在这里插入图片描述

第一次接触V4L2,直接对内核提供的Virtual Video Driver(vivid)进行分析,只要熟悉了vivid,后续对摄像头再进行分析,就会轻松很多。vivid是内核提供的一个虚拟视频驱动,此处我们将它作为一个例子来进行分析。

2.1 分析vivi.c(virtual video driver)
①分配video_device这个结构体;
②设置这个结构体;
③注册这个结构体:video_register_device
在这里插入图片描述
解释:
video_register_device(video_device, type:VFL_TYPE_GRABBER, nr)
参1:video_device结构体;
参2:视频类型(根据类型就会去创建不同的设备节点,不同类型此设备号也是不一样的);
参3:number数量。
2.2 分析vivi.c的open,read,write,ioctl过程
(1) open
在这里插入图片描述
(2)read(write函数和read差不多)
在这里插入图片描述
(3)ioctl
在这里插入图片描述
当应用层open()/read()/write()操作/dev/videox时,先找到v4l2_fops,然后调用这个结构体里的v4l2_open/v4l2_read/v4l2_write,再通过video_devdata根据次设备号从数组中得到video_device,再找到vivid_fops里对应的操作函数。
ioctl的前面流程类似,后面通过video_usercopy()获取传入的ioctl类型,找到对应ioctl_ops,调用不同的ioctl。

2.3 怎么写v4l2驱动?
①分配/设置/注册v4l2_device结构体:核心是v4l2_device_register(感觉函数名改为v4l2_device_init更恰当),它会得到v4l2_device结构体;
②分配videv_device结构体:使用video_device_alloc函数来分配;
③设置:
a.得到videv_device vfd结构体后,让它的成员vfd.v4l2_dev结构体指向第一步得到的v4l2_device结构体,以后会使用到这个结构体(它起辅助作用,如提供自旋锁,引用计数);
b.<1>vfd结构体中还有成员v4l2_file_operations *fops结构体,它里面有open、read、write等成员。
应用程序调用open、read、write函数,内核会调用驱动里面v4l2_fops结构体里的open、read、write,这些是通用的函数,它们会调用vfd.fops结构体里面的open、read、write函数(这些才是具体的操作函数,它们被上层的v4l2_fops结构体调用);
<2>vfd结构体中还有成员ioctl_ops结构体,它被v4l2_fops结构体里的ioctl函数调用。
c.APP可以通过ioctl来设置亮度等信息,那么驱动程序里,谁来接收/存储/设置到硬件?APP可以通过ioctl来获得亮度等信息,那么谁来提供这些信息?
①属性:在驱动程序里面抽象出了一个v4l2_ctrl结构体,每个v4l2_ctrl对应一项属性,属性用v4l2_ctrl来表示,比如可以对应音量、亮度等;
②管理:使用v4l2_ctrl_handler来管理。
<1>v4l2_ctrl_handler_init来初始化这个v4l2_ctrl_handler结构体;
<2>v4l2_ctrl_new_std或v4l2_ctrl_new_custom来填充、创建v4l2_ctrl结构体里的各个属性,这两个函数起到创建v4l2_ctrl结构体并将这个结构体放入v4l2_ctrl_handler链表的作用;
<3>跟vdev关联:使用dev->v4l2_dev.ctrl_handler = hdl(hdl等于<1>、<2>步骤所创建的v4l2_ctrl_handler)和video_dev->v4l2_dev =上面的v4l2_dev(video_dev是核心)来关联。
③驱动程序里的ioctl会调用v4l2_ctrl结构体。
在这里插入图片描述

2.4 v4l2_ctrl_handler的使用过程(接着上面ioctl过程)
在这里插入图片描述
V4L2的框架实质上并没有脱离字符设备的框架,只是ioctrl复杂了一点。

猜你喜欢

转载自blog.csdn.net/yanxuan321/article/details/87546960