0
\$\begingroup\$

I'm working on a device emulating a USB HID gamepad with 32 buttons. This is the basic Report Descriptor I created

Usage Page(Generic Desktop)
Usage(Gamepad)
Collection(Application)
    Collection(Physical)
        Usage Page(Button)
        Usage Minimum(1)
        Usage Maximum(32)
        Logical Minimum(0)
        Logical Maximum(1)
        Report Count(32)
        Report Size(1)
        Input(Data, Variable, Absolute)
    End Collection
End Collection
    

This descriptor generally seems to work fine — a Linux USB host sees a HID gamepad, and evtest is detecting button press/release events as I generate them.

However, I'm a bit confused by some of the output from evtest:

user@system:~$ sudo evtest /dev/input/event3
Input driver version is 1.0.1
Input device ID:   ########################
Input device name: ########################
Supported events:
  Event type 0 (EV_SYN)
  Event type 1 (EV_KEY)
    Event code 304 (BTN_SOUTH)
    Event code 305 (BTN_EAST)
    Event Code 306 (BTN_C)
    Event Code 307 (BTN_NORTH)
    # Remaining 28 keys omitted

evtest believes that my first button corresponds to "Event code 304", but I'm not really sure where this mapping is coming from.

I've skimmed through the HID specification and Usage Tables, and I can't see how a HID gamepad can define a mapping between its physical buttons and key codes understood by the input HID driver in an OS. Is it possible to specify this in the report descriptor somehow?

\$\endgroup\$
1
  • \$\begingroup\$ # Remaining 28 keys omitted ... please post the full output \$\endgroup\$
    – jsotola
    Jun 23, 2023 at 1:31

1 Answer 1

1
\$\begingroup\$

hidinput_configure_usage is the function that maps the HID descriptor(s) to the gamepad button codes used in the Linux input subsystem. Specifically, there's this block in that function:

case HID_GD_GAMEPAD:
        if (code <= 0xf)
            code += BTN_GAMEPAD;
        else
            code += BTN_TRIGGER_HAPPY - 0x10;
        break;

These constants (e.g. BTN_GAMEPAD) are found in input-event-codes.h.

In the case of my USB HID gamepad, I specify buttons 1 through 32. The code referenced above is decremented from the button number (making it zero-indexed), so the 32-button gamepad falls into two button ranges:

  • 16 sequential input event codes starting at BTN_GAMEPAD
  • 16 sequential input event codes starting at BTN_TRIGGER_HAPPY

I did not include the full evtest output in my original question, but that lines up with what I observed.

To summarize, I cannot see any way for a HID descriptor to specify the mapping to Linux event codes. The HID kernel driver has a static mapping from HID gamepad button numbers to input event codes, so the solution is to specify buttons in the HID Report Descriptor that map to the intended event codes.

There may be software to remap these events at a higher level, but that is not something that can be implemented by a generic USB HID gamepad itself.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.