USB基础 -- 字符串描述符 (String Descriptor) 系统整理文档
整理一份 系统完整的教学培训文档,主题是 USB String Descriptor(字符串描述符)的体系、用法与扩展。
内容会覆盖:概念 → 标准字段 → 索引映射机制 → 类描述符扩展 → 自定义扩展 → 实战示例 → 注意事项 → 总结。
USB 字符串描述符 (String Descriptor) 系统整理文档
一、概念与作用
USB 协议中的 字符串描述符 (String Descriptor, bDescriptorType = 0x03) 用于为设备提供人类可读的文本信息。
这些信息并非设备功能必需,但对 用户显示、设备识别、调试区分 非常重要。
常见用途:
- 厂商名称 (Manufacturer)
- 产品名称 (Product)
- 序列号 (Serial Number)
- 配置名称 (Configuration String)
- 接口名称 (Interface String)
- 类扩展(如 UVC Camera Terminal、Audio Terminal 等)
- 厂商自定义信息(固件版本、OEM 定制标识)
二、字符串描述符格式
字符串描述符采用 UTF-16LE 编码,保证跨语言兼容性。
格式如下:
偏移 | 字段 | 长度 | 说明 |
---|---|---|---|
0 | bLength | 1 字节 | 描述符总长度 |
1 | bDescriptorType | 1 字节 | 固定值 0x03 |
2 | bString | n 字节 | 字符串内容(UTF-16LE,每字符 2 字节) |
示例:字符串 “USB”
08 03 55 00 53 00 42 00
- bLength = 8
- bDescriptorType = 0x03
- bString = “U”=55 00, “S”=53 00, “B”=42 00
三、语言 ID 描述符 (String[0])
String Index = 0 不存放字符串,而是存放 支持的语言 ID (LANGID) 列表。
示例:
04 03 09 04
表示支持 0x0409 = English (US)。
主机会先请求 Index=0,获取支持的语言,再用 wLANGID
去请求对应语言的字符串。
四、标准描述符中的 String Index 字段
USB 协议里,字符串描述符本身不会直接写在 Device/Config/Interface 描述符中,而是通过 索引引用。
1. Device Descriptor
- iManufacturer → 厂商名
- iProduct → 产品名
- iSerialNumber → 序列号
2. Configuration Descriptor
- iConfiguration → 配置名称
3. Interface Descriptor
- iInterface → 接口名称
4. Endpoint Descriptor
- 标准 Endpoint 没有 iEndpoint 字段。
五、类扩展 (Class-Specific) 中的 String Index
不同的 USB 类规范(Class)允许在其专用描述符中使用字符串字段。
1. HID (Human Interface Device)
- HID 报告项可以引用字符串索引,用于描述按钮/功能名。
2. Audio Class (UAC1/UAC2)
- iTerminal → Terminal 名称
- iFeature → Feature Unit 名称
- iMixer → Mixer 名称
- iSelector → Selector 名称
- iClockSource / iClockSelector / iClockMultiplier → 时钟单元名
3. Video Class (UVC)
- iTerminal → Camera Terminal 名称
- iProcessing → Processing Unit 名称
- iExtension → Extension Unit 名称
4. Hub Descriptor
- iHub → Hub 名称
六、索引映射机制
规则:
- iXXX = N → 表示该字段引用 String Descriptor[N]
- 主机通过
GET_DESCRIPTOR(String, Index=N, LANGID)
请求该字符串 - String Descriptor 表 = 一张索引到字符串的映射表
索引分配范围:
- 0 → 语言 ID 表
- 1–255 → 字符串(厂商可自由分配)
七、厂商自定义扩展
厂商可以定义自己的描述符,并添加字符串索引字段。
示例:自定义 Vendor Descriptor
struct vendor_device_info {u8 bLength;u8 bDescriptorType; // Vendor specific = 0xFFu8 bCustomField; // 自定义字段u8 iCustomString; // 字符串索引
};
如果 iCustomString = 10
,则 String[10] 必须存在,例如:
String[10] = "Firmware v1.2.3"
八、实战示例
1. Device Descriptor
struct usb_device_descriptor dev_desc = {.bLength = 18,.bDescriptorType = USB_DT_DEVICE,.idVendor = 0x1234,.idProduct = 0x5678,.iManufacturer = 1, // String[1].iProduct = 2, // String[2].iSerialNumber = 3, // String[3]
};
2. String Table
String[0] = 04 03 09 04 // English (US)
String[1] = "MyCompany"
String[2] = "SuperUSB Device"
String[3] = "SN123456789"
String[10] = "Firmware v1.2.3" // 自定义
3. 主机解析流程
- 读到
iManufacturer=1
→ 请求 String[1] →"MyCompany"
- 读到
iProduct=2
→ 请求 String[2] →"SuperUSB Device"
- 读到
iSerialNumber=3
→ 请求 String[3] →"SN123456789"
- 读到 Vendor Descriptor
iCustomString=10
→ 请求 String[10] →"Firmware v1.2.3"
九、注意事项
-
必须 UTF-16LE,即便只含英文。
-
Index=0 保留:仅返回语言 ID。
-
长度上限:字符串 ≤ 126 个字符(255 字节 - 2 字节头)。
-
多语言支持:一个 Index 可以对应多个语言版本。
-
不需要的字段填 0:表示没有对应字符串。
-
调试方法:
- Linux →
lsusb -v
- Windows → USBView/USBlyzer
- 抓包工具 → Beagle USB Analyzer
- Linux →
十、总结
-
字符串描述符是 USB 的“标签”机制,便于用户和系统识别设备。
-
所有 iXXX 字段只存索引,不存字符串。
-
索引值 → String Descriptor 表 → UTF-16LE 文本。
-
Class 扩展和厂商扩展 都可以引入更多字符串字段。
-
实战中建议最少提供:
- iManufacturer
- iProduct
- iSerialNumber
- 再根据类规范/自定义需求扩展。
👉 建议:如果你在做 USB Gadget/固件开发,可以先画一张 描述符树(Device → Config → Interface → Endpoint → Class Specific),把所有可能用到的 iXXX
标出来,并对应到 String Table,这样设计清晰,不容易遗漏。