本文转自公众号,欢迎关注
基于DWC2的USB驱动开发-UVC的处理单元详解 (qq.com)
一.前言
本篇来详细分析下UVC的处理单元相关的内容,同样的我们理论结合实践来进行。
二.处理单元简介
处理单元(PU)控制通过它传输的视频的图像属性。有一个单一的输入和输出引脚,注意是单一的,也就是一个处理单元只能处理一个输入只有一个输出。
支持以下功能:
用户控制:
- Brightness亮度·
- Hue色调·
- Saturation饱和度·
- Sharpness清晰度·
- Gamma伽马·
- Digital Multiplier (Zoom) 数字乘法器(缩放)
自动控制
- White Balance Temperature 白平衡温度控制
- White Balance Component 白平衡成分控制
- Backlight Compensation 背光补偿
- Contrast 对比度
其他
对上述功能的支持都是可选的,但是,如果设备支持白平衡功能,则应实现白平衡温度控制或白平衡成分控制,但不能同时实现。
用户控制表示由用户偏好设置的属性,不受设备的自动控制的影响。
自动控制支持是否使能的设置(具有打开/关闭状态)。如果使能则设备自动调整,对相关属性的读请求则反映自动设置的值。
如果打开自动模式,尝试以手动方式设置将导致STALL,错误代码为bRequestErrorCode=“错误状态”。当退出自动模式时,相关控制属性应保持在转换前有效的值。
后面可以看到基本所有的属性都对应有一个自动控制,使能自动控制就不能再手动配置了。
处理单元的符号如下图所示。
注意这里的但输入单输出
三.拓扑结构
以下从描述符来看处理单元的拓扑结构,如下图是一个实际的UVC产品的描述符,只截取了和UVC相关的IAD下的描述符。
可以看到处理单元的ID是bUnitID=2,其源头是bSourceID=1即前面的bTerminaIID=1的视频控制输入终端;而其后面是bUnitID=3的视频控制扩展单元,该单元的baSourceID[1]=2表示其源头是本处理单元。
其拓扑如下
四.处理单元描述符
处理单元的描述符应该位于UVC的控制接口描述符VideoControl Interface Descriptors的Class-specific VC Interface Header Descriptor的后面
如下所示红色线所指示
本实例处理单元描述符对应的具体内容如下
处理单元的描述详细内容见规格书P69
3.7.2.5 Processing Unit Descriptor
偏移 | 区域 | 大小 | 值 | 说明 |
---|---|---|---|---|
0 | bLength | 1 | 数字值,13 | 本描述符的字节数 |
1 | bDescriptorType | 1 | 常数CS_INTERFACE=0x24 | 描述符类型 |
2 | bDescriptorSubtype | 1 | 常数VC_PROCESSING_UNIT =0x05 | 描述符子类 |
3 | bUnitID | 1 | 数字 | 单元ID |
4 | bSourceID | 1 | 常数 | 该单元前面所连接的单元或终端的ID。 |
5 | wMaxMultiplier | 2 | 数字 | 数字放大 |
7 | bControlSize | 1 | 数字,3 | 后面 bmControls域 的字节数 |
8 | bmControls | 3 | Bitmap | 支持的处理类型 |
11 | iProcessing | 1 | Index | 描述本处理单元的字符串描述索引,填0则没有字符串描述符。 |
12 | bmVideoStandards | 1 | Bitmap | 支持的标准 |
l其中bDescriptorType的定义参考规格书的P171 A.5. Video Class-Specific VC Interface Descriptor Subtypes
l其中bDescriptorSubtype的定义参考规格书的P172 A.4. Video Class-Specific Descriptor Types
l其中bUnitID
处理单元由处理单元描述符(PUD)的bUnitID字段的值唯一标识。 非零常数 ,用于唯一标识本功能接口中的单元。类相关请求时Index的高位即该值。
这里为什么要是非零常数呢?为什么从0开始编号呢,因为在请求中wIndex的高8位为0用于区分是接口请求,其他非0值为对应了终端和单元ID,所以不能从0开始编号了。
在本功能对应的接口内单该值和其他单元和终端的ID不能重复。
lbSourceID
该单元前面所连接的单元或终端的ID。
处理单元肯定是要处理一个东西的,即需要输入的,处理什么呢,肯定是处理摄像头的输入,所以前面一般就是Input Terminal,该值就是前面的Input Terminal的ID。
如下所示,这里bSourceID=1即前面连接的是bTerminalID=1的输入终端
l其中wMaxMultiplier
如果支持数字放大Digital Multiplier控制,则该值除以100表示放大倍数,比如设置值450则表示1-4.5X,即4.5倍数字放大,如果不支持则设置为0.
l其中bmControls,表示支持的处理类型
某一位置位则对应的处理支持,小端模式
D0: Brightness
D1: Contrast
D2: Hue
D3: Saturation
D4: Sharpness
D5: Gamma
D6: White Balance Temperature
D7: White Balance Component
D8: Backlight Compensation
D9: Gain
D10: Power Line Frequency
D11: Hue, Auto
D12: White Balance Temperature, Auto
D13: White Balance Component, Auto
D14: Digital Multiplier
D15: Digital Multiplier Limit
D16: Analog Video Standard
D17: Analog Video Lock Status
D18: Contrast, Auto
D19 – D23: Reserved. Set to zero
l其中bmVideoStandards表示支持的标准
0表示忽略该字段.
某位置1则表示支持该标准
D0: None
D1: NTSC – 525/60
D2: PAL – 625/50
D3: SECAM – 625/50
D4: NTSC – 625/50
D5: PAL – 525/60
D6-D7: Reserved. Set to zero.
以下是对应一个实例,注意其bmControls域只有两个字节,且没有bmVideoStandards,所以只有11个字节。
-------- Video Control Processing Unit Descriptor -----
bLength : 0x0B (11 bytes)
bDescriptorType : 0x24 (Video Control Interface)
bDescriptorSubtype : 0x05 (Processing Unit)
bUnitID : 0x02 (2)
bSourceID : 0x01 (1)
wMaxMultiplier : 0x0000
bControlSize : 0x02 (2 bytes)
bmControls : 0x7B, 0x07
D0 : 1 yes - Brightness
D1 : 1 yes - Contrast
D2 : 0 no - Hue
D3 : 1 yes - Saturation
D4 : 1 yes - Sharpness
D5 : 1 yes - Gamma
D6 : 1 yes - White Balance Temperature
D7 : 0 no - White Balance Component
D8 : 1 yes - Backlight Compensation
D9 : 1 yes - Gain
D10 : 1 yes - Power Line Frequency
D11 : 0 no - Hue, Auto
D12 : 0 no - White Balance Temperature, Auto
D13 : 0 no - White Balance Component, Auto
D14 : 0 no - Digital Multiplier
D15 : 0 no - Digital Multiplier Limit
iProcessing : 0x00 (No String Descriptor)
Data (HexDump) : 0B 24 05 02 01 00 00 02 7B 07 00 .$......{..
五. 处理单元相关的请求
参考规格书P109 4.2.2.3 Processing Unit Control Requests
处理单元控制请求用于读或者设置处理单元的属性,所以包括SET_xx 和GET_xx。
一共支持如下19种属性的请求
对应的CS编码见P175 A.9.5. Processing Unit Control Selectors
以下做了一个总结,所以值都是无符号值。
类型 | CS | 大小B | 支持的操作[]表示可选 | 最少支持操作 | 说明 |
---|---|---|---|---|---|
背光补偿控制 | PU_BACKLIGHT_COMPENSATION_CONTROL | 2 | SET_CURGET_CURGET_MINGET_MAXGET_RESGET_INFOGET_DEF | GET_DEF | 设置0说明不支持背光补偿,可以支持范围值或者仅仅是开关。小端模式,无符号16位值。 |
亮度控制 | PU_BRIGHTNESS_CONTROL | 2 | SET_CUR,GET_CUR GET_MIN GET_MAXGET_RESGET_INFOGET_DEF | GET_DEF | 该值是相对值配置的是增量,RES值必须是1小端模式,有符号16位值。 |
对比度控制 | PU_CONTRAST_CONTROL | 2 | SET_CUR GET_CUR GET_MIN GET_MAXGET_RESGET_INFOGET_DEF | GET_DEF | 该值是相对值配置的是增量,RES值必须是1小端模式,有符号16位值。 |
对比度自动控制 | PU_CONTRAST_AUTO_CONTROL | 1 | SET_CURGET_CUR GET_INFOGET_DEF | GET_DEF | 值为1表示使能自动控制,此时尝试设置相关对比度控制将导致STALL和bRequestErrorCode=“错误状态”的错误代码。 |
增益控制 | PU_GAIN_CONTROL | 2 | SET_CURGET_CURGET_MIN GET_MAXGET_RESGET_INFOGET_DEF | GET_DEF | 该值是相对值配置的是增量,RES值必须是1小端模式,有符号16位值。 |
电力线频率控制 | PU_POWER_LINE_FREQUENCY_CONTROL | 1 | SET_CURGET_CURGET_INFOGET_DEF | GET_DEF | 值对应如下0: Disabled1: 50 Hz2: 60 Hz3: Auto |
色度控制 | PU_HUE_CONTROL | 2 | GET_CUR GET_MIN GET_MAXGET_RESGET_INFOGET_DEF[SET_CUR] | GET_DEF | 默认值必须是0,设置值是实际值乘以100,实际值范围是(-180 到+180degrees). 则设置值发呢欸是-18000 ~18000 有符号16位,小端 |
色度自动控制 | PU_HUE_AUTO_CONTROL | 1 | SET_CUR,GET_CUR,GET_INFO GET_DEF | GET_DEF | 值为1表示使能自动控制,此时尝试设置相关色度控制将导致STALL和bRequestErrorCode=“错误状态”的错误代码 |
饱和度控制 | PU_SATURATION_CONTROL | 2 | SET_CURGET_CURGET_MINGET_MAXGET_RESGET_INFOGET_DEF | GET_DEF | 0表示灰度值为相对值,RES必须为1 |
清晰度设置 | PU_SHARPNESS_CONTROL | 2 | SET_CURGET_CURGET_MINGET_MAXGET_RESGET_INFOGET_DEF | GET_DEF | 相对值,MIN意味着“无清晰度处理”RES必须为1 |
伽马设置 | PU_GAMMA_CONTROL | 2 | SET_CURGET_CURGET_MINGET_MAXGET_RES,GET_INFOGET_DEF | GET_DEF | 设置值是实际值乘以100,设置值范围1 |
白平衡温度控制 | PU_WHITE_BALANCE_TEMPERATURE_CONTROL | 2 | GET_CURGET_MINGET_MAXGET_RESGET_INFOGET_DEF | GET_DEF | 这用于将白平衡设置指定为以开尔文度为单位的色温。这是作为白平衡组件控制的替代方案提供的。网络摄像头和双模摄像头的最小范围应为2800(白炽)至6500(日光)。 |
白平衡温度自动控制 | PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL | 1 | SET_CURGET_CURGET_INFOGET_DEF | GET_DEF | 值为1表示使能自动控制,此时尝试设置相关白平衡温度控制将导致STALL和bRequestErrorCode=“错误状态”的错误代码 |
白平衡成分控制 | PU_WHITE_BALANCE_COMPONENT_CONTROL | 4 | GET_CURGET_MIN GET_MAXGET_RESGET_INFOGET_DEF[SET_CUR] | GET_DEF | 前面2字节是蓝色成分设置后面2字节是红色成分设置 |
白平衡成分自动控制 | PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL | 1 | SET_CURGET_CURGET_INFOGET_DEF | GET_DEF | 值为1表示使能自动控制,此时尝试设置相关白平衡成分控制将导致STALL和bRequestErrorCode=“错误状态”的错误代码 |
数字乘法器控制 | PU_DIGITAL_MULTIPLIER_CONTROL | 2 | SET_CURGET_CURGET_MINGET_MAX GET_RESGET_INFOGET_DEF | 已弃用,下一版将删除值为 Z’cur这用于指定应用于光学图像的数字缩放量。这是乘法器m的可能值范围内的位置,允许通过设备实现来描述乘法器分辨率。RES 必须为1如果支持数字乘法器限制控制,则最小值和最大值应与数字乘法器控制的最小值和最高值相匹配。数字乘法器限制控制允许设备或主机为Z¢cur 值建立临时上限,从而动态减小数字乘法器控制的范围。如果使用数字乘法器限制将限制降低到当前Z¢cur ,Z¢cur 值将进行调整以匹配新的限制,数字乘法器控制应发送控制更改事件以通知主机调整。 | |
数字乘法器限制控制 | PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL | 2 | SET_CURGET_CURGET_MINGET_MAX GET_RESGET_INFOGET_DEF | RES 为1上述Z’cur的上限 | |
模拟视频标准控制 | PU_ANALOG_VIDEO_STANDARD_CONTROL | 1 | GET_CURGET_INFO | 0: None1: NTSC – 525/602: PAL – 625/503: SECAM – 625/504: NTSC – 625/505: PAL – 525/606-255: Reserved. Do not use. | |
模拟视频锁定状态控制 | PU_ANALOG_LOCK_STATUS_CONTROL | 1 | GET_CURGET_INFO | 这用于报告视频解码器是否已经实现模拟输入信号的水平锁定。如果解码器被锁定,则假定正在生成有效的视频流。此控制仅支持模拟视频解码器功能。 |
六. 处理单元请求驱动代码
处理单元类相关请求的解析,需要注意两个关键参数,一个是处理单元所在的接口号,上面实例接口是0,处理单元本身的ID,上面实例是2。
1.通过接口号和单元ID即可定位到是哪一个ID,接口号和单元号都是从wIndex字段解析,低位是接口号高位是单元ID号
2.然后再通过wValue确定对应的是什么操作,比如是亮度控制还是增益控制等。
即A.9.5. Processing Unit Control Selectors的CS
3.然后再通过bRequest确定是做什么类型的操作比如是获取当前值GET_CUR还是设置当前值SET_CUR
见规格书P173A.8. Video Class-Specific Request Codes
参考规格书4.2.2 Unit and Terminal Control Requests,终端和单元的请求的layout
请求分为SET和GET两大类
bmRequestType | bRequest | wValue | wIndex | wLength | Data |
---|---|---|---|---|---|
00100001 | SET_CUR | CS(高字节) | 单元或终端ID(高位)+接口(低位) | 数据长度 | |
10100001 | GET_CURGET_MINGET_MAXGET_RESGET_INFOGET_DEF | ||||
00100001 | SET_CUR_ALL | 0 | 单元或终端ID | ||
10100001 | GET_CUR_ALLGET_MIN_ALLGET_MAX_ALLGET_RES_ALLGET_DEF_ALL |
下面对解析过程进行详细分析
bmRequest指定是什么操作,其中MIN,MAX和RES不能SET因为其是设备实现决定的,不能修改。
wValue字段在高位字节中对应CS,即表示对什么属性进行操作,低字节为0.设备收到不支持的CS则需要STALL
wIndex高8位为0则表示是接口请求,不是0则表示单元和终端的ID,第8位表示对应的接口。所以这里终端和单元的ID不能为0,因为要和接口区分。
注意*(MAX-MIN)/RES* 和*(CURMIN)/RES *都需要是整数。如果SET_CUR操作中提供了无效的CUR值,设备应STALL,并用0x04“超出范围”更新请求错误代码。
收到setup后检查如果是类相关请求,即bmRequestType的bit6:6为1则进入类相关处理接口
usb_function_request
然后再看如果bmRequestType的bit4:0为1,则对应接口相关处理
然后调用注册的类回调,usb_uvc_class_set
再根据wIndex的高8位如果是0则对应的接口请求uvc_class_itf_req,
否则是终端单元相关请求uvc_class_ut_req
进入uvc_class_ut_req后
再根据wIndex的低8位确认接口,高8位定位终端和单元,然后根据wValue低8位确认CS即对应操作什么属性,然后根据bRequest确定是什么操作,比如GET_CUR
比如如下的一个实例的解析
a1表示类相关接口请求
86表示GET_INFO
0002 高8位02表示PU_BRIGHTNESS_CONTROL 处理单元的CS
0002 高8位表示单元ID2,低8位表示接口0,如下图接口0的ID2的单元就是处理单元
0100表示数据长度,GET_INFO即数据只有1个字节
后面的0x82 0x83 0x84 0x87也是类似
分别是GET_IN GET_MAX GET_RES GET_DEF
一般主机请求显示GET_INFO看你支持啥,然后再进行后续操作。
驱动的优化
上述层层switch解析的方式,比较好理解,但是代码冗余太大,且这部分代码应该是属于类实现层,不应该暴漏给用户,而且实际所有的端点和处理单元都是类似的,我们可以根据bRequest等参数进行查表跳转到对应的处理函数,用户只需要注册表格和回调即可,借用反射的设计范式。
GET_MIN GET_MAX GET_RES GET_CUR等只需要提供对应的存储区域的地址,可以建议一个二维表格,分别是哪个端点对应的哪个CS有哪些值操作。这个后面再单独一篇介绍。
七. 总结
以上详细介绍了处理单元,包括描述符和其拓扑结构,请求等。可以先了解其拓扑结构,在描述符中如何描述这有利于从整体把握,然后了解其请求的过程。
审核编辑:汤梓红
-
usb
+关注
关注
60文章
7888浏览量
263922 -
驱动开发
+关注
关注
0文章
130浏览量
12061 -
处理单元
+关注
关注
0文章
9浏览量
6914 -
uvc
+关注
关注
1文章
126浏览量
14501 -
DWC2
+关注
关注
0文章
35浏览量
119
发布评论请先 登录
相关推荐
评论