USB:可以在一个接口上定义多个不同的HID操纵杆吗?

USB:可以在一个接口上定义多个不同的HID操纵杆吗?,usb,protocols,hid,usb-descriptor,Usb,Protocols,Hid,Usb Descriptor,我正在构建一个适配器,通过USB将各种视频游戏控制器连接到PC。它的核心是使用Cortex-M4处理器的Teensy 3.1微控制器 M4能够处理原始USB数据包,从而模拟任何类型的USB设备。我已成功地将其编程为显示复合USB设备: 接口1,端点1:USB串行端口(用于调试)-状态接口 接口1,端点2:USB串行发送/接收接口 接口2,端点3:HID操纵杆 现在的问题是,我希望能够同时连接几种不同类型的游戏控制器(例如任天堂和超级任天堂)。总之,我的适配器有超过15个端口,这意味着我不能只

我正在构建一个适配器,通过USB将各种视频游戏控制器连接到PC。它的核心是使用Cortex-M4处理器的Teensy 3.1微控制器

M4能够处理原始USB数据包,从而模拟任何类型的USB设备。我已成功地将其编程为显示复合USB设备:

  • 接口1,端点1:USB串行端口(用于调试)-状态接口
  • 接口1,端点2:USB串行发送/接收接口
  • 接口2,端点3:HID操纵杆
现在的问题是,我希望能够同时连接几种不同类型的游戏控制器(例如任天堂和超级任天堂)。总之,我的适配器有超过15个端口,这意味着我不能只为每个端口分配一个端点,因为USB总共只允许16个端点

阅读HID报告描述符规范,我得到的印象是,可以在同一个接口上定义多个独立的设备。然而,尽管我尽了最大的努力,我似乎还是无法成功。应用程序(如
jstestgtk
)只能看到一个巨大的操纵杆

现在我正在使用此报告描述符:

static uint8_t joystick_report_desc[] = {
    0x05, 0x01,                     // Usage Page (Generic Desktop)
    0x09, 0x04,                     // Usage (Joystick)
    0xA1, 0x01,                     // Collection (Application)
        0x85, 0x01,                     // Report ID (1)
        0x15, 0x00,                     // Logical Minimum (0)
        0x25, 0x01,                     // Logical Maximum (1)
        0x75, 0x01,                     // Report Size (1)
        0x95, 0x08,                     // Report Count (8)
        0x05, 0x09,                     // Usage Page (Button)
        0x19, 0x01,                     // Usage Minimum (Button #1)
        0x29, 0x08,                     // Usage Maximum (Button #8)
        0x81, 0x02,                     // Input (variable,absolute)
    0xC0,                           // End Collection

    0x05, 0x01,                     // Usage Page (Generic Desktop)
    0x09, 0x04,                     // Usage (Joystick)
    0xA1, 0x01,                     // Collection (Application)
        0x85, 0x02,                     // Report ID (2)
        0x15, 0x00,                     // Logical Minimum (0)
        0x25, 0x01,                     // Logical Maximum (1)
        0x75, 0x01,                     // Report Size (1)
        0x95, 0x10,                     // Report Count (16)
        0x05, 0x09,                     // Usage Page (Button)
        0x19, 0x01,                     // Usage Minimum (Button #1)
        0x29, 0x10,                     // Usage Maximum (Button #16)
        0x81, 0x02,                     // Input (variable,absolute)
    0xC0,                           // End Collection
};
我曾希望它能提供一个有8个按钮的操纵杆和一个有16个按钮的操纵杆,但应用程序看到的是一个有24个按钮的操纵杆


实际上可以这样定义多个独立的操纵手柄吗?

我最近使用mbed实现了一个类似的项目,并且可以确认,可以仅使用您描述的报告描述符来定义多个操纵手柄

在Windows中,它应该可以正常工作。对于Linux,需要使用
HID\u QUIRK\u MULTI\u输入加载usbhid驱动程序

# rmmod usbhid && modprobe usbhid quirks=0xVID:0xPID:0x40

其中,
VID
是您的供应商id,
PID
是您的产品id。然后它应该在
/dev/input

中显示为多个操纵杆设备。目标是同时连接多个控制器进行多人游戏,还是让单个用户随意在控制器之间交换?似乎在单控制器的情况下,Teensy可以将控制器输入多路复用到单个16按钮控制器中。理想情况下,我希望同时连接多个控制器。在实践中,一次使用的可能不超过4个,但例如,您可能有一个播放器使用SNES控制器,另一个使用N64,您希望能够将它们全部插入,然后拿起一个并使用它。我可能会一次在两个控制器之间切换,但我更希望所有连接的控制器始终显示为操纵杆。这是一个很大的问题。我认为最简单的方法(老实说我不知道)是将几个控制器多路复用到一个“播放器”中,这样您就可以将四个(或更多个)“播放器”作为USB端点。然后,只要控制器上有活动,Teensy就会将输入报告排队。这可能是个好主意,尽管我担心这会使游戏/模拟器的配置复杂化。(特别是有些功能只允许为每个功能分配一个按钮,因此无法在不同的控制器之间切换。)我的另一个想法是模拟一个USB集线器,连接各种操纵杆设备,但这似乎要复杂得多。(此外,每个虚拟设备都会达到127个设备的限制,但这并不是什么大问题……)