1. 概述
描述符用来描述USB设备性能或特性的数据结构,与设备类相关的信息都是主机向设备获取描述符来得到的。
一个UVC设备除了常用的标准描述符,另外还定义了视频设备的特殊类描述符,主要如下:
标准描述符
- 设备描述符(Device Descriptor)
- 设备限定描述符(Device QualifierDescriptor)
- 设备配置描述符(Configure Descriptor)
- 其他速度描述符(Other Speed Descriptor)
- 字符描述符(String Descriptor)
特殊类描述符
- 接口联合描述符(Interface Association Descriptor)
- 视频控制接口描述符(VideoControl Interface Descriptor)
- 视频控制端点描述符(VideoControl Endpoint Descriptor)
- 视频流接口描述符(VideoStreaming Interface Descriptor)
- 视频流端点描述符(VideoStreaming Endpoint Descriptor)
接下来,我们将重点分析这些描述符信息。
2. UVC设备逻辑组织
uvc 设备逻辑组织如下。至少包含一个配置描述符两个接口,接口0负责VideoControl,接口1负责VideoStream。
3. 描述符介绍
3.1 设备描述符
设备描述符信息如下(来源于USB_Video_Class_1.5)
- bLength:固定长度 0x12
- bDescriptorType:设备类型,默认设为1
- bcdUSB:USB版本号。1.1~0x0110 2.0~0x0200
- bDeviceClass:设备类.此处设为0xEF
- bDeviceSubClass:设备子类。此处设为0x02
- bDeviceProtocol:协议代码。默认为0x1
- bMaxPacketSize0:控制端点最大包长。动态设置
- idVendor:厂商编号
- idProduct:产品ID
- bcDevice:设备版本号
- iManufacturer:厂商字符串描述符索引
- iProduct:产品字符串描述符索引
- iSerialNumber:产品序列号描述符索引
- bNumConfigurations:支持的配置数量,一般为1
对比 driver/usb/gadget/webcam.c,可以看到dynamic都是可以动态调整的。
static struct usb_device_descriptor webcam_device_descriptor = { .bLength = USB_DT_DEVICE_SIZE, .bDescriptorType = USB_DT_DEVICE, .bcdUSB = cpu_to_le16(0x0200), .bDeviceClass = USB_CLASS_MISC, .bDeviceSubClass = 0x02, .bDeviceProtocol = 0x01, .bMaxPacketSize0 = 0, /* dynamic */ .idVendor = cpu_to_le16(WEBCAM_VENDOR_ID), .idProduct = cpu_to_le16(WEBCAM_PRODUCT_ID), .bcdDevice = cpu_to_le16(WEBCAM_DEVICE_BCD), .iManufacturer = 0, /* dynamic */ .iProduct = 0, /* dynamic */ .iSerialNumber = 0, /* dynamic */ .bNumConfigurations = 0, /* dynamic */ };
3.2 配置描述符
配置描述符如下:
- bLength:描述符长度,固定为0x9
- bDescriptorType:配置描述符类型。默认为0x2
- wTotalLength:表示整个配置描述符的总长度,包括配置描述符,接口描述符,类特殊描述符和端点描述符
- bNumInterFaces:配置支持的接口数
- bConfigurationValue:配置ID,每个配置都有一个标识值
- iConfiguration:配置描述符字符串索引。
- bmAttributes:描述供电特性 D7保留,D6辨识供电方式,为1表示自供电的,否则是总线供电,D5标识是否支持远程唤醒(1),D4-D0保留
- bMaxPower:总线供电时的最大电流,如值为100则最大电流为200mA。
配置描述符配置在driver/usb/gadget/compsite.c下
/* driver/usb/gadget/compsite.c */ static int config_buf(struct usb_configuration *config, enum usb_device_speed speed, void *buf, u8 type) { struct usb_config_descriptor *c = buf; void *next = buf + USB_DT_CONFIG_SIZE; int len; struct usb_function *f; int status; len = USB_COMP_EP0_BUFSIZ - USB_DT_CONFIG_SIZE; /* write the config descriptor */ c = buf; c->bLength = USB_DT_CONFIG_SIZE; c->bDescriptorType = type; /* wTotalLength is written later */ c->bNumInterfaces = config->next_interface_id; c->bConfigurationValue = config->bConfigurationValue; c->iConfiguration = config->iConfiguration; c->bmAttributes = USB_CONFIG_ATT_ONE | config->bmAttributes; c->bMaxPower = encode_bMaxPower(speed, config); ...... /* add each function's descriptors */ ...... len = next - buf; c->wTotalLength = cpu_to_le16(len); return len; }
3.3 接口关联描述符(IAD)
接口关联描述符信息如下:
- bLength:固定长度,为0x8
- bDescriptorType:接口关联描述符类型。0xb 表示IAD
- bFristInterface:接口number
- bInterfaceCount:连续的video 接口数,这里为2
- bFunctionClass:设备类。0xE 表示Video Class
- bFunctionSubClass:子类。表示支持的具体功能。这里是0x3对应
VIDEO_INTERFACE_COLLECTION,支持VideoControl 和VideoInterface
- bFunctionProtocol:默认0
- iFunction:字符串索引
可以看到,UVC设备通过 IAD 去描述一个视频接口集合(Video Interface Collection)
注:Video Interface Collection 是一个视频接口集合。一个UVC设备必须通过IAD来描述Video Interface Collection,并且至少包含一个VideoControl Interface 和一个或多个VideoStream Interface
/* driver/usb/gadget/function/f_uvc.c */ static struct usb_interface_assoc_descriptor uvc_iad = { .bLength = sizeof(uvc_iad), .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, .bFirstInterface = 0, .bInterfaceCount = 2, .bFunctionClass = USB_CLASS_VIDEO, .bFunctionSubClass = UVC_SC_VIDEO_INTERFACE_COLLECTION, .bFunctionProtocol = 0x00, .iFunction = 0, };
4. 总结
有关 UVC的描述符组织信息,实在太多,本文先介绍基础描述符,后续陆续介绍,VideoControl ,VideoStream等描述符信息,这个是UVC的关键。
所有信息来源于《UVC 1.5 Class specfication》和《USB_Video_Example.pdf》以及内核源码参考。