The below isn’t up-to-date.
Some good news, I did some digging and managed to find a fix for most, but not all function combos. Tested working in Sway and Gnome 40, and since it affects udev in systemd, should work for systems using that. I do still lean towards this ultimately being a firmware issue with the Fn function key, but I’m not entirely sure.
Create this file (I don’t think the name of the file actually matters).
/etc/udev/hwdb.d/70-keyboard-framework-fix.hwdb
Explanation, click to expand
Thanks @carlos1001 for the bit of info on showkeys -s
, that prompted me to do some searching and I came across this, which led this this.
/lib/udev/hwdb.d/60-keyboard.hwdb
provides a lot of insight.
# ######################### KEY MAPPING ######################################
#
# Keyboard mapping of scan codes to key codes, and
# scan codes to add to the AT keyboard's 'force-release' list.
#
# Scan codes are specified as:
# KEYBOARD_KEY_<hex scan code>=<key code identifier>
# The scan code should be expressed in hex lowercase. The key codes
# are retrieved and normalized from the kernel input API header.
# Keycodes are either KEY_* defines in lowercase with the key_ prefix
# optionally removed or BTN_ defines in lowercase with btn_ preserved.
#
# An '!' as the first character of the key identifier string
# will add the scan code to the AT keyboard's list of scan codes
# where the driver will synthesize a release event and not expect
# it to be generated by the hardware.
#
# To debug key presses and access scan code mapping data of
# an input device use the commonly available tool: evtest(1).
The evtest
utility can get <hex scan code>
and <key code identifier>
like so:
sudo evtest
No device specified, trying to scan all of /dev/input/event*
Available devices:
/dev/input/event0: Lid Switch
/dev/input/event1: Power Button
/dev/input/event2: AT Translated Set 2 keyboard
/dev/input/event3: FRMW0001:00 32AC:0006 Wireless Radio Control
/dev/input/event4: FRMW0001:00 32AC:0006 Consumer Control
/dev/input/event5: PIXA3854:00 093A:0274 Mouse
/dev/input/event6: PIXA3854:00 093A:0274 Touchpad
/dev/input/event7: Video Bus
...
Select the device event number [0-27]:
And type in the number, in this case 2. 3 seems to capture the Airplane Mode key, and 4 seems to capture the brightness down/up key.
Can also run for a specific input event like so:
sudo evtest /dev/input/event2
sudo evtest /dev/input/event3
sudo evtest /dev/input/event4
So run sudo evtest /dev/input/event2
and press a combo like Fn + Volume Up
(ensure function lock Fn + Esc
is set correctly).
Output:
Event: time 1635015297.625073, type 4 (EV_MSC), code 4 (MSC_SCAN), value b0
Event: time 1635015297.625073, type 1 (EV_KEY), code 115 (KEY_VOLUMEUP), value 1
Event: time 1635015297.625073, -------------- SYN_REPORT ------------
Event: time 1635015297.625102, type 4 (EV_MSC), code 4 (MSC_SCAN), value b0
Event: time 1635015297.625102, type 1 (EV_KEY), code 115 (KEY_VOLUMEUP), value 0
Event: time 1635015297.625102, -------------- SYN_REPORT ------------
From this we can get the values we need for KEYBOARD_KEY_<hex scan code>=<key code identifier>
:
(MSC_SCAN), value b0
KEY_VOLUMEUP
The scan code should be expressed in hex lowercase.
MSC_SCAN, value
shows the hex scan code b0
Keycodes are either KEY_* defines in lowercase with the key_ prefix optionally removed or BTN_ defines in lowercase with btn_ preserved.
- so we take the value from
KEY_*
and lowercase it
the driver will synthesize a release event and not expect it to be generated by the hardware.
- then prepend
!
to the value from 2. resulting in:
KEYBOARD_KEY_b0=!volumeup
Add this in the file either /etc/udev/hwdb.d/
to designate which input devices to affect:
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnFramework:pnLaptop:pvr*:*
From (asterisks are wildcards):
cat /sys/class/dmi/id/modalias
dmi:bvnINSYDECorp.:bvr03.02:bd07/01/2021:br3.2:svnFramework:pnLaptop:pvrA6:rvnFramework:rnFRANBMCP06:rvrA6:cvnFramework:ct10:cvrA6:skuFRANBMCP06:
Can also filter using evdev:input:*
like so:
cat /proc/bus/input/devices
...
I: Bus=0011 Vendor=0001 Product=0001 Version=ab83
N: Name="AT Translated Set 2 keyboard"
P: Phys=isa0060/serio0/input0
S: Sysfs=/devices/platform/i8042/serio0/input/input2
U: Uniq=
H: Handlers=sysrq kbd leds event2
B: PROP=0
B: EV=120013
B: KEY=402000000 3803078f800d001 feffffdfffefffff fffffffffffffffe
B: MSC=10
B: LED=7
...
- Bus=0011
- Vendor=0001
- Product=0001
turns into evdev:input:b0011v0001p0001*
. Note b=Bus, v=Vender, p=Product, and any characters must be capitalized.
So a fix for the Volume keys is like so, where KEYBOARD_KEY* must start with a single space, and go under the input (AFAICT using only evdev:atkbd:*
or evdev:input:*
works, only one input filter is required cause they both affect /dev/input/event2: AT Translated Set 2 keyboard
):
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnFramework:pnLaptop:pvr*:*
evdev:input:b0011v0001p0001*
KEYBOARD_KEY_a0=!mute
KEYBOARD_KEY_ae=!volumedown
KEYBOARD_KEY_b0=!volumeup
This seems to work for all keys captured under
/dev/input/event2: AT Translated Set 2 keyboard
except, what I haven’t found a fix for:
Fn + F9
Projector key
The Fn + F9
Projector key sticks, tested in Gnome. It seems to be captures as some combination of KEY_P
and KEY_LEFTMETA
? I tried adding these two entries on separate lines like so:
KEYBOARD_KEY_19=!p
KEYBOARD_KEY_db=!leftmeta
Which didn’t work. It just turned the Fn + F9
Projector key into Windows/Super + P
which I guess is (LeftMeta + P
).
Fn + F7
Brightness Down / Fn + F8
Brightness Up
Brightness Down/Brightness Up are captured under
/dev/input/event4: FRMW0001:00 32AC:0006 Consumer Control
I tried
# Fix for brightness keys on Framework keyboards
evdev:input:b0018v32ACp0006*
KEYBOARD_KEY_c0070=!brightnessdown
KEYBOARD_KEY_c006f=!brightnessup
Which targets /dev/input/event4
, confirmed with
udevadm info /dev/input/event4 | grep KEYBOARD_KEY
E: KEYBOARD_KEY_c006f=!brightnessup
E: KEYBOARD_KEY_c0070=!brightnessdown
but unfortunately that doesn’t work.
Notably the Brightness Down and Brightness Up keys can be remapped like so:
# disables them
evdev:input:b0018v32ACp0006*
KEYBOARD_KEY_c0070=reserved
KEYBOARD_KEY_c006f=reserved
or even remapped to another key (here Brightness Down is remapped to mute)
evdev:input:b0018v32ACp0006*
KEYBOARD_KEY_c0070=!mute
KEYBOARD_KEY_c006f=!brightnessup
But with Fn + F7
Brightness Downkey remapped to
!mute`:
- Pressing
Fn + F7
Brightness Down
does trigger mute, but theFn + F7
Brightness Down key can still become stuck resulting in infinitely muting/unmuting.
I think it has something to do with the brightness keys not triggering under
/dev/input/event4: FRMW0001:00 32AC:0006 Consumer Control
and the !
synthetic release “hack” not working for those.
Fn + 10
Airplane mode (AFAICT no issue to begin with)
Airplane Mode is captured under
/dev/input/event3: FRMW0001:00 32AC:0006 Wireless Radio Control
and it doesn’t seem to stick on my end, that I know of.
With all that being said, I think this is still a firmware issue specifically with how the Fn function key is handled.
Key data collected:
Key Combo |
Hex Scan Code |
Key Code Identifier |
FN + F1 |
a0 |
KEY_MUTE |
FN + F2 |
ae |
KEY_VOLUMEDOWN |
FN + F3 |
b0 |
KEY_VOLUMEUP |
FN + F4 |
90 |
KEY_PREVIOUSSONG |
FN + F5 |
a2 |
KEY_PLAYPAUSE |
FN + F6 |
99 |
KEY_NEXTSONG |
FN + F7 |
c0070 |
KEY_BRIGHTNESSDOWN |
FN + F8 |
c006f |
KEY_BRIGHTNESSUP |
FN + F9 (first half) |
19 |
KEY_P |
FN + F9 (second half) |
db |
KEY_LEFTMETA |
FN + F10 |
100c6 |
KEY_RFKILL |
FN + F11 |
b7 |
KEY_SYSRQ |
FN + F12 |
ed |
KEY_MEDIA |
FN + Left Arrow |
c7 |
KEY_HOME |
FN + Right Arrow |
cf |
KEY_END |
FN + Down Arrow |
d1 |
KEY_PAGEDOWN |
FN + Up Arrow |
c9 |
KEY_PAGEUP |
Some links/information I read:
-
https://www.linuxquestions.org/questions/linux-laptop-and-netbook-25/fvolume-function-keys-from-laptop-external-keyboard-works-get-stuck-in-x11-wayland-but-seem-to-work-with-kernel-4175650371/
-
https://askubuntu.com/questions/994333/volume-buttons-stay-pressed/1061500#1061500
-
https://bbs.archlinux.org/viewtopic.php?id=150199
-
https://wiki.archlinux.org/title/Acpid
-
https://bbs.archlinux.org/viewtopic.php?id=240543
-
https://wiki.gentoo.org/wiki/ACPI/ThinkPad-special-buttons
-
https://askubuntu.com/questions/239560/problem-binding-a-shortcut-to-a-function-multimedia-