El descriptor de gamepad HID compuesto funciona en Windows pero no en Linux

4

Estoy construyendo un adaptador USB para un controlador de juego antiguo. Hasta ahora todo está funcionando bien. Mi descriptor de HID se ve así:

0x05, 0x01,  /* USAGE_PAGE (Generic Desktop)       */
0x09, 0x05,  /* USAGE (Game Pad)                   */
0xa1, 0x01,  /* COLLECTION (Application)           */
0xa1, 0x03,  /*   COLLECTION (Report)              */
0x85, 0x01,  /*     REPORT_ID (1)                  */
0x05, 0x09,  /*     USAGE_PAGE (Button)            */
0x19, 0x01,  /*     USAGE_MINIMUM (Button 1)       */
0x29, 0x0e,  /*     USAGE_MAXIMUM (Button 14)      */
0x15, 0x00,  /*     LOGICAL_MINIMUM (0)            */
0x25, 0x01,  /*     LOGICAL_MAXIMUM (1)            */
0x95, 0x0e,  /*     REPORT_COUNT (14)              */
0x75, 0x01,  /*     REPORT_SIZE (1)                */
0x81, 0x02,  /*     INPUT (Data,Var,Abs)           */
0x95, 0x01,  /*     REPORT_COUNT (1)               */
0x75, 0x02,  /*     REPORT_SIZE (2)                */
0x81, 0x03,  /*     INPUT (Cnst)                   */
0xa1, 0x00,  /*     COLLECTION (Physical)          */
0x05, 0x01,  /*       USAGE_PAGE (Generic Desktop) */
0x09, 0x30,  /*       USAGE (X)                    */
0x09, 0x31,  /*       USAGE (Y)                    */
0x15, 0x00,  /*       LOGICAL_MINIMUM (0)          */
0x25, 0x64,  /*       LOGICAL_MAXIMUM (100)        */
0x75, 0x08,  /*       REPORT_SIZE (8)              */
0x95, 0x02,  /*       REPORT_COUNT (2)             */
0x81, 0x02,  /*       INPUT (Data,Var,Abs)         */
0xc0,        /*     END_COLLECTION                 */
0xc0,        /*   END_COLLECTION                   */
0xc0         /* END_COLLECTION                     */

Ahora quiero agregar soporte para hasta 4 de estos controladores. Si entiendo el HID correctamente, una forma de hacerlo es repetir el descriptor 4 veces, cada vez con un ID de informe diferente. (Sé que probablemente podría tener varias interfaces USB con la clase HID, pero preferiría no hacerlo de esa manera; mi código USB se volvería mucho más complicado).

Cuando intenté esto, Linux se negó a reconocer el dispositivo como un gamepad. El HID el controlador ( hid-generic ) está cargado y el descriptor parece analizarse correctamente, pero no hay ningún archivo de dispositivo en /dev/input/ .

EDIT:

Probé mi código en Windows 7 y parece que este problema es específico de Linux. Así que estoy reformulando mi pregunta original:

¿Cómo debo modificar mi descriptor de HID para que funcione tanto en Windows como en Linux?

Al conectar el dispositivo, dmesg informa de esto:

usb 3-6: new low-speed USB device number 8 using xhci_hcd
usb 3-6: ep 0x81 - rounding interval to 64 microframes, ep desc says 80 microframes
input: XYZ Adapter as /devices/pci0000:00/0000:00:14.0/usb3/3-6/3-6:1.0/0003:16C0:05DC.0009/input/input20
hid-generic 0003:16C0:05DC.0009: input,hidraw4: USB HID v1.01 Gamepad [XYZ Adapter] on usb-0000:00:14.0-6/input0

Esto es idéntico a lo que dice al conectar la versión de 1 controlador que funciona. El dispositivo aparece en lsusb , con los ID / descriptores correctos.

    
pregunta puyawsiht

2 respuestas

5

Después de algunas horas de hurgando en las debugfs y las fuentes del kernel, lo descubrí.

Como resultó que el descriptor estaba bien, el problema era que udev (por cualquier razón) decidió crear el archivo del dispositivo con acceso solo de raíz. Después de solucionar esto, mi dispositivo ahora aparece como un gamepad de 56 botones con 8 ejes, que no es exactamente lo que quería, pero aún lo suficientemente cerca.

    
respondido por el puyawsiht
2

Para que el dispositivo se muestre como dos dispositivos de entrada separados en linux, el vendor_id y device_id del dispositivo deben configurarse con el HID_QUIRK_MULTI_INPUT quirk en el controlador USB HID en Linux. Consulte hid-quirks.c en la fuente del kernel de Linux para ver ejemplos: Actualmente hay 35 dispositivos configurados con una línea como:

{ HID_USB_DEVICE(USB_VENDOR_ID_MOJO, USB_DEVICE_ID_RETRO_ADAPTER), HID_QUIRK_MULTI_INPUT },

Nota: USB_VENDOR_ID_MOJO y USB_DEVICE_ID_RETRO_ADAPTER se definen en hid-ids.h en la fuente del kernel de Linux. También deberá agregar las ID de sus proveedores y dispositivos.

Después de realizar estos cambios, deberías poder volver a compilar tu kernel o solo el controlador USB-hid si es un módulo, y obtener múltiples dispositivos de entrada.

    
respondido por el stonecrusher

Lea otras preguntas en las etiquetas