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的关键。
如果觉得我的内容对你有用,欢迎点赞,分享,转发!