USB UVC7 -- XU

UVC(USB Video Class)设备通过USB接口提供视频流,支持标准的视频控制和数据传输。UVC设备还支持扩展单元(XU,Extension Unit),它允许设备制造商定义非标准的、专有的功能,通过控制XU可以实现自定义的设备配置。下面详细介绍UVC XU(扩展单元)信息的处理流程,尤其是从客户端到设备应用的流转过程。

1. UVC XU概述

UVC扩展单元(XU)是在标准UVC控制命令之外提供的额外接口,通常用来控制摄像头的非标准功能。XU可以在UVC的Video Control Interface (VC) 描述符中定义,通过设置不同的属性(如亮度、对比度、特殊效果等),允许客户端应用对设备进行控制。

2. 客户端对UVC XU的访问

客户端应用程序可以使用操作系统提供的标准接口访问UVC XU,通常通过V4L2 (Video for Linux 2)DirectShow 等多媒体框架进行访问。

操作步骤:
  1. 发现设备:当客户端启动时,它会通过USB查询连接的UVC设备。USB设备会返回设备描述符(Device Descriptor),包括接口信息。

  2. 请求XU单元信息

    • 在初始化过程中,客户端会通过UVC标准的Video Control Requests与设备交互,获取设备所支持的功能,包括扩展单元(XU)的信息。
    • 这个过程可以通过 V4L2 IOCTLs 访问,如 VIDIOC_QUERY_EXT_CTRL,该接口允许客户端获取支持的扩展控制项的属性,包括控制ID、范围、步进值等。
  3. 发送XU控制请求

    • 客户端通过Control Requests与扩展单元进行交互。扩展单元的访问需要通过特定的控制命令(通常是GET_CURSET_CUR)。
    • 例如,使用 V4L2 时,VIDIOC_G_EXT_CTRLSVIDIOC_S_EXT_CTRLS 可以分别用于获取和设置XU的属性。
    • 在Windows上,可以通过 IOCTL_VIDEO_PROPERTY_CONTROL 等控制代码发送自定义的XU控制请求。

3. XU请求的USB传输

在客户端发送请求到USB设备时,UVC协议会将这些命令打包成USB传输进行通信。流程如下:

  1. 设置XU请求

    • 当客户端通过系统接口发出XU请求后,内核会根据请求打包成USB控制传输(Control Transfer)
    • 具体地,这些请求会通过标准的USB SETUP包发送到设备,典型的UVC控制命令包括bmRequestTypebRequestwValuewIndex等字段。
  2. 控制传输的过程

    • bmRequestType 指示是一个设备的控制请求,通常设置为向接口发送数据的方向。
    • bRequest 代表要进行的UVC控制命令,比如GET_CUR、SET_CUR。
    • wValuewIndex 对应于具体的XU控制单元和属性。
    • wLength 表示数据的长度,当控制信息通过控制传输阶段成功发送后,数据会通过Data阶段被送达设备。

4. 设备端的XU处理

UVC设备接收到扩展单元(XU)请求后,需要解析这些命令,并对设备内部的应用逻辑做出响应。

  1. 解析控制命令

    • UVC设备固件会通过USB堆栈接收并解析XU命令。根据请求的类型(GET/SET),设备可以选择返回当前属性值或更新设备内部配置。
  2. 应用逻辑的处理

    • 如果是GET请求,设备会查询内部当前配置值,并通过USB控制传输返回给客户端。
    • 如果是SET请求,设备将会根据收到的值更新自身的状态,可能会改变某些硬件配置(如改变摄像头的图像处理方式、更新传感器的增益值等)。
    • 这些处理逻辑通常由设备厂商在固件层面实现。
  3. 返回数据

    • 当设备完成控制命令的处理后,通过USB返回确认包或实际的数据(如当前设置的值)给主机,完成整个控制交互。

5. 客户端处理设备响应

