KMKfw / kmk_firmware

Clackety Keyboards Powered by Python
https://kmkfw.zulipchat.com
Other
1.45k stars 486 forks source link

[Enhancement] Gamepad Support #1003

Open hendrix04 opened 4 months ago

hendrix04 commented 4 months ago

Is your feature request related to a problem? Please describe. This project is a great springboard for HID devices, but currently it only supports Keyboards and Mice. It would be great if it could be extended to support gamepads as well.

Describe the solution you'd like The difficulty with gamepads vs other devices is that the HID report is custom per device. This would likely require a refactor of the HID module to allow hardware to define their own HID report. Perhaps there could be helper functions to make that a bit more straightforward.

Additional context I am more than happy to contribute to this feature request, but I didn't want to do a lot of work that would then be denied due to no desire within the community to have this type of functionality. It is very common for the sim racing community to create their own custom "button boxes". This functionality could also be used to make DIY Stream boxes.

claycooper commented 4 months ago

Do gamepads use codes outside of those defined for keyboards/mice? Do they normally use a matrix or are you thinking of adding a module that maps a PIN to a code or code+"N-meta"?

hendrix04 commented 4 months ago

I am no expert in HID so please excuse anything that I might get wrong here....

Gamepads can have any number of buttons / switches / whatever so every HID report is different based on the hardware. They definitely don't report as a keyboard or mouse so any existing key mapping / definitions wouldn't work for this use case.

My imagined first pass would be to ignore any analog / joystick type input. I don't think that would really fit within this project anyway (though the pattern used for encoders COULD work for referencing single pins could be fine). When not worrying about those things it comes down to a simple button press or switch which can easily be implemented via a a matrix which would be my plan.

My personal first use case would be to use the Pico 14 (which is already defined as a keyboard in this project) to act as a gamepad (from a hid perspective) so that I can then read those values with a script on my computer to create a DIY Streamdeck. By making it a gamepad instead of a keyboard, I don't have to worry about conflicts with my actual keyboard.

xs5871 commented 4 months ago

Gamepads are a separate HID usage page and would need some custom logic. We have a conversation about that in the Zulip chat somewhere. We'll probably support that at some point, but in my opinion analog inputs are a requirement -- otherwise it's almost pointless.

@hendrix04 Your use case does not necessitate a different HID: there are function keys (F13-F24), international/language keys (INT1-LANG9), and there are lots of consumer control codes ("media keys", most of which we don't use in KMK). Even better: make your script listen to a specific device.

hendrix04 commented 4 months ago

I am not opposed to putting in analog support given that there is prior art on doing single pin inputs (encoders) as opposed to matrix input.

While I can definitely make my script listen to a specific HID, that doesn't prevent the OS from also picking up that keystroke. That is my fear of using a keyboard type input for something that isn't necessarily intended to be a keyboard.

If a PR came up with full support for gamepads,.is that something that would be accepted? Does the Tulip discussion have ideas that are a must have?

My hope is that the device layout that is generally included for devices can be used to generate an appropriate HID usage.

xs5871 commented 4 months ago

While I can definitely make my script listen to a specific HID, that doesn't prevent the OS from also picking up that keystroke. That is my fear of using a keyboard type input for something that isn't necessarily intended to be a keyboard.

You're not the first one who wants to use a small keyboard as a macropad. There are numerous blog posts, tutorials, etc. out there that cover using a second keyboard as a custom macropad for every common OS. Intercepting keycodes before they get passed on to any UI is trivial. There's absolutely zero need to make your life harder as necessary. I would highly recommend going that route.

If a PR came up with full support for gamepads,.is that something that would be accepted? Does the Tulip discussion have ideas that are a must have?

Depends on quality, how intrusive it is, how much it bulks up core code. If it were possible to put all that into a module I'd say go for it. It's not though (well technically it is, but it would not fit into the general design of KMK). I looked into it and I don't think that's going to happen in the near future. It's not the HID endpoint itself that's complicated, it's weaving it into the mess that is KMK. Axis handling needs refactoring. The enpoint handling is convoluted and doesn't scale and I don't want to add yet another "special case" to core code that only 1% of people use. There is currently no way to unit test anything other than 6KRO reports. There's probably more. I'm not against adding more HID reports, quite the contrary. But detangling some of the "organic" design of KMK and reducing memory footprint, speed, latency, code duplication has been and is a lot of work, and I don't want to regress on that.


edit: after rereading, fixed a couple of embarrassing grammar and spelling mistakes.