Created attachment 186765 [details]
This patch adds support for media keys (such as play/pause, next/prev track, volume up/down) on USB keyboards where they're implemented as HID Consumer Control reports by converting them into plain old key presses of matching keys.
Background: my mouse (Logitech G402) pretends to also be a keyboard, to allow two programmable extra buttons to press any keyboard key. One of the options for these keys is volume control, and I really like that. These key presses were not recognized by the FreeBSD kernel. With this patch, libinput-debug-events shows them as KEY_VOLUMEDOWN (114) and KEY_VOLUMEUP (115), just like on Linux, and my XF86AudioRaise(Lower)Volume bindings in Xorg work fine! Nothing in this patch is evdev specific though, it literally translates these events to key presses.
Also: I have a wireless keyboard that pretends to also be a mouse (…yeah), and for the media keys, it sends identical packets, but through a ums device. Tried to do a similar thing (but evdev-only, since the normal mouse interface can't press keys I guess) in the ums driver, wasted several hours only to encounter weird problems… hid_locate couldn't even find the stuff, though it's clearly there (uhidd recognizes it fine!). After removing the "Only copy HID item, increment position and return if correct kindset" check from hid_get_item, hid_locate "found" it but returned wrong data… So screw that for now, hopefully most input devices use ukbd for media keys :D
I think it is clever to add a check:
if (data != 0) ->>>
if (sc->sc_ndata.keycode == KEY_ERROR && data != 0)
So that you don't override valid key input.
Or else scan the keycode array and place data last.
(In reply to Greg V from comment #0)
Did you check events generated by your patched ukbd when two HID consumer-page keys are pressed and then released simultaneously? I think you will get press events for both keys but release event only for a one of them.
(In reply to Hans Petter Selasky from comment #1)
(In reply to Vladimir Kondratyev from comment #2)
From what I understand, consumer control packets are completely separate packets that cannot contain keyboard keypresses (totally different usage page than keyboard keys, 0xC vs 0x7). Just confirmed at https://deskthority.net/wiki/Media_key#USB
Pressing both volume buttons on my mouse results in the two keys pressed-released in order. Some devices *might* support simultaneous presses of multiple media keys, but I think in that case, we would just lose the extra key presses.
(In reply to Greg V from comment #3)
> Pressing both volume buttons on my mouse results in the two keys pressed-released in order.
Did you observed it with evemu or with libinput? Please use former as it connects directly to input device and gives raw data.
> Some devices *might* support simultaneous presses of multiple media keys, but I think in that case, we would just lose the extra key presses.
I recently implemented evdev support for consumer page for bluetooth keyboards (not publicly available yet) and found out that my bt-keyboard loses *release* events on simultaneous presses as it is unable to report "which key has been depressed" at HID-protocol level. It is capable only to say that "last/all key has been depressed" so my driver has to generate release event at next interrupt at his own. I do not see how your patch does such "autorelease". Maybe ukbd does this automagically? I should look deeper in its internals. Unfortunately I cant do hardware testing now
(In reply to Vladimir Kondratyev from comment #4)
Didn't know about evemu, nice tool. Just tried it, events are always sequential: 1, 0, 1, 0…
My mouse does not support simultaneous media key presses, it always returns only one key.
ukbd gets the report with all zeros and generates the release event. My patch only allows one media key to be pressed, others are lost, so the release event will always release that key.
Can you make the patch so that no other keys are lost. For example by extending the key array?
Created attachment 186814 [details]
ok here's a version that supports multiple keys.