Skip to content

Instantly share code, notes, and snippets.

@andrebrait
Last active July 17, 2025 16:18
Show Gist options
  • Save andrebrait/961cefe730f4a2c41f57911e6195e444 to your computer and use it in GitHub Desktop.
Save andrebrait/961cefe730f4a2c41f57911e6195e444 to your computer and use it in GitHub Desktop.
Keychron keyboards on Linux + Bluetooth fixes

Here is the best setup (I think so :D) for K-series Keychron keyboards on Linux.

Note: many newer Keychron keyboards use QMK as firmware and most tips here do not apply to them. Maybe the ones related to Bluetooth can be useful, but everything related to Apple's keyboard module (hid_apple) on Linux, won't work. As far as I know, all QMK-based boards use the hid_generic module instead. Examples of QMK-based boards are: Q, Q-Pro, V, K-Pro, etc.

Most of these commands have been tested on Ubuntu 20.04 and should also work on most Debian-based distributions. If a command happens not to work for you, take a look in the comment section.

Make Fn + F-keys work (NOT FOR QMK-BASED BOARDS)

Older Keychron keyboards (those not based on QMK) use the hid_apple driver on Linux, even in the Windows/Android mode, both in Bluetooth and Wired modes. By default, this driver uses the F-keys as multimedia shortcuts and you have to press Fn + the key to get the usual F1 through F12 keys.

In order to change this, you need to change the fnmode parameter for the hid_apple kernel module. Here's some documentation on it, but a quick summary can be found below:

  • 0 = disabled: Disable the 'fn' key. Pressing 'fn'+'F8' will behave like you only press 'F8'
  • 1 = fkeyslast: Function keys are used as last key. Pressing 'F8' key will act as a special key. Pressing 'fn'+'F8' will behave like a F8.
  • 2 = fkeysfirst: Function keys are used as first key. Pressing 'F8' key will behave like a F8. Pressing 'fn'+'F8' will act as special key (play/pause).

You can temporarily set the value (for testing, for example) by doing:

# replace <value> below with 0, 1 or 2
# example: echo 2 | sudo tee /sys/module/hid_apple/parameters/fnmode
echo <value> | sudo tee /sys/module/hid_apple/parameters/fnmode

Test how the keyboard behaves after each value. Pick the one the works for you. Once you have found the value that works for you, you can make the change permanent:

  1. Create the file /etc/modprobe.d/hid_apple.conf
  2. Add this line to the file: options hid_apple fnmode=<value>, replacing <value> with the one that worked for you in the previous step (0, 1 or 2)
  3. Save the file
  4. Run sudo update-initramfs -u
  5. Reboot

Here's a script, for convenience:

# replace <value> below with the one that worked for you in the previous step (0, 1 or 2)
# example: echo "options hid_apple fnmode=2 | sudo tee /etc/modprobe.d/hid_apple.conf"
# this will erase any pre-existing contents from /etc/modprobe.d/hid_apple.conf
echo "options hid_apple fnmode=<value>" | sudo tee /etc/modprobe.d/hid_apple.conf
# the "-k all" part is not always needed, but it's better to do that for all kernels anyway
sudo update-initramfs -u -k all
sudo systemctl reboot

If get stuck with numpad mode: Double hit F6 or fn + F6.

Enable Bluetooth fast connect config:

If your keyboard takes too long to connect to your computer over Bluetooth (for example, when you press a key and wakes it up), you can enable the Bluetooth fast connect. This usually makes the keyboard connect in less than 1 second.

Some users have reported issues with Bluetooth headphones such as popping audio and general instability, but I haven't experienced anything like that.

  1. Edit the file /etc/bluetooth/main.conf
  2. Uncomment FastConnectable config and set it to true: FastConnectable = true
  3. Uncomment ReconnectAttempts=7 (set the value to whatever number that you want)
  4. Uncomment ReconnectIntervals=1, 2, 3

Disable Autosuspend for USB Bluetooth dongles:

If your keyboard just won't reconnect after sleep, it might be because your Bluetooth card or dongle was automatically suspended by the operating system. You can disable the auto suspend feature for USB Bluetooth dongles by changing the settings for the btusb module.

Note: you might need to target a different module if your Bluetooth controller is somehow using some other module. The options and values themselves might change as well. You need to check the documentation for the module your Bluetooth controller uses. Most USB Bluetooth dongles (and sometimes internal cards that are wired to the USB bus) use btusb. Please check if the btusb module is used by your controller first.

