发布: subdev和media子系统
BIN
IMX6ULL/doc_pic/13_V4L2/05-3-1_subdev和media子系统引入.tif
Normal file
BIN
IMX6ULL/doc_pic/13_V4L2/05-3-1_subdev和media子系统的作用与关系_bak.tif
Normal file
BIN
IMX6ULL/doc_pic/13_V4L2/05-3-2_subdev概览与数据结构.tif
Normal file
BIN
IMX6ULL/doc_pic/13_V4L2/05-3-3_media子系统概览与数据结构.tif
Normal file
BIN
IMX6ULL/doc_pic/13_V4L2/05-3-4_subdev的注册与使用.tif
Normal file
@@ -395,7 +395,692 @@ vi ./device/config/chips/v853/configs/100ask/linux-4.9/sys_partition.fex
|
||||
|
||||
|
||||
|
||||
## 4. subdev和media子系统
|
||||
|
||||
### 4.1 subdev和media子系统的引入
|
||||
|
||||
#### 4.1.1 subdev的引入
|
||||
|
||||
##### 1. 简单驱动
|
||||
|
||||
对于比较简单的摄像头,我们把它当做一个整体,它的核心就是一个video_device。以前面讲过的虚拟驱动程序为例,它的源码位于如下目录:
|
||||
|
||||

|
||||
|
||||
这个驱动程序的核心是video_device,如下:
|
||||
|
||||

|
||||
|
||||
在整个驱动程序中,没有subdev,没有media子系统。
|
||||
|
||||
|
||||
|
||||
##### 2. UVC驱动
|
||||
|
||||
USB摄像头稍微复杂一点,它的内部有各类Unit或Terminal,如下图所示:
|
||||
|
||||

|
||||
|
||||
但是这些Unit或Terminal的独立性不强,并且它们遵守UVC规范,没必要单独为它们编写驱动程序。在UVC驱动程序里,每一个Unit或Terminal都有一个"struct uvc_entity"结构体,每一个"struct uvc_entity"里面也都有一个"struct v4l2_subdev",如下图所示:
|
||||
|
||||

|
||||
|
||||
但是,这些subdev没有什么作用,它们的ops函数都是空的:
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
##### 3. 复杂驱动
|
||||
|
||||
下图是使用v853 mipi摄像头时,涉及的内部结构或内部流程:
|
||||
|
||||

|
||||
|
||||
内部涉及的模块非常多,这些模块相对独立,有必要单独给这些模块编写驱动程序。
|
||||
|
||||
这些模块被抽象为subdev,原因有2:
|
||||
|
||||
* 屏蔽硬件操作的细节,有些模块是I2C接口的,有些模块是SPI接口的,它们都被封装为subdev
|
||||
* 方便内核使用、APP使用:可以在内核里调用subdev的函数,也可以在用户空间调用subdev的函数:很多厂家不愿意公开ISP的源码,只能在驱动层面提供最简单的subdev,然后通过APP调用subdev的基本读写函数进行复杂的设置。
|
||||
|
||||
subdev结构体如下:
|
||||
|
||||

|
||||
|
||||
里面有各类ops结构体,比如core、tuner、audio、video等等。编写subdev驱动程序时,核心就是实现各类ops结构体的函数。
|
||||
|
||||
以上图中第1个模块gc2053为例,它的代码为"drivers\media\platform\sunxi-vin\modules\sensor\gc2053_mipi.c",核心结构体如下:
|
||||
|
||||

|
||||
|
||||
#### 4.1.2 media子系统的引入
|
||||
|
||||
即使我们给每一个子模块都编写了驱动程序,都构造了subdev,但是它们之间的相互关系怎么表示?如下图:
|
||||
|
||||
* 每一个模块都构造了subdev
|
||||
* 但是,框图里黑色箭头所表示的关系如何描述?
|
||||
* 比如,从"格式解析"模块出来的数据,到底是输出到"ISP0"还是"ISP1"?用户如何选择?
|
||||
* 当我们指定"格式解析"模块输出的数据格式后,是否也要同步指定ISP0或ISP1模块的输入数据格式?
|
||||
|
||||

|
||||
|
||||
这就需要引入media子系统,简化如下:
|
||||
|
||||

|
||||
|
||||
怎么操作上图的各个对象?使用subdev。subdev里含有各个对象的操作函数。
|
||||
|
||||
怎么表示上图的各个对象之间的关系?使用media子系统。在media子系统里,
|
||||
|
||||
* 每个对象都是一个media_entity
|
||||
* media_entity有media_pad,可以认为是端点(不能简单认为是硬件引脚),有source pad(输出数据),sink pad(输入数据)
|
||||
* media_entity之间的连接被称为media_link
|
||||
* media_link仅仅表示两个media_entity之间的连接,要构成一个完整的数据通道,需要多个系列的连接,这被称为pipeline
|
||||
* media子系统的作用就在于管理"拓扑关系",就是各个对象的连接关系。
|
||||
|
||||
|
||||
|
||||
把V853的拓扑图精简一下:
|
||||
|
||||

