ZhctTrayBindingMachine0610:2010 的两款 HID RF Picc Reader两款读卡器的厂商、产品名和 VID/PID 相同,但 HID Report Descriptor 和 Android 可见的中断端点拓扑不同。终端 CPU 或 Android 系统的 32/64 位架构与 HID 报文长度无关。
| 项目 | 读卡器 A | 读卡器 B |
|---|---|---|
| VID/PID | 0610:2010 |
0610:2010 |
| 产品名 | HID RF Picc Reader |
HID RF Picc Reader |
| 序列号(仅用于实物记录) | 0001A0000001 |
0001A0000000 |
| 描述符关键项 | 75 08 95 20 |
75 08 95 40 |
| Input/Output Report | 32/32 字节 | 64/64 字节 |
| Interrupt IN 端点 | 1 个 | 1 个 |
| Interrupt OUT 端点 | 0 个 | 1 个 |
75 08 表示 Report Size 为 8 位,95 20 和 95 40 分别表示 Report Count 为 32 和 64。端点的 maxPacketSize=64 只是 USB 传输上限,不能单独用来判断实际 HID 报文长度。
最初设计拟通过 Android USB Host API 读取 HID Report Descriptor。目标 F700(Android 11)实测了三种读取时机和缓冲区策略:
三种标准 GET_DESCRIPTOR 请求均未返回 Report Descriptor。继续依赖该 API 会导致两款读卡器都无法连接,因此经确认改为使用 Android 能稳定枚举的中断端点拓扑。描述符解析试验代码已删除,避免保留不可达分支。
CONTROL_SET_REPORT 写入路径。连接时只统计选中 HID 接口的 Interrupt 端点:
| Interrupt IN 数量 | Interrupt OUT 数量 | 连接级 Profile |
|---|---|---|
| 1 | 0 | Input 32 / Output 32 |
| 1 | 1 | Input 64 / Output 64 |
| 其他 | 其他 | UNSUPPORTED_HID_REPORT,拒绝连接 |
这是一项基于两款实物验证结果的协议族映射,集中在 HidReportProfileSelector 中。它不读取序列号、不判断终端位数,也不以 VID/PID 区分报文长度。若未来出现第三种拓扑,必须先取得协议和真机证据再扩展映射。
HidReportProfile连接级不可变值对象,分别保存 Input 和 Output Report 字节数。当前仅接受 32 或 64 字节。连接建立后到断开前不可切换,防止消费过程中改变协议外层长度。
HidReportProfileSelector无 Android 依赖的纯 Java 组件,接收 Interrupt IN/OUT 数量并返回 profile。未知组合返回明确错误,不降级到默认长度。
AndroidUsbHidTransport连接顺序为:
发送继续使用已验证的 CONTROL_SET_REPORT。64 字节读卡器虽然暴露 Interrupt OUT 端点,但端点在本次设计中只作为稳定的规格特征,不改变写入路径。
HidFrameCodec 与 NewcapecProtocolUNSUPPORTED_HID_REPORT,不得伪装成 NO_CARD。TRANSACTION_OUTCOME_UNKNOWN 保护,禁止自动重复扣款。每次连接记录:
USB_ENDPOINT_TOPOLOGY。端点 maxPacketSize 与 report 长度分别记录,避免现场把两者混为一谈。
1 IN + 0 OUT 选择 32/32。1 IN + 1 OUT 选择 64/64。:app:testDebugUnitTest 与 :app:assembleDebug 通过。NO_CARD,但不得出现长度错误或通信超时。采用“Android USB 中断端点拓扑识别 + 不可变连接级 profile + 未知拓扑安全失败”的方案。同一套一卡通业务代码兼容已验证的 32 和 64 字节读卡器,不依赖终端位数或序列号,也不通过业务指令试探设备。