一旦设备处理了XU请求并返回数据,客户端需要处理该数据,通常包括更新UI或将结果应用到视频流处理。

  1. 获取响应数据

    • GET请求的情况下,客户端会接收到设备返回的数据,通常是通过 V4L2Windows API 获取,结果会包含在控制请求响应中。
  2. UI更新

    • 客户端可能会根据设备返回的状态更新UI。例如,如果用户调整了摄像头的对比度,摄像头返回成功响应后,UI会更新显示新对比度值。
  3. 应用到视频处理

    • 有时,扩展单元的控制会直接影响到视频流。例如,通过扩展单元设置特殊的滤镜效果,设备端在处理XU命令时,会改变视频流的特性,客户端就能看到视频输出的变化。

6. 实例:通过V4L2访问XU

假设我们想通过V4L2设置一个UVC摄像头的扩展单元控制项(例如调整一个定制的镜头增益)。

struct v4l2_ext_controls ctrls;
struct v4l2_ext_control ctrl[1];

memset(&ctrls, 0, sizeof(ctrls));
memset(&ctrl, 0, sizeof(ctrl));

ctrl[0].id = CUSTOM_XU_CTRL_ID; // XU控制项的ID
ctrl[0].value = desired_gain_value; // 要设置的值

ctrls.ctrl_class = V4L2_CTRL_CLASS_USER;
ctrls.count = 1;
ctrls.controls = ctrl;

// 使用VIDIOC_S_EXT_CTRLS设置扩展控制
if (ioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls) < 0) {
    perror("Failed to set XU control");
}

总结

UVC的XU(扩展单元)机制允许自定义和专有控制功能。数据从客户端发送到设备的过程通常涉及V4L2或DirectShow等框架,UVC协议用于封装和传输这些控制请求,设备端固件解析请求后执行相应的动作,最后返回结果给客户端应用。这种机制不仅增强了UVC设备的可扩展性,还为设备制造商提供了灵活的自定义功能接口。

当一个UVC(USB Video Class)设备注册了多个扩展单元(XU)并为每个XU分配不同的GUID时,客户端需要通过以下步骤来识别和调用自己需要的XU。整个流程涉及查询设备的描述符、匹配GUID、确定XU的控制ID,以及使用正确的XU来进行操作。

1. 查询设备的扩展单元信息

  • UVC设备通过其设备描述符上报所有扩展单元的信息。描述符中包含各个扩展单元的GUID,以及其他相关的信息如控制ID(Control ID)、属性和功能。
  • 客户端可以通过标准的接口,如V4L2Windows的IOCTL,来查询设备的扩展单元列表和其对应的GUID。
在Linux的V4L2中,VIDIOC_QUERY_EXT_CTRL可以获取所有已注册的扩展单元控制项。以下是如何获取XU控制项的步骤:
  1. 打开设备文件(通常在/dev/videoX下):

    int fd = open("/dev/video0", O_RDWR);
    if (fd == -1) {
        perror("Error opening device");
        return -1;
    }
    
  2. 查询扩展单元控制信息
    使用VIDIOC_QUERY_EXT_CTRL循环遍历设备中注册的扩展单元控制项,并获取每个控制项的GUID。

    struct v4l2_queryctrl query_ctrl;
    memset(&query_ctrl, 0, sizeof(query_ctrl));
    
    // 控制ID的初始值
    query_ctrl.id = V4L2_CTRL_FLAG_NEXT_CTRL;
    
    // 遍历所有的控制项
    while (0 == ioctl(fd, VIDIOC_QUERYCTRL, &query_ctrl)) {
        if (query_ctrl.type == V4L2_CTRL_TYPE_CTRL_CLASS) {
            // 这是一个控制类,不是扩展控制,跳过
            continue;
        }
    
        // 如果是扩展单元控制项,获取GUID信息
        if (query_ctrl.flags & V4L2_CTRL_FLAG_NEXT_COMPOUND) {
            printf("Found XU control with ID: 0x%x\n", query_ctrl.id);
    
            // 这里可以获取更多关于扩展控制的信息,GUID可以通过其他相关调用获取
        }
    
        // 查询下一个控制项
        query_ctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
    }
    
  3. 匹配GUID

    • 在遍历控制项时,客户端可以使用设备上报的GUID来与自己预期的GUID进行匹配,以确定哪个XU是客户端需要的。
    • 一旦匹配成功,客户端就知道了该XU的控制ID,并可以通过该ID对XU进行操作。

