still don't have a title

Getting the Function keys of a Keychron working on Linux

Having destroyed the third Cherry Stream keyboard in 4 years, I wanted to try a more substantial keyboard for a change. After some research I decided that I want a mechanical, wired, tenkeyless keyboard without any fancy LEDs.

At the end I settled for a Keychron C1 with red switches. It meets all requirements, looks very nice and the price is reasonable.

Surprise!

After the keyboard was delivered, I connected it to my Debian machine and was unpleasantly surprised to notice that the Function-keys did not work at all. The keyboard shares the Multimedia keys with the F-keys and you have an fn key that supposedly switches between the two modes, like you’re used to on a laptop. On Linux, however you cannot access the F-keys at all: pressing fn + F1 or F1 makes no difference, you’ll always get the Multimedia key. Switching the keyboard between “Windows” and “Mac” mode makes no difference either, in both modes the F-keys are not accessible.

Apparently Keychron is aware of the problem, because the quick start manual tells you:

“We have a Linux user group on facebook. Please search “Keychron Linux Group” on facebook. So you can better experience with our keyboard.”

Customer support at its finest!

So at this point you should probably just send the keyboard back, get the refund and buy a proper one with functioning F-keys.

The fix

Test if this command fixes the issue and enables the Fn + F-key-combos:

# as root:
echo 2 > /sys/module/hid_apple/parameters/fnmode

Depending on the mode the keyboard is in, you should now be able to use the F-keys by simply pressing them, and the Multimedia keys by pressing fn + F-key (or the other way round). To switch the default mode of the F-keys to Function- or Multimedia-mode, press and hold fn + X + L for 4 seconds.

If everything works as expected, you can make the change permanent by creating the file /etc/modprobe.d/hid_apple.conf and adding the line:

options hid_apple fnmode=2

and running

# as root
update-initramfs -u -k all

This works regardless if the keyboard is in Windows- or Mac-mode, and that might hint at the problem: in both cases the Linux thinks you’re connecting a Mac keyboard.

The rant

Although the fix was not very hard to find and apply, this experience still leaves a foul taste. I naively assumed the problem of having a properly functioning keyboard that simply works when you plug it in, has been thoroughly solved by 2021.

To make it worse, I assume Keychron must be aware of the problem because the other Keychron models have the same issue! But instead of fixing it on their end, they forward you to a facebook “community” and expect you to somehow fix it yourself.

So dear Keychron, you do make really beautiful keyboards! But before you release your next model with the same bug, maybe invest a bit on fixing the basics? I see that your keyboards support firmware updates for Windows and Mac – maybe you can talk to the folks over at the Linux Vendor Firmware Service and support Linux as well? Maybe you can even fix this annoying bug for the keyboards you’ve already sold? I found it really cute that you sent different keycaps for Windows and Mac setups – a few disappointed Linux users might accept an apology in form of a Linux cap…

Update (2022-08)

Starting with version 5.19, Linux comes with a fix for the Keychron keyboards, so all models should work as expected out of the box. The relevant commit message says:

Keychron’s C-series and K-series of keyboards copy the vendor and product IDs of an Apple keyboard, but only behave like that device when set to “Mac” mode. In “Windows” mode, the Fn key doesn’t generate a scancode, so it’s impossible to use the F1-F12 keys when fnmode is set to its default value of 1.

To fix this, make fnmode default to the new value of 3, which behaves like fnmode=2 for Keychron keyboards and like fnmode=1 for actual Apple keyboards. This way, Keychron devices are fully usable in both “Windows” and “Mac” modes, while behavior is unchanged for everything else.