USB-клавиатура – как получить нажатую клавишу?

Вопрос или проблема

У меня возникла проблема с клавиатурой, которую я купил в Китае, это клавиатура, предназначенная для osu! Однако производитель предоставляет драйверы только для Windows. Несмотря на нажатие клавиши, мне возвращается буква c.

Я пробовал многие методы, такие как прослушивание необработанного ввода с клавиатуры, но он всегда возвращает мне 01 00 06 ... (когда клавиша нажата) или 01 00 00 ... (когда клавиша не нажата). Я не могу получить, какая клавиша нажата в момент прослушивания.

Я также пробовал evtest, но когда я нажимаю, ничего не происходит, хотя evdev возвращает мне, что присутствуют три клавиши:

Input driver version is 1.0.1
Input device ID: bus 0x3 vendor 0x1189 product 0x8890 version 0x110
Input device name: "HID 1189:8890"
Supported events:
  Event type 0 (EV_SYN)
  Event type 1 (EV_KEY)
    Event code 272 (BTN_LEFT)
    Event code 273 (BTN_RIGHT)
    Event code 274 (BTN_MIDDLE)
  Event type 2 (EV_REL)
    Event code 0 (REL_X)
    Event code 1 (REL_Y)
    Event code 8 (REL_WHEEL)
    Event code 11 (REL_WHEEL_HI_RES)
  Event type 4 (EV_MSC)
    Event code 4 (MSC_SCAN)

