USB UVC7 -- XU

news2024/10/10 9:16:06

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来实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2201622.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python酷库之旅-第三方库Pandas(140)

目录 一、用法精讲 631、pandas.Timestamp类 631-1、语法 631-2、参数 631-3、功能 631-4、返回值 631-5、说明 631-6、用法 631-6-1、数据准备 631-6-2、代码示例 631-6-3、结果输出 632、pandas.Timestamp.asm8属性 632-1、语法 632-2、参数 632-3、功能 632…

java类和对象_成员变量方法修饰符局部变量this关键字-cnblog

java类和对象 成员变量 权限修饰符 变量类型 变量名; 成员变量可以是任意类型,整个类是成员变量的作用范围 成员变量 成员方法 权限修饰符 返回值类型 方法名() 成员方法可以有参数&#xff0c;也可以有返回值&#xff0c;用return声明 权限修饰符 private 只能在本类…

IDEA必装的插件:Spring Boot Helper的使用与功能特点

在IntelliJ IDEA中&#xff0c;Spring Boot Helper插件是一个非常实用的工具&#xff0c;可以帮助我们更快速地创建和管理Spring Boot项目。以下是Spring Boot Helper插件的详细介绍和使用方法&#xff1a; 激活码地址: 点击获取 一、安装Spring Boot Helper插件 1 打开Intell…

如何设计三极管放大电路?

设计放大电路 分压式串联负反馈放大电路 可以看下面这个视频 , 讲得更加详细 366-单管放大电路偏置电阻的计算&#xff0c;看完自己也会设计一个_哔哩哔哩_bilibili 计算流过电阻Rb2的电流过程中,工程当中常发现Rb2上的电流是Ib的5倍 , 因此由基尔霍夫电流定律也能知道流过R…

Java的基础概念和常识(二)

什么是字节码&#xff1f;采用字节码的好处是什么&#xff1f; 字节码&#xff08;Byte-code&#xff09;是一种中间形式的代码&#xff0c;是源代码编译后生成的一种低级表示&#xff0c;通常是在编译阶段生成的。在 Java 中&#xff0c;JVM 可以理解的代码就叫做字节码&…

K8s(学习笔记)

swap分区是什么呀&#xff1f; 什么是ipvs呀&#xff1f; yaml是什么呀&#xff1f;&#xff1f;&#xff1f; p20看不下去了&#xff01;&#xff01;&#xff01;

ansible 流程控制

目录 1.流程控制 2.handlers触发器 2.1使用handlers案例 3.when 判断 3.1 案例1 用于给task设置条件 满足或者不满足运行对应模块 3.2 案例2 如果系统是centos则安装sl&#xff0c;cowsay 如果是unbantu则安装cmatrix 4.循环 4.1案例 1.流程控制 hand…

飞腾CPU技术发展分析

飞腾CPU剖析 CPU&#xff1a;信创根基&#xff0c;国之重器 国产CPU市场呈现三大领军阵营&#xff1a;x86、ARM以及其他创新架构。鲲鹏与飞腾在ARM阵营中引领风潮&#xff0c;依托ARM技术授权研发高性能处理器&#xff1b;海光与兆芯则以x86架构为基石&#xff0c;深入挖掘其潜…

图论day56|广度优先搜索理论基础 、bfs与dfs的对比(思维导图)、 99.岛屿数量(卡码网)、100.岛屿的最大面积(卡码网)

图论day56|广度优先搜索理论基础 、bfs与dfs的对比&#xff08;思维导图&#xff09;、 99.岛屿数量&#xff08;卡码网&#xff09;、100.岛屿的最大面积&#xff08;卡码网&#xff09;&#xff09; 广度优先搜索理论基础bfs与dfs的对比&#xff08;思维导图&#xff09;&…

Spring Boot Starter Parent介绍

引言 spring-boot-starter-parent 是一个特殊的项目&#xff0c;为基于 Spring Boot 的应用程序提供默认配置和默认依赖。 在本 Spring Boot 教程中&#xff0c;我们将深入了解所有 Spring Boot 项目内部使用的 spring-boot-starter-parent 依赖项。我们将探讨此依赖项所提供…

