v4l2: [02-1]_驱动总体框架,[02-2]_ioctl调用流程分析

This commit is contained in:
weidongshan
2023-08-03 09:18:38 +08:00
parent c94156c59d
commit 7355c13ef5
21 changed files with 237 additions and 8 deletions

View File

@@ -0,0 +1,111 @@
# V4L2驱动程序框架 #
参考资料:
* 深入理解linux内核v4l2框架之videobuf2https://blog.csdn.net/yyjsword/article/details/9243717
## 1. 整体框架
* 字符设备驱动程序的核心是file_operations结构体
* V4L2设备驱动程序的核心是video_device结构体它里面有2大成员
* v4l2_file_operations结构体实现具体的open/read/write/ioctl/mmap操作
* v4l2_ioctl_ops结构体v4l2_file_operations结构体一般使用video_ioctl2函数它要调用v4l2_ioctl_ops结构体
![image-20230802131727705](pic/21_v4l2_framework.png)
### 1.1 V4L2驱动程序注册流程
参考`drivers\media\usb\airspy\airspy.c`
```shell
static struct video_device airspy_template = {
.name = "AirSpy SDR",
.release = video_device_release_empty,
.fops = &airspy_fops,
.ioctl_ops = &airspy_ioctl_ops,
};
// 分配/设置video_device结构体
s->vdev = airspy_template;
// 初始化一个v4l2_device结构体(起辅助作用)
/* Register the v4l2_device structure */
s->v4l2_dev.release = airspy_video_release;
ret = v4l2_device_register(&intf->dev, &s->v4l2_dev);
// video_device和4l2_device建立联系
s->vdev.v4l2_dev = &s->v4l2_dev;
// 注册video_device结构体
ret = video_register_device(&s->vdev, VFL_TYPE_SDR, -1);
__video_register_device
// 根据次设备号把video_device结构体放入数组
video_device[vdev->minor] = vdev;
// 注册字符设备驱动程序
vdev->cdev->ops = &v4l2_fops;
vdev->cdev->owner = owner;
ret = cdev_add(vdev->cdev, MKDEV(VIDEO_MAJOR, vdev->minor), 1);
```
### 1.2 ioctl调用流程分析
#### 1.2.1 两类ioctl
底层驱动程序提供了很多ioctl的处理函数比如
![image-20230802171650240](pic/23_std_ioctls.png)
这些ioctl被分为2类
* INFO_FL_STD标准的无需特殊的代码来处理APP的调用可以直达这些处理函数
* INFO_FL_FUNC这类ioctl需要特殊处理比如对于`VIDIOC_ENUM_FMT`,它需要根据设备的类型分别枚举:
![image-20230802182129884](pic/26_func_ioctl_example.png)
简单地说这2类ioctl的差别在于
* INFO_FL_STDAPP发出的ioctl直接调用底层的video_device->ioctl_ops->xxxx(....)
* INFO_FL_FUNCAPP发出的ioctl交给`drivers\media\v4l2-core\v4l2-ioctl.c`它先进行一些特殊处理后再调用底层的video_device->ioctl_ops->xxxx(....)
怎么区分这些ioctl呢`drivers\media\v4l2-core\v4l2-ioctl.c`中有个数组:
![image-20230802182925664](pic/27_v4l2_ioctls.png)
这个数组里每一项都表示一个ioctl
* 使用`IOCTL_INFO_FNC`定义的数组项,表示它是`INFO_FL_FUNC`类型的
![image-20230802183344592](pic/24_ioctl_func.png)
* 使用`IOCTL_INFO_STD`定义的数组项,表示它是`INFO_FL_STD`类型的
![image-20230802183251984](pic/25_v4l2_ioctls_offset.png)
#### 1.2.2 调用流程
APP调用摄像头的ioctl流程为
![image-20230802170836061](pic/22_ioctl_detail.png)
### 1.3 buffer的内核实现
APP操作buffer的示意图如下
![image-20230617171816630](pic/05_buffers.png)
驱动程序中如何管理这些buffer呢
## 2. 从0编写一个虚拟的摄像头驱动

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 223 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

View File

