Learning USB HID in Linux Part 7 - Understanding Keyboard Report Descriptors and Reports

The below is the Report Descriptor of USB Keyboard connected to my system:

usbhid-dump -d 413c:2107 | tail -n +2 | xxd -r -p | hidrd-convert -o spec
Usage Page (Desktop),               ; Generic desktop controls (01h)
Usage (Keyboard),                   ; Keyboard (06h, application collection)
Collection (Application),
    Usage Page (Keyboard),          ; Keyboard/keypad (07h)
    Usage Minimum (KB Leftcontrol), ; Keyboard left control (E0h, dynamic value)
    Usage Maximum (KB Right GUI),   ; Keyboard right GUI (E7h, dynamic value)
    Logical Minimum (0),
    Logical Maximum (1),
    Report Size (1),
    Report Count (8),
    Input (Variable),
    Report Count (1),
    Report Size (8),
    Input (Constant),
    Report Count (5),
    Report Size (1),
    Usage Page (LED),               ; LEDs (08h)
    Usage Minimum (01h),
    Usage Maximum (05h),
    Output (Variable),
    Report Count (1),
    Report Size (3),
    Output (Constant),
    Report Count (6),
    Report Size (8),
    Logical Minimum (0),
    Logical Maximum (255),
    Usage Page (Keyboard),          ; Keyboard/keypad (07h)
    Usage Minimum (None),           ; No event (00h, selector)
    Usage Maximum (FFh),
    Input,
    Usage Page (Consumer),          ; Consumer (0Ch)
    Usage (00h),
    Logical Minimum (-128),
    Logical Maximum (127),
    Report Size (8),
    Report Count (8),
    Feature (Variable),
End Collection

Analysis of Report Descriptor:

Usage Page (Desktop),               ; Generic desktop controls (01h)
Usage (Keyboard),                   ; Keyboard (06h, application collection)

The above means that the report is intended for a generic USB Device, in this case a keyboard.


Usage Page (Keyboard),          ; Keyboard/keypad (07h)
    Usage Minimum (KB Leftcontrol), ; Keyboard left control (E0h, dynamic value)
    Usage Maximum (KB Right GUI),   ; Keyboard right GUI (E7h, dynamic value)
    Logical Minimum (0),
    Logical Maximum (1),
    Report Size (1),
    Report Count (8),
    Input (Variable),

This defines the modifier keys in the input report. This defines 8 fields which are 1 bit long each, resulting in the modifier byte mentioned previously. The values stored in these fields must be in the range [224, 231], as these are the key codes defined for the modifier keys




KB LeftControl Usage ID is e0 and KB Right GUI is E7 - So 8 usages in sequence
Left GUI is the Left Windows Key and Right GUI is the Right Windows Key.
So, the first byte will contain the information about the Controls (Ctrl, alt, shift, Win (both Right and left))

Report Count (1),
Report Size (8),
Input (Constant),

This defines the constant/reserved byte in the input report, which is again formed by 8 fields which are 1 bit long each.

 Report Count (5),
    Report Size (1),
    Usage Page (LED),               ; LEDs (08h)
    Usage Minimum (01h),
    Usage Maximum (05h),
    Output (Variable),
    Report Count (1),
    Report Size (3),
    Output (Constant),

The next 5 bits are for LED and and 3 bits are constant
This defines LEDs that can be set in the output report, formed by 5 fields which are 1 bit long each. LEDs are specified in the following order:

Num Lock
Caps Lock
Scroll Lock
Compose
Kana

For example, a value of 3 (011) will set LEDs Num Lock and Caps Lock.

As I mentioned previously, output reports are 1 byte long. The block above set 5 bits, so it is necessary to add 3 constant fields which are 1 bit long each in order to complete the byte.



 Report Count (6),
    Report Size (8),
    Logical Minimum (0),
    Logical Maximum (255),
    Usage Page (Keyboard),          ; Keyboard/keypad (07h)
    Usage Minimum (None),           ; No event (00h, selector)
    Usage Maximum (FFh),
    Input,

Finally, this specifies the key codes pressed in the keyboard in the input report. As shown, the block specifies 6 fields which are 8 bits (1 byte) long each. The value of each field corresponds to the HID code of the key pressed, in the range [0, 255].


Input reports (sent from keyboard to computer) have the following structure for a total of 8 bytes:

1 byte: modifier keys (Control, Shift, Alt, etc.), where each bit corresponds to a key
1 byte: unused/reserved for OEM
6 bytes: pressed key codes

While output reports (sent from computer to keyboard) have the following structure:

1 byte: LED states (Num lock, Caps lock, etc.), where each bit corresponds to a LED

References:

https://www.rmedgar.com/blog/using-rpi-zero-as-keyboard-report-descriptor

Comments

  1. Well very thanks for such a nice information! Now please check out this - backlit keyboard

    ReplyDelete

Post a Comment

Popular posts from this blog

bb.utils.contains yocto

make config vs oldconfig vs defconfig vs menuconfig vs savedefconfig

PR, PN and PV Variable in Yocto