3. USB描述符家族:结构与字段深度解析

USB描述符是设备向主机报告自身能力与属性的结构化数据块,是枚举过程中主机获取设备信息的唯一途径。任何描述符的格式错误、长度不匹配或字段值异常,都会导致枚举失败或功能受限。本章逐一拆解五大核心描述符的结构与关键字段。

核心原则:所有描述符的第一个字节均为 bLength(描述符长度),第二个字节均为 bDescriptorType(描述符类型代码)。主机通过这两个字段验证描述符的完整性与类型。

3.1 设备描述符 (Device Descriptor)

设备描述符是枚举过程中主机读取的第一个描述符,位于描述符树的根节点。它定义了设备的整体属性,包括USB规范版本、设备类/子类/协议、厂商与产品标识等。

偏移字段大小说明
0bLength1描述符长度,固定为18字节 (0x12)
1bDescriptorType1描述符类型代码,设备描述符为0x01
2bcdUSB2USB规范版本号,BCD编码,如0x0200 (USB 2.0)
4bDeviceClass1设备类代码,0x00表示在接口描述符中定义
5bDeviceSubClass1设备子类代码,与bDeviceClass配合使用
6bDeviceProtocol1设备协议代码,0x00表示无协议
7bMaxPacketSize01端点0的最大包大小,USB 2.0通常为64
8idVendor2厂商ID (VID),由USB-IF分配
10idProduct2产品ID (PID),由厂商自行分配
12bcdDevice2设备版本号,BCD编码
14iManufacturer1厂商字符串描述符索引,0表示无字符串
15iProduct1产品字符串描述符索引
16iSerialNumber1序列号字符串描述符索引
17bNumConfigurations1支持的配置描述符数量,通常为1
调试要点:当主机收到设备描述符后,会立即验证bLength是否为18。若长度异常,主机将发送复位信号并重试枚举。bMaxPacketSize0字段若小于8(USB 2.0要求至少8字节),也会导致枚举失败。
设备描述符结构图 设备描述符 (18字节) bLength (1B) bDescriptorType (1B) bcdUSB (2B) bDeviceClass (1B) bDeviceSubClass (1B) bDeviceProtocol (1B) bMaxPacketSize0 (1B) idVendor (2B) idProduct (2B) bcdDevice (2B) iManufacturer (1B) iProduct (1B) iSerialNumber (1B) bNumConfigurations (1B) 关键检查点 bLength = 0x12 bMaxPacketSize0 ≥ 8

3.2 配置描述符 (Configuration Descriptor)

配置描述符描述设备的电源管理能力与接口数量。一个设备可以有多个配置,但同一时刻只能激活一个配置。主机通过标准请求 Get_Descriptor(Configuration) 获取完整配置树,包括配置描述符本身及其下属的所有接口描述符和端点描述符。

偏移字段大小说明
0bLength1描述符长度,固定为9字节 (0x09)
1bDescriptorType1描述符类型代码,配置描述符为0x02
2wTotalLength2整个配置树的总长度(含所有子描述符)
4bNumInterfaces1该配置支持的接口数量
5bConfigurationValue1用于Set_Configuration请求的配置值
6iConfiguration1配置字符串描述符索引
7bmAttributes1配置特性:D7=总线供电,D6=自供电,D5=远程唤醒
8bMaxPower1最大电流,单位2mA,值×2即为毫安数
常见故障:wTotalLength字段若小于实际描述符树的总长度,主机将无法完整解析后续的接口和端点描述符,导致枚举卡在配置描述符阶段。调试时务必使用USB分析仪抓取原始描述符数据,逐字节核对wTotalLength。
配置描述符与子描述符层级关系 配置描述符 (9B) bDescriptorType = 0x02 接口描述符1 (9B) bInterfaceNumber = 0 接口描述符2 (9B) bInterfaceNumber = 1 端点描述符1 (7B) bEndpointAddress = 0x81 端点描述符2 (7B) bEndpointAddress = 0x02 端点描述符3 (7B) bEndpointAddress = 0x83 wTotalLength = 配置描述符(9) + 接口描述符1(9) + 端点描述符1(7) + 端点描述符2(7) + 接口描述符2(9) + 端点描述符3(7) = 48字节 主机一次性读取wTotalLength字节,然后按类型代码逐层解析

3.3 接口描述符 (Interface Descriptor)

