USB: можно ли определить несколько отдельных джойстиков HID на одном интерфейсе?

Я создаю адаптер для подключения различных контроллеров видеоигр к ПК через USB. Сердце его - микроконтроллер Teensy 3.1, в котором используется процессор Cortex-M4.

M4 может работать с необработанными USB-пакетами и, таким образом, имитировать любой тип USB-устройства. Я успешно запрограммировал его для представления составного USB-устройства:

  • Интерфейс 1, конечная точка 1: последовательный порт USB (для отладки) - интерфейс состояния
  • Интерфейс 1, конечная точка 2: последовательный интерфейс USB TX / RX
  • Интерфейс 2, конечная точка 3: джойстик HID

Теперь проблема в том, что я хочу иметь возможность одновременно подключать несколько разных типов игровых контроллеров (например, Nintendo и Super Nintendo). Всего у моего адаптера более 15 портов, что означает, что я не могу просто назначить одну конечную точку для каждого порта, поскольку USB позволяет всего 16 конечных точек.

Читая спецификацию дескриптора отчета HID, у меня складывается впечатление, что можно определить несколько независимых устройств на одном интерфейсе. Однако, несмотря на все мои усилия, я не могу этого добиться. Приложения (например, jstest-gtk) видят только один огромный джойстик.

Прямо сейчас я использую этот дескриптор отчета:

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 кнопками.

Можно ли таким образом определить несколько независимых джойстиков?


person Rena    schedule 30.03.2015    source источник
comment
Является ли цель одновременным подключением нескольких контроллеров для многопользовательских игр или просто позволить одному пользователю переключаться между контроллерами по своему желанию? Похоже, что в случае с одним контроллером Teensy может мультиплексировать входы контроллера в один 16-кнопочный контроллер.   -  person Austin Mullins    schedule 31.03.2015
comment
В идеале я хотел бы подключить несколько контроллеров одновременно. На практике, вероятно, будет использоваться не более 4 одновременно, но, например, у вас может быть один игрок, использующий контроллер SNES, а другой - N64, и вы хотите, чтобы они все оставались подключенными, просто возьмите один и используйте его. Я мог бы прибегнуть к переключению между парой за раз, но я бы предпочел, чтобы все подключенные контроллеры всегда были представлены в виде джойстиков.   -  person Rena    schedule 31.03.2015
comment
Это большая проблема. Я думаю, что проще всего (честно говоря, я не знаю) было бы мультиплексировать несколько контроллеров в один проигрыватель, чтобы вы представили четыре (или более) проигрывателя как конечные точки USB. Затем Teensy будет ставить в очередь входные отчеты всякий раз, когда на контроллере есть активность.   -  person Austin Mullins    schedule 31.03.2015
comment
Это может быть хорошей идеей, хотя я боюсь, что это усложнит настройку игр / эмуляторов. (В частности, некоторые позволяют назначать только одну кнопку для каждой функции, поэтому вы не сможете переключаться между разными контроллерами.) Другая идея, которая у меня была, заключалась в моделировании концентратора USB с различными подключенными джойстиками, но это кажется намного более сложным. сложный. (Кроме того, каждое виртуальное устройство будет вносить свой вклад в ограничение в 127 устройств, но это не имеет большого значения ...)   -  person Rena    schedule 31.03.2015


Ответы (1)


Недавно я реализовал аналогичный проект с mbed и могу подтвердить, что несколько джойстиков можно определить, используя только описанный вами дескриптор отчета.

В Windows это должно просто работать. В Linux драйвер usbhid необходимо загружать с помощью причуды HID_QUIRK_MULTI_INPUT.

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

Где VID - идентификатор вашего поставщика, а PID - идентификатор вашего продукта. Затем он должен отображаться как несколько устройств с джойстиком в /dev/input.

person B.A. Parker    schedule 01.04.2015