四、USB协议中的描述符

四、USB 协议中的描述符(Descriptor)详解

USB 协议学习目录

点击标题可跳转到对应的网络文章

目录

  • 一、概述
    • [1.1 描述符的作用](#1.1 描述符的作用)
    • [1.2 描述符的级联结构](#1.2 描述符的级联结构)
    • [1.3 描述符通用格式](#1.3 描述符通用格式)
  • [二、设备描述符(Device Descriptor)](#二、设备描述符(Device Descriptor))
    • [2.1 结构详解](#2.1 结构详解)
    • [2.2 关键字段解析](#2.2 关键字段解析)
  • [三、配置描述符(Configuration Descriptor)](#三、配置描述符(Configuration Descriptor))
    • [3.1 结构详解](#3.1 结构详解)
    • [3.2 配置属性解析](#3.2 配置属性解析)
  • [四、接口描述符(Interface Descriptor)](#四、接口描述符(Interface Descriptor))
    • [4.1 结构详解](#4.1 结构详解)
    • [4.2 接口类速查](#4.2 接口类速查)
  • [五、端点描述符(Endpoint Descriptor)](#五、端点描述符(Endpoint Descriptor))
    • [5.1 结构详解](#5.1 结构详解)
    • [5.2 端点地址解析](#5.2 端点地址解析)
    • [5.3 端点属性解析](#5.3 端点属性解析)
  • [六、字符串描述符(String Descriptor)](#六、字符串描述符(String Descriptor))
    • [6.1 语言 ID 描述符](#6.1 语言 ID 描述符)
    • [6.2 Unicode 字符串描述符](#6.2 Unicode 字符串描述符)
  • [七、接口关联描述符 IAD](#七、接口关联描述符 IAD)
  • 八、类特定描述符
    • [8.1 HID 描述符](#8.1 HID 描述符)
    • [8.2 CDC 功能描述符](#8.2 CDC 功能描述符)
    • [8.3 Hub 描述符](#8.3 Hub 描述符)
  • 九、描述符获取流程
  • 十、描述符实例分析
  • 十一、总结

一、概述

1.1 描述符的作用

USB 设备通过描述符(Descriptor)向主机自描述自身的能力。描述符是一种层次化的数据结构,Host 在枚举阶段通过控制传输读取这些描述符,从而了解设备的一切信息。
自描述
读取
解析
USB Device
描述符集
USB Host
加载驱动

配置端点

描述符回答的核心问题:

  • 这是什么设备?(VID/PID/设备类)
  • 支持什么 USB 版本?(bcdUSB)
  • 有多少种配置?(bNumConfigurations)
  • 每个配置有哪些接口?(bNumInterfaces)
  • 每个接口有哪些端点?(bNumEndpoints)
  • 端点支持什么传输类型?(bmAttributes)
  • 设备叫什么名字?(字符串描述符)

1.2 描述符的级联结构

Device Descriptor

设备描述符

18字节
Configuration Descriptor 1

配置描述符

9字节 + 子描述符
Configuration Descriptor 2

(可选)
Interface Descriptor 0

接口描述符

9字节
Interface Descriptor 1

(可选)
HID Descriptor

HID描述符

(如为HID设备)
Endpoint Descriptor 0-1

端点描述符

7字节
Endpoint Descriptor 0-2

(可选)
CDC Functional Descriptor

CDC功能描述符

(如为CDC设备)
Endpoint Descriptor 1-1

描述符层级关系:

  • 1 个设备描述符 → 包含 bNumConfigurations 个配置描述符
  • 每个配置描述符 → 包含 bNumInterfaces 个接口描述符
  • 每个接口描述符 → 包含 bNumEndpoints 个端点描述符
  • 接口描述符 → 可能附带类特定描述符(HID、CDC 等)

1.3 描述符通用格式

所有 USB 描述符都以相同的 2 字节头部开始:

偏移 大小 字段 说明
0 1 bLength 描述符长度(字节)
1 1 bDescriptorType 描述符类型

标准描述符类型值:

类型值 名称 长度
0x01 Device Descriptor 18
0x02 Configuration Descriptor 9
0x03 String Descriptor 可变
0x04 Interface Descriptor 9
0x05 Endpoint Descriptor 7
0x0B Interface Association Descriptor (IAD) 8
0x21 HID Descriptor 9+
0x29 Hub Descriptor 9+
0x2A SuperSpeed Hub Descriptor 12

二、设备描述符(Device Descriptor)

设备描述符是根描述符,位于描述符树的顶层,Host 首先获取的就是它。

2.1 结构详解

c 复制代码
typedef struct {
    uint8_t  bLength;            // 描述符长度 (18)
    uint8_t  bDescriptorType;    // 描述符类型 (0x01)
    uint16_t bcdUSB;             // USB 规范版本号 (如 0x0200 = USB 2.0)
    uint8_t  bDeviceClass;       // 设备类代码
    uint8_t  bDeviceSubClass;    // 设备子类代码
    uint8_t  bDeviceProtocol;    // 设备协议代码
    uint8_t  bMaxPacketSize0;    // 端点 0 最大包大小
    uint16_t idVendor;           // 厂商 ID (VID)
    uint16_t idProduct;          // 产品 ID (PID)
    uint16_t bcdDevice;          // 设备版本号 (BCD)
    uint8_t  iManufacturer;      // 厂商字符串索引
    uint8_t  iProduct;           // 产品字符串索引
    uint8_t  iSerialNumber;      // 序列号字符串索引
    uint8_t  bNumConfigurations; // 配置描述符数量
} USB_DeviceDescriptor;

2.2 关键字段解析

bcdUSB - USB 版本号(BCD 编码):

值 USB 版本
0x0100 USB 1.0
0x0110 USB 1.1
0x0200 USB 2.0
0x0250 USB 2.1 (LPM)
0x0300 USB 3.0
0x0310 USB 3.1
0x0320 USB 3.2

bDeviceClass - 设备类:

值 含义
0x00 每接口定义类(复合设备)
0x02 CDC 通信设备
0x03 HID 人机接口设备
0x08 Mass Storage 大容量存储
0x09 Hub 集线器
0x0E Video 视频设备
0xE0 Wireless 无线控制器
0xEF Miscellaneous 杂项
0xFF Vendor Specific 厂商自定义

bMaxPacketSize0 - 端点 0 最大包大小:

速度 有效值
Low Speed 8
Full Speed 8, 16, 32, 64
High Speed 64

idVendor / idProduct:

  • VID 由 USB-IF 统一分配(如 0x046D = Logitech)
  • PID 由厂商自行定义
  • Host 通过 VID/PID 匹配特定驱动

字符串索引字段:

  • iManufacturer:厂商名称字符串索引(0 = 无字符串)
  • iProduct:产品名称字符串索引
  • iSerialNumber:序列号字符串索引

三、配置描述符(Configuration Descriptor)

配置描述符定义了设备的一种工作模式。一个设备可以有多个配置(如"总线供电模式"和"自供电模式"),但同一时间只能激活一个配置。

3.1 结构详解

c 复制代码
typedef struct {
    uint8_t  bLength;             // 描述符长度 (9)
    uint8_t  bDescriptorType;     // 描述符类型 (0x02)
    uint16_t wTotalLength;        // 配置总长度(含所有子描述符)
    uint8_t  bNumInterfaces;      // 接口数量
    uint8_t  bConfigurationValue; // 配置值(SET_CONFIGURATION 参数)
    uint8_t  iConfiguration;      // 配置描述字符串索引
    uint8_t  bmAttributes;        // 配置属性
    uint8_t  bMaxPower;           // 最大功耗(单位:2mA)
} USB_ConfigurationDescriptor;

3.2 配置属性解析

bmAttributes 字段:

位 名称 值 说明
Bit7 保留 1 必须置 1(历史兼容)
Bit6 自供电 1 设备支持自供电
0 设备仅总线供电
Bit5 远程唤醒 1 支持远程唤醒
0 不支持远程唤醒
Bit4~0 保留 0 必须置 0

bMaxPower:

  • 单位 = 2mA
  • 例如:值 = 50,表示最大功耗 = 50 × 2mA = 100mA
  • USB 2.0 最大值为 250(500mA)
  • USB 3.0 最大值为 250(500mA),但 SuperSpeed 设备可支持 900mA

wTotalLength:

  • 这是整个配置描述符集的总长度
  • 包含:配置描述符 + 所有接口描述符 + 所有端点描述符 + 所有类特定描述符
  • Host 通过此值一次性获取完整配置信息

四、接口描述符(Interface Descriptor)

接口描述符定义了设备的一个逻辑功能。一个配置可包含多个接口,每个接口对应一个独立功能(如键盘 + 鼠标复合设备)。

4.1 结构详解

c 复制代码
typedef struct {
    uint8_t bLength;             // 描述符长度 (9)
    uint8_t bDescriptorType;     // 描述符类型 (0x04)
    uint8_t bInterfaceNumber;    // 接口编号(从 0 开始)
    uint8_t bAlternateSetting;   // 备用设置编号
    uint8_t bNumEndpoints;       // 端点数量(不含 EP0)
    uint8_t bInterfaceClass;     // 接口类代码
    uint8_t bInterfaceSubClass;  // 接口子类代码
    uint8_t bInterfaceProtocol;  // 接口协议代码
    uint8_t iInterface;          // 接口描述字符串索引
} USB_InterfaceDescriptor;

bInterfaceNumber:

  • 接口在配置中的唯一编号,从 0 开始递增
  • 复合设备中,每个功能对应一个独立的接口编号

bAlternateSetting:

  • 同一接口的不同设置(Alternate Setting)
  • 用于动态切换接口配置(如 USB 音频中切换采样率)
  • 默认设置 = 0,通过 SET_INTERFACE 请求切换

bNumEndpoints:

  • 该接口使用的非零端点数量
  • 控制端点 EP0 是所有接口共用的,不计入此值

4.2 接口类速查

类代码 名称 典型应用 子类示例
0x00 保留 - -
0x02 CDC-Control 串口/调制解调器 ACM=0x02
0x03 HID 键盘/鼠标/手柄 Boot=0x01
0x08 Mass Storage U盘/读卡器 SCSI=0x06, BOT=0x50
0x0A CDC-Data CDC 数据接口 -
0x0B Smart Card 读卡器 CCID=0x00
0x0E Video 摄像头 UVC=0x01
0x01 Audio 声卡/耳机 UAC
0x09 Hub 集线器 -
0xE0 Wireless 蓝牙/WiFi Bluetooth=0x01
0xFF Vendor Specific 自定义 -

五、端点描述符(Endpoint Descriptor)

端点描述符定义了数据传输的通道属性,包括方向、传输类型、最大包大小和轮询间隔。

5.1 结构详解

c 复制代码
typedef struct {
    uint8_t  bLength;            // 描述符长度 (7)
    uint8_t  bDescriptorType;    // 描述符类型 (0x05)
    uint8_t  bEndpointAddress;   // 端点地址
    uint8_t  bmAttributes;       // 端点属性
    uint16_t wMaxPacketSize;     // 最大包大小
    uint8_t  bInterval;          // 轮询间隔
} USB_EndpointDescriptor;

5.2 端点地址解析

bEndpointAddress:

复制代码
Bit7    Bit6~4    Bit3~0
方向    保留       端点编号
0=OUT   000       0~15
1=IN
值 含义
0x00 控制端点 0 (OUT)
0x80 控制端点 0 (IN)
0x01 端点 1 (OUT)
0x81 端点 1 (IN)
0x02 端点 2 (OUT)
0x82 端点 2 (IN)

5.3 端点属性解析

bmAttributes:

复制代码
Bit1~0: 传输类型
  00 = Control    控制传输
  01 = Isochronous 同步传输
  10 = Bulk       批量传输
  11 = Interrupt  中断传输

Bit3~2: 同步类型 (仅同步传输)
  00 = None       无同步
  01 = Asynchronous 异步
  10 = Adaptive   自适应
  11 = Synchronous 同步

Bit5~4: 用法类型 (仅同步传输)
  00 = Data Endpoint
  01 = Feedback Endpoint
  10 = Implicit Feedback
  11 = Reserved

wMaxPacketSize:

速度 控制 批量 中断 同步
Low Speed 8 - 8 -
Full Speed 8/16/32/64 8/16/32/64 64 1023
High Speed 64 512 1024 1024
SuperSpeed 512 1024 1024 1024

bInterval:

速度 含义 典型值
Full Speed 中断 轮询间隔(ms) 1~255 ms
High Speed 中断 轮询间隔(125μs × 2^(bInterval-1)) 1~16
Full Speed 同步 轮询间隔(ms) 1 ms
High Speed 同步 轮询间隔(125μs × 2^(bInterval-1)) 1~16
批量/控制 忽略 -

六、字符串描述符(String Descriptor)

字符串描述符提供设备的可读文本信息 (厂商名、产品名、序列号),采用 UTF-16LE 编码。

6.1 语言 ID 描述符

字符串描述符 0 是特殊的,它返回设备支持的语言 ID 列表。

c 复制代码
// 字符串描述符 0 结构
uint8_t bLength;           // 描述符长度 (2 + 2*N)
uint8_t bDescriptorType;   // 0x03
uint16_t wLANGID[0];       // 语言 ID 数组
// ...
uint16_t wLANGID[N-1];

常用语言 ID:

语言 LANGID
英语(美国) 0x0409
简体中文 0x0804
繁体中文 0x0404
日语 0x0411
韩语 0x0412

6.2 Unicode 字符串描述符

c 复制代码
// 字符串描述符 N (N >= 1)
uint8_t  bLength;          // 描述符长度 (2 + 字符串字节数)
uint8_t  bDescriptorType;  // 0x03
uint16_t bString[];        // UTF-16LE 编码字符串 (不含结尾 \0)

示例:字符串 "Kimi USB Device"

复制代码
bLength       = 0x22        // 2 + 16×2 = 34 字节
bDescriptorType = 0x03
bString[0]    = 'K' = 0x004B (小端: 4B 00)
bString[1]    = 'i' = 0x0069 (小端: 69 00)
...

七、接口关联描述符 IAD

当多个接口组成一个复合功能时,需要使用 IAD(Interface Association Descriptor)进行关联声明。

c 复制代码
typedef struct {
    uint8_t  bLength;           // 描述符长度 (8)
    uint8_t  bDescriptorType;   // 描述符类型 (0x0B)
    uint8_t  bFirstInterface;   // 第一个接口编号
    uint8_t  bInterfaceCount;   // 关联的接口数量
    uint8_t  bFunctionClass;    // 功能类
    uint8_t  bFunctionSubClass; // 功能子类
    uint8_t  bFunctionProtocol; // 功能协议
    uint8_t  iFunction;         // 功能描述字符串索引
} USB_IADDescriptor;

典型应用 - CDC 设备:
IAD

bFirstInterface=0

bInterfaceCount=2

FunctionClass=0x02 CDC
Interface 0

CDC-Control

bInterfaceClass=0x02
Interface 1

CDC-Data

bInterfaceClass=0x0A
中断端点

通知端点
CDC Functional Descriptors

Header/ACM/Union/CallMgmt
批量端点 IN

数据接收
批量端点 OUT

数据发送


八、类特定描述符

8.1 HID 描述符

HID 接口必须附带 HID 描述符,定义 HID 规范版本和报告描述符信息。

c 复制代码
typedef struct {
    uint8_t  bLength;           // 描述符长度 (9)
    uint8_t  bDescriptorType;   // 0x21 = HID
    uint16_t bcdHID;            // HID 规范版本 (如 0x0111 = 1.11)
    uint8_t  bCountryCode;      // 国家代码 (0=未本地化)
    uint8_t  bNumDescriptors;   // 附属描述符数量 (>=1)
    uint8_t  bDescriptorType2;  // 0x22 = Report Descriptor
    uint16_t wDescriptorLength; // 报告描述符长度
    // 可选:Physical Descriptor
    // uint8_t  bDescriptorType3;
    // uint16_t wDescriptorLength2;
} USB_HIDDescriptor;

8.2 CDC 功能描述符

CDC 接口附带一组功能描述符(Functional Descriptor),定义通信参数。

描述符子类型 值 说明
Header 0x00 CDC 版本信息
Call Management 0x01 呼叫管理
Abstract Control Management 0x02 ACM 管理
Direct Line Management 0x03 直路管理
Union 0x06 接口关联

Union Functional Descriptor:

c 复制代码
typedef struct {
    uint8_t bLength;           // 4
    uint8_t bDescriptorType;   // 0x24 (CS_INTERFACE)
    uint8_t bDescriptorSubtype;// 0x06 (UNION)
    uint8_t bMasterInterface;  // 控制接口编号
    uint8_t bSlaveInterface0;  // 数据接口编号
} CDC_UnionFunctionalDescriptor;

8.3 Hub 描述符

Hub 设备特有的描述符,定义下行端口数量、电源特性等。

c 复制代码
typedef struct {
    uint8_t  bLength;           // 描述符长度 (9)
    uint8_t  bDescriptorType;   // 0x29 = Hub
    uint8_t  bNbrPorts;         // 下行端口数量
    uint16_t wHubCharacteristics; // Hub 特性
    uint8_t  bPwrOn2PwrGood;    // 端口上电到就绪时间 (2ms 单位)
    uint8_t  bHubContrCurrent;  // Hub 控制器最大电流 (mA)
    uint8_t  DeviceRemovable;   // 设备可移除位图
    uint8_t  PortPwrCtrlMask;   // 端口电源控制掩码
} USB_HubDescriptor;

wHubCharacteristics 字段:

复制代码
Bit1~0: 逻辑电源切换模式
  00 = Ganged power switching (所有端口一起)
  01 = Individual port power switching (独立)
  1x = 无电源切换

Bit2: 复合设备标志
  0 = Hub 不是复合设备的一部分
  1 = Hub 是复合设备的一部分

Bit4~3: TT (Transaction Translator)  Think Time
  00 = <=8 FS bit times
  01 = <=16 FS bit times
  10 = <=24 FS bit times
  11 = <=32 FS bit times

Bit5: TT 端口指示器
  0 = 不支持端口指示器
  1 = 支持端口指示器

九、描述符获取流程

Host 在枚举阶段按以下顺序获取描述符:
USB Device USB Host USB Device USB Host 阶段1: 获取设备描述符 阶段2: 获取配置描述符 阶段3: 获取字符串描述符 阶段4: 设置配置 GET_DESCRIPTOR(Device, 8) 前 8 字节 (含 bMaxPacketSize0) SET_ADDRESS(addr) ACK GET_DESCRIPTOR(Device, 18) 完整设备描述符 GET_DESCRIPTOR(Config, 9) 配置描述符 (含 wTotalLength) GET_DESCRIPTOR(Config, wTotalLength) 完整配置描述符集 GET_DESCRIPTOR(String, 0) 语言 ID 列表 GET_DESCRIPTOR(String, iManufacturer) 厂商名称 GET_DESCRIPTOR(String, iProduct) 产品名称 SET_CONFIGURATION(value) ACK

GET_DESCRIPTOR 请求格式:

复制代码
bmRequestType = 0x80  (Device→Host, Standard, Device)
bRequest      = 0x06  (GET_DESCRIPTOR)
wValue        = (描述符类型 << 8) | 描述符索引
                如: 设备描述符 = 0x0100
                    配置描述符 = 0x0200
                    字符串描述符(厂商) = 0x0301
wIndex        = 0 (设备/配置) 或语言 ID (字符串)
wLength       = 期望返回的字节数

十、描述符实例分析

以下是一个USB HID 键盘的完整描述符字节流实例:

设备描述符(18 字节)

复制代码
偏移  值      说明
----  ----    ----
00    0x12    bLength = 18
01    0x01    bDescriptorType = Device
02    0x00    bcdUSB = 0x0200 (USB 2.0)
03    0x02
04    0x00    bDeviceClass = 0 (每接口定义)
05    0x00    bDeviceSubClass = 0
06    0x00    bDeviceProtocol = 0
07    0x08    bMaxPacketSize0 = 8 (Full Speed)
08    0x83    idVendor = 0x0483 (ST Microelectronics)
09    0x04
10    0x10    idProduct = 0x5710
11    0x57
12    0x00    bcdDevice = 0x0100
13    0x01
14    0x01    iManufacturer = 1 (字符串1)
15    0x02    iProduct = 2 (字符串2)
16    0x00    iSerialNumber = 0 (无)
17    0x01    bNumConfigurations = 1

配置描述符及子描述符(34 字节)

复制代码
偏移  值      说明
----  ----    ----
00    0x09    bLength = 9 (Configuration)
01    0x02    bDescriptorType = Configuration
02    0x22    wTotalLength = 0x0022 = 34 字节
03    0x00
04    0x01    bNumInterfaces = 1
05    0x01    bConfigurationValue = 1
06    0x00    iConfiguration = 0 (无)
07    0xA0    bmAttributes = 10100000 (自供电, 远程唤醒)
08    0x32    bMaxPower = 50 × 2mA = 100mA

09    0x09    bLength = 9 (Interface)
10    0x04    bDescriptorType = Interface
11    0x00    bInterfaceNumber = 0
12    0x00    bAlternateSetting = 0
13    0x01    bNumEndpoints = 1
14    0x03    bInterfaceClass = 0x03 (HID)
15    0x01    bInterfaceSubClass = 0x01 (Boot)
16    0x01    bInterfaceProtocol = 0x01 (Keyboard)
17    0x00    iInterface = 0 (无)

18    0x09    bLength = 9 (HID)
19    0x21    bDescriptorType = HID
20    0x11    bcdHID = 0x0111 (HID 1.11)
21    0x01
22    0x00    bCountryCode = 0
23    0x01    bNumDescriptors = 1
24    0x22    bDescriptorType = Report
25    0x3F    wDescriptorLength = 0x003F = 63 字节
26    0x00

27    0x07    bLength = 7 (Endpoint)
28    0x05    bDescriptorType = Endpoint
29    0x81    bEndpointAddress = 0x81 (EP1 IN)
30    0x03    bmAttributes = 0x03 (Interrupt)
31    0x08    wMaxPacketSize = 8
32    0x00
33    0x0A    bInterval = 10 ms

字符串描述符

字符串 0(语言 ID):

复制代码
00    0x04    bLength = 4
01    0x03    bDescriptorType = String
02    0x09    wLANGID[0] = 0x0409 (英语-美国)
03    0x04

字符串 1(厂商名 "STMicroelectronics"):

复制代码
00    0x26    bLength = 38 (2 + 18×2)
01    0x03    bDescriptorType = String
02~   ...     "STMicroelectronics" in UTF-16LE

十一、总结

Level 4
Level 3
Level 2
Level 1
Level 0
Device Descriptor

18字节

设备全局信息
Configuration Descriptor

9字节 + 子描述符

一种工作模式
Interface Descriptor

9字节

一个逻辑功能
IAD

8字节

接口关联
Endpoint Descriptor

7字节

数据传输通道
Class-Specific

HID/CDC/Hub...

类特定描述符
String Descriptor

可变

可读文本信息

描述符设计核心思想:

  1. 自描述:设备通过描述符告知主机"我是谁、我能做什么"
  2. 分层级联:从设备 → 配置 → 接口 → 端点,层层细化
  3. 灵活扩展:通过类特定描述符支持各种设备类
  4. 动态配置:同一设备可有多套配置/接口,按需切换
相关推荐
我是谁??6 天前
VMware 虚拟机无法识别 USB 设备?一个参数搞定!
vmware·usb
橘色的喵6 天前
USB枚举、协商、传输:以USB相机为例看识别与格式协商
串口·usb·设备枚举
小黑(感觉你阻抗≥1MΩ)16 天前
TYPE-C电路
usb·电路·原理图·type-c
一个平凡而乐于分享的小比特16 天前
解剖USB控制器移植:从VeriSilicon到MindMotion的“外科手术式”改造
usb·verisilicon·mindmotion
一个平凡而乐于分享的小比特16 天前
USB协议完全指南:从“识别设备”到“数据狂飙”的硬核浪漫
usb协议
ZenasLDR18 天前
LDR6600实现AR眼镜边充电边投屏功能
接口·芯片·usb
橘色的喵1 个月前
一根数据源,两条出图路:UVC(USB)与 CSI-2(MIPI)对比解读
usb·isp·mipi·uvc·csi-2
ZenasLDR1 个月前
Type-C边充边听音频转接器
接口·芯片·usb
kdxiaojie1 个月前
Linux USB驱动阅读笔记(1)
linux·笔记·学习·usb
深念Y1 个月前
JMS583 USB-NVMe 桥接芯片 LED 控制探索
嵌入式硬件·嵌入式·led·usb·电子·维修·硬盘盒