接口描述符定义了一个功能单元,包含一组端点。一个配置可以包含多个接口,每个接口可以有一个或多个备用设置(Alternate Setting)。主机通过 Set_Interface 请求切换备用设置,以改变接口的带宽或功能。

偏移字段大小说明
0bLength1描述符长度,固定为9字节 (0x09)
1bDescriptorType1描述符类型代码,接口描述符为0x04
2bInterfaceNumber1接口编号,从0开始递增
3bAlternateSetting1备用设置编号,0为默认设置
4bNumEndpoints1该接口使用的端点数量(不含端点0)
5bInterfaceClass1接口类代码,如0x08为Mass Storage
6bInterfaceSubClass1接口子类代码
7bInterfaceProtocol1接口协议代码
8iInterface1接口字符串描述符索引
类请求关联:接口描述符中的bInterfaceClass/bInterfaceSubClass/bInterfaceProtocol决定了主机加载哪个类驱动程序。例如,HID设备(bInterfaceClass=0x03)会触发HID驱动加载,并随后发送HID类请求获取报告描述符。

3.4 端点描述符 (Endpoint Descriptor)

端点描述符定义数据传输的端点属性,包括传输方向、传输类型、最大包大小和轮询间隔。除端点0外,每个非0端点都必须有对应的端点描述符。

偏移字段大小说明
0bLength1描述符长度,固定为7字节 (0x07)
1bDescriptorType1描述符类型代码,端点描述符为0x05
2bEndpointAddress1端点地址:Bit7=方向(0:OUT,1:IN),Bit3-0=端点号
3bmAttributes1传输类型:0x00=控制,0x01=等时,0x02=批量,0x03=中断
4wMaxPacketSize2最大包大小,USB 2.0高速批量端点最大512字节
6bInterval1轮询间隔:中断端点单位ms,等时端点单位125μs
调试陷阱:bEndpointAddress的Bit7必须正确设置方向。若IN端点被错误配置为OUT方向(Bit7=0),主机将无法从该端点读取数据,导致批量传输或中断传输超时。wMaxPacketSize必须与USB速度匹配:全速批量端点最大64字节,高速批量端点最大512字节。
端点描述符字段解析 端点描述符 (7字节) bLength bDescriptorType bEndpointAddress bmAttributes wMaxPacketSize bInterval bEndpointAddress 位域结构 Bit7: 方向 (0=OUT, 1=IN) Bit6-4: 保留 (必须为0) Bit3-0: 端点号 (0-15) bmAttributes 传输类型 0x00: 控制传输 0x01: 等时传输 0x02: 批量传输 | 0x03: 中断传输

3.5 字符串描述符 (String Descriptor)

字符串描述符提供人类可读的文本信息,如厂商名称、产品名称和序列号。字符串描述符使用Unicode编码(UTF-16LE),主机通过 Get_Descriptor(String, Index) 请求获取。字符串描述符索引0为特殊语言ID描述符,用于获取设备支持的语言列表。

偏移字段大小说明
0bLength1描述符长度,等于2 + 字符串字节数
1bDescriptorType1描述符类型代码,字符串描述符为0x03
2bStringNUnicode字符串,UTF-16LE编码,无NULL终止符
枚举优化:字符串描述符是可选的。如果设备不需要显示名称或序列号,可以将iManufacturer、iProduct、iSerialNumber设置为0,主机将跳过字符串请求,从而加快枚举速度。但某些操作系统(如Windows)在检测到序列号索引非0但字符串请求失败时,会认为设备异常并重试枚举。

3.6 描述符家族关系总览

五大描述符构成严格的树形层级:设备描述符 → 配置描述符 → 接口描述符 → 端点描述符。字符串描述符作为辅助节点,通过索引被其他描述符引用。主机枚举时按此层级逐级读取,任何一级的异常都会导致枚举中断。

USB描述符家族层级关系 设备描述符 bNumConfigurations = 1 配置描述符 bNumInterfaces = 2 接口描述符0 bNumEndpoints = 2 接口描述符1 bNumEndpoints = 1 端点0x81 (IN) 端点0x02 (OUT) 端点0x83 (IN) 字符串描述符

3.7 枚举日志中的描述符解析实战

以下是一段真实的USB枚举日志,展示了主机读取设备描述符和配置描述符的原始数据。注意观察字段值与实际设备属性的对应关系。

// 设备描述符原始数据 (18字节)
// 主机