Skip to content

Instantly share code, notes, and snippets.

@andrebrait
Last active September 17, 2024 19:49
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.

@JwanKhalaf
Copy link

Thanks @andrebrait. So, if the K15 Pro uses QMK as firmware, instead of trying to impersonate an Apple keyboard, does that mean I should have the switch on the keyboard pointing at Windows?

Also, my understanding is that VIA has more to do with customising the keyboard mappings. My issue is that the keyboard isn't being detected when searching for Bluetooth devices.

I suspect it might be related to my Asus ProArt X670E-Creator Wifi motherboard because on my ThinkPad T480s laptop (also running Arch), the laptop is detected and paired fine. I also tried it on my iPhone (iOS) and on there, it works fine too (it pairs and I can type on my iPhone using the K15 Pro).

@andrebrait
Copy link
Author

Thanks @andrebrait. So, if the K15 Pro uses QMK as firmware, instead of trying to impersonate an Apple keyboard, does that mean I should have the switch on the keyboard pointing at Windows?
For Linux, yes, but that's only mapping, as yoh noted below as well. For pairing issues, I honestly have no clue. Maybe they have an update on their firmware repository? Probably worth looking at what I mention further down below instead, though.

Also, my understanding is that VIA has more to do with customising the keyboard mappings. My issue is that the keyboard isn't being detected when searching for Bluetooth devices.

I suspect it might be related to my Asus ProArt X670E-Creator Wifi motherboard because on my ThinkPad T480s laptop (also running Arch), the laptop is detected and paired fine. I also tried it on my iPhone (iOS) and on there, it works fine too (it pairs and I can type on my iPhone using the K15 Pro).

Depending on the Bluetooth controller it uses, it could be it. I'm assuming it's an Intel AX210, right? If so, that should work well and it's weird that you're having issues.

Maybe you can try to look up issues with the BT controller on Linux then.

@nmicht
Copy link

nmicht commented Jan 22, 2024

Does any one see issues with K1 SE having issues when connected via bluetooth to ubuntu? In my case:

* intermittently the keyboard gets mad and starts typing by itself, sometimes just starts adding the last character I made an input for... for example something like `exxxxxaaaaaaaaaaaaaaaaaaaaaaaaammmmplllllllllllleeeee` etc. This is really weird and I've been facing this for a long time. This doesn't happen even once while connected via Cable...

Same on K6 and fedora

@ipiepiepie I had the same issue in Ubuntu 22 and K7. It was resolved by enabling the Bluetooth fast connect. I hope this works for you.

@javierspn
Copy link

Does any one see issues with K1 SE having issues when connected via bluetooth to ubuntu? In my case:

* intermittently the keyboard gets mad and starts typing by itself, sometimes just starts adding the last character I made an input for... for example something like `exxxxxaaaaaaaaaaaaaaaaaaaaaaaaammmmplllllllllllleeeee` etc. This is really weird and I've been facing this for a long time. This doesn't happen even once while connected via Cable...

Same on K6 and fedora

@ipiepiepie I had the same issue in Ubuntu 22 and K7. It was resolved by enabling the Bluetooth fast connect. I hope this works for you.

This is confirmed to solve a lot of issues.

@GERJanB
Copy link

GERJanB commented Mar 9, 2024

I currently face a Problem with my K8 Pro where I can use it in wired mode just fine but when I try to use it via Bluetooth, i can connect it just fine but I cannot do any input.

I get this error in journalctl -u bluetooth

profiles/input/device.c:ioctl_is_connected() Can't get HIDP connection info
profiles/input/device.c:hidp_add_connection() Rejected connection from !bonded device /org/bluez/hci0/dev_6C_93_08_62_55_AF

and this on systemctl status bluetooth

profiles/input/device.c:hidp_add_connection() Rejected connection from !bonded device /org/bluez/hci0/dev_6C_93_08_62_55_AF

@andrebrait
Copy link
Author

andrebrait commented Mar 9, 2024

I currently face a Problem with my K8 Pro where I can use it in wired mode just fine but when I try to use it via Bluetooth, i can connect it just fine but I cannot do any input.

I get this error in journalctl -u bluetooth

profiles/input/device.c:ioctl_is_connected() Can't get HIDP connection info
profiles/input/device.c:hidp_add_connection() Rejected connection from !bonded device /org/bluez/hci0/dev_6C_93_08_62_55_AF

and this on systemctl status bluetooth

profiles/input/device.c:hidp_add_connection() Rejected connection from !bonded device /org/bluez/hci0/dev_6C_93_08_62_55_AF

The K Pro line is QMK-based and thus an entirely different beast. Some of the tips here, however, might help in general. Have you tried enabling fast connect?

@GERJanB
Copy link

GERJanB commented Mar 9, 2024

Yes I have enabled that. Also made sure that hid-generic module is loaded. The board connects fine. It shows up in blueman and Bluetooth to as connected. But no input is made when I press a key

@parkerlreed
Copy link

parkerlreed commented Mar 18, 2024

Enable Bluetooth fast connect config:

Holy crap thank you. My K10 was taking 10+ seconds for the reconnect.

@rafakwolf
Copy link

Hey folks, anyone was able to show the battery percentage?

@parkerlreed
Copy link

parkerlreed commented Mar 19, 2024

Hey folks, anyone was able to show the battery percentage?

That should already be reported via upower and your Desktop environment.

upower -e to list

and upower -i <keyboardpath> to get the info

@rafakwolf
Copy link

rafakwolf commented Mar 19, 2024

Thanks @parkerlreed , what's "upower" ? It looks like the battery percentage is not shared by the keyboard. So my DE is not able to show it up.
For instance, I also have a Logitech Bluetooth mouse, and I can see the battery percentage

@parkerlreed
Copy link

Thanks @parkerlreed , what's "upower" ? It looks like the battery percentage is not shared by the keyboard. So my DE is not able to show it up. For instance, I also have a Logitech Bluetooth mouse, and I can see the battery percentage

I added some more info. You can check the command line to see if it shows up.

@parkerlreed
Copy link

Keep in mind, this would only work for Bluetooth.

@rafakwolf
Copy link

@parkerlreed Thank you so much for the help, but, unfortunately, my keyboard does not even appear on the list when I run upower -e

@mchlschlz
Copy link

On Debian Sid running 6.7.9 my K2 Pro Wireless (using a wired connection) is being picked up by hid-generic instead of hid-apple. Thus, function keys are not working. Only the mute, volup and voldown do.
I have tried forcing the device into hid-apple with a udev rule but was not successful.

@andrebrait
Copy link
Author

@mchlschlz yes, the Pro line is a completely different beast. See the note from the beginning of the document:

Note: K-Pro and Q-Pro series 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 else, especially stuff related to Apple's keyboard module on Linux, likely won't work.

@mchlschlz
Copy link

Note: K-Pro and Q-Pro series 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 else, especially stuff related to Apple's keyboard module on Linux, likely won't work.

🤦 man have I overlooked that... thank you for pointing it out. hm not sure where to go from here tbh.

@andrebrait
Copy link
Author

@mchlschlz because it's QMK, it should work just fine. Keychron probably has some shortcuts or something to alternate the behavior.

Normally the function keys would be on a separate layer you'd access by holding Fn. When in Mac mode, it should be the opposite. Media keys by default and F keys accessed by holding Fn.

@patrislav1
Copy link

On Debian Sid running 6.7.9 my K2 Pro Wireless (using a wired connection) is being picked up by hid-generic instead of hid-apple. Thus, function keys are not working. Only the mute, volup and voldown do. I have tried forcing the device into hid-apple with a udev rule but was not successful.

Just set the OS switch on the back of the keyboard to "Win/Android" and everything, including function keys, will work out of the box with hid-generic.

@patrislav1
Copy link

I believe the following text in the gist is misleading and should probably be changed:

"Keychron Keyboards on Linux use the hid_apple driver (even in Windows/Android mode)"

AFAICS, the K-Pro series, and maybe even all QMK based models, do not use hid_apple but hid_generic, and their function keys work out of the box without any fiddling.

@andrebrait
Copy link
Author

@patrislav1 ah, yeah. I probably forgot to update that section.

Will do that.

This gist is quite old.

@mchlschlz
Copy link

On Debian Sid running 6.7.9 my K2 Pro Wireless (using a wired connection) is being picked up by hid-generic instead of hid-apple. Thus, function keys are not working. Only the mute, volup and voldown do. I have tried forcing the device into hid-apple with a udev rule but was not successful.

Just set the OS switch on the back of the keyboard to "Win/Android" and everything, including function keys, will work out of the box with hid-generic.

Well, I feel dumb now. I tried that to see whether it picks up the hid-apple 😅 but never checked if the function keys work. They do. Thank you. 🙏

@rogeriopvl
Copy link

rogeriopvl commented Apr 21, 2024

Thanks @andrebrait. So, if the K15 Pro uses QMK as firmware, instead of trying to impersonate an Apple keyboard, does that mean I should have the switch on the keyboard pointing at Windows?

Also, my understanding is that VIA has more to do with customising the keyboard mappings. My issue is that the keyboard isn't being detected when searching for Bluetooth devices.

I suspect it might be related to my Asus ProArt X670E-Creator Wifi motherboard because on my ThinkPad T480s laptop (also running Arch), the laptop is detected and paired fine. I also tried it on my iPhone (iOS) and on there, it works fine too (it pairs and I can type on my iPhone using the K15 Pro).

@JwanKhalaf Did you end up getting this to work? I’m having the same issue with a K3 Max on Ubuntu 22 (Thinkpad x1 nano). The k3 doesn’t show up in bt devices, it never did actually. I can pair with other devices, but not the keyboard.

@samgagne
Copy link

Hello,
Sorry I am kinda newb on Linux so maybe this is a dumb question. When I try to alter the /etc/bluetooth/main.conf file, I don't see the FastConnectable field. Is it because I have an older version of the config file ? I am on Manjaro, is the config file different on that system than Debian distros ? Had no trouble adapting the steps so far but this one is bugging me.
Thanks

@parkerlreed
Copy link

You can add the field. It depends on whatever the distro shipped as their default.

@Kranerian
Copy link

Unsure if this is a good place to ask. I have a Keychron K2 and am running MX Linux. Everything works fine at my desk. but less than 10 feet away the keyboard is unusable due to extreme input lag. It works fine when I'm booted into Windows though.

@tvallois
Copy link

tvallois commented Aug 6, 2024

Hmm i've a strange issue with a k2 where keyboard mapping is not working properly only in bluetooth. E.g, "o" is returning "6"... Not sure to understand why.

@m0mosenpai
Copy link

m0mosenpai commented Aug 8, 2024

I currently face a Problem with my K8 Pro where I can use it in wired mode just fine but when I try to use it via Bluetooth, i can connect it just fine but I cannot do any input.

I get this error in journalctl -u bluetooth

profiles/input/device.c:ioctl_is_connected() Can't get HIDP connection info
profiles/input/device.c:hidp_add_connection() Rejected connection from !bonded device /org/bluez/hci0/dev_6C_93_08_62_55_AF

and this on systemctl status bluetooth

profiles/input/device.c:hidp_add_connection() Rejected connection from !bonded device /org/bluez/hci0/dev_6C_93_08_62_55_AF

@GERJanB I have been seeing the exact same error on Arch with my Keychron K2v2 (it's the Japanese Layout version but I'm not sure if that makes a difference). It works perfectly fine in wired mode but no input is registered in Bluetooth mode. Were you able to find a fix for this?

@boscho87
Copy link

I currently face a Problem with my K8 Pro where I can use it in wired mode just fine but when I try to use it via Bluetooth, i can connect it just fine but I cannot do any input.
I get this error in journalctl -u bluetooth

profiles/input/device.c:ioctl_is_connected() Can't get HIDP connection info
profiles/input/device.c:hidp_add_connection() Rejected connection from !bonded device /org/bluez/hci0/dev_6C_93_08_62_55_AF

and this on systemctl status bluetooth
profiles/input/device.c:hidp_add_connection() Rejected connection from !bonded device /org/bluez/hci0/dev_6C_93_08_62_55_AF

The K Pro line is QMK-based and thus an entirely different beast. Some of the tips here, however, might help in general. Have you tried enabling fast connect?

Same here

Some news?

Im ON EndavourOs (Arch Linux, with Sway Desktop)

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