一次UAC设备不识别问题追查
USB枚举流程
USB连接过程
这个过程包括Attached、Powered、Reset(进入Default状态)、Set Address(进入Address状态)。然后会进入config阶段,如下:
Config过程
请求device描述符
- bmRequestType:0x80表示从设备到主机,请求标准命令,接收者为设备
- bRequest:0x06表示读取描述符
- wValue: 表示要获取描述符的索类型。(高字节为描述符类型,低字节为描述符索引)
1 | 描述符的类型有: |
这里0x0100,表示设备描述符,索引为0
- wIndex:字段表示字符串描述符的语言ID, 其它描述符为0
- wLength:指定了描述符的字节数,这里为0x12(18)字节
device的设备描述符
- bLength:设备描述符的字节数大小,这里长度为0x12(18)字节
- bDescriptorType:描述符类型编号,0x01代表设备描述符
- bdcUSB:USB版本号,0x200表示USB version 2.0
- bDeviceClass:USB分配的设备类代码,0x01~0xfe为标准设备类,0xff为厂商自定义类型,0x00不是在设备描述符中定义的,如HID
- bDeviceSubClass:usb分配的子类代码,同上,值由USB规定和分配的,这里是0x00
- bDeviceProtocol:USB分配的设备协议代码,同上
- bMaxPacketSize0:端点0的最大包的大小,这里是0x40(64 bytes)
- idVendor:0x18d1,我们在configfs中配置的
- idProduct:0x4e26,我们在configfs中配置的
- bcdDevice:设备出厂编号 这里是0x0606
- iManufacturer:描述厂商字符串的索引,这里是1(字符串为amlogic)
- iProduct:描述产品字符串的索引(p2101)
- iSerialNumber:描述设备序列号字符串的索引 (ap2228096a10802321724)
- bNumConfiguration:可能的配置数量 (1)
请求config描述符
与请求设备描述符差别在于wValue,bDescriptorType=0x02表示配置描述符
获得的配置描述符
配置描述符在USB设备的枚举过程中,需要获取两次:第一次只获取配置描述符的基本长度9字节,获取后从wTotalLength字节中解析出配置描述符的总长度,然后再次获取全部的描述符。如下图所示,第一次获取描述符基本数据得到的respond是配置描述符有301字节,需要再获取一次301字节的请求,第二次数据量太大包含配置描述符的拓扑结构这里不列出来,只把第一次请求返回的结果列出来,如下图所示。
抓包数据和windows显示的描述符两者是一致的。
获取其他描述符
之后就是相同的流程继续获取各string描述符。
对于UAC的FU,会有获取CUR、MIN、MAX、RANGE、RES等流程以及设置CUR的流程。
其中获取CUR、MIN、MAX、RANGE、RES等是通过USB设备请求format获取的,其相关字段解释如下:
Format of Setup Data
问题现象
- 前提:我们的公版和客户的板子usb驱动和uac驱动完全一致
- 我们的公版UAC1+ADB+Feature Unit接PC和手机都可以识别
- 客户板子UAC1+ADB+Feature Unit设备接手机时UAC设备不识别,接PC的时候能够被识别
- 客户板子UAC1+Feature Unit接手机可以被识别
- 客户板子UAC1+Feature Unit(disabled int ep)+ADB接手机可以被识别
问题分析
通过以上现象发现UAC1不识别跟端点相关,但是统计发现端点数量是够用的,可以支持同时开启UAC1+Feature Unit+ADB。可以对比同时开启UAC1+Feature Unit+ADB公版和客户版的usb包。
端点号统计
只有低4bit位代表端点号 harman Board.(UAC先申请的EP)
- uac 端点号:
- FU:129->1
- OUT: 1
- IN: 130->2
- FFS 端点号:
- 2
- 131->3
手机下发的endpoint=130->2 匹配到FFS端点2上了
公版 Board:(FFS先申请的ep)
- uac 端点号:
- FU:130->2
- OUT: 2
- IN: 131->3
- FFS 端点号:
- 1
- 129->1
手机下发131->3,对应UAC IN端口
这是wIndex各bit组成,通过测试发现,客户的板子先初始化了UAC后初始化了ADB,我们公版先初始化了ADB后初始化了UAC 由于FFS驱动在匹配端点号的时候只匹配了低4bit,也就是只匹配了ep num,而忽略了dir,导致FFS匹配错端点号了,手机下发的wIndex是130实际对应的是UAC的IN端点,但是FFS驱动在匹配端点的函数中(ffs_func_req_match)忽略了dir bit,导致手机下发的UAC IN端点号130取低4bit=2跟FFS的端点2重复了。本来该UAC处理的请求被FFS驱动匹配端点号后由FFS驱动处理了。导致后续很多异常包。
解决办法
- 可以修改启动脚本,先初始化ADB后初始化UAC来绕过这个问题
- 修改FFS端点匹配机制,除了低4bit的ep num需要匹配外,dir也要匹配
- 修改EP num编号,IN和OUT使用不同的endpoint number,例如IN使用奇数,OUT使用偶数