|
||||
|
||||
怎么表示上图的各个对象?使用media子系统,media子系统的作用在于管理"拓扑关系",就是各个对象的连接关系。
|
||||
|
||||
怎么操作上图的各个对象?使用subdev。subdev里含有各个对象的操作函数。
|
||||
|
||||
|
||||
|
||||
命令示例:
|
||||
|
||||
```shell
|
||||
media-ctl -v -l '"gc2053_mipi":0->"sunxi_mipi.0":0[1]'
|
||||
v4l2-ctl -D -d /dev/v4l-subdev0
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 4.2 subdev概览与数据结构
|
||||
|
||||
#### 4.2.1 实例
|
||||
|
||||
以`drivers\media\platform\sunxi-vin\modules\sensor\gc2053_mipi.c`为例:
|
||||
|
||||
```c
|
||||
sensor_probe
|
||||
/* 分配sensor_info结构体,里面含有v4l2_subdev */
|
||||
struct v4l2_subdev *sd;
|
||||
struct sensor_info *info;
|
||||
|
||||
info = kzalloc(sizeof(struct sensor_info), GFP_KERNEL);
|
||||
sd = &info->sd;
|
||||
|
||||
cci_dev_probe_helper(sd, client, &sensor_ops, &cci_drv[sensor_dev_id++]);
|
||||
v4l2_i2c_subdev_init(sd, client, sensor_ops);
|
||||
v4l2_subdev_init(sd, ops);
|
||||
```
|
||||
|
||||

|
||||
|
||||
#### 4.2.2 数据结构
|
||||
|
||||
一个模块对应一个subdev,怎么操作这个模块?subdev里面有ops:
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
怎么管理多个subdev?必定是放入一个链表里:
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
### 4.3 media子系统概览与数据结构
|
||||
|
||||
#### 4.3.1 拓扑结构
|
||||
|
||||
对于V853精简的拓扑图:
|
||||
|
||||

|
||||
|
||||
在media子系统里,怎么表示上面的各个entity的关系?以最左边2个entity为例,结构体如下:
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
#### 4.3.2 数据结构
|
||||
|
||||
一个media子系统使用"struct media_device"来表示,结构体如下:
|
||||
|
||||

|
||||
|
||||
media_device里有多个entity,它使用"struct media_entity"来表示:
|
||||
|
||||

|
||||
|
||||
media_entity里有多个pad,它使用"struct media_pad"来表示:
|
||||
|
||||

|
||||
|
||||
entity通过pad跟其他entity相连,这被称为link,它使用"media_link"来表示:
|
||||
|
||||

|
||||
|
||||
两个entity之间的连接,被称为link;多个已经使能的link构成一条完整的数据通道,这被称为pipeline。驱动程序在进行streamon操作时,有些驱动会调用"media_entity_pipeline_start"函数,类似下面的代码:
|
||||
|
||||
```c
|
||||
ret = media_entity_pipeline_start(sensor, camif->m_pipeline);
|
||||
```
|
||||
|
||||
第1个参数是第1个entity,第2个参数就是pipeline(它在media_entity_pipeline_start函数内部构造)。
|
||||
|
||||
media_entity_pipeline_start的目的,是从第1个entity开始,遍历所有的link,把已经使能的link都执行"link_validate"。
|
||||
|
||||
media_entity_pipeline_start内部,是按照深度优先来操作entity的,以下图为例:
|
||||
|
||||
* 有两条pipeline:e0->e1->e2->e3,e0->e1->e4->e5
|
||||
* 先遍历e0->e1->e2->e3这条pipeline,调用e3、e2的"link_validate"
|
||||
* 再遍历e0->e1->e4->e5这条pipeline,调用e5、e4的"link_validate"
|
||||
* 接着处理e1,调用它的"link_validate"
|
||||
* 最后处理e0,它没有sink pad,无需调用它的"link_validate"
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#### 4.3.3 media子系统和subdev的关系
|
||||
|
||||
内核空间,v4l2_subdev里含有media_entity,两者都很容易找到对方:
|
||||
|
||||

|
||||
|
||||
从entity找到subdev,使用以下代码:
|
||||
|
||||
```shell
|
||||
#define media_entity_to_v4l2_subdev(ent) \
|
||||
container_of(ent, struct v4l2_subdev, entity)
|
||||
```
|
||||
|
||||
|
||||
|
||||
用户空间里,怎么从entity找到对应的/dev/v4l-subdevX?参考`v4l-utils-1.20.0\utils\media-ctl\libmediactl.c`
|
||||
|
||||
```c
|
||||
// 1. open /dev/media0
|
||||
media->fd = open(media->devnode, O_RDWR);
|
||||
|
||||
// 2.循环调用ioctl(MEDIA_IOC_ENUM_ENTITIES), 得到每一个entity的信息
|
||||
entity = &media->entities[media->entities_count];
|
||||
memset(entity, 0, sizeof(*entity));
|
||||
entity->fd = -1;
|
||||
entity->info.id = id | MEDIA_ENT_ID_FLAG_NEXT;
|
||||
entity->media = media;
|
||||
|
||||
// entity->info类型为: struct media_entity_desc info;
|
||||
// 里面含有major, minor
|
||||
ret = ioctl(media->fd, MEDIA_IOC_ENUM_ENTITIES, &entity->info);
|
||||
|
||||
|
||||
// 3. 使用media_get_devname_sysfs函数获得entity对应的设备节点
|
||||
// 根据主设备号、次设备号在/sys/dev/char目录下找到类似这样的文件: /sys/dev/char/81:2
|
||||
// 它是一个连接文件,连接到:../../devices/platform/soc/5800800.vind/video4linux/v4l-subdev0
|
||||
// /dev/v4l-subdev0就是这个entity对应的设备节点
|
||||
// APP的media_entity.devname[32]里就是"/dev/v4l-subdev0"
|
||||
static int media_get_devname_sysfs(struct media_entity *entity);
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 4.4 subdev的注册与使用
|
||||
|
||||
#### 4.4.1 内核注册过程
|
||||
|
||||
subdev里含有模块的操作函数,谁调用这些函数?
|
||||
|
||||
* 内核调用:subdev完全可以不暴露给用户,在摄像头驱动程序内部"偷偷地"调用subdev的函数,用户感觉不到subdev的存在。
|
||||
* APP调用:对于比较复杂的硬件,驱动程序应该"让用户有办法调节各类参数",比如ISP模块几乎都是闭源的,对它的设置只能通过APP进行。这类subdev的函数,应该暴露给用户,用户可以调用它们。
|
||||
|
||||
在内核里,subdev的注册过程为分为2步:
|
||||
|
||||
* v4l2_device_register_subdev: 把subdev放入v4l2_device的链表
|
||||
|
||||
```c
|
||||
int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,
|
||||
struct v4l2_subdev *sd);
|
||||
```
|
||||
|
||||
* v4l2_device_register_subdev_nodes:遍历v4l2_device链表里各个subdev,如果它想暴露给APP,就把它注册为普通字符设备
|
||||
|
||||
```c
|
||||
int v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev);
|
||||
|
||||
// 调用过程如下
|
||||
v4l2_device_register_subdev_nodes
|
||||
struct video_device *vdev;
|
||||
vdev->fops = &v4l2_subdev_fops;
|
||||
err = __video_register_device(vdev, VFL_TYPE_SUBDEV, -1, 1,
|
||||
sd->owner);
|
||||
name_base = "v4l-subdev";
|
||||
vdev->cdev->ops = &v4l2_fops;
|
||||
ret = cdev_add(vdev->cdev, MKDEV(VIDEO_MAJOR, vdev->minor), 1);
|
||||
```
|
||||
|
||||
|
||||
|
||||
v4l2_device_register_subdev_nodes的注册过程涉及2个结构体:
|
||||
|
||||
* file_operations:
|
||||