Я также пробовал использовать hidapi, но когда я пытаюсь проверить, нажата ли клавиша (с помощью if (event.type == EV_KEY), это ничего не возвращает.

Также я пробовал получать необработанный ввод с помощью WireShark, и он возвращает мне некоторые разные байты при нажатии клавиши (поэтому я знаю, что клавиши распознаются как разные).

Что же я могу сделать? Мне действительно нужно запрограммировать эту клавиатуру, но большинство инструментов HID разочаровывают меня и всегда возвращают необработанный ввод без информации о том, какая клавиша нажата. Я пытаюсь написать драйвер для Linux для этой клавиатуры, но не знаю, с чего начать.

Вот вывод usbhid-dump:

001:008:003:DESCRIPTOR         1736873035.175572
 05 01 09 02 A1 01 09 01 A1 00 05 09 19 01 29 03
 15 00 25 01 75 01 95 03 81 02 75 05 95 01 81 01
 05 01 09 30 09 31 09 38 15 81 25 7F 75 08 95 03
 81 06 C0 C0

001:008:002:DESCRIPTOR         1736873035.176839
 05 01 09 06 A1 01 85 01 05 07 19 E0 29 E7 15 00
 25 01 75 01 95 08 81 02 95 01 75 08 81 03 95 08
 75 01 05 08 19 01 29 05 91 02 95 09 75 08 15 00
 25 FF 05 07 19 00 29 FF 81 00 C0 05 0C 09 01 A1
 01 85 02 95 01 75 10 16 00 00 26 FF 02 1A 00 00
 2A FF 02 81 00 C0

001:008:000:DESCRIPTOR         1736873035.177888
 05 01 09 06 A1 01 85 01 05 07 19 E0 29 E7 15 00
 25 01 75 01 95 08 81 02 95 01 75 08 81 01 95 03
 75 01 05 08 19 01 29 03 91 02 95 05 75 01 91 01
 95 06 75 08 26 FF 00 05 07 19 00 29 91 81 00 C0

Я выяснил, что в клавиатуре есть четыре прерывания (0x02, которое возвращает мне случайные байты, 0x81, которое сообщает, нажата ли клавиша или нет, но без информации о том, какая клавиша нажата, 0x82 и 0x83)

Вот вывод lsusb:


Bus 001 Device 005: ID 1189:8890 Acer Communications & Multimedia 
Negotiated speed: Full Speed (12Mbps)
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               1.10
  bDeviceClass            0 [unknown]
  bDeviceSubClass         0 [unknown]
  bDeviceProtocol         0 
  bMaxPacketSize0         8
  idVendor           0x1189 Acer Communications & Multimedia
  idProduct          0x8890 
  bcdDevice            0.00
  iManufacturer           0 
  iProduct                0 
  iSerial                 0 
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength       0x006d
    bNumInterfaces          4
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0xa0
      (Bus Powered)
      Remote Wakeup
    MaxPower              100mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      1 Boot Interface Subclass
      bInterfaceProtocol      1 Keyboard
      iInterface              0 
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.11
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 (null)
          wDescriptorLength      64
          Report Descriptors: 
            ** UNAVAILABLE **
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval              10
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      0 [unknown]
      bInterfaceProtocol      0 
      iInterface              0 
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.00
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 (null)
          wDescriptorLength      36
          Report Descriptor: (length is 36)
            Item(Global): Usage Page, data= [ 0x00 0xff ] 65280
                            (null)
            Item(Local ): (null), data= [ 0x01 ] 1
                            (null)
            Item(Main  ): (null), data= [ 0x01 ] 1
                            Application
            Item(Global): (null), data= [ 0x03 ] 3
            Item(Local ): (null), data= [ 0x02 ] 2
                            (null)
            Item(Global): (null), data= [ 0x00 ] 0
            Item(Global): (null), data= [ 0x00 0xff ] 65280
            Item(Global): (null), data= [ 0x08 ] 8
            Item(Global): (null), data= [ 0x40 ] 64
            Item(Main  ): (null), data= [ 0x06 ] 6
                            Data Variable Relative No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Local ): (null), data= [ 0x02 ] 2
                            (null)
            Item(Global): (null), data= [ 0x00 ] 0
            Item(Global): (null), data= [ 0x00 0xff ] 65280
            Item(Global): (null), data= [ 0x08 ] 8
            Item(Global): (null), data= [ 0x40 ] 64
            Item(Main  ): (null), data= [ 0x06 ] 6
                            Data Variable Relative No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Main  ): (null), data=none
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x02  EP 2 OUT
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval              10
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        2
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      0 [unknown]
      bInterfaceProtocol      0 
      iInterface              0 
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.00
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 (null)
          wDescriptorLength      86
          Report Descriptors: 
            ** UNAVAILABLE **
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x83  EP 3 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0004  1x 4 bytes
        bInterval              10
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        3
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      1 Boot Interface Subclass
      bInterfaceProtocol      2 Mouse
      iInterface              0 
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.10
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 (null)
          wDescriptorLength      52
          Report Descriptors: 
            ** UNAVAILABLE **
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0004  1x 4 bytes
        bInterval              10
Device Status:     0x0000
  (Bus Powered)

И вот выводы, которые WireShark дает мне для выбранных клавиш:
Клавиша 1: 00 01 03 00 00 00 09 21 00 01 00 01 22 56 00 07 05 83 03 04 00 0a 09 04 03 00 01 03 01 02 00 09 21 10 01 00 01 22 34 00 07 05 82 03 04 00 0a 0e 03 6b 00 65 00 79 00 35 00 35 00 32 00 04 03 09 04 0e 03 77 00 63 00 68 00 2e 00 63 00 6e 00 0c 03 43 00 48 00 35 00 35 00 39 00 90 01 32 e0 ff 75 f0 0e a4 24 2d f5 82 e4 34 01 f5 83 e0 64 03 70 5c 90 01 36 e0 70 56 ef 75 f0 0e a4 24 39

Клавиша 2: 90 01 32 f0 22 90 01 37 e0 ff a3 e0 fe c3 9f 40 03 02 1d 1a ed 64 01 60 03 02 1c f8 ee 14 60 32 14 60 41 14 60 50 14 60 5f 24 04 70 75 90 01 35 e0 ff 75 f0 0e a4 24 3e f5 82 e4 34 01 f5 83 e0 90 01 d0 f0 ef 75 f0 0e a4 24 3f f5 82 e4 34 01 80 46 90 01 35 e0 ff 75 f0 0e a4 24 41 f5 82 e4 34 01 80 34 90 01 35 e0 ff 75 f0 0e a4 24 43 f5 82 e4 34 01 80 22 90 01 35 e0 ff 75 f0 0e a4

