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!