USB 组合设备调试:接口编号、IAD、端点与驱动绑定

组合设备中一个接口工作、另一个失败、或者主机绑错驱动时怎么排查,从描述符结构、接口编号、端点分配、IAD 行为几个维度定位。

USB 组合设备, IAD 调试, 接口绑定, 驱动绑定, CDC 接口, HID 接口, 端点冲突

USB 组合设备既方便又危险。一台设备可以同时暴露 HID 控制、CDC 串口、大容量存储、厂商自定义端点、音频、视频、诊断接口。一切描述符都对的时候,主机会装上对应的驱动,每个功能都正常工作。但只要一个描述符字段错了,整台设备就可能变得像不可靠。

搜 "USB 组合设备识别不出来"、"CDC 接口没出来"、"HID 正常但串口不正常"、"USB 接口绑错驱动" 这一类关键词,根因基本都指向描述符结构、接口编号、端点分配,或者 IAD(Interface Association Descriptor)的行为。

组合设备需要一份自洽的 Configuration

Configuration Descriptor 是顶层地图。它必须描述总长度、接口数量、电源属性,以及所有嵌套的接口和端点描述符。wTotalLength 错了,主机可能读不全所有功能。接口数错了,主机可能跳过后面的接口。端点地址冲突,传输就会歧义甚至非法。

重点查:

  • Configuration 的 wTotalLength
  • Interface 数量
  • Interface 编号
  • Alternate Settings
  • Endpoint 地址
  • Endpoint 方向
  • Class / Subclass / Protocol
  • 描述符的排列顺序

抓包应该能呈现:主机有没有把完整的 Configuration 要走,设备回了哪些字节。

IAD 帮主机把相关接口归到一起

IAD(Interface Association Descriptor)常用来把属于同一功能的多个接口归为一组——例如 CDC Communication Interface 加 CDC Data Interface。如果分组错了,主机可能装错驱动,或者只暴露功能的一部分。

IAD 要查的证据:

  • First Interface
  • Interface Count
  • Function Class / Subclass / Protocol
  • 是不是放在了被分组的接口之前
  • 是不是和实际接口描述符对得上

如果 CDC 串口出不来但 HID 正常,那 HID 接口大概率没问题,CDC 那边的分组出错的可能性更大。

端点地址冲突很容易被忽略

端点地址是包含方向的。0x810x01 是两个方向,但同一个 Configuration 内不能有两个方向相同的 IN 端点占用同一个地址。固件团队在接口之间复制端点描述符的时候,经常忘了改地址。

症状包括:

  • 一个接口工作,另一个接口沉默
  • 主机把传输发到了意料之外的端点
  • 类驱动装上了但应用拿不到数据
  • 配置完成后端点 STALL 或超时
  • 同一时刻只有一个功能能用

抓包应该把端点描述符和后面的传输流量并排放。

驱动绑定本身也是证据

主机的驱动选择完全依据描述符。设备绑错驱动,往往能从描述符证据里找到原因。Class、Subclass、Protocol、Interface Association、Compatible ID 以及 OS 特定描述符都会影响绑定。

不要只从设备管理器或应用日志去诊断驱动绑定。要把主机的类特定请求和描述符树对照起来看——如果期望的类请求一条都没来,主机大概率就没装上预期的驱动。

Bus Scope 在这个场景里做什么

Bus Scope 应该帮固件团队在两个层面同时审视组合设备:

  • 描述符地图
  • 驱动绑定之后的传输证据

一份合格的 .bscope 组合设备调试会话,应该展示:

  • 全部接口
  • IAD 分组
  • 端点分配
  • 每个接口的类特定请求
  • 原始描述符字节
  • 配置之后的传输状态

这样支持对话就能落到具体细节。不再是"Windows 不喜欢我们的组合设备",而可以是"Interface 2 一直没收到 CDC 类请求,因为 IAD 分组描述符和实际声明的接口布局对不上"。

这就是固件团队需要的证据颗粒度。