2. 匹配GUID

  • UVC扩展单元的GUID是设备制造商定义的,用来标识设备的特定功能。因此,客户端需要有预先的知识,知道设备上注册了哪些GUID,以及每个GUID对应的功能。
  • 当客户端获取到设备的所有扩展单元信息后,它会对这些GUID进行匹配。匹配过程可以通过简单的比较算法来完成(例如将设备返回的GUID与客户端预期的GUID进行字节比较)。
示例:匹配GUID
uint8_t desired_guid[16] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0};

// 获取设备XU的GUID
uint8_t device_guid[16];
// 设备GUID从扩展单元描述符中获取
get_device_xu_guid(device_guid);  // 假设这是获取设备XU GUID的函数

if (memcmp(desired_guid, device_guid, sizeof(desired_guid)) == 0) {
    printf("Matched desired XU GUID\n");
    // 可以继续访问该扩展单元
} else {
    printf("GUID mismatch\n");
}

3. 通过控制ID操作XU

一旦匹配了GUID,客户端就知道了对应的控制ID(通常是扩展单元的Control ID)。客户端可以使用这个控制ID来对该扩展单元进行具体的操作,如设置值或获取当前状态。

操作扩展单元的控制项(设置或获取控制)

使用V4L2中的VIDIOC_S_EXT_CTRLSVIDIOC_G_EXT_CTRLS操作扩展单元控制项:

  • 设置扩展单元控制项

    struct v4l2_ext_control ctrl;
    struct v4l2_ext_controls ctrls;
    
    ctrl.id = CONTROL_ID;  // 通过GUID匹配后获取的XU控制ID
    ctrl.value = desired_value;  // 设置值
    
    ctrls.ctrl_class = V4L2_CTRL_CLASS_USER;
    ctrls.count = 1;
    ctrls.controls = &ctrl;
    
    if (ioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls) == -1) {
        perror("Failed to set XU control");
    }
    
  • 获取扩展单元控制项

    struct v4l2_ext_control ctrl;
    struct v4l2_ext_controls ctrls;
    
    ctrl.id = CONTROL_ID;  // 通过GUID匹配后获取的XU控制ID
    
    ctrls.ctrl_class = V4L2_CTRL_CLASS_USER;
    ctrls.count = 1;
    ctrls.controls = &ctrl;
    
    if (ioctl(fd, VIDIOC_G_EXT_CTRLS, &ctrls) == -1) {
        perror("Failed to get XU control");
    } else {
        printf("XU control value: %d\n", ctrl.value);
    }
    

4. 其他考虑

  • 多XU支持:当UVC设备注册了多个XU并且每个XU都有不同的GUID时,客户端必须确保遍历所有可用的XU并检查每个XU的GUID,以确定其是否支持需要的功能。
  • 功能预期:客户端通常已经知道要寻找哪些GUID,具体GUID的意义通常是设备制造商定义的。例如,一个XU可能用于调整镜头的曝光,另一个XU可能用于设置特定的视频滤镜效果。
  • 错误处理:如果客户端无法匹配任何GUID,它可能会记录错误日志或提示用户设备不支持所需的功能。

总结

当UVC设备注册了多个GUID时,客户端通过查询设备的扩展单元描述符来获取每个扩展单元的GUID,并根据预期的GUID进行匹配。一旦匹配成功,客户端就可以使用对应的控制ID对扩展单元进行操作。这一过程通常通过标准的操作系统接口如V4L2或DirectShow来实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值