1.1. 设备打开与关闭

1.1.1. 通过 V4L2 控制硬件外设

使用 V4L2 uAPI 支持的硬件通常由多个设备或外围设备组成,每个设备或外围设备都有自己的驱动程序。

桥接驱动程序会公开一个或多个 V4L2 设备节点(请参阅V4L2 设备节点命名)。

还有其他驱动程序为硬件的其他组件提供支持,这些组件也可能公开称为 V4L2 子设备的设备节点。

当公开此类 V4L2 子设备时,它们允许控制其他硬件组件 - 通常通过串行总线(如 I²C、SMBus 或 SPI)连接。根据桥接驱动程序的不同,可以通过桥接驱动程序间接控制这些子设备,也可以通过媒体控制器V4L2 子设备显式控制。

需要使用媒体控制器的设备称为 MC 中心 设备。通过 V4L2 设备节点完全控制的设备称为 视频节点中心 设备。

用户空间可以通过调用ioctl VIDIOC_QUERYCAP并检查device_caps 字段来检查 V4L2 硬件外围设备是否为 MC 中心。

如果设备在 device_caps 返回 V4L2_CAP_IO_MC 标志,则它是 MC 中心,否则,它是视频节点中心。

MC 中心驱动程序需要识别 V4L2 子设备,并在使用外围设备之前通过媒体控制器 API配置管道。此外,子设备的配置应通过子设备 API进行控制。

注意

视频节点中心设备仍然可以提供媒体控制器和子设备接口。

但是,在这种情况下,媒体控制器和子设备接口是只读的,仅提供有关设备的信息。实际配置是通过视频节点完成的。

1.1.2. V4L2 设备节点命名

V4L2 驱动程序实现为内核模块,由系统管理员手动加载或在首次发现设备时自动加载。驱动程序模块插入到 videodev 内核模块中。它提供辅助函数和本文档中指定的通用应用程序接口。

因此,每个加载的驱动程序都使用主编号 81 注册一个或多个设备节点。除非使用内核选项 CONFIG_VIDEO_FIXED_MINOR_RANGES 编译内核,否则次编号会动态分配。在这种情况下,次编号会根据设备节点类型在范围内分配。

Video4Linux 子系统支持的设备节点是

默认设备节点名称

用法

/dev/videoX

用于捕获/输出设备的视频和元数据

/dev/vbiX

垂直消隐数据(即隐藏式字幕、图文电视)

/dev/radioX

无线电调谐器和调制器

/dev/swradioX

软件定义无线电调谐器和调制器

/dev/v4l-touchX

触摸传感器

/dev/v4l-subdevX

视频子设备(由传感器和硬件外围设备的其他组件使用)[1]

其中 X 是一个非负整数。

注意

  1. 实际的设备节点名称取决于系统,因为 udev 规则可能会应用。

  2. 不能保证对于同一设备,X 将保持不变,因为该编号取决于设备驱动程序的探测顺序。如果您需要唯一的名称,udev 默认规则会生成 /dev/v4l/by-id//dev/v4l/by-path/ 目录,其中包含可用于唯一标识 V4L2 设备节点的链接

    $ tree /dev/v4l
    /dev/v4l
    ├── by-id
    │   └── usb-OmniVision._USB_Camera-B4.04.27.1-video-index0 -> ../../video0
    └── by-path
        └── pci-0000:00:14.0-usb-0:2:1.0-video-index0 -> ../../video0
    

许多驱动程序支持 “video_nr”、“radio_nr” 或 “vbi_nr” 模块选项来选择特定的视频/无线电/vbi 节点编号。这允许用户请求将设备节点命名为例如 /dev/video5,而不是听天由命。当驱动程序支持同一类型的多个设备时,可以分配多个设备节点编号,并用逗号分隔

# modprobe mydriver video_nr=0,1 radio_nr=0,1

/etc/modules.conf 中,可以将其写入为

options mydriver video_nr=0,1 radio_nr=0,1

当没有将设备节点编号作为模块选项给出时,驱动程序会提供一个默认值。

通常,udev 会自动在 /dev 中为您创建设备节点。如果未安装 udev,则需要启用 CONFIG_VIDEO_FIXED_MINOR_RANGES 内核选项,以便能够正确将次编号与设备节点编号相关联。也就是说,您需要确保次编号 5 映射到设备节点名称 video5。使用此内核选项,不同的设备类型具有不同的次编号范围。这些范围在接口中列出。

创建字符特殊文件 (使用 mknod) 是一项特权操作,并且设备不能通过主次编号打开。这意味着应用程序不能 可靠地 扫描已加载或安装的驱动程序。用户必须输入设备名称,或者应用程序可以尝试使用传统的设备名称。

1.1.4. 多次打开

V4L2 设备可以多次打开。[2] 当驱动程序支持时,例如,用户可以启动一个“面板”应用程序来更改亮度或音频音量等控件,而另一个应用程序捕获视频和音频。换句话说,面板应用程序类似于 ALSA 音频混音器应用程序。仅打开 V4L2 设备不应更改设备的状态。[3]

一旦应用程序分配了流式数据所需的内存缓冲区(通过调用ioctl VIDIOC_REQBUFSioctl VIDIOC_CREATE_BUFS ioctl,或通过调用read()write()函数隐式地实现),该应用程序(文件句柄)将成为设备的所有者。不再允许进行会影响缓冲区大小的更改(例如通过调用VIDIOC_S_FMT ioctl),并且不再允许其他应用程序分配缓冲区或启动或停止流式传输。将返回 EBUSY 错误代码。

仅打开 V4L2 设备并不会授予独占访问权限。[4] 然而,启动数据交换会为该文件描述符分配读取或写入请求类型数据以及更改相关属性的权限。应用程序可以使用应用程序优先级中描述的优先级机制来请求其他访问权限。

1.1.5. 共享数据流

V4L2 驱动程序不应支持多个应用程序通过复制缓冲区、时间多路复用或类似方式读取或写入设备上的相同数据流。这最好由用户空间中的代理应用程序处理。

1.1.6. 函数

要打开和关闭 V4L2 设备,应用程序分别使用open()close()函数。设备使用ioctl()函数进行编程,如下节所述。