11. Linux USB 视频类 (UVC) 驱动程序

本文档记录了 UVC 驱动程序的某些特定于驱动程序的方面,例如特定于驱动程序的 ioctl 和实现说明。

问题和意见可以发送到 Linux UVC 开发邮件列表:linux-media@vger.kernel.org

11.1. 扩展单元 (XU) 支持

11.1.1. 简介

UVC 规范允许通过扩展单元 (XU) 进行供应商特定的扩展。Linux UVC 驱动程序通过两种不同的机制支持扩展单元控件 (XU 控件)

  • 通过将 XU 控件映射到 V4L2 控件

  • 通过特定于驱动程序的 ioctl 接口

第一种机制允许通用 V4L2 应用程序通过将某些 XU 控件映射到 V4L2 控件来使用 XU 控件,这些控件随后会在普通控件枚举期间显示。

第二种机制要求应用程序具有 uvcvideo 特定的知识才能访问 XU 控件,但会将整个 UVC XU 概念公开给用户空间,以实现最大的灵活性。

这两种机制相互补充,并在下面进行更详细的描述。

11.1.2. 控件映射

UVC 驱动程序提供了一个 API,供用户空间应用程序在运行时定义所谓的控件映射。这些映射允许将单个 XU 控件或其中的字节范围映射到新的 V4L2 控件。这些控件的出现和功能与正常的 V4L2 控件完全相同(即库存控件,例如亮度、对比度等)。但是,读取或写入此类 V4L2 控件会触发关联的 XU 控件的读取或写入。

用于创建这些控件映射的 ioctl 称为 UVCIOC_CTRL_MAP。之前的驱动程序版本(0.2.0 之前)需要预先使用另一个 ioctl (UVCIOC_CTRL_ADD) 将 XU 控件信息传递给 UVC 驱动程序。由于较新的 uvcvideo 版本直接从设备查询信息,因此不再需要这样做。

有关 UVCIOC_CTRL_MAP ioctl 的详细信息,请参阅下面标题为“IOCTL 参考”的部分。

  1. 驱动程序特定的 XU 控件接口

对于需要直接访问 XU 控件的应用程序,例如出于测试目的、固件上传或访问二进制控件,提供了第二种机制,以驱动程序特定的 ioctl 的形式访问 XU 控件,即 UVCIOC_CTRL_QUERY。

调用此 ioctl 允许应用程序向 UVC 驱动程序发送查询,这些查询直接映射到低级 UVC 控件请求。

为了发出这样的请求,需要知道控件的扩展单元的 UVC 单元 ID 和控件选择器。此信息要么需要在应用程序中硬编码,要么使用其他方式查询,例如通过解析 UVC 描述符,或者如果可用,使用媒体控制器 API 枚举设备的实体。

除非控件大小已知,否则首先需要发出 UVC_GET_LEN 请求,以便能够分配足够大的缓冲区并将缓冲区大小设置为正确的值。同样,要确定 UVC_GET_CUR 或 UVC_SET_CUR 是否是给定控件的有效请求,应发出 UVC_GET_INFO 请求。结果字节的位 0(支持 GET)和 1(支持 SET)指示哪些请求有效。

随着 UVCIOC_CTRL_QUERY ioctl 的添加,UVCIOC_CTRL_GET 和 UVCIOC_CTRL_SET ioctl 已经过时,因为它们的功能是前一个 ioctl 的子集。目前仍然支持它们,但鼓励应用程序开发人员改用 UVCIOC_CTRL_QUERY。

有关 UVCIOC_CTRL_QUERY ioctl 的详细信息,请参阅下面标题为“IOCTL 参考”的部分。

11.1.3. 安全性

该 API 目前没有提供细粒度的访问控制设施。UVCIOC_CTRL_ADD 和 UVCIOC_CTRL_MAP ioctl 需要超级用户权限。

欢迎提出有关如何改进此功能的建议。

