USB HID 输入延迟与丢报告:键盘、手柄、扫描枪和自定义 HID 设备排查
USB HID 输入延迟、丢报告、按键重复、手柄延迟、条码扫描枪丢包——Interrupt 端点时序、轮询间隔、Report Descriptor 问题一套排查思路。
USB HID 问题经常以用户的语言被描述出来:键盘卡、按键丢、双击、条码枪扫不上、手柄延迟、脚踏不响应、自定义 HID 设备报告发了但应用从来没收到过。搜 "USB HID 输入延迟"、"HID 报告丢失"、"HID Interrupt 端点延迟"、"USB 键盘重复按键"、"手柄延迟 USB 抓包" 出来的都是同一个工程诉求:别只盯着应用层事件,去看 HID 报告流。
HID 设备一般走 Interrupt 端点。它不是桌面语义下的"硬件中断",而是说主机按固定间隔去 poll 这个端点。如果报告畸形、延迟、频率不对、太大、或者描述符写得不对,应用看到的就是延迟或丢输入。
Bus Scope 在这个场景下有用——HID 诊断要把描述符、端点、轮询、报告这几样证据凑齐。
HID Report Descriptor 很重要
HID Report Descriptor 决定了报告的含义。它描述了 usages、report sizes、report counts、logical ranges、report IDs、input/output/feature 报告。
如果描述符和设备实际发的字节对不上,症状会很奇怪:
- 应用看不到任何输入
- 部分按键工作,其他不行
- 轴跳变或饱和
- 键盘按键重复
- 应该有的 Report ID 没发
- Report 长度和描述符不一致
- 主机拒收或忽略报告
设备可能在发字节,但主机按描述符解错了。
Interrupt 端点的轮询间隔
HID Interrupt IN 端点带一个 polling interval。Low-Speed 和 Full-Speed 设备的轮询方式可能和 High-Speed 不同。如果轮询间隔比预期用途慢,输入延迟就被写进了设备配置里。
手柄或实时控制设备对 Report 间隔很敏感。条码枪偶尔报几帧可以接受,但帧格式必须可靠。
查端点描述符:
- 端点地址
- Interrupt 传输类型
- Max Packet Size
- Polling Interval
- 设备速率
不要只靠应用 UI 去猜延迟。
丢报告 ≠ 应用事件丢失
报告丢失可能发生在好几层:
- 设备固件没发
- USB 传输失败
- 主机轮询太慢。
- 报告发了但畸形
- 驱动解法不同
- 应用把它过滤了
- 焦点或操作系统输入路由丢了事件
总线层证据能回答前四项。如果总线上报告都正常,往上看驱动和应用处理;如果总线上报告就缺,回到固件、端点时序、电源状态去查。
重复按键和按键卡死
"按键按下"的报告发了,但"按键释放"丢了或畸形,就会出现重复按键。手柄按键卡死的原因也一样。
事件前后抓一段:
Report: key A down
Report: no keys down
如果释放报告根本没出现,嫌疑就在设备或 USB 通路。如果总线上释放报告已经在了,应用还认为按键是按下的,去查驱动 / 应用映射。
条码扫描枪丢包
很多条码扫描枪模拟键盘。一次扫描会产生一串快速的 HID 报告。如果报告速度超过应用处理能力,问题可能不在 USB。但如果 trace 显示报告丢失、Report ID 错、端点错误——嫌疑就是扫描枪或 Hub 通路。
有用的证据:
- 完整的扫描报告序列
- Report 间隔
- 释放报告是否缺失
- 端点错误
- 扫描过程中是否断连或挂起
排查清单
按这个流程:
- 从插入开始抓枚举
- 把 HID Report Descriptor 保存下来
- 识别 Interrupt IN 端点和 polling interval
- 抓一段已知的输入序列
- 对比实际 Report 长度和描述符声明
- 检查 Report ID
- 看有没有 down/up 配对缺失
- 查端点有没有出错
- 对比直连 vs 走 Hub
- 把总线证据和应用日志放在一起看
最终诊断
USB HID 输入延迟和丢报告,必须从 HID 描述符、Interrupt 端点、轮询间隔、实际报告字节这几样一起取证。UI 现象不能证明责任在设备、总线、驱动还是应用。
Bus Scope 让 HID 报告序列可见——键盘、手柄、扫描枪、自定义 HID 的问题都能从 USB 的事实出发调试。