Managing keyboard backlight settings declaratively on the Framework Laptop

Hi!

I’m trying to find a way to declaratively manage a few things on my Framework laptop via NixOS options. Managing keyboard backlight brightness seemed like a good place to start. Currently, I know two ways of controlling this imperatively, so I started looking into ways to manage either of these declaratively.

The first thing I knew worked imperatively was using the Gnome control center in the top right, as seen in this screenshot.

I immediately ran into issues here. My instinct was that these buttons would change something in dconf that I could wrap easily. However, after using dconf watch /, that didn’t seem to be the case. I wasn’t able to find anything online about what’s run internally when interacting with these buttons. This is partially due to the fact that the Gnome Settings app is internally referred to as the “gnome-control-center”, making it nearly impossible to find anything referring to the actual control center. If anyone knows something about how this control center actually works, what it’s internally named, and whether it can be controlled declaratively, let me know! However, I moved on from this after not having much luck.

My second idea was to work with the framework tool directly. I had great luck with this initially – interacting with the brightness imperatively is as simple as installing the kernel module (I have it installed via nixos-hardware), and running the command sudo framework_tool --kblight $BRIGHTNESS.

I thought it’d be trivial to just write a little module that ran these commands. However, I suddenly realized that I didn’t actually know how to actually run these commands via the module system. I then got into a rabbit hole of questions, which I’ll post here for posterity.

Should I just write a bash script and run it conditionally with mkIf? Would that work properly on rebuilds, or persist across reboots? I don’t really see people doing that in nixpkgs, so maybe there’s a better way? Is an activation script the correct choice here? Apparently that’s not performant? What actually is an activation script? Maybe a systemd service? But that seems to be all about running things with timers, which is overcomplicated for what I’m looking for, right? Hmm, maybe I shouldn’t be wrapping the framework tool, and instead just sending the commands directly to the kernel, since I think that’s what it’s doing? How in the world would I do that? Why is it showing the Chromium EC Driver when I’m not on ChromeOS (relevant debug output: [DEBUG] Chromium EC Driver: CrosEc)? Should I be using this magical set_command method? Why does it not show the actual value it’s being set to (debug output when setting the backlight to 50%: [DEBUG] send_command(command=Some(PwmSetKeyboardBacklight), ver=0, data_len=1)? Am I trying to reinvent the wheel here? Why does the manual not say something about this?

My problems here are realistically just my inexperience with writing modules. I’m sure there’s some magic piece of documentation I missed here. If anyone knows how this kind of thing is typically done, please let me know! My instinct is that the easiest way would be to just manage the framework_tool directly, but maybe I’m wrong on this. Let me know!

Just a quick related question:

Wouldn’t it make sense to make the system save the backlight state and restore it after a reboot? Same for Bluetooth, WiFi, Airplane mode, etc. by the way. – Then the user is able to decide once and the solution sticks forever.

There might be a kernel parameter value to achieve that. I just found out about “acpi_backlight”, but that likely refers to screen brightness only. According to the kernel docs the values are:

	acpi_backlight=	[HW,ACPI]
			{ vendor | video | native | none }
			If set to vendor, prefer vendor-specific driver
			(e.g. thinkpad_acpi, sony_acpi, etc.) instead
			of the ACPI video.ko driver.
			If set to video, use the ACPI video.ko driver.
			If set to native, use the device's native backlight mode.
			If set to none, disable the ACPI backlight interface.

Alternatively, ArchLinux has extensive documentation on the topic.

For me, the problem is currently that the keyboard backlight is turned on after every reboot, which is pretty annoying, because I usually turn it off to save battery.

Basically if there is nothing provided, the answer is to make something up yourself. If I had this problem I would make module with two options 1. enable 2. brightness and the implementation would produce an activation script that set the keyboard brightness using whatever stupid command set the keyboard brightness. There might be some cooler way to do it, but this would solve the problem permanently enough that I’d never think about it again. Alternative, don’t use activationScripts, use a one shot systemd service. I don’t think there is much to choose from here, but if you need to depend on a certain device existing then systemd might be a better choice.

Yeah, I ended up writing a module for this that did exactly that, and totally forgot to post it here!

1 Like