Skip to content

inconsistent HID Report Descriptor for Keyboard #8789

@tlyu

Description

@tlyu

CircuitPython version

Adafruit CircuitPython 8.2.9 on 2023-12-06; Adafruit Macropad RP2040 with rp2040
Board ID:adafruit_macropad_rp2040
UID:DF61B0C28717182F

Code/REPL

# N/A; this is a bug in the HID Report Descriptor as seen by a host, but here is the code.py, which is one of the MacroPad demos

# SPDX-FileCopyrightText: Copyright (c) 2021 Kattni Rembor for Adafruit Industries
#
# SPDX-License-Identifier: Unlicense
"""
Rainbow LED grid layout demo for MacroPad. Displays the key pressed in a grid matching the key
layout on the built-in display, and animates a rainbow the first time you press a key and turns it
off on the next press.
"""
import displayio
import terminalio
from rainbowio import colorwheel
from adafruit_display_text import bitmap_label as label
from adafruit_displayio_layout.layouts.grid_layout import GridLayout
from adafruit_macropad import MacroPad

macropad = MacroPad()

main_group = displayio.Group()
macropad.display.root_group = main_group
title = label.Label(
    y=4,
    font=terminalio.FONT,
    color=0x0,
    text="      KEYPRESSES      ",
    background_color=0xFFFFFF,
)
layout = GridLayout(x=0, y=10, width=128, height=54, grid_size=(3, 4), cell_padding=5)
labels = []
for _ in range(12):
    labels.append(label.Label(terminalio.FONT, text=""))

for index in range(12):
    x = index % 3
    y = index // 3
    layout.add_content(labels[index], grid_position=(x, y), cell_size=(1, 1))

main_group.append(title)
main_group.append(layout)

lit_keys = [False] * 12
wheel_offset = 0
while True:
    key_event = macropad.keys.events.get()
    if key_event:
        if key_event.pressed:
            labels[key_event.key_number].text = "KEY{}".format(key_event.key_number)
            # Turn the LED on with the first press, and off with the second press.
            lit_keys[key_event.key_number] = not lit_keys[key_event.key_number]
        else:
            labels[key_event.key_number].text = ""

    wheel_offset += 1  # Glow thru the colorwheel.
    for pixel in range(12):
        if lit_keys[pixel]:  # Animate the specific LED.
            macropad.pixels[pixel] = colorwheel((pixel / 12 * 256) + wheel_offset)
        else:
            macropad.pixels[pixel] = 0  # Otherwise, turn the LED off.

Behavior

When using the hid_parser module on the host to parse the Report Descriptor, an error occurs, because there are 5 usages, but the Output field expects 3. I obtained the Report Descriptor by using a custom script, but it is also available using a tool such as usbhid-dump. (I have also fixed a few bugs in that module, which haven't yet been reviewed by the maintainers.) To my knowledge, there are no hosts that reject the Report Descriptor for this inconsistency, but I haven't tested widely, either.

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/tlyu/src/keyboardio/.venv/lib/python3.10/site-packages/hid_parser/__init__.py", line 613, in __init__
    self._parse()
  File "/Users/tlyu/src/keyboardio/.venv/lib/python3.10/site-packages/hid_parser/__init__.py", line 848, in _parse
    self._append_items(
  File "/Users/tlyu/src/keyboardio/.venv/lib/python3.10/site-packages/hid_parser/__init__.py", line 784, in _append_items
    raise InvalidReportDescriptor(error_str)
hid_parser.InvalidReportDescriptor: Expecting 3 usages but got 5

Description

The error is in these lines:

0x95, 0x03, // Report Count (3)
0x75, 0x01, // Report Size (1)
0x05, 0x08, // Usage Page (LEDs)
0x19, 0x01, // Usage Minimum (Num Lock)
0x29, 0x05, // Usage Maximum (Kana)
0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)

Note the Usage Maximum (Kana) is 5, while Report Count is 3, and Report Size is 1. Either reduce the Usage Maximum to 3, or increase the Report Count to 5, while also adjusting the following padding field. I might get around to submitting a PR eventually, once I get a working CircuitPython build environment again.

Additional information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions