Add HID report protocol support for keyboards and mice, including scroll wheel support #675
Add HID report protocol support for keyboards and mice, including scroll wheel support #675chrisgleissner wants to merge 15 commits intoGideonZ:masterfrom
Conversation
…te tests for keyboard and mouse descriptors
…enu navigation methods, update tests, and improve visibility handling
- Fixed the normalization of vertical wheel direction in HidMouseInterpreterTest. - Added active_configuration member to UsbDevice to track the current configuration. - Improved configuration handling in UsbDevice, preventing unnecessary configuration changes. - Enhanced keyboard source management in usb_hid, allowing for better tracking and reporting of keyboard inputs. - Updated interrupt handling in UsbHidDriver to correctly manage mouse and keyboard visibility. - Refactored USB Hub driver to clean up code and improve readability. - Introduced active_config_browser in ConfigBrowser to manage active configuration states and refresh UI accordingly. - General code cleanup, including removal of unnecessary whitespace and comments.
…ndling in UsbHidDriver
… injected key counting, and update tests for improved behavior
…and update user interface help text for mouse controls
…nd update related tests for improved accuracy
…date related tests for improved accuracy
There was a problem hiding this comment.
Pull request overview
This PR expands the USB HID stack to support standards-based HID report protocol devices (mouse + keyboard), with a boot-protocol fallback, and integrates mouse-wheel-driven navigation into the UI/menu system. It also adds new configuration/status items and host-side tests to validate HID parsing and behavior.
Changes:
- Add HID report-descriptor parsing for mice/keyboards (including vertical + horizontal wheel) and synthesize boot keyboard reports for non-boot descriptors.
- Extend UI/config to show connected USB mouse/keyboard visibility + HID mode and add wheel/menu navigation settings.
- Add host-side USB/HID unit tests plus a Linux helper script for capturing wheel behavior.
Reviewed changes
Copilot reviewed 22 out of 24 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| software/userinterface/userinterface.h | Exposes UserInterface::anyMenuActive() for menu-override behavior. |
| software/userinterface/userinterface.cc | Tracks UI instances and extends help text for USB mouse menu controls. |
| software/userinterface/config_menu.h | Adds deinit() and a static refresh hook for the active config browser. |
| software/userinterface/config_menu.cc | Implements active ConfigBrowser tracking and refresh trigger. |
| software/u64/u64_config.h | Adds on_edit() hook to update dynamic HID status items. |
| software/u64/u64_config.cc | Adds HID-related config items, exposes config getter for USB HID, and publishes HID visibility into the config menu. |
| software/io/usb/usb_hub.h | Whitespace-only cleanup. |
| software/io/usb/usb_hub.cc | Whitespace/indentation cleanup in IRQ handling. |
| software/io/usb/usb_hid.h | Extends HID driver state to support report parsing, wheel/menu navigation, and visibility reporting. |
| software/io/usb/usb_hid.cc | Major rework: report/boot handling, wheel scaling, menu override logic, keyboard source merging, and visibility publishing. |
| software/io/usb/usb_device.h | Tracks active configuration in UsbDevice. |
| software/io/usb/usb_device.cc | Makes set_configuration() idempotent and adjusts set_interface() behavior. |
| software/io/usb/tests/usb_keyboard_queue_test.cpp | Adds host-side tests for injected key queue behavior. |
| software/io/usb/tests/usb_hid_mouse_test.cpp | Adds host-side tests for HID mouse parsing + wheel/menu scaling logic. |
| software/io/usb/tests/usb_hid_keyboard_test.cpp | Adds host-side tests for HID keyboard parsing and composite-report handling. |
| software/io/usb/tests/task.h | Stub header to build tests without RTOS task API. |
| software/io/usb/tests/Makefile | Simple build/run targets for host-side tests. |
| software/io/usb/tests/host_test/host_test.h | Minimal unit test framework for host-side C++ tests. |
| software/io/usb/tests/host_test_main.cpp | Test runner main for the host-side framework. |
| software/io/usb/tests/FreeRTOS.h | Stub header to build tests without RTOS headers. |
| software/io/usb/keyboard_usb.h | Expands keyboard buffering and adds injected-key APIs for menu navigation. |
| software/io/usb/keyboard_usb.cc | Implements injected key queue + matrix overlay behavior and safer keymap lookups. |
| software/io/usb/hid_decoder.h | Extends HID parsing (counts, IDs, truncated descriptors) and adds helpers for boot synthesis + wheel/menu interpretation. |
| python/mouse_wheel_capture.py | Adds a Linux tool to capture wheel event streams for tuning/analysis. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Hi Christian! This is really AWESOME work! I am totally stunned that you were able to produce so much code in so little time. Did you get help with AI? I don't understand all the changes yet. In particular, what I don't understand is the contamination with the user interface. Could you explain me why the user interface needs to know about the user interface, or vice versa? Does it have somethign to do with the focus? Like: where do the mouse movements go to? And if so, why is this needed for the mouse, but not for the keyboard? (it wasn't necessary, but apparently now it is..) And.. it doesn't build for RiscV... Apparently there is now some code that needs getpid, or kill. I think you accidentally pulled in some libary stuff that is not yet natively supported. I still have to figure out where, though. |
|
Hi Gideon, Thanks a lot for your positive feedback. Much appreciated. I have further refined the code and addressed the review comments. Here are some details:
And yes, I did leverage some AI help for these changes, specifically GPT 5.4 and Claude Opus 4.6. I find it's become very useful last year. Thanks |
|
Sounds good! I would like to understand tho where the getpid and kill functions were needed. I am concerned that we pulled in a library (-function) that is not supposed to be pulled in. |
|
I did some digging and the use of Either way, I am in the process of removing that call and pushing the various other simplifications I mentioned earlier - as soon as I have done a sanity check on my Ultimate 64 Elite. Should not take too long. |
|
Hi Gideon, I investigated the On the UI side, the only remaining coupling (it's a feature, not a bug... :-) ) is mouse routing: when the menu is open, wheel and buttons control the menu; otherwise input follows the normal path. The keyboard already uses the existing queue and does not require this gating. I retested the full PR on my local U64 Elite. All previously demonstrated tests pass, along with additional checks including live keyboard and mouse reconnect with immediate menu updates, and general keyboard functionality. Note on the Joystick menu: it shows the most recently active device, either by connection or latest input. For example, if a keyboard exposing both keyboard and mouse interfaces is connected while the menu is open, it may appear under both until distinct input is received. Updates are immediate and do not require reopening the menu. I added a new section to the PR overview at the top of this page titled "HID Mouse And Keyboard Flow". I hope that helps with the PR review. Thanks again for reviewing and for the positive feedback. I may be less available for the rest of the week due to travel, but please let me know if anything else needs attention. All the best, |
…eded for optimizing the menu handling of the mouse.
|
Hi @GideonZ , I successfully built the u64, ue2, and u2r targets locally. I understand the latter two use the RISC-V CPU. So the issue that failed the CI build should be resolved now: The Thanks for approving the workflow so it can rebuild on CI. Best, |
|
Hi Christian, I hope to have some time this weekend to dig through your pull request and merge it. I might come back with some questions. :) Best regards, |
|
Hi @GideonZ , Thanks a lot for your interest, it is much appreciated. If you'd like me to change any of it, just let me know. Happy Easter! |
|
Just a quick update:
|
- Introduce adaptive mouse acceleration options in the HID configuration. - Implement functions for resolving and scaling pointer sensitivity. - Update mouse sensitivity handling in the USB HID driver. - Add tests for new mouse acceleration features and ensure proper configuration.
|
Hi @GideonZ , I hope you are well. Earlier today, the version 1.1 of the C64U firmware got released. There are a lot of test reports and articles about it. A few people mentioned that their mice were not working properly, or were not getting recognized. It would be great if this PR could get merged so more people can benefit from its improved mouse support. I've implemented a few additional improvements:
The following screenshot shows all changes: I have not re-recorded the demo video since the new features are pretty self-explanatory. I've successfully built the U64 and UE2 firmwares, and I tested this via JTAG deployment to my Ultimate 64 Elite. All the best, |
|
Wow nice!
…On Wed, Apr 8, 2026, 2:09 PM Christian Gleissner ***@***.***> wrote:
*chrisgleissner* left a comment (GideonZ/1541ultimate#675)
<#675 (comment)>
Hi @GideonZ <https://github.com/GideonZ> ,
I hope you are well.
Earlier today, the version 1.1 of the C64U firmware got released. There
are a lot of test reports and articles about it. A few people mentioned
that their mice were not working properly, or were not getting recognized.
It would be great if this PR could get merged so more people can benefit
from its improved mouse support.
I've implemented a few additional improvements:
- Improved UX with separators between related sections and consistent
terminology: We now refer to mouse pointer / mouse wheel speed-up factors
consistency using the simpler term "Sensitivity".
- Fixed "jittery" mouse movement (and issue in the official 3.14d
firmware) when moving the mouse quickly.
- Added *Mouse Sensitivity* with values *Auto, 1, ..., 16*
- Added *Mouse Acceleration* with values *Off, Adaptive*. This is
useful for having more control over precise small movements whilst ensuring
fast movements allow you to quickly navigate across the entire screen.
The following screenshot shows all changes:
MouseExtensions.png (view on web)
<https://github.com/user-attachments/assets/66863a2c-48d5-4dfc-91ca-37814284e6a8>
I have not re-recorded the demo video since the new features are pretty
self-explanatory.
I've successfully built the U64 and UE2 firmwares, and I tested this via
JTAG deployment to my Ultimate 64 Elite.
All the best,
Christian
—
Reply to this email directly, view it on GitHub
<#675 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAOSHCR3ZUVRNDJTM75ZN7D4U2PVXAVCNFSM6AAAAACXIFUTZGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHM2DEMBYHEYDOOBXHE>
.
You are receiving this because you are subscribed to this thread.Message
ID: ***@***.***>
|

Hi Gideon,
I reworked the earlier PR so it no longer depends on any specific mouse model. It now targets standard HID reporting devices in general, and also adds keyboard support.
Features
The main features are:
Demo
U64 Elite-I with Logitech MX Master 3 (wireless via Logitech Unifying receiver) and Goldtouch USB keyboard:
https://youtu.be/QtKnri4DVqY
The video shows:
Joystick Menu
Implementation Notes
HID Mouse And Keyboard Flow
This is a high-level overview of the runtime flow added by the HID mouse and keyboard work.
The important behavior is:
Keyboard_USBpath.Further details:
flowchart TD A[USB HID interface discovered] --> B[Inspect interface capabilities] B --> C{Standard HID report fields found?} C -->|Yes| D[Activate report-protocol mouse and or keyboard] C -->|No| E{Boot mouse or keyboard available\nand no active report sibling?} E -->|Yes| F[Activate boot-protocol fallback] E -->|No| G[Ignore interface for HID input] D --> H[Receive interrupt reports] F --> H H --> I{Report type} I -->|Keyboard| J[Normalize to boot-style 8-byte report] J --> K[Merge all active USB keyboard sources] K --> L[Feed existing Keyboard_USB path] I -->|Mouse| M[Decode motion, buttons and wheel] M --> N[Update machine-side mouse state] M --> O{Menu active and\nmenu mouse navigation enabled?} O -->|Yes| P[Map wheel to navigation keys\nand left or right button to menu actions] O -->|No| Q[No additional menu actions] D --> R[Update HID name and mode snapshot] F --> R R --> S[Bump HID status generation] S --> T[Config menu refreshes visible HID status]It would be great if you would consider merging it.
Thanks!