11.1.4. 调试

为了调试与 XU 控件或一般控件相关的问题,建议在模块参数“trace”中启用 UVC_TRACE_CONTROL 位。这会导致额外的输出写入系统日志。

11.1.5. IOCTL 参考

11.1.5.1. UVCIOC_CTRL_MAP - 将 UVC 控件映射到 V4L2 控件

参数:struct uvc_xu_control_mapping

描述:

此 ioctl 在 UVC 控件或 UVC 控件的一部分与 V4L2 控件之间创建映射。一旦定义了映射,用户空间应用程序就可以通过 V4L2 控件 API 访问供应商定义的 UVC 控件。

要创建映射,应用程序需要使用 UVCIOC_CTRL_ADD 定义的现有 UVC 控件和新的 V4L2 控件的信息填充 uvc_xu_control_mapping 结构。

一个 UVC 控件可以映射到多个 V4L2 控件。例如,一个 UVC 平移/倾斜控件可以映射到单独的平移和倾斜 V4L2 控件。UVC 控件使用“size”和“offset”字段划分为非重叠字段,然后独立映射到 V4L2 控件。

对于有符号整数 V4L2 控件,data_type 字段应设置为 UVC_CTRL_DATA_TYPE_SIGNED。当前忽略其他值。

返回值:

成功返回 0。发生错误时,返回 -1 并且 errno 会被适当地设置。

ENOMEM

没有足够的内存来执行操作。

EPERM

权限不足(需要超级用户权限)。

EINVAL

没有这样的 UVC 控件。

EOVERFLOW

请求的偏移量和大小会溢出 UVC 控件。

EEXIST

映射已存在。

数据类型:

* struct uvc_xu_control_mapping

__u32   id              V4L2 control identifier
__u8    name[32]        V4L2 control name
__u8    entity[16]      UVC extension unit GUID
__u8    selector        UVC control selector
__u8    size            V4L2 control size (in bits)
__u8    offset          V4L2 control offset (in bits)
enum v4l2_ctrl_type
        v4l2_type       V4L2 control type
enum uvc_control_data_type
        data_type       UVC control data type
struct uvc_menu_info
        *menu_info      Array of menu entries (for menu controls only)
__u32   menu_count      Number of menu entries (for menu controls only)

* struct uvc_menu_info

__u32   value           Menu entry value used by the device
__u8    name[32]        Menu entry name


* enum uvc_control_data_type

UVC_CTRL_DATA_TYPE_RAW          Raw control (byte array)
UVC_CTRL_DATA_TYPE_SIGNED       Signed integer
UVC_CTRL_DATA_TYPE_UNSIGNED     Unsigned integer
UVC_CTRL_DATA_TYPE_BOOLEAN      Boolean
UVC_CTRL_DATA_TYPE_ENUM         Enumeration
UVC_CTRL_DATA_TYPE_BITMASK      Bitmask
UVC_CTRL_DATA_TYPE_RECT         Rectangular area

11.1.5.2. UVCIOC_CTRL_QUERY - 查询 UVC XU 控件

参数:struct uvc_xu_control_query

描述:

此 ioctl 查询由其扩展单元 ID 和控件选择器标识的 UVC XU 控件。

有许多不同的查询可用,它们与 UVC 规范中描述的低级控件请求密切对应。这些请求是

UVC_GET_CUR

获取控件的当前值。

UVC_GET_MIN

获取控件的最小值。

UVC_GET_MAX

获取控件的最大值。

UVC_GET_DEF

获取控件的默认值。

UVC_GET_RES

查询控件的分辨率,即允许的控件值的步长。

UVC_GET_LEN

查询控件的大小(以字节为单位)。

UVC_GET_INFO

查询控件信息位图,该位图指示是否支持 get/set 请求。

UVC_SET_CUR

更新控件的值。