基于jmeter+perfmon的稳定性测试记录

1. 引子 最近承接了项目中一些性能测试的任务&#xff0c;因此决定记录一下&#xff0c;将测试的过程和一些心得收录下来。 说起来性能测试算是软件测试行业内&#xff0c;有些特殊的部分。这部分的测试活动&#xff0c;与传统的测试任务差别是比较大的&#xff0c;也比较依赖…

用Python实现运筹学——Day 12: 线性规划在物流优化中的应用

一、学习内容 线性规划在物流优化中可以用于解决诸如配送路径优化、货物运输调度等问题。配送中心的路径优化问题本质上是寻找一条最优路径&#xff0c;在满足需求点的需求条件下&#xff0c;最小化配送的总运输成本或时间。常见的物流优化问题包括&#xff1a; 配送中心的货…

集师知识付费小程序:打造培训机构在线教育的金字招牌 集师知识付费系统 集师知识付费小程序 集师知识服务系统 集师线上培训系统 集师线上卖课小程序

在数字化浪潮的推动下&#xff0c;在线教育已成为教育领域的热门话题。而在众多在线教育平台中&#xff0c;集师知识付费小程序凭借其独特的定位和创新的模式&#xff0c;成功为培训机构打造了一张闪亮的在线教育金字招牌。 集师知识付费小程序&#xff0c;是一个集课程展示、…

Python 如何使用 Matplotlib 和 Seaborn 可视化数据

Python 如何使用 Matplotlib 和 Seaborn 可视化数据 一、简介 数据可视化是数据分析过程中非常重要的步骤。通过可视化&#xff0c;复杂的数据变得更直观&#xff0c;数据中的模式、趋势和异常可以更容易被识别。Python 提供了多个强大的库来进行数据可视化&#xff0c;其中最…

ChatGPT:引领人工智能新潮流!

一、ChatGPT 是什么&#xff1f; 1. ChatGPT 的强大功能和广泛应用。 ChatGPT 作为一款先进的 AI 语言模型&#xff0c;拥有众多强大功能。它可以进行文本生成、文本分类、情感分析、机器翻译等多种自然语言处理任务。同时&#xff0c;ChatGPT 还能进行对话式交互&#xff0c;…

python之详解集合

一种无序且不重复的数据容器&#xff0c;集合用大括号{}表示。 1、集合的查找访问 集合是不能通过 集合名[index] 这种方式访问的&#xff0c;其作用在于快速读取&#xff0c;而不是针对某个元素。 但&#xff0c;可将集合转为列表&#xff0c;再由列表访问元素。不过&#…

Laravel Filament 如何配置多语言支持

演示 一、安装拓展包outerweb/filament-translatable-fields composer require outerweb/filament-translatable-fields配置模型 该套件包含一个名为 HasTranslations 的特性&#xff0c;用于使 Eloquent 模型具备多语言功能。翻译值以 JSON 格式存储&#xff0c;并不需要额外…

叙说 OSI 七层网络模型 | 你在第几层

引言 开放系统互联&#xff08;OSI&#xff0c;Open Systems Interconnection&#xff09;模型&#xff0c;这一国际标准化组织&#xff08;ISO&#xff09;提出的理论框架&#xff0c;是计算机网络通信领域内不可或缺的基础工具。如同语法和句法对于构建和解析语言的重要性一…

Python对PDF文件页面的旋转和切割

Python对PDF文件页面的旋转和切割 利用Python的.rotate()方法和.mediabox属性对PDF页面进行旋转和切割&#xff0c;最终生成一个PDF。下面结合案例进行说明&#xff0c;本示例中的名为split_and_rotate.pdf文件在practice_files文件夹中&#xff0c; 示例&#xff08;1&#…

ShardingSphere分库分表产品介绍

目录 一、ShardingSphere分库分表产品介绍 二、客户端分库分表与服务端分库分表 1、ShardingJDBC客户端分库分表 2、ShardingProxy服务端分库分表 3、ShardingSphere混合部署架构 三、分库分表&#xff0c;能不分就不分&#xff01; 1、为什么要分库分表&#xff1f; 2、…