|
||||
|
||||
* v4l2_file_operations:
|
||||

|
||||
|
||||
|
||||
|
||||
APP对/dev/v4l-subdev*这类的设备进行ioctl操作时,内核里流程如下:
|
||||
|
||||
```shell
|
||||
App: ioctl
|
||||
--------------
|
||||
kernel:
|
||||
v4l2_fops.unlocked_ioctl, 即v4l2_ioctl
|
||||
ret = vdev->fops->unlocked_ioctl(filp, cmd, arg);
|
||||
v4l2_subdev_fops.unlocked_ioctl, 即subdev_ioctl
|
||||
video_usercopy(file, cmd, arg, subdev_do_ioctl);
|
||||
```
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
#### 4.4.2 内核态使用subdev
|
||||
|
||||
可以直接调用subdev里的操作函数,也可以使用下面的宏:
|
||||
|
||||
```c
|
||||
#define v4l2_subdev_call(sd, o, f, args...) \
|
||||
(!(sd) ? -ENODEV : (((sd)->ops->o && (sd)->ops->o->f) ? \
|
||||
(sd)->ops->o->f((sd), ##args) : -ENOIOCTLCMD))
|
||||
```
|
||||
|
||||
|
||||
|
||||
#### 4.4.3 用户态使用subdev
|
||||
|
||||
APP可以打开设备文件/dev/v4l-subdevX,执行ioctl调用驱动里面的各个ops函数,调用关系如下:
|
||||
|
||||
##### 1. v4l2_subdev_core_ops
|
||||
|
||||
* VIDIOC_SUBSCRIBE_EVENT:APP订阅感兴趣的事件,导致core->subscribe_event被调用
|
||||
* VIDIOC_UNSUBSCRIBE_EVENT:APP取消兴趣,导致core->unsubscribe_event被调用
|
||||
* VIDIOC_DBG_G_REGISTER:调试作用,读寄存器,导致core->g_register被调用
|
||||
* VIDIOC_DBG_S_REGISTER:调试作用,写寄存器,导致core->s_register被调用
|
||||
* VIDIOC_LOG_STATUS:调试作用,打印调试信息,导致core->log_status被调用
|
||||
|
||||
##### 2. v4l2_subdev_video_ops
|
||||
|
||||
* VIDIOC_SUBDEV_G_FRAME_INTERVAL:获得帧间隔,导致video->g_frame_interval被调用
|
||||
* VIDIOC_SUBDEV_S_FRAME_INTERVAL:设置帧间隔,导致video->s_frame_interval被调用
|
||||
* VIDIOC_SUBDEV_QUERY_DV_TIMINGS:导致video->query_dv_timings被调用
|
||||
* VIDIOC_SUBDEV_G_DV_TIMINGS:导致video->g_dv_timings被调用
|
||||
* VIDIOC_SUBDEV_S_DV_TIMINGS:导致video->s_dv_timings被调用
|
||||
|
||||
|
||||
|
||||
##### 3. v4l2_subdev_pad_ops
|
||||
|
||||
* VIDIOC_SUBDEV_G_FMT:导致pad->get_fmt被调用
|
||||
* VIDIOC_SUBDEV_S_FMT:导致pad->set_fmt被调用
|
||||
* VIDIOC_SUBDEV_G_CROP/VIDIOC_SUBDEV_G_SELECTION:导致pad->get_selection被调用
|
||||
* VIDIOC_SUBDEV_S_CROP/VIDIOC_SUBDEV_S_SELECTION:导致pad->set_selection被调用
|
||||
* VIDIOC_SUBDEV_ENUM_MBUS_CODE:导致pad->enum_mbus_code被调用
|
||||
* VIDIOC_SUBDEV_ENUM_FRAME_SIZE:导致pad->enum_frame_size被调用
|
||||
* VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL:导致pad->enum_frame_interval被调用
|
||||
* VIDIOC_G_EDID:导致pad->get_edid被调用
|
||||
* VIDIOC_S_EDID:导致pad->set_edid被调用
|
||||
* VIDIOC_SUBDEV_DV_TIMINGS_CAP:导致pad->dv_timings_cap被调用
|
||||
* VIDIOC_SUBDEV_ENUM_DV_TIMINGS:导致pad->enum_dv_timings被调用
|
||||
|
||||
驱动内部调用:
|
||||
|
||||
* v4l2_subdev_link_validate:导致pad->link_validate被调用
|
||||
* v4l2_subdev_alloc_pad_config:导致pad->init_cfg被调用
|
||||
|
||||
|
||||
|
||||
### 4.5 media子系统的注册与使用
|
||||
|
||||
#### 4.5.1 内核注册过程
|
||||
|
||||
在内核里,media子系统的注册过程为:
|
||||
|
||||
```shell
|
||||
media_device_register
|
||||
__media_device_register
|
||||
struct media_devnode *devnode;
|
||||
devnode->fops = &media_device_fops;
|
||||
ret = media_devnode_register(mdev, devnode, owner);
|
||||
cdev_init(&devnode->cdev, &media_devnode_fops);
|
||||
ret = cdev_add(&devnode->cdev, MKDEV(MAJOR(media_dev_t), devnode->minor), 1);
|
||||
```
|
||||
|
||||
上述注册过程涉及2个结构体:
|
||||
|
||||
* file_operations:
|
||||