应用程序必须将“size”字段设置为控件的正确长度。例外情况是 UVC_GET_LEN 和 UVC_GET_INFO 查询,其大小必须分别设置为 2 和 1。“data”字段必须指向足够大的有效可写缓冲区,以容纳指示的数据字节数。

数据直接从设备复制,没有任何驱动程序端处理。应用程序负责数据缓冲区格式化,包括小端/大端转换。这对于 UVC_GET_LEN 请求的结果尤为重要,该请求始终由设备返回为小端 16 位整数。

返回值:

成功返回 0。发生错误时,返回 -1 并且 errno 会被适当地设置。

ENOENT

设备不支持给定的控件,或者找不到指定的扩展单元。

ENOBUFS

指定的缓冲区大小不正确(太大或太小)。

EINVAL

传递了无效的请求代码。

EBADRQC

给定控件不支持给定的请求。

EFAULT

数据指针引用了无法访问的内存区域。

数据类型:

* struct uvc_xu_control_query

__u8    unit            Extension unit ID
__u8    selector        Control selector
__u8    query           Request code to send to the device
__u16   size            Control data size (in bytes)
__u8    *data           Control value

11.2. 特定于驱动程序的 V4L2 控件

uvcvideo 驱动程序实现了以下特定于 UVC 的控件

V4L2_CID_UVC_REGION_OF_INTEREST_RECT (struct)

此控件确定感兴趣区域 (ROI)。ROI 是一个由 struct v4l2_rect 表示的矩形区域。该矩形位于全局传感器坐标中,使用像素单位。它独立于视场,不受任何裁剪或缩放的影响。

使用 V4L2_CTRL_WHICH_MIN_VALV4L2_CTRL_WHICH_MAX_VAL 查询矩形大小的范围。

设置 ROI 允许相机针对该区域优化捕获。 V4L2_CID_REGION_OF_INTEREST_AUTO 控件的值确定了详细的行为。

可以在以下位置找到使用此控件的示例:Chrome OS USB 相机 HAL。 <https://chromium.googlesource.com/chromiumos/platform2/+/refs/heads/release-R121-15699.B/camera/hal/usb/>

V4L2_CID_UVC_REGION_OF_INTEREST_AUTO (bitmask)

这确定了哪些(如果有)板载功能应跟踪到由 V4L2_CID_UVD__REGION_OF_INTEREST_RECT 的当前值指定的感兴趣区域。

最大值是一个指示所有支持的自动控制的掩码。

V4L2_UVC_REGION_OF_INTEREST_AUTO_EXPOSURE

设置此位会导致自动曝光跟踪感兴趣区域而不是整个图像。

V4L2_UVC_REGION_OF_INTEREST_AUTO_IRIS

设置此位会导致自动光圈跟踪感兴趣区域而不是整个图像。

V4L2_UVC_REGION_OF_INTEREST_AUTO_WHITE_BALANCE

设置此位会导致自动白平衡跟踪感兴趣区域而不是整个图像。

V4L2_UVC_REGION_OF_INTEREST_AUTO_FOCUS

设置此位会导致自动对焦调整跟踪感兴趣区域而不是整个图像。

V4L2_UVC_REGION_OF_INTEREST_AUTO_FACE_DETECT

设置此位会导致自动人脸检测跟踪感兴趣区域而不是整个图像。

V4L2_UVC_REGION_OF_INTEREST_AUTO_DETECT_AND_TRACK

设置此位将启用自动人脸检测和跟踪。驱动程序可能会更新 V4L2_CID_REGION_OF_INTEREST_RECT 的当前值。

V4L2_UVC_REGION_OF_INTEREST_AUTO_IMAGE_STABILIZATION

设置此位将启用自动图像稳定。驱动程序可能会更新 V4L2_CID_REGION_OF_INTEREST_RECT 的当前值。

V4L2_UVC_REGION_OF_INTEREST_AUTO_HIGHER_QUALITY

如果可能,设置此位将启用自动捕获指定区域并提高质量。