基于DWC2的USB驱动开发-UVC的处理单元详解

描述

本文转自公众号,欢迎关注
基于DWC2的USB驱动开发-UVC的处理单元详解 (qq.com)

一.前言

本篇来详细分析下UVC的处理单元相关的内容,同样的我们理论结合实践来进行。

二.处理单元简介

处理单元(PU)控制通过它传输的视频的图像属性。有一个单一的输入和输出引脚,注意是单一的,也就是一个处理单元只能处理一个输入只有一个输出。

支持以下功能:

用户控制:

  • Brightness亮度·
  • Hue色调·
  • Saturation饱和度·
  • Sharpness清晰度·
  • Gamma伽马·
  • Digital Multiplier (Zoom) 数字乘法器(缩放)

自动控制

  • White Balance Temperature 白平衡温度控制
  • White Balance Component 白平衡成分控制
  • Backlight Compensation 背光补偿
  • Contrast 对比度

其他

  • Gain 增益
  • Power Line Frequency 电力线频率
  • Analog Video Standard 模拟视频标准
  • Analog Video Lock Status 模拟视频锁定状态

对上述功能的支持都是可选的,但是,如果设备支持白平衡功能,则应实现白平衡温度控制或白平衡成分控制,但不能同时实现。

用户控制表示由用户偏好设置的属性,不受设备的自动控制的影响。

自动控制支持是否使能的设置(具有打开/关闭状态)。如果使能则设备自动调整,对相关属性的读请求则反映自动设置的值。

如果打开自动模式,尝试以手动方式设置将导致STALL,错误代码为bRequestErrorCode=“错误状态”。当退出自动模式时,相关控制属性应保持在转换前有效的值。

后面可以看到基本所有的属性都对应有一个自动控制,使能自动控制就不能再手动配置了。

处理单元的符号如下图所示。

注意这里的但输入单输出
usb

三.拓扑结构

以下从描述符来看处理单元的拓扑结构,如下图是一个实际的UVC产品的描述符,只截取了和UVC相关的IAD下的描述符。
usb

可以看到处理单元的ID是bUnitID=2,其源头是bSourceID=1即前面的bTerminaIID=1的视频控制输入终端;而其后面是bUnitID=3的视频控制扩展单元,该单元的baSourceID[1]=2表示其源头是本处理单元。

其拓扑如下

usb

四.处理单元描述符

处理单元的描述符应该位于UVC的控制接口描述符VideoControl Interface Descriptors的Class-specific VC Interface Header Descriptor的后面

如下所示红色线所指示

usb

本实例处理单元描述符对应的具体内容如下

usb

处理单元的描述详细内容见规格书P69

3.7.2.5 Processing Unit Descriptor

偏移区域大小说明
0bLength1数字值,13本描述符的字节数
1bDescriptorType1常数CS_INTERFACE=0x24描述符类型
2bDescriptorSubtype1常数VC_PROCESSING_UNIT =0x05描述符子类
3bUnitID1数字单元ID
4bSourceID1常数该单元前面所连接的单元或终端的ID。
5wMaxMultiplier2数字数字放大
7bControlSize1数字,3后面 bmControls域 的字节数
8bmControls3Bitmap支持的处理类型
11iProcessing1Index描述本处理单元的字符串描述索引,填0则没有字符串描述符。
12bmVideoStandards1Bitmap支持的标准

l其中bDescriptorType的定义参考规格书的P171 A.5. Video Class-Specific VC Interface Descriptor Subtypes
usb

l其中bDescriptorSubtype的定义参考规格书的P172 A.4. Video Class-Specific Descriptor Types
usb

l其中bUnitID

处理单元由处理单元描述符(PUD)的bUnitID字段的值唯一标识。 非零常数 ,用于唯一标识本功能接口中的单元。类相关请求时Index的高位即该值。

