为什么我在 QEMU 上的 GET_DESCRIPTOR USB 请求之后在端点描述符之前获得 2 个接口描述符?

问题描述

我正在编写一个使用 UEFI 启动的小型 x86-64 爱好操作系统。我目前正在为 Intel 的 xHC 编写驱动程序。我现在可以寻址 USB 设备并为每个设备的端点 0 分配一个传输环。然后我使用 GET_DESCRIPTOR 请求来获取每个设备的配置描述符。我要求 QEMU 模拟 USB 键盘和 USB 鼠标。因此,我得到了 2 个不同的描述符,如下所示:

user@user-System-Product-Name:~$ hexdump -C result.bin
00000000  09 02 22 00 01 01 06 a0  32 09 04 00 00 01 03 01  |..".....2.......|
00000010  02 00 09 21 01 00 00 01  22 34 00 07 05 81 03 04  |...!...."4......|
00000020  00 07 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00001000  09 02 22 00 01 01 08 a0  32 09 04 00 00 01 03 01  |..".....2.......|
00001010  01 00 09 21 11 01 00 01  22 3f 00 07 05 81 03 08  |...!...."?......|
00001020  00 07 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00001030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00002000
@H_502_5@

基本上,我要求 GDB 输出 RAM 的内容,我将描述符放在文件 result.bin 中。然后我在控制台中十六进制转储 result.bin 的内容。这里可以先看到USB鼠标的配置。然后,1页后,USB键盘的配置。

鼠标的配置描述符是09 02 22 00 01 01 06 a0 32。紧随其后的是 2 个接口描述符:09 04 00 00 01 03 01 02 0009 21 01 00 00 01 22 34 00。后面跟着一个端点描述符:07 05 81 03 08 00 07

在鼠标和键盘的第一个接口描述符中,表示有一个端点描述符(由描述符的 bNumEndpoints 字段表示,该字段是从 0 开始索引的字节数 4)。我希望以下描述符是端点描述符。相反,我得到了第二个接口描述符(由它的长度为 9 个字节而不是 7 个字节以及不同字段的值来表示)。

https://wiki.osdev.org/Universal_Serial_Bus所述:

每个CONfigURATION描述符至少有一个INTERFACE描述符,每个INTERFACE描述符最多可以有15个ENDPOINT描述符。当主机请求某个 CONfigURATION 描述符时,设备返回 CONfigURATION 描述符,紧接着是第一个 INTERFACE 描述符,紧接着是接口定义的端点的所有 ENDPOINT 描述符(可能没有)。如果存在,则紧跟其后是下一个接口描述符,然后是其端点描述符(如果适用)。这种模式一直持续到特定配置范围内的所有信息都传输完毕。

在我的例子中,为什么我会得到 2 个接口描述符,然后是端点描述符?这是一个 QEMU 错误还是我应该期待的?

解决方法

您没有准确描述我在您的 shell 输出中看到的二进制数据。

转储以类型 2 的 9 字节描述符开始,因此这是您的设备描述符:

09 02 22 00 01 01 06 a0 32

然后有一个类型为 4 的 9 字节描述符,因此它是一个接口,并且它的 bNumEndpoints 设置为 1:

09 04 00 00 01 03 01 02 00

然后还有另一个 0x21 类型的 9 字节描述符。我脑子里没认出那个代码,但它可能是标准的:

09 21 01 00 00 01 22 34 00

然后我们有一个类型为 5 的 7 字节描述符,所以这是一个端点描述符:

07 05 81 03 04 00 07