Клавиша 3: e4 f0 90 01 47 75 f0 0e ed 12 0f ad ec 75 f0 0e a4 25 83 f5 83 e4 f0 0d bd 00 01 0c ed 64 09 4c 60 03 02 1d 29 22 48 01 c4 00 00 00 00 00 00 00 00 41 01 31 00 60 7e 01 3a 01 01 01 00 00 06 00 00 00 00 00 00 00 00 02 01 01 00 00 06 00 00 00 00 00 00 00 00 03 01 01 00 00 06 00 00 00 00 00 00 00 00 04 01 01 00 00 06 00 00 00 00 00 00 00 00 05 01 01 00 00 06 00 00 00 00 00 00 00 00

.

Ответ или решение

Чтобы решить проблему с клавиатурой, которую вы приобрели, и которая предназначена для игры osu!, но не имеет корректных драйверов под Linux, нужно глубже изучить взаимодействие с HID-устройством и рассмотреть возможность написания собственного драйвера. Ваши попытки, включая использование evtest, hidapi и анализа трафика через WireShark, дают определенные подсказки, но до конца не решают проблему.

Теория

Клавиатуры и другие периферийные устройства используют протоколы, основанные на Human Interface Device (HID), для взаимодействия с компьютером. Сообщения HID содержат отчеты с информацией о действиях пользователя, таких как нажатие клавиш. В частности, каждый отчет может содержать информацию о том, какая клавиша была нажата, но формат данных зависит от устройства.

В вашем случае, несмотря на детектирование трех клавиш (EV_KEY 272, 273 и 274), данные не соответствуют привычному формату компьютерных клавиатур. Вероятно, это связано с нестандартной реализацией протокола производителем.

Пример

Исходя из информации оdescriptor-ах, устройство предоставляет несколько интерфейсов, и один из них, вероятно, использует нестандартный формат отчетов, так как данные, захваченные в WireShark, показывают различия в байтах при нажатии различных клавиш. Заметьте, что общий формат описания включает в себя Page (65280), что может указывать на стороние назначения ввода.

Применение

  1. Анализ захваченного трафика: Используйте WireShark, чтобы внимательнее рассмотреть данные, поступающие от каждого нажатия клавиши. Ищите паттерны. Например, если конкретный байт изменяется при нажатии определенной клавиши, то это может быть идентификатор этой клавиши.

  2. Углубленный анализ через hidapi: Хотя вы уже пробовали hidapi, возможно, стоит углубиться в документацию и поискать примеры работы с нестандартными HID-устройствами. Попробуйте использовать hid_read() для считывания полного отчета с устройства и посимвольного анализа полученных данных.

  3. Написание кастомного драйвера: Если предыдущие шаги не помогают, стоит рассмотреть написание драйвера. В Linux драйверы для HID-устройств пишутся на C. Вы можете начать с базового драйвера, который просто считывает и выводит в syslog данные с устройства. Со временем, добавив логику интерпретации данных, вы сможете преобразовывать их в понятные нажатия клавиш.

  4. Сообщество и библиотеки: Изучите, возможно, есть уже существующие проекты или фреймворки, которые могут работать с нестандартными HID-драйверами. Например, libusb может предоставить интерфейс для реализации низкоуровневого взаимодействия с устройством в случае, если стандартный драйвер не подходит.

Таким образом, для успешного решения проблемы с вашим устройством необходимо последовательно протестировать и проанализировать полученные данные, потенциально разрабатывая собственное решение на основе собранной информации. Обращение к сообществу экспертов может также предоставить ценные инсайты и готовые решения.

Оцените материал
Добавить комментарий

Капча загружается...