# Disable autosuspend for btusb to make the bluetooth keyboard work again
# this will erase any pre-existing contents from /etc/modprobe.d/btusb_disable_autosuspend.conf
echo "options btusb enable_autosuspend=n" | sudo tee /etc/modprobe.d/btusb_disable_autosuspend.conf
sudo update-initramfs -u

Now reboot your computer, or run:

sudo modprobe -r btusb
sudo systemctl restart bluetooth
sudo modprobe btusb

Enable Bluetooth after waking up from sleep:

When your computer wakes up from sleep mode, the Bluetooth controller might not turn on automatically. In order to force it to do so, we can create a script that will be executed every time the computer comes back from sleep mode.

Note: just like in the previous step, this script assumes your Bluetooth controller uses the btusb module.

# Unload the btusb module, restart the bluetooth service and reload the module again
# post = after the computer wakes up
sudo tee /lib/systemd/system-sleep/bt << EOT
#!/bin/sh
case $1 in
  post)
    modprobe -r btusb
    sleep 1
    service bluetooth restart
    sleep 1
    modprobe btusb
    ;;
esac
EOT
# Now let's make the script executable
sudo chmod +x /lib/systemd/system-sleep/bt

Other resources

If the steps above haven't done it for you, try checking kurgol/keychron. Currently, it only mentions K2 and K6 keyboards, but the tips should work for most Keychron boards.

@harrychopra
Copy link

Unfortunately on POP OS (Ubuntu), The fnmode option 1 doesn't work on my Keychron K2V2. Both with & without Fn key pressed, the function keys are read as special keys. So, I had to resort to selecting option 2 i.e. to have the function keys read as function keys as default & special keys with the Fn key pressed. Also tested with option 0 which behaves the same as option 2.

Leaving this comment, in case anyone else have a similar experience or an alternative fix. Thanks!

@nevertomorrow
Copy link

@christianpadovano I'm using Linux Mint 21 and I have same issue like yours. I ended up with pairing my Keychron K2 through terminal. This article contains all the commands you'll need. And it works for me like a charm. (Well, my original thoughts was to check detailed errors during re-pairing)

@Roman-AE
Copy link

Roman-AE commented Aug 25, 2022

Unfortunately on POP OS (Ubuntu), The fnmode option 1 doesn't work on my Keychron K2V2. Both with & without Fn key pressed, the function keys are read as special keys. So, I had to resort to selecting option 2 i.e. to have the function keys read as function keys as default & special keys with the Fn key pressed. Also tested with option 0 which behaves the same as option 2.

Leaving this comment, in case anyone else have a similar experience or an alternative fix. Thanks!

For some reason fnmode 3 (not listed there) works for option 2 (fkeyslast: Function keys are used as last key. Pressing 'F8' key will act as a special key. Pressing 'fn'+'F8' will behave like a F8.). Tested on Ubuntu 22.04 with Keychron K3 (Bluetooth, Windows mode).

@harrychopra
Copy link

@Roman-AE Mate, POP was a tad unstable for me with occasional freezes (known issue) and odd bugs in their bundled software. Since I posted my original comment, I have returned to Ubuntu 22.04 and Option 2 works as described in the Gist. I rely somewhat on the function keys and I'm happy with the setting. Glad you found the solution for yourself and thanks for posting it here. I'm sure it would help someone with your config and similar requirement. Cheers!

@Max95Cohen
Copy link

Hello, there!

For Keychron K8L1 functional keys and multimedia keys work. Thanks for author!

@khaled4vokalz
Copy link

Worked for Keychron K7,

Thanks :)

@r-vdp
Copy link

r-vdp commented Sep 13, 2022

@khaled4vokalz how's the K7 on Linux? Are all the keys working correctly with fn1 and fn2?

@khaled4vokalz
Copy link

@r-vdp , It works fine... Except for the fact that Function keys doesn't work by default. https://gist.github.com/andrebrait/961cefe730f4a2c41f57911e6195e444