这里为什么要是非零常数呢?为什么从0开始编号呢,因为在请求中wIndex的高8位为0用于区分是接口请求,其他非0值为对应了终端和单元ID,所以不能从0开始编号了。

本功能对应的接口内单该值和其他单元和终端的ID不能重复。

lbSourceID

该单元前面所连接的单元或终端的ID。

处理单元肯定是要处理一个东西的,即需要输入的,处理什么呢,肯定是处理摄像头的输入,所以前面一般就是Input Terminal,该值就是前面的Input Terminal的ID。

如下所示,这里bSourceID=1即前面连接的是bTerminalID=1的输入终端

usb

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种属性的请求

usb

对应的CS编码见P175 A.9.5. Processing Unit Control Selectors

usb

以下做了一个总结,所以值都是无符号值。

类型CS大小B支持的操作[]表示可选最少支持操作说明
背光补偿控制PU_BACKLIGHT_COMPENSATION_CONTROL2SET_CURGET_CURGET_MINGET_MAXGET_RESGET_INFOGET_DEFGET_DEF设置0说明不支持背光补偿,可以支持范围值或者仅仅是开关。小端模式,无符号16位值。
亮度控制PU_BRIGHTNESS_CONTROL2SET_CUR,GET_CUR GET_MIN GET_MAXGET_RESGET_INFOGET_DEFGET_DEF该值是相对值配置的是增量,RES值必须是1小端模式,有符号16位值。
对比度控制PU_CONTRAST_CONTROL2SET_CUR GET_CUR GET_MIN GET_MAXGET_RESGET_INFOGET_DEFGET_DEF该值是相对值配置的是增量,RES值必须是1小端模式,有符号16位值。
对比度自动控制PU_CONTRAST_AUTO_CONTROL1SET_CURGET_CUR GET_INFOGET_DEFGET_DEF值为1表示使能自动控制,此时尝试设置相关对比度控制将导致STALL和bRequestErrorCode=“错误状态”的错误代码。
增益控制PU_GAIN_CONTROL2SET_CURGET_CURGET_MIN GET_MAXGET_RESGET_INFOGET_DEFGET_DEF该值是相对值配置的是增量,RES值必须是1小端模式,有符号16位值。
电力线频率控制PU_POWER_LINE_FREQUENCY_CONTROL1SET_CURGET_CURGET_INFOGET_DEFGET_DEF值对应如下0: Disabled1: 50 Hz2: 60 Hz3: Auto
色度控制PU_HUE_CONTROL2GET_CUR GET_MIN GET_MAXGET_RESGET_INFOGET_DEF[SET_CUR]GET_DEF默认值必须是0,设置值是实际值乘以100,实际值范围是(-180 到+180degrees). 则设置值发呢欸是-18000 ~18000 有符号16位,小端
色度自动控制PU_HUE_AUTO_CONTROL1SET_CUR,GET_CUR,GET_INFO GET_DEFGET_DEF值为1表示使能自动控制,此时尝试设置相关色度控制将导致STALL和bRequestErrorCode=“错误状态”的错误代码
饱和度控制PU_SATURATION_CONTROL2SET_CURGET_CURGET_MINGET_MAXGET_RESGET_INFOGET_DEFGET_DEF0表示灰度值为相对值,RES必须为1
清晰度设置PU_SHARPNESS_CONTROL2SET_CURGET_CURGET_MINGET_MAXGET_RESGET_INFOGET_DEFGET_DEF相对值,MIN意味着“无清晰度处理”RES必须为1
伽马设置PU_GAMMA_CONTROL2SET_CURGET_CURGET_MINGET_MAXGET_RES,GET_INFOGET_DEFGET_DEF设置值是实际值乘以100,设置值范围1500 ,实际值范围1.05.0默认一般是100 (gamma = 1)或220 (gamma = 2.2).
白平衡温度控制PU_WHITE_BALANCE_TEMPERATURE_CONTROL2GET_CURGET_MINGET_MAXGET_RESGET_INFOGET_DEFGET_DEF这用于将白平衡设置指定为以开尔文度为单位的色温。这是作为白平衡组件控制的替代方案提供的。网络摄像头和双模摄像头的最小范围应为2800(白炽)至6500(日光)。
白平衡温度自动控制PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL1SET_CURGET_CURGET_INFOGET_DEFGET_DEF值为1表示使能自动控制,此时尝试设置相关白平衡温度控制将导致STALL和bRequestErrorCode=“错误状态”的错误代码
白平衡成分控制PU_WHITE_BALANCE_COMPONENT_CONTROL4GET_CURGET_MIN GET_MAXGET_RESGET_INFOGET_DEF[SET_CUR]GET_DEF前面2字节是蓝色成分设置后面2字节是红色成分设置
白平衡成分自动控制PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL1SET_CURGET_CURGET_INFOGET_DEFGET_DEF值为1表示使能自动控制,此时尝试设置相关白平衡成分控制将导致STALL和bRequestErrorCode=“错误状态”的错误代码
数字乘法器控制PU_DIGITAL_MULTIPLIER_CONTROL2SET_CURGET_CURGET_MINGET_MAX GET_RESGET_INFOGET_DEF已弃用,下一版将删除值为 Z’cur这用于指定应用于光学图像的数字缩放量。这是乘法器m的可能值范围内的位置,允许通过设备实现来描述乘法器分辨率。RES 必须为1如果支持数字乘法器限制控制,则最小值和最大值应与数字乘法器控制的最小值和最高值相匹配。数字乘法器限制控制允许设备或主机为Z¢cur 值建立临时上限,从而动态减小数字乘法器控制的范围。如果使用数字乘法器限制将限制降低到当前Z¢cur ,Z¢cur 值将进行调整以匹配新的限制,数字乘法器控制应发送控制更改事件以通知主机调整。
数字乘法器限制控制PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL2SET_CURGET_CURGET_MINGET_MAX GET_RESGET_INFOGET_DEFRES 为1上述Z’cur的上限
模拟视频标准控制PU_ANALOG_VIDEO_STANDARD_CONTROL1GET_CURGET_INFO0: 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_CONTROL1GET_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