@@ -771,22 +771,29 @@ git clone https://e.coding.net/weidongshan/linux/doc_and_source_for_drivers.git
* 2023.06.18 发布"摄像头驱动" * 2023.06.18 发布"摄像头驱动"
```shell ```shell
01_V4L2应用程序开发_数据采集流程 [01-1]_V4L2应用程序开发_数据采集流程
``` ```
* 2023.06.18 发布"摄像头驱动" * 2023.07.18 发布"摄像头驱动"
```shell ```shell
02_V4L2应用程序开发_控制流程 [01-2]_V4L2应用程序开发_控制流程
``` ```
* 2023.06.18 发布"摄像头驱动" * 2023.07.18 发布"摄像头驱动"
```shell ```shell
03_V4L2应用程序开发_列出帧细节 [01-3]_V4L2应用程序开发_列出帧细节
04_V4L2应用程序开发_获取数据 [01-4]_V4L2应用程序开发_获取数据
05_V4L2应用程序开发_调试 [01-5]_V4L2应用程序开发_调试
06_V4L2应用程序开发_控制亮度 [01-6]_V4L2应用程序开发_控制亮度
```
* 2023.08.03 发布"摄像头驱动"
```shell
[02-1]_驱动总体框架
[02-2]_ioctl调用流程分析
``` ```

View File

@@ -0,0 +1,111 @@
# V4L2驱动程序框架 #
参考资料:
* 深入理解linux内核v4l2框架之videobuf2https://blog.csdn.net/yyjsword/article/details/9243717
## 1. 整体框架
* 字符设备驱动程序的核心是file_operations结构体
* V4L2设备驱动程序的核心是video_device结构体它里面有2大成员
* v4l2_file_operations结构体实现具体的open/read/write/ioctl/mmap操作
* v4l2_ioctl_ops结构体v4l2_file_operations结构体一般使用video_ioctl2函数它要调用v4l2_ioctl_ops结构体
![image-20230802131727705](pic/21_v4l2_framework.png)
### 1.1 V4L2驱动程序注册流程
参考`drivers\media\usb\airspy\airspy.c`
```shell
static struct video_device airspy_template = {
.name = "AirSpy SDR",
.release = video_device_release_empty,
.fops = &airspy_fops,
.ioctl_ops = &airspy_ioctl_ops,
};
// 分配/设置video_device结构体
s->vdev = airspy_template;
// 初始化一个v4l2_device结构体(起辅助作用)
/* Register the v4l2_device structure */
s->v4l2_dev.release = airspy_video_release;
ret = v4l2_device_register(&intf->dev, &s->v4l2_dev);
// video_device和4l2_device建立联系
s->vdev.v4l2_dev = &s->v4l2_dev;
// 注册video_device结构体
ret = video_register_device(&s->vdev, VFL_TYPE_SDR, -1);
__video_register_device
// 根据次设备号把video_device结构体放入数组
video_device[vdev->minor] = vdev;
// 注册字符设备驱动程序
vdev->cdev->ops = &v4l2_fops;
vdev->cdev->owner = owner;
ret = cdev_add(vdev->cdev, MKDEV(VIDEO_MAJOR, vdev->minor), 1);
```
### 1.2 ioctl调用流程分析
#### 1.2.1 两类ioctl
底层驱动程序提供了很多ioctl的处理函数比如
![image-20230802171650240](pic/23_std_ioctls.png)
这些ioctl被分为2类
* INFO_FL_STD标准的无需特殊的代码来处理APP的调用可以直达这些处理函数
* INFO_FL_FUNC这类ioctl需要特殊处理比如对于`VIDIOC_ENUM_FMT`,它需要根据设备的类型分别枚举:
![image-20230802182129884](pic/26_func_ioctl_example.png)
简单地说这2类ioctl的差别在于
* INFO_FL_STDAPP发出的ioctl直接调用底层的video_device->ioctl_ops->xxxx(....)
* INFO_FL_FUNCAPP发出的ioctl交给`drivers\media\v4l2-core\v4l2-ioctl.c`它先进行一些特殊处理后再调用底层的video_device->ioctl_ops->xxxx(....)
怎么区分这些ioctl呢`drivers\media\v4l2-core\v4l2-ioctl.c`中有个数组:
![image-20230802182925664](pic/27_v4l2_ioctls.png)
这个数组里每一项都表示一个ioctl
* 使用`IOCTL_INFO_FNC`定义的数组项,表示它是`INFO_FL_FUNC`类型的
![image-20230802183344592](pic/24_ioctl_func.png)
* 使用`IOCTL_INFO_STD`定义的数组项,表示它是`INFO_FL_STD`类型的
![image-20230802183251984](pic/25_v4l2_ioctls_offset.png)
#### 1.2.2 调用流程
APP调用摄像头的ioctl流程为
![image-20230802170836061](pic/22_ioctl_detail.png)
### 1.3 buffer的内核实现
APP操作buffer的示意图如下
![image-20230617171816630](pic/05_buffers.png)
驱动程序中如何管理这些buffer呢
## 2. 从0编写一个虚拟的摄像头驱动

Binary file not shown.

After

Width:  |  Height:  |  Size: 223 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB