USB 厂商自定义控制请求超时排查
USB 厂商自定义控制请求超时的排查方法,涵盖 bmRequestType、bRequest、wValue、wIndex、端点 0 固件处理、Bootloader 命令、设备状态。
厂商自定义 USB 控制请求在固件工具、校准上位机、工厂测试软件、Bootloader、调试模式、自定义设备里很常见。一旦失败,应用那边通常只看到 "control transfer timeout"、"vendor request failed"、"device not responding",或者 LIBUSB_ERROR_TIMEOUT。用户搜 "USB 厂商请求超时"、"bmRequestType 调试"、"控制传输端点 0 超时"、"厂商 USB 命令失败"——因为这个失败藏在一个操作系统解释不了的私有协议里。
Bus Scope 在这个场景下有用,因为厂商自定义控制请求同样有标准的 Setup Packet。即使命令含义是私有的,传输结构在总线上是可见的。
Setup Packet 的字段
一个 Control Request 包含:
bmRequestTypebRequestwValuewIndexwLength
对厂商请求来说,bmRequestType 标识厂商类型和方向。bRequest、wValue、wIndex 由设备固件自己定义。
方向或长度错了,设备就可能 STALL 或超时。
超时 vs STALL
STALL 意味着设备明确拒绝了请求。超时意味着主机在时间内没收到完成。
超时可能意味着:
- 固件处理命令时挂了
- 请求过程中设备复位了
- 方向不匹配
- 主机期望数据但设备没发
- 设备期望 OUT 数据但主机请求 IN
- 命令只在另一个状态下合法
- Flash 擦除或传感器操作耗时过长
Trace 应该能看出有没有数据阶段、设备之后是否消失。
Bootloader 和固件升级命令
厂商请求常常触发 Bootloader 进入、Flash 擦除、固件写入、Reset、状态轮询。这些命令本来就需要时间,但主机的超时必须和预期行为对得上。
如果请求总是在重连之前超时,设备可能确实复位成功了。如果超时之后再也没重新枚举,固件可能是卡死了。
排查清单
按这个流程:
- 在发厂商命令之前先抓包
- 解码 Setup Packet 字段
- 确认方向和期望的数据阶段匹配
- 检查
wLength - 看数据阶段字节
- 看 STALL、超时、Reset、断连
- 看设备是否以另一种模式重新枚举
- 对比已知正常的工具的命令序列
- 只有在证明命令确实需要更久之后,才加大超时
- 失败前后的厂商请求序列都保留
最终诊断
厂商自定义控制请求超时是私有协议的失败,但 USB 证据仍然可见。Setup Packet、方向、长度、时序、Reset 行为、端点 0 的响应能告诉你:到底责任在主机的请求形态,还是在设备固件状态。
Bus Scope 把一个私有固件命令的失败,变成可审查的 USB 证据。