And personally, I don't like the fact that it doesn't have a separate row for numbers :( it blocks productivity (WPM) when you have to use ` (backticks) by pressing two keys and ~ (tilda) by pressing three :(

@sayeg84
Copy link

sayeg84 commented Sep 26, 2022

Is there an alternative that doesn't require root permission?

@andrebrait
Copy link
Author

Is there an alternative that doesn't require root permission?

@sayeg84 I guess not. Every alternative I looked up for changing fnmode requires root.

@dilayn
Copy link

dilayn commented Sep 29, 2022

Hello, I have an issue with the K2 when using Bluetooth and I don't know if this is normal behavior or if it can be fixed. the keyboard seems to go in a semi-asleep state after 3 to 10+ seconds of idling, where the first key press after idling for 3 to 10+ seconds will be slightly delayed. A similar issue seems to occur if I'm holding down a key for 3 to 10+ seconds, where releasing the key won't immediately register

So for example if I'm playing a game and I'm holding W to move forward for 3 to 10+ seconds or more and I release W to stop moving, my character would move a few more steps before stopping. Similarly if I stand idle and do nothing for 3 to 10+ seconds and then I press W to move forward, my character would only move after a short delay.

The reason I say 3 to 10+ seconds and not 3+ seconds is because this sometimes happens if it's between 3 to 10 seconds but will ALWAYS happen if it's more than 10 seconds.

Any ideas? This never happened with the 2.4g wireless keyboard I used before this.

@andrebrait
Copy link
Author

Hello, I have an issue with the K2 when using Bluetooth and I don't know if this is normal behavior or if it can be fixed. the keyboard seems to go in a semi-asleep state after 3 to 10+ seconds of idling, where the first key press after idling for 3 to 10+ seconds will be slightly delayed. A similar issue seems to occur if I'm holding down a key for 3 to 10+ seconds, where releasing the key won't immediately register

So for example if I'm playing a game and I'm holding W to move forward for 3 to 10+ seconds or more and I release W to stop moving, my character would move a few more steps before stopping. Similarly if I stand idle and do nothing for 3 to 10+ seconds and then I press W to move forward, my character would only move after a short delay.

The reason I say 3 to 10+ seconds and not 3+ seconds is because this sometimes happens if it's between 3 to 10 seconds but will ALWAYS happen if it's more than 10 seconds.

Any ideas? This never happened with the 2.4g wireless keyboard I used before this.

Bluetooth is a completely different thing. The K2 has a key combo to disable sleep. You can try that. It's still supposed to sleep, however.

Did you try enabling the FastConnect?

@KuleRucket
Copy link

KuleRucket commented Sep 29, 2022

@dilayn I experienced something similar when using the K7 3m away from the PC while sitting on my sofa. First I was using the on-board bluetooth adapter. Next I tried with a small TP-Link dongle which made it better but didn't fix it. However this problem only went away when I got a long range Class 1 BT adapter and it works perfectly now even at 10m through 2 walls.

None of my other BT devices had a problem but I think the keyboard just has quite a weak BT signal compared to e.g. an xbox controller.

@dilayn
Copy link

dilayn commented Sep 29, 2022

Yes, and I also disabled the AutoSuspend... and I tried disabling the autosleep as well, still the same.

@dilayn
Copy link

dilayn commented Sep 29, 2022

@dilayn I experienced something similar when using the K7 3m away from the PC while sitting on my sofa. First I was using the on-board bluetooth adapter. Next I tried with a small TP-Link dongle which made it better but didn't fix it. However this problem only went away when I got a long range Class 1 BT adapter and it works perfectly now even at 10m through 2 walls.

None of my other BT devices had a problem but I think the keyboard just has quite a weak BT signal compared to e.g. an xbox controller.

hmm, then this could be due to that fact I have the BT dongle plugged into a USB hub? The USB hub is wall powered and is connected to the PC with a 3m cable

@dilayn
Copy link

dilayn commented Sep 29, 2022

yep that fixed it... I gotta find a good class 1 long range adapter then. any recommendation?

@andrebrait
Copy link
Author

yep that fixed it... I gotta find a good class 1 long range adapter then. any recommendation?

What did you do? Move the BT dongle off the hub to a USB port on the computer itself?

Is your USB hub 3.0? USB 3.0 hubs are known to cause interference with some 2.4GHz devices.

@dilayn
Copy link

dilayn commented Sep 29, 2022

Yes and yes, but for some reason the issue is completely fixed now even when I put the dongle back in the hub... I tried unplugging and re-pairing earlier which didn't help. The only different thing I tried right now is pairing the keyboard with the dongle connected to a PC USB port before moving the dongle back to the hub. Interesting...

@KuleRucket
Copy link

I have the Bluetooth 5.0 version of this:
https://www.amazon.de/-/en/Bluetooth-Distance-Transmitter-Compatible-Smartphone-black-gold/dp/B09NVPTS6J?ref_=ast_sto_dp&th=1

The 5.0 version works well in Linux, but can't say whether the 5.1 version would or not.

@lbrealdev
Copy link

Thanks for the solution, performing a quick test, I see a total difference, but I still have some characters not working, for example the "|" (pipe). Can anyone tell me where to go, maybe it would be necessary to remap the keys ?

@lbrealdev
Copy link

lbrealdev commented Oct 21, 2022

Thanks for the solution, performing a quick test, I see a total difference, but I still have some characters not working, for example the "|" (pipe). Can anyone tell me where to go, maybe it would be necessary to remap the keys ?

I come here to say that I managed to solve my problem and configure the keys I needed, and in the end my configuration looked like this:

Fn keys:

echo "options hid_apple fnmode=0" | sudo tee /etc/modprobe.d/hid_apple.conf

Keyboard layout configuration /etc/default/keyboard:

# KEYBOARD CONFIGURATION FILE

# Consult the keyboard(5) manual page.

XKBMODEL="pc105"
XKBLAYOUT="us,br"
XKBVARIANT=""
XKBOPTIONS="grp: alt_shift_toggle"

BACKSPACE="guess"

NOTE: To make everything work correctly it is necessary to switch between the layouts configured on the keyboard, of course as I was already used to this, for me it is not a difficult task.

Switch between configured keyboard layouts:

Ctrl + Alt + Shift

If it helps, my setup is:

Thanks for that!!

@RemcoSchrijver
Copy link

Adding the hid_apple.conf file makes it such that wired mode no longer works for at least the K4 keyboard, when it is working fine for other devices like my android phone. But setting fnmode manually does work so that is a thing to note when doing this.

@rodrmigu
Copy link

Worked on my K1, and solved both issues, Bluetooth slow connection, and Fn+Keys.
Thanks.

@nilsmagnus
Copy link

Thanks. Confirmed on a thinkpad z13 with ubuntu 22.04 and keychron k8.

@madushan1000
Copy link

Looks like ubuntu lts 22.04 5.15 kernel has this patch backported (https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/diff/drivers/hid/hid-apple.c?id=v5.19&id2=v5.18). So setting fnmode to 3 works. But for some reason it's not the default.

@kespineira
Copy link

kespineira commented Nov 7, 2022

Hi! I'm trying to connect my K6 by bluetooth but not once it establishes the connection it disconnects instantly. I'm using Ubuntu 22.04.

@tutikaka
Copy link

tnx

@hwilson03
Copy link

Sorted a lot of problems for me on Keychron K3

@ErdemOzgen
Copy link

sudo mkinitcpio -P can be use for arch based system instead of sudo update-initramfs -u

@gavingc
Copy link

gavingc commented Nov 17, 2022

Success & Thanks to Everyone

Keychron K4V2 on Debian 11 (11.5 Bullseye) w/Keychron Firmware

Out of the box, fnmode reported as 1 by:
cat /sys/module/hid_apple/parameters/fnmode

fnmode = 0 or 2 (I chose 2 but both seemed to work the same)

Keyboard switches: Windows/Android, Bluetooth or Cable.

As per included instructions, press "fn + x + l" keys together for 4 seconds.
(until keyboard lights flash; yes lower case works)
This toggles between Multimedia Keys and F1-F12 as first layer.

Caps Lock LED is red only and works as expected.

Num Lock LED is red only and works as expected, but it is possible to get into a state where it is always-off by playing with the NumLock on laptop keyboard or Plasma Startup settings.
Personally, I'd like an always-off state that was reliable as I have the OS force Num Lock function on, so don't need the red LED amongst my chosen RGB.
In either case the Num Lock key still works as expected.

Keyboard 'model' used: Generic 105-key PC (intl.).
Keyboard layout: us.

Bonus:
Fn + F5 adjusts RGB brightness down.
Fn + F6 adjusts RGB brightness up.
Fn + lamp key toggles RGB on/off and keeps brightness setting.

Would be fantastic to see QMK fully support these keyboards + Bluetooth - fingers crossed!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment