摘要:USB 描述符复制了例程,只是改了个 PID,电脑就提示“设备描述符请求失败”?不是 USB 栈坏了,而是描述符长度(bLength)或总长度(wTotalLength)算错了。本文拆解 USB 描述符的“字节级”潜规则。


一、问题描述(现象)

**用 CubeMX 生成的 HID 例程,枚举一切正常;

只是加了一个自定义 Usage Page,设备管理器就开始报黄叹号;

Bus Hound 抓包显示 GET_DESCRIPTOR 返回的数据长度不对。**

很多工程师的排查方向是:

  1. 是不是 PID/VID 冲突了?

  2. 描述符数组是不是没对齐?

  3. 换个 USB 端口试试?


二、原理分析

1. 物理模型

USB 主机在枚举时,会先问设备:“你多长?”

Host: GET_DESCRIPTOR (wLength = 64)
Device: [Descriptor Data...]

2. 核心参数

  • bLength:当前这个描述符结构体的实际字节数

  • wTotalLength整个配置描述符集合(Configuration + Interface + Endpoint)的总字节数。

3. 反直觉真相

USB 主机根本不相信你给的长度,它会自己算。

  • 如果你在代码中修改了某个描述符(比如多加了一个 Endpoint)。

  • 但忘了更新 wTotalLength

  • 结果:主机算出的长度和实际发送的不一致 → 枚举失败。


三、工程级解决方案

方案 1:手算长度(最稳,推荐)

Configuration Descriptor​ 为例:

// 标准配置描述符长度 = 9 字节
// 接口描述符 = 9 字节
// 端点描述符 = 7 字节
// 如果有两个端点:
wTotalLength = 9 + 9 + 7 + 7 = 32;

切记:wTotalLength小端格式(低字节在前)。

方案 2:利用编译器自动算(进阶)

如果是 C 语言,可以用结构体技巧。

typedef struct {
    USB_ConfigDescTypeDef config;
    USB_InterfaceDescTypeDef interface;
    USB_EndpointDescTypeDef ep_in;
    USB_EndpointDescTypeDef ep_out;
} __attribute__((packed)) USBD_CDC_DescTypedef;

#define USBD_CDC_DESC_SIZE sizeof(USBD_CDC_DescTypedef)

方案 3:用工具验证

不要只靠眼睛看。

  • USBView (Windows):直接展开描述符树,看每一项的长度是否正确。

  • Bus Hound:查看 GET_DESCRIPTOR 返回的原始字节流。


四、选型避坑建议

  1. bLength 必须精确

    • Device Descriptor = 18 bytes

    • Configuration Descriptor = 9 bytes

    • Interface Descriptor = 9 bytes

    • Endpoint Descriptor = 7 bytes

  2. 字符串描述符

    • bLength包含字符串长度 × 2 + 2(Unicode)。

  3. 不要混用:HID 描述符有自己的长度计算方法,不能直接套用 CDC/MSC。


五、总结 Checklist

  • [ ] 是否检查了每个描述符的 bLength是否正确?

  • [ ] 修改描述符后,是否更新了 wTotalLength

  • [ ] wTotalLength是否按小端格式填写?

  • [ ] 是否用 USBView/Bus Hound 验证过原始数据?


六、写在最后(关注我,少走弯路)

我是 gqqsherry,一个拒绝调包、专注底层逻辑的嵌入式工程师。

USB 描述符是“写一次,调三天”的典型代表,一个字节的错误就能让整个设备变砖。

关注我的专栏《嵌入式底层避坑指南》,我会持续更新 USB、CAN、UART 等外设的真实调试案例量产级解决方案

👉 下一篇预告:《USB CDC 虚拟串口识别不了?别只怪驱动,看看 VID/PID 与 INF》


References

  • USB 2.0 Specification – Chapter 9 (Device Framework)

  • Microsoft Docs – USB Descriptor Overview


如果你在写 USB 描述符时遇到过“怎么改都报错”的情况,欢迎在评论区晒出你的描述符代码片段。

原创文章,转载请注明出处。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