Framework Laptop 16 keyboard backlight pulses on/off by itself on Fedora

Published 14 June 2026

date
env
linux Fedora 44 (GNOME/Wayland) — Framework Laptop 16, AMD Ryzen AI 300, white Keyboard Module (ISO) macos N/A

Symptom

On a Framework Laptop 16 under Fedora, the keyboard backlight “turns on and off by itself” — the brightness ramps up and down on a continuous loop instead of staying at a fixed level. No standard Linux control fixes it:

  • the GNOME Quick Settings keyboard-backlight slider does not appear or has no effect,
  • brightnessctl does not list the keyboard,
  • setting a value with Framework’s own framework_tool appears to do nothing:
$ sudo framework_tool --kblight 80
$ sudo framework_tool --kblight
Keyboard backlight: 80%

The value reads back as 80% but the keys stay dark / keep pulsing.


Root cause

Two independent facts combine here, both confirmed:

  1. The pulsing is the QMK “breathing” effect. The FW16 keyboard runs open QMK firmware, and the white backlight has a breathing animation that smoothly cycles brightness — perceived as the light switching itself on and off. This is firmware behaviour, not a Linux/UPower/driver bug, and not the inactivity timeout. Disabling breathing on the keyboard stops it (verified on this machine).

  2. framework_tool --kblight cannot drive this keyboard. On the FW16 the keyboard is a separate QMK/VIA device with its own microcontroller and is not driven by the embedded controller (EC) (stated by a Framework engineer — see Sources). framework_tool --kblight writes an EC-side value that never reaches the QMK keyboard, so it reads back a number while the keys do not respond. The tool that actually talks to the keyboard is qmk_hid (raw HID).

So the fix is: control the keyboard with qmk_hid and turn the breathing effect off.


Diagnosis

Confirm the false lead and the real cause on your own machine.

Check the keyboard is the separate QMK device (it enumerates as a USB HID keyboard module):

Terminal window
lsusb | grep -i "Framework Laptop 16 Keyboard"

Confirm framework_tool only stores an EC value without lighting the keys:

Terminal window
sudo framework_tool --kblight 80
sudo framework_tool --kblight

If the report shows the percentage but the keys keep pulsing or stay dark, you are in this case: the value is not reaching the QMK keyboard, and the visible pulsing is the breathing effect.


Solution

There is no official one-command fix and no Fedora package for qmk_hid; on Linux it must be built from source. The steps below install the build toolchain, build qmk_hid, then disable the breathing effect.

Prerequisites / warnings

  • qmk_hid releases provide a Windows .exe but no prebuilt Linux binary — Linux users build from source.
  • Writing to the keyboard with qmk_hid requires sudo (or QMK udev rules for non-root access).
  • --save writes to the keyboard’s persistent storage; use it only for settings you want to keep across a keyboard power-cycle.

Steps

  1. Install the build dependencies (HID/udev headers and a C toolchain):

    Terminal window
    sudo dnf install systemd-devel hidapi-devel gcc pkgconf-pkg-config
  2. Install a Rust toolchain. This machine already uses mise, so no root is needed:

    Terminal window
    mise use -g rust
    cargo --version
  3. Get the source. Download the Source code (zip) from the releases page rather than cloning — on this machine git clone over HTTPS prompted for a GitHub username/password and failed (a public repo does not need authentication; this happens when the local git config rewrites the URL to SSH or injects a credential helper). The release ZIP needs no authentication.

    Download from https://github.com/FrameworkComputer/qmk_hid/releases, then:

    Terminal window
    cd ~/Downloads
    unzip qmk_hid-0.1.13.zip
    cd qmk_hid-0.1.13
  4. Build and install the binary:

    Terminal window
    cargo build --release
    sudo install -m755 target/release/qmk_hid /usr/local/bin/qmk_hid
  5. Disable the breathing effect and set a steady level (white keyboard uses --backlight):

    Terminal window
    sudo qmk_hid via --backlight-breathing false --save
    sudo qmk_hid via --backlight 80 --save

Verify

The binary is installed:

Terminal window
qmk_hid --version

Breathing is off and the brightness is the value you set:

Terminal window
sudo qmk_hid via --backlight-breathing
sudo qmk_hid via --backlight

Expected: breathing reports false and backlight reports 80. The keyboard now stays lit at a constant level instead of pulsing.


Alternatives

  • GNOME slider + brightness keys. Disabling breathing fixes the self-toggling, but the keyboard is still not a native UPower.KbdBacklight device, so GNOME’s slider and keyboard-brightness keys won’t adjust it. A userspace uleds → UPower bridge (a small daemon that exposes a virtual kbd_backlight LED and relays writes to qmk_hid via --backlight) restores native control. See the companion how-to fw16-keyboard-backlight-gnome.md. This is optional and does not affect the pulsing.
  • framework_tool --kblight. Works for EC-side functions on other Framework models but does not drive the FW16 keyboard backlight; do not rely on it here.
  • Firmware update. If instead of pulsing the backlight turns off only after inactivity, that is a separate timeout/USB-suspend behaviour addressed in recent Framework QMK firmware releases — update the keyboard firmware rather than using the breathing flag.

Sources

Sources verified on 2026-06-14.