usb_hid: honor a boot protocol request that arrives after startup - #11282
Open
mikeysklar wants to merge 1 commit into
Open
usb_hid: honor a boot protocol request that arrives after startup#11282mikeysklar wants to merge 1 commit into
mikeysklar wants to merge 1 commit into
Conversation
mikeysklar
force-pushed
the
fix-1136-boot-hid
branch
from
September 1, 2026 00:29
dd114ae to
cd80fd8
Compare
Collaborator
|
I worked on this a lot years ago, as you can tell. I am surprised you need a new report descriptor without the Report ID slot. Part of the point of boot keyboard and boot mouse is that the descriptor sent by the device is ignored. Instead the host assumes the standard descriptors, as described in https://www.usb.org/sites/default/files/hid1_12.pdf in the boot devices sections So is this a work-around for something that Macs are not doing properly in their "BIOS"? I think the original code solved the issue on PC's. |
Collaborator
Author
|
You're right about the descriptor. The bug is timing: the swap runs only at VM start, so a later SET_PROTOCOL is missed. Not Mac specific. I'll cut it to that. |
usb_hid_setup_devices() swaps in the boot keyboard or mouse, whose report ID is 0, but it only runs from usb_setup_with_vm() at VM start. A SET_PROTOCOL(boot) arriving while code.py is already running is not acted on until the next VM restart, so reports keep their report-ID prefix while the host is reading them as 8-byte boot reports. That matches bitboy85's report in adafruit#1136: get_boot_device() returns 1 yet a phantom left Ctrl is held, because the 0x01 prefix lands in the modifier byte. Check tud_hid_get_protocol() in send_report() instead, and drop the report ID while the host has the interface in boot protocol. Measured on a Metro RP2040, with the host request simulated by setting TinyUSB's protocol_mode over SWD: before, reports stay 9 bytes after the switch; after, they become 8 bytes on the next send. Default HID configuration is unchanged.
mikeysklar
force-pushed
the
fix-1136-boot-hid
branch
from
September 1, 2026 02:24
cd80fd8 to
8861fe9
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
send_report()now drops the report ID while the host has the interface in boot protocol.Why
I went looking for old issues. #1136 is eight years old, 69 comments.
usb_hid_setup_devices()swaps in the boot device, whose report ID is 0, but runs only fromusb_setup_with_vm()at VM startSET_PROTOCOL(boot)arriving whilecode.pyruns is missed until the next restart, so reports keep the prefix while the host reads 8-byte boot reports0x01lands in the modifier byte, a held left Ctrl. Matches bitboy85'sget_boot_device()returning 1 alongside a phantom CtrlHardware tested
Metro RP2040 on Linux. Not tested: real BIOS, GRUB, KVM, Windows, non-RP2 ports, zephyr-cp.
How I tested it
Two devices, so report IDs stay in use:
code.pysent 'a' once per second, read from USB DPRAM over SWD.d897c15f2401 00 00 04 ..., 9 bytes01 00 00 04 ..., 9 bytes00 00 04 ..., 8 bytesboot.pyScope
protocol_modeover SWD, not sent by a real hostSET_PROTOCOLAI assistance
Written with an LLM agent (Claude). I ran the boards myself.