|
||||
|
||||
* media_file_operations:
|
||||

|
||||
|
||||
|
||||
|
||||
APP对/dev/media0这类的设备进行ioctl操作时,内核里流程如下:
|
||||
|
||||
```shell
|
||||
App: ioctl
|
||||
--------------
|
||||
kernel:
|
||||
media_devnode_fops.unlocked_ioctl, 即media_ioctl
|
||||
__media_ioctl(filp, cmd, arg, devnode->fops->ioctl);
|
||||
media_device_ioctl
|
||||
const struct media_ioctl_info *info;
|
||||
info = &ioctl_info[_IOC_NR(cmd)];
|
||||
ret = info->arg_from_user(karg, arg, cmd);
|
||||
ret = info->fn(dev, karg);
|
||||
ret = info->arg_to_user(arg, karg, cmd);
|
||||
```
|
||||
|
||||
核心在于ioctl_info:
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#### 4.5.2 调用关系
|
||||
|
||||
APP使用media子系统时,除了open之外,就只涉及5个ioctl:
|
||||
|
||||
* MEDIA_IOC_DEVICE_INFO
|
||||
* MEDIA_IOC_ENUM_ENTITIES
|
||||
* MEDIA_IOC_ENUM_LINKS
|
||||
* MEDIA_IOC_SETUP_LINK
|
||||
* MEDIA_IOC_G_TOPOLOGY
|
||||
|
||||
这5个ioctl将导致内核中如下函数被调用(drivers\media\media-device.c):
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
##### 1.MEDIA_IOC_DEVICE_INFO
|
||||
|
||||
这个ioctl被用来获得/dev/mediaX的设备信息,设备信息结构体如下
|
||||

