|
|
把HID设备插上USB,到第一次成功发包,中间主机和设备其实握了好几次手。理解这个流程,排查“设备认不到”类问题会快很多。
一、枚举的完整时序
整个流程可以分成七步:
- 上电与复位:设备插入,Hub检测到D+/D-电平变化,通知主机
- 默认地址通信:主机先用地址0跟设备通信
- 读取设备描述符:GET_DESCRIPTOR(DEVICE),拿到VID/PID/最大包长
- 分配新地址:SET_ADDRESS,之后通信换用新地址
- 读取配置描述符:GET_DESCRIPTOR(CONFIG),里面包含接口、端点信息
- SET_CONFIGURATION:选定配置,端点正式生效
- HID类请求:GET_DESCRIPTOR(HID/REPORT)拿到描述符,SET_IDLE、SET_PROTOCOL按需设置
走完这七步,设备才进入“可操作”状态。整个过程在USB全速下大约几十毫秒,肉眼感觉就是“插上就能用”。
二、每个请求在干什么
主机发的标准请求就那么十几个,HID相关的记住四个:
- GET_DESCRIPTOR(HID):拿HID描述符,里面写着报告描述符有多长
- GET_DESCRIPTOR(REPORT):拿报告描述符,就是真正的报文格式合同
- SET_IDLE:设定空闲率,限制“无变化时重复上报”的频率
- SET_PROTOCOL:在引导协议(启动时的固定键盘格式)和报告协议间切换
SET_IDLE这个参数经常被忽略,但它直接影响轮询行为——设太大,状态变化上报慢;设太小,总线上一堆重复报文。
三、枚举失败的典型原因
设备认不到,按这个顺序查:
- 供电不足:电流不够,枚举到一半掉电,换个供电口试试
- 描述符错误:报告长度和实际对不上,主机校验失败
- 线材问题:USB2.0高速线内部断了一组,能供电不能传数据
- Hub级联太深:超过五级信号劣化
- 固件Bug:状态机漏了某个跳转
其中线材问题最隐蔽——很多“时好时坏”最后都是换根线解决的。
四、排障时怎么看
- Windows用USB Device Viewer看枚举过程和描述符原文
- Linux用`lsusb -v`直接dump全部描述符
- 抓包仪(硬件)能看到最真实的时序
建议每个做HID的人都装一个`lsusb -v`,遇到认不到的设备先dump一份描述符,九成问题当场现形。
枚举机制清楚了,“插上没反应”就不再是玄学。你们还遇到过什么奇葩的枚举问题?评论区聊聊。 |
|