usb

参考规格书4.2.2 Unit and Terminal Control Requests,终端和单元的请求的layout

请求分为SET和GET两大类

bmRequestTypebRequestwValuewIndexwLengthData
00100001SET_CURCS(高字节)单元或终端ID(高位)+接口(低位)数据长度
10100001GET_CURGET_MINGET_MAXGET_RESGET_INFOGET_DEF
00100001SET_CUR_ALL0单元或终端ID
10100001GET_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

usb

usb

然后再看如果bmRequestType的bit4:0为1,则对应接口相关处理

usb

usb

然后调用注册的类回调,usb_uvc_class_set

再根据wIndex的高8位如果是0则对应的接口请求uvc_class_itf_req,

否则是终端单元相关请求uvc_class_ut_req

usb

进入uvc_class_ut_req后

再根据wIndex的低8位确认接口,高8位定位终端和单元,然后根据wValue低8位确认CS即对应操作什么属性,然后根据bRequest确定是什么操作,比如GET_CUR

usb

比如如下的一个实例的解析

a1表示类相关接口请求

86表示GET_INFO

0002 高8位02表示PU_BRIGHTNESS_CONTROL 处理单元的CS

0002 高8位表示单元ID2,低8位表示接口0,如下图接口0的ID2的单元就是处理单元

0100表示数据长度,GET_INFO即数据只有1个字节

usb

usb

后面的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有哪些值操作。这个后面再单独一篇介绍。

七. 总结

以上详细介绍了处理单元,包括描述符和其拓扑结构,请求等。可以先了解其拓扑结构,在描述符中如何描述这有利于从整体把握,然后了解其请求的过程。

审核编辑:汤梓红

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分