|
||||
|
||||
APP代码如下:
|
||||
|
||||
```c
|
||||
memset(&media->info, 0, sizeof(media->info)); // struct media_device_info info;
|
||||
ret = ioctl(media->fd, MEDIA_IOC_DEVICE_INFO, &media->info);
|
||||
```
|
||||
|
||||
驱动中对应核心代码如下:
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
##### 2. MEDIA_IOC_ENUM_ENTITIES
|
||||
|
||||
这个ioctl被用来获得指定entity的信息,APP参考代码为
|
||||

|
||||
|
||||
驱动中对应核心代码如下:
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
##### 3. MEDIA_IOC_ENUM_LINKS
|
||||
|
||||
这个ioctl被用来枚举enity的link,APP参考代码为
|
||||

|
||||
|
||||
驱动中对应核心代码如下:
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
##### 4. MEDIA_IOC_SETUP_LINK
|
||||
|
||||
这个ioctl被用来设置link,把源pad、目的pad之间的连接激活(active),或者闲置(inactive),APP示例代码为:
|
||||

|
||||
|
||||
APP传入的flags的取值有2种:
|
||||
|
||||
* 0:闲置link
|
||||
* 1:激活link
|
||||
|
||||
内核里link的flag有如下取值:
|
||||
|
||||

|
||||
|
||||
如果这个link的flag不是MEDIA_LINK_FL_IMMUTABLE的话,就可以去更改它的bit0状态:激活或闲置。
|
||||
|
||||
|
||||
|
||||
驱动中对应核心代码如下:
|
||||
|
||||

|
||||
|
||||
##### 5. MEDIA_IOC_G_TOPOLOGY
|
||||
|
||||
这个ioctl被用来获得整体的拓扑图,包括entities、interfaces、pads、links的信息,示例代码如下
|
||||
|
||||

|
||||
|
||||
驱动中对应核心代码如下,只要APP提供了对应的buffer,它就可以复制对应的信息,比如entities、interfaces、pads、links的信息:
|
||||
|
||||

