FN Keys Sticking

Hi everybody!

I’m posting here because I’m not sure if this is a Linux problem or a firmware problem.

Has anybody noticed that the arrow keys may stick if you do something like fn + right arrow or sometimes the keybinding won’t work for secondary functions like when trying to do ctrl + end?

I know for a fact that it’s possible to get any key with a secondary function to stick if you press and hold the two-functioned key, press fn, and then release the first key while still holding down fn.

Has anybody encountered a similar problem?

Thanks,

Carlos

1 Like

So glad you posted this – I’ve had this issue sporadically (batch 1 here) and thought it was an issue with Sway/wlroots (I’m running Fedora 34). I can reproduce the issue with your steps.

E.g. hold down FN + Volume Up, release FN, then finally release Volume Up. Volume continues to increase as if FN + Volume Up is stuck.

May be related: my arrow keys randomly stick, sometimes with FN so they act like a stuck Home/End/Page Up/Page Down. If I press any other key, it temporarily unsticks until switching active windows (with the touchpad or external mouse). Then the previously stuck key sticks again. If I press the stuck key, like Left Arrow or FN+Left Arrow (Home), it’ll actually unstick. However, this seems to only affect XWayland apps and not Wayland, and I haven’t noticed it in Gnome or Windows, so I think this particular issue is Sway/wlroots related.

Hmm, I don’t think so. I’m running gnome under Xorg on my setup. I guess I can try booting the windows 10 install media to see if it also does it…

1 Like

Welp, I tested again in Fedora 34 on Gnome and Sway and the issue happens Wayland and XWayland apps. Booted into Windows and seems like the issue isn’t present there, as far as I can tell.

So it does seem like at least a general Linux issue :confused: (or we have faulty/lemon keyboards)

I can make a function combo like volume/brightness up/down stuck. I can also make page up/down or home/end stuck on e.g. a web browser so that the page keeps scrolling down.

E.g. if I press FN + Right Arrow (End); then release FN before Right Arrow; that specific window will scroll down continuously like End is stuck. If I focus/activate another browser window, that page seems fine and doesn’t keep scrolling down. Then if I try to press FN + Right Arrow (End) on the new active window, the combination doesn’t work until I press the combination multiple times.

If anyone doesn’t have this issue on Linux and can chime in with their distro and kernel version, that’d be super helpful! I want to see if we have lemon keyboards, or this is a software issue.

1 Like

Huh, that’s interesting that the issue isn’t showing up in Windows. I’m starting to think that this may be a firmware problem because fn doesn’t appear to send a scancode to the kernel. I’m running showkey -s in the terminal and don’t see a scancode appear when just pressing fn. Unless we both have unique keyboards. Not sure if it helps, but this is the fourth batch.

Yes! I experience similar behavior but without any key presses at all on Wayland (sway/wlroots). This occurs almost constantly across native wayland applications where the window scrolls to the bottom and stays “locked” there. Scrolling upward produces the effect of moving the page slightly and the jumping back to the bottom as though you are holding the down the arrow key. Pressing a single key such as the up arrow alleviates the issue until the behavior until resumes usually ~20-60 seconds later in another window.

I tried in vain to monitor libinput debug-events and determine if there is some phantom key press event which is causing the behavior.

The behavior does not occur in an X based DE such as Xfce.

I take my last post back about it maybe being a firmware problem; the keyboard appears to work perfectly in a tty console.

Back to the drawing board I guess :slight_smile:

1 Like

EDIT:
See this thread instead:
Function (Fn) Keys Sticking + Fix for Linux


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.

What I haven’t found the fix for (so these keys still stick):

  • Fn + F7/Fn + F8 Brightness Down/Up
    • seems to go through a separate input that isn’t fixed with the ! synthesized release hack
  • Fn + F9 Projector key
    • uses a combination of the KEY_P and KEY_LEFTMETA (not sure how to deal with that)

Except:

  • Fn + F10 Airplane Mode
    • there’s no sticking issue with this key combo AFAICT, on my end. It also seems to go through a separate input. So no fix was added.

The fix (well temporary workaround):

Create this file (I don’t think the name of the file actually matters).
/etc/udev/hwdb.d/70-keyboard-framework-fix.hwdb

# Fix for Fn keys sticking on Framework laptop
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnFramework:pnLaptop:pvr*:*
evdev:input:b0011v0001p0001*
 KEYBOARD_KEY_a0=!mute
 KEYBOARD_KEY_ae=!volumedown
 KEYBOARD_KEY_b0=!volumeup
 KEYBOARD_KEY_90=!previoussong
 KEYBOARD_KEY_a2=!playpause
 KEYBOARD_KEY_99=!nextsong
 KEYBOARD_KEY_b7=!sysrq
 KEYBOARD_KEY_c7=!home
 KEYBOARD_KEY_cf=!end
 KEYBOARD_KEY_d1=!pagedown
 KEYBOARD_KEY_c9=!pageup
 KEYBOARD_KEY_ed=!media

Then run (as root):

systemd-hwdb update
udevadm trigger --verbose --sysname-match="event*"

To double check the settings applied:
udevadm info /dev/input/event2 | grep KEYBOARD_KEY

E: KEYBOARD_KEY_90=!previoussong
E: KEYBOARD_KEY_99=!nextsong
E: KEYBOARD_KEY_a0=!mute
E: KEYBOARD_KEY_a2=!playpause
E: KEYBOARD_KEY_ae=!volumedown
E: KEYBOARD_KEY_b0=!volumeup
E: KEYBOARD_KEY_b7=!sysrq
E: KEYBOARD_KEY_c7=!home
E: KEYBOARD_KEY_c9=!pageup
E: KEYBOARD_KEY_cf=!end
E: KEYBOARD_KEY_d1=!pagedown
E: KEYBOARD_KEY_ed=!media

Table of keys:

Key Combo Fixes?
F1 Fn + Volume Down Yes
F2 Fn + Mute Yes
F3 Fn + Volume Up Yes
F4 Fn + Previous Song Yes
F5 Fn + Play Pause Yes
F6 Fn + Next Song Yes
F7 Fn + Brightness Down No
F8 Fn + Brightness Up No
F9 Fn + Projector No
F10 Fn + Airplane Mode N/A
F11 Fn + Print Screen Yes
F12 Fn + Framework (Media) Yes
Left Arrow Fn + Home Yes
Right Arrow Fn + End Yes
Down Arrow Fn + Page Down Yes
Up Arrow Fn + Page Up Yes

Explanation (lengthy, click to expand):

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. 
  1. 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.

  1. 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.

  1. 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 + F7Brightness 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:

  1. 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/

  2. https://askubuntu.com/questions/994333/volume-buttons-stay-pressed/1061500#1061500

  3. https://bbs.archlinux.org/viewtopic.php?id=150199

  4. https://wiki.archlinux.org/title/Acpid

  5. https://bbs.archlinux.org/viewtopic.php?id=240543

  6. https://wiki.gentoo.org/wiki/ACPI/ThinkPad-special-buttons

  7. https://askubuntu.com/questions/239560/problem-binding-a-shortcut-to-a-function-multimedia-

1 Like

Wow! Thank you. This makes a lot of sense. I don’t think Windows really relies on the keyrelease events as much, which is why it isn’t as noticeable probably. The only reason why the keyboard appears to work without issues in the regular tty console is because it also doesn’t rely on key release events to detect if you’re holding down a key, but I have no evidence to support this.

So I ended up doing a deeper dive into the issue!

And posted this: