文章目录
前段时间想模仿 BLEUnlock 搞个使用指纹给 macOS 解锁的应用,让 AI Vibe Coding 了很多代码,特别是 USB HID 通信以及 CTAP 协议处理部分。
这中间在调试协议时,AI 花了相当多的时间来反复调整 USB HID 通信时的 Payload 大小,AI 最终的结论是:macOS IOKIT 在发送数据到 USB 设备时有 Bug,会缺少 1 个字节,所以通过宏定义的方式,将包大小减少 1 个字节来绕过这个 Bug 😂。
当然我是不相信这个结论的,毕竟 macOS 上通过 USB HID 通信的设备那么多,不可能有这么明显的 Bug,周末花了点时间来看看到底是咋回事。
问题表现
在整个通信协议相关代码写完,并且主机和设备通信测试成功之后,在设备端会提示 USB HID 在收到消息时,Payload 大小为 63 字节,预期应该是 64 字节,但是第 64 个字节是 0x00,因此提示说这是一个 macOS Bug。

AI 的解决方案
来回增加了很多详细日志,输出包的具体内容之后,最终 AI 决定通过宏定义 Payload 为实际接收到数据的大小来解决这个问题。
正常情况下应该是:
- 包大小:64 字节
 - 首包 Payload 大小:64 - 4 字节 CID - 1 字节命令 - 2 字节 Payload 大小 = 57 字节
 - 后续包 Payload 大小: 64 - 4 字节 CID - 1 字节包序号 = 59 字节
 
但是因为中间调试下来总是少一个字节,因此 AI 认为是这一个 macOS IOKIT 的 Bug,通过宏将实际 Payload 定义正常情况下少 1 个字节的方式来解决这个 Bug。

发现问题
就这个问题问了半天 AI 也没搞明白为什么,这时想到了实现同样目的的一个开源项目 U2F Zero,我来看看它的的 USB HID Descriptor 和项目中的有什么不一样。
u2f-zero/firmware/src/descriptors.c

上面是 U2F Zero 项目中的 USB HID Descriptor,下面是我的项目中的,通过逐行对比发现,我这个额外加了个 Report ID 字段:

这个会不会是问题的根源?
先问问 AI
毕竟对 USB HID 协议也不熟悉,先问问 AI,这个 Report ID 是啥情况。

原来 Report ID 真的不是必需的!

在有 Report ID 字段时,Report ID 会存放在数据 Payload 中,怪不得之前测试时,传输数据总是会少一个字节。
尝试解决
先来看看主机端发送数据的代码是咋实现的:

可以看到,AI 编写的上位机程序中,在主机端发送数据时,直接无脑将 Report ID 字段添加在要发送的数据 Payload 前面,并且直接将 HID Packet Size + 1,完全无视了 USB HID Descriptor 中定义的数据包大小,怪不得实际测试时,设备端会永远少收到一个字节。
这里尝试将 Report ID 改为 0,就可以在设备端完整收到 64 个字节的数据了。

当然这里还没有处理 Report ID 的情况,会报额外的错误。
ESP32 的库咋实现的?
到这里问题已经基本上清楚并且可以解决了,不过还想探索一下,为什么 ESP32-S3 Arduino 框架中在处理消息时,似乎没有碰到任何问题呢?
找到 Arduino 库中 USB HID 相关的代码,发现它的操作还真是简单直接,先默认用 Report ID 0 去尝试调用 callback,不行再用 Payload 第 1 个字节作为 Report ID 去调用 callback 🤯。
USBHID.cpp


小结
只能说,可能受制于上下文长度的限制,AI 在某些时候还是会有幻觉,还会钻死胡同。如果真的不了解相关知识,可能真就被骗过去了,开发者还是在实际参与一下项目的开发 😃。

0 条评论。