|
||||
|
||||
*
|
||||
|
||||
### 4.6 v4l2-utils使用详解
|
||||
|
||||
v4l2-utils中含有多个APP,比如:
|
||||
|
||||
- [DVBv5_Tools](https://www.linuxtv.org/wiki/index.php/DVBv5_Tools): tools to scan, zap and do other neat things with DVB devices;
|
||||
- ir-keytable: Dump, Load or Modify ir receiver input tables;
|
||||
- ir-ctl: A swiss-knife tool to handle raw IR and to set lirc options;
|
||||
- media-ctl: Tool to handle media controller devices;
|
||||
- qv4l2: QT v4l2 control panel application;
|
||||
- v4l2-compliance: Tool to test v4l2 API compliance of drivers;
|
||||
- v4l2-ctl: tool to control v4l2 controls from the cmdline;
|
||||
- v4l2-dbg: tool to directly get and set registers of v4l2 devices;
|
||||
- v4l2-sysfs-path: checks the media devices installed on a machine and the corresponding device nodes;
|
||||
- xc3028-firmware: Xceive XC2028/3028 tuner module firmware manipulation tool;
|
||||
- cx18-ctl: tool to handle cx18 based devices (deprecated in favor of v4l2-ctl);
|
||||
- ivtv-ctl: tool to handle ivtv based devices (deprecated in favor of v4l2-ctl);
|
||||
- rds-ctl: tool to handle RDS radio devices;
|
||||
- decode_tm6000: ancillary tool to decodes tm6000 proprietary format streams;
|
||||
- cec-ctl: tool to control CEC devices from the command line;
|
||||
- cec-follower: tool used to emulate CEC followers;
|
||||
- cec-compliance: tool to test CEC API compliance of drivers and remote CEC devices;
|
||||
|
||||
|
||||
|
||||
media-ctl使用方法为:
|
||||
|
||||
```shell
|
||||
media-ctl --help
|
||||
media-ctl [options]
|
||||
-d, --device dev Media device name (default: /dev/media0)
|
||||
If <dev> starts with a digit, then /dev/media<dev> is used.
|
||||
If <dev> doesn't exist, then find a media device that
|
||||
reports a bus info string equal to <dev>.
|
||||
-e, --entity name Print the device name associated with the given entity
|
||||
-V, --set-v4l2 v4l2 Comma-separated list of formats to setup
|
||||
--get-v4l2 pad Print the active format on a given pad
|
||||
--get-dv pad Print detected and current DV timings on a given pad
|
||||
--set-dv pad Configure DV timings on a given pad
|
||||
-h, --help Show verbose help and exit
|
||||
-i, --interactive Modify links interactively
|
||||
-l, --links links Comma-separated list of link descriptors to setup
|
||||
--known-mbus-fmts List known media bus formats and their numeric values
|
||||
-p, --print-topology Print the device topology. If an entity
|
||||
is specified through the -e option, print
|
||||
information for that entity only.
|
||||
--print-dot Print the device topology as a dot graph
|
||||
-r, --reset Reset all links to inactive
|
||||
-v, --verbose Be verbose
|
||||
|
||||
Links and formats are defined as
|
||||
links = link { ',' link } ;
|
||||
link = pad '->' pad '[' flags ']' ;
|
||||
pad = entity ':' pad-number ;
|
||||
entity = entity-number | ( '"' entity-name '"' ) ;
|
||||
|
||||
v4l2 = pad '[' v4l2-properties ']' ;
|
||||
v4l2-properties = v4l2-property { ',' v4l2-property } ;
|
||||
v4l2-property = v4l2-mbusfmt | v4l2-crop | v4l2-interval
|
||||
| v4l2-compose | v4l2-interval ;
|
||||
v4l2-mbusfmt = 'fmt:' fcc '/' size ; { 'field:' v4l2-field ; } { 'colorspace:' v4l2-colorspace ; }
|
||||
{ 'xfer:' v4l2-xfer-func ; } { 'ycbcr-enc:' v4l2-ycbcr-enc-func ; }
|
||||
{ 'quantization:' v4l2-quant ; }
|
||||
v4l2-crop = 'crop:' rectangle ;
|
||||
v4l2-compose = 'compose:' rectangle ;
|
||||
v4l2-interval = '@' numerator '/' denominator ;
|
||||
|
||||
rectangle = '(' left ',' top, ')' '/' size ;
|
||||
size = width 'x' height ;
|
||||
|
||||
where the fields are
|
||||
entity-number Entity numeric identifier
|
||||
entity-name Entity name (string)
|
||||
pad-number Pad numeric identifier
|
||||
flags Link flags (0: inactive, 1: active)
|
||||
fcc Format FourCC
|
||||
width Image width in pixels
|
||||
height Image height in pixels
|
||||
numerator Frame interval numerator
|
||||
denominator Frame interval denominator
|
||||
v4l2-field One of the following:
|
||||
any
|
||||
none
|
||||
top
|
||||
bottom
|
||||
interlaced
|
||||
seq-tb
|
||||
seq-bt
|
||||
alternate
|
||||
interlaced-tb
|
||||
interlaced-bt
|
||||
v4l2-colorspace One of the following:
|
||||
default
|
||||
smpte170m
|
||||
smpte240m
|
||||
rec709
|
||||
unknown
|
||||
470m
|
||||
470bg
|
||||
jpeg
|
||||
srgb
|
||||
oprgb
|
||||
bt2020
|
||||
raw
|
||||
dcip3
|
||||
v4l2-xfer-func One of the following:
|
||||
default
|
||||
709
|
||||
srgb
|
||||
oprgb
|
||||
smpte240m
|
||||
none
|
||||
dcip3
|
||||
smpte2084
|
||||
v4l2-quant One of the following:
|
||||
default
|
||||
full-range
|
||||
lim-range
|
||||
```
|
||||
|
||||
|
||||
|
||||
v4l2-ctl使用方法如下:
|
||||
|
||||
```shell
|
||||
v4l2-ctl --help
|
||||
|
||||
General/Common options:
|
||||
--all display all information available
|
||||
-C, --get-ctrl <ctrl>[,<ctrl>...]
|
||||
get the value of the controls [VIDIOC_G_EXT_CTRLS]
|
||||
-c, --set-ctrl <ctrl>=<val>[,<ctrl>=<val>...]
|
||||
set the value of the controls [VIDIOC_S_EXT_CTRLS]
|
||||
-D, --info show driver info [VIDIOC_QUERYCAP]
|
||||
-d, --device <dev> use device <dev> instead of /dev/video0
|
||||
if <dev> starts with a digit, then /dev/video<dev> is used
|
||||
Otherwise if -z was specified earlier, then <dev> is the entity name
|
||||
or interface ID (if prefixed with 0x) as found in the topology of the
|
||||
media device with the bus info string as specified by the -z option.
|
||||
-e, --out-device <dev> use device <dev> for output streams instead of the
|
||||
default device as set with --device
|
||||
if <dev> starts with a digit, then /dev/video<dev> is used
|
||||
Otherwise if -z was specified earlier, then <dev> is the entity name
|
||||
or interface ID (if prefixed with 0x) as found in the topology of the
|
||||
media device with the bus info string as specified by the -z option.
|
||||
-E, --export-device <dev> use device <dev> for exporting DMA buffers
|
||||
if <dev> starts with a digit, then /dev/video<dev> is used
|
||||
Otherwise if -z was specified earlier, then <dev> is the entity name
|
||||
or interface ID (if prefixed with 0x) as found in the topology of the
|
||||
media device with the bus info string as specified by the -z option.
|
||||
-z, --media-bus-info <bus-info>
|
||||
find the media device with the given bus info string. If set, then
|
||||
-d, -e and -E options can use the entity name or interface ID to refer
|
||||
to the device nodes.
|
||||
-h, --help display this help message
|
||||
--help-all all options
|
||||
--help-io input/output options
|
||||
--help-meta metadata format options
|
||||
--help-misc miscellaneous options
|
||||
--help-overlay overlay format options
|
||||
--help-sdr SDR format options
|
||||
--help-selection crop/selection options
|
||||
--help-stds standards and other video timings options
|
||||
--help-streaming streaming options
|
||||
--help-subdev sub-device options
|
||||
--help-tuner tuner/modulator options
|
||||
--help-vbi VBI format options
|
||||
--help-vidcap video capture format options
|
||||
--help-vidout vidout output format options
|
||||
--help-edid edid handling options
|
||||
-k, --concise be more concise if possible.
|
||||
-l, --list-ctrls display all controls and their values [VIDIOC_QUERYCTRL]
|
||||
-L, --list-ctrls-menus
|
||||
display all controls and their menus [VIDIOC_QUERYMENU]
|
||||
-r, --subset <ctrl>[,<offset>,<size>]+
|
||||
the subset of the N-dimensional array to get/set for control <ctrl>,
|
||||
for every dimension an (<offset>, <size>) tuple is given.
|
||||
-w, --wrapper use the libv4l2 wrapper library.
|
||||
--list-devices list all v4l devices. If -z was given, then list just the
|
||||
devices of the media device with the bus info string as
|
||||
specified by the -z option.
|
||||
--log-status log the board status in the kernel log [VIDIOC_LOG_STATUS]
|
||||
--get-priority query the current access priority [VIDIOC_G_PRIORITY]
|
||||
--set-priority <prio>
|
||||
set the new access priority [VIDIOC_S_PRIORITY]
|
||||
<prio> is 1 (background), 2 (interactive) or 3 (record)
|
||||
--silent only set the result code, do not print any messages
|
||||
--sleep <secs> sleep <secs>, call QUERYCAP and close the file handle
|
||||
--verbose turn on verbose ioctl status reporting
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 166 KiB After Width: | Height: | Size: 161 KiB |
BIN
IMX6ULL/doc_pic/13_V4L2/pic/v853/17_media_file_ops.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
IMX6ULL/doc_pic/13_V4L2/pic/v853/18_media_device_fops.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
IMX6ULL/doc_pic/13_V4L2/pic/v853/19_ioctl_info.png
Normal file
|
After Width: | Height: | Size: 107 KiB |
BIN
IMX6ULL/doc_pic/13_V4L2/pic/v853/20_media_device_info.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
IMX6ULL/doc_pic/13_V4L2/pic/v853/21_enum_entity.png
Normal file
|
After Width: | Height: | Size: 129 KiB |
BIN
IMX6ULL/doc_pic/13_V4L2/pic/v853/22_enum_link.png
Normal file
|
After Width: | Height: | Size: 150 KiB |
BIN
IMX6ULL/doc_pic/13_V4L2/pic/v853/23_setup_link.png
Normal file
|
After Width: | Height: | Size: 135 KiB |
BIN
IMX6ULL/doc_pic/13_V4L2/pic/v853/24_get_topology.png
Normal file
|
After Width: | Height: | Size: 172 KiB |
BIN
IMX6ULL/doc_pic/13_V4L2/pic/v853/25_v4l2_fops.png
Normal file
|
After Width: | Height: | Size: 43 KiB |
BIN
IMX6ULL/doc_pic/13_V4L2/pic/v853/26_subdev_fops.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
IMX6ULL/doc_pic/13_V4L2/pic/v853/27_subdev_do_ioctl.png
Normal file
|
After Width: | Height: | Size: 108 KiB |
BIN
IMX6ULL/doc_pic/13_V4L2/pic/v853/28_uvc_media0.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
IMX6ULL/doc_pic/13_V4L2/pic/v853/29_v853_video0.png
Normal file
|
After Width: | Height: | Size: 116 KiB |
BIN
IMX6ULL/doc_pic/13_V4L2/pic/v853/30_media_ioctl.png
Normal file
|
After Width: | Height: | Size: 126 KiB |
BIN
IMX6ULL/doc_pic/13_V4L2/pic/v853/31_media_device_get_info.png
Normal file
|
After Width: | Height: | Size: 62 KiB |
|
After Width: | Height: | Size: 71 KiB |
BIN
IMX6ULL/doc_pic/13_V4L2/pic/v853/33_media_link_flag.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
IMX6ULL/doc_pic/13_V4L2/pic/v853/34_media_device_enum_links.png
Normal file
|
After Width: | Height: | Size: 130 KiB |
BIN
IMX6ULL/doc_pic/13_V4L2/pic/v853/35_media_device_setup_link.png
Normal file
|
After Width: | Height: | Size: 255 KiB |
|
After Width: | Height: | Size: 307 KiB |
BIN
IMX6ULL/doc_pic/13_V4L2/pic/v853/37_media_device.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
IMX6ULL/doc_pic/13_V4L2/pic/v853/38_media_entity.png
Normal file
|
After Width: | Height: | Size: 46 KiB |
BIN
IMX6ULL/doc_pic/13_V4L2/pic/v853/39_media_pad.png
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
IMX6ULL/doc_pic/13_V4L2/pic/v853/40_media_link.png
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
IMX6ULL/doc_pic/13_V4L2/pic/v853/41_pipeline_start.png
Normal file
|
After Width: | Height: | Size: 93 KiB |
BIN
IMX6ULL/doc_pic/13_V4L2/pic/v853/42_subdev_ops.png
Normal file
|
After Width: | Height: | Size: 92 KiB |
BIN
IMX6ULL/doc_pic/13_V4L2/pic/v853/43_entity_subdev.png
Normal file
|
After Width: | Height: | Size: 60 KiB |
BIN
IMX6ULL/doc_pic/13_V4L2/pic/v853/44_virtual_video.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
IMX6ULL/doc_pic/13_V4L2/pic/v853/45_virtual_video.png
Normal file
|
After Width: | Height: | Size: 9.0 KiB |
BIN
IMX6ULL/doc_pic/13_V4L2/pic/v853/46_subdev_in_uvc_entity.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
IMX6ULL/doc_pic/13_V4L2/pic/v853/47_ops_of_uvc_subdev.png
Normal file
|
After Width: | Height: | Size: 71 KiB |
BIN
IMX6ULL/doc_pic/13_V4L2/pic/v853/48_gc2053_ops.png
Normal file
|
After Width: | Height: | Size: 60 KiB |
BIN
IMX6ULL/doc_pic/13_V4L2/pic/v853/49_media_import.png
Normal file
|
After Width: | Height: | Size: 66 KiB |
BIN
IMX6ULL/doc_pic/13_V4L2/pic/v853/50_media_concept.png
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
IMX6ULL/doc_pic/13_V4L2/pic/v853/51_media_topo.png
Normal file
|
After Width: | Height: | Size: 250 KiB |
BIN
IMX6ULL/doc_pic/13_V4L2/pic/v853/52_v4l2_subdev_init.png
Normal file
|
After Width: | Height: | Size: 70 KiB |
BIN
IMX6ULL/doc_pic/13_V4L2/pic/v853/53_v4l2_device.png
Normal file
|
After Width: | Height: | Size: 34 KiB |
@@ -1113,6 +1113,17 @@ vin_md_register_core_entity
|
||||
|
||||
|
||||
|
||||
设备树里vinc@0,4,8,12的status都是okay,但是vinc@4,8里:
|
||||
|
||||
```shell
|
||||
vinc4_rear_sensor_sel = <1>;
|
||||
vinc8_rear_sensor_sel = <1>;
|
||||
```
|
||||
|
||||
并没有sensor 1,所以没有创建出对应的subdev,没有创建出对应的/dev/video4,8
|
||||
|
||||
|
||||
|
||||
### 10.8 vin_video0
|
||||
|
||||
drivers/media/platform/sunxi-vin/vin-video/vin_video.c
|
||||
@@ -1120,8 +1131,7 @@ drivers/media/platform/sunxi-vin/vin-video/vin_video.c
|
||||

|
||||
|
||||
```shell
|
||||
vin_capture_subdev_registered
|
||||
if (vin_init_video(sd->v4l2_dev, &vinc->vid_cap))
|
||||
vin_init_video
|
||||
snprintf(cap->vdev.name, sizeof(cap->vdev.name),
|
||||
"vin_video%d", cap->vinc->id);
|
||||
cap->vdev.fops = &vin_fops;
|
||||
@@ -1156,3 +1166,6 @@ sd->internal_ops何时被调用?
|
||||
|
||||
|
||||
|
||||
## 12. 其他
|
||||
|
||||
v4l2-event:自定义事件调试 https://blog.csdn.net/qq_34341546/article/details/131329503
|
||||