I'm building an adaptor to connect various video game controllers to a PC via USB. The heart of it is the Teensy 3.1 microcontroller, which uses the Cortex-M4 processor.
The M4 is able to deal with raw USB packets and thus simulate any type of USB device. I've successfully programmed it to present a composite USB device:
- Interface 1, endpoint 1: USB serial port (for debugging) - status interface
- Interface 1, endpoint 2: USB serial TX/RX interface
- Interface 2, endpoint 3: HID joystick
The problem now is, I want to be able to connect several different types of game controller at once (e.g. Nintendo and Super Nintendo). In all my adaptor has more than 15 ports, which means I can't just assign one endpoint to each port, as USB allows only 16 endpoints total.
Reading the HID report descriptor spec, I get the impression that it's possible to define multiple independent devices on the same interface. However despite my best efforts, I can't seem to pull this off. Applications (such as jstest-gtk
) only see a single huge joystick.
Right now I'm using this report descriptor:
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
};
I had hoped that would present one joystick with 8 buttons and one with 16, but instead applications see a single joystick with 24 buttons.
Is it actually possible to define multiple independent joysticks this way?
I recently implemented a similar project with mbed, and can confirm that multiple joysticks can be defined using only the report descriptor as you described.
In Windows, it should just work. With Linux, the usbhid driver needs to be loaded using the
HID_QUIRK_MULTI_INPUT
quirk.Where
VID
is your vendor id, andPID
is your product id. It should then show up as multiple joystick devices in/dev/input
.