uvc_parse_control解析拓扑结构uvc_parse_standard_control
2024-03-18
106
0
对于大部分的UVC设备,都不会存在厂家自定义的所谓“自定义扩展单元”,都是很规矩的使用UVC标准的扩展单元。当然扩展单元在UVC的控制接口描述符中混着,所以LINUX&UVC驱动就使用uvc_parse_standard_control函数解析这些标准的UVC描述符。
在分析代码之前,先回顾一下UVC标准结构体的通用结构。
通过UVC规范可知,在其UVC控制接口描述符中,可能会存以下描述符,分别为:
- 输入端子(ST)
- 输出端子(OT)
- 选择器单元(SU)
- 处理单元(PU)
- 编码单元(EU)
- 扩展单元(XU)
这些描述符的通用结构体如下:
其中bDescriptorType固件定为0x24,而bDescriptorSubType为以下值时,其内容分别如下:BYTE bLength; BYTE bDescriptorType; BYTE bDescriptorSubType;
bDescriptorSubType | 值 |
---|---|
VC_HEADER | 0x01 |
VC_INPUT_TERMINAL | 0x02 |
VC_OUTPUT_TERMINAL | 0x03 |
VC_SELECTOR_UNIT | 0x04 |
VC_PROCESSING_UNIT | 0x05 |
VC_EXTENSION_UNIT | 0x06 |
VC_ENCODING_UNIT | 0x07 |
这时,再回头来分析uvc_parse_standard_control源代码,其可见:
static int uvc_parse_standard_control(struct uvc_device *dev,
const unsigned char *buffer, int buflen)
{
/*
0=bLength
1= bDescriptorType
2= bDescriptorSubType
*/
switch (buffer[2]) {
case UVC_VC_HEADER:break; //UVC控制接口头描述符
case UVC_VC_INPUT_TERMINAL:break;//输入终端
case UVC_VC_OUTPUT_TERMINAL:break;//输出终端
case UVC_VC_SELECTOR_UNIT:break;//选择选择器单元
case UVC_VC_PROCESSING_UNIT:break;//处理单元
case UVC_VC_EXTENSION_UNIT:break;//扩展单元
default://其它
}
}
对于UVC_VC_INPUT_TERMINAL至UVC_VC_EXTENSION_UNIT,都会执行
list_add_tail(&term->list, &dev->entities);
而对于UVC_VC_HEADER,会执行解析UVC视频流接口描述符。
/* Parse all USB Video Streaming interfaces. */
for (i = 0; i < n; ++i) {
intf = usb_ifnum_to_if(udev, buffer[12+i]);
if (intf == NULL) {
uvc_trace(UVC_TRACE_DESCR, "device %d "
"interface %d doesn't exists\n",
udev->devnum, i);
continue;
}
uvc_parse_streaming(dev, intf);
}
另外,对于输入终端,其它4个字节wTerminalType指定了具体的类型:
-------- Video Control Input Terminal Descriptor ------
bLength : 0x12 (18 bytes)
bDescriptorType : 0x24 (Video Control Interface)
bDescriptorSubtype : 0x02 (Input Terminal)
bTerminalID : 0x01 (1)
wTerminalType : 0x0201 (ITT_CAMERA)
wTerminalType可选的值有:
wTerminalType | 值 | 描述 |
---|---|---|
ITT_VENDOR_SPECIFIC | 0x200 | 厂商用自定义 |
ITT_CAMERA | 0x201 | 相机 |
ITT_MEDIA_TRANSPORT_INPUT | 0x202 | 序列媒介 |