Ghetto Brightness Control

in /var/log

This is the second post in the series where I’m trying to switch away from the mac for a while.

One of the things I miss is the ability to adjust brightness of my monitor with the multimedia keyboard keys. When at home, my mac is usually hooked up to a 22” LG UltraFine, which controls its brightness automatically based on the ambient light sensor on the laptop, or I could adjust it by holding ctrl and using the brigthness keys on my MX Keys keyboard. If I plug the laptop into my Dell (which is usually hooked to the Linux desktop), I then use a tiny tool called MonitorControl to control the brightness with the multimedia keys. I can’t do that on the Linux desktop.

Tapping the brightness buttons does move the slider in the taskbar but the monitor's brightness remains unchanged.
Tapping the brightness buttons does move the slider in the taskbar but the monitor's brightness remains unchanged.

I did a bit of research online and the general consensus seems to be that you need a specific kernel extension to make it work for your particular setup. Screw that - there’s gotta be another way. Digging a bit further reveals the way MonitorControl works on the mac is by talking to the monitor with a protocol called DDC/CI, or Display Data Channel / Command Interface. It turns out ddcutil for Linux does just that.

It has a super simple command line interface. If you have more than one screen attached to your computer, you will need to work out which monitor’s brightness you’ll want to control:

$ ddcutil detect

Next run

$ ddcutil capabilities

and make a note of the number of the feature you’d like to control. On my machine brightness is 10, so to change it, the command is simply:

$ ddcutil setvcp 10 50

where the argument after setvcp is the code for the brightness VCP feature, and the next one is the desired brightness value between 0-100. Easy!

Ok, so if there’s a way to run this command every time I hit one of the brightness keys, then my all my troubles are over. I could set up a standard Ubuntu keyboard key assignment, e.g. pressing Meta + + would increase brightness, but I want to use the media keys for that.

If you read carefully, I did mention that my brightness multimedia keys are already moving the brightness slider back and forth. Luckily Pop_OS! stores this slider’s value in a file

$ cat /sys/class/backlight/acpi_video0/brightness

That’s right, try changing the slider either with your mouse or with the keyboard and watch the contents of the file change. Another file stores the maximum value: /sys/class/backlight/acpi_video0/max_brightness. Nice! Let’s put that in a script we can call once we have set our brightness to the desired level.

#!/bin/env ruby
slider_current ='/sys/class/backlight/acpi_video0/brightness')
slider_max ='/sys/class/backlight/acpi_video0/max_brightness')

brightness_max = 100

ratio = Float(slider_current) / Float(slider_max)

brightness = (ratio * brightness_max).to_i

`ddcutil setvcp 10 #{brightness}`

Move the slider and run your script. Sweet! Now all we need is something that will run our script everytime the slider changes. I’ll use a Rust program called watchexec which does exactly what you’d think - it watches a file for changes and runs a command everytime it does. Time to put all that in a systemd service so it runs on the background at boot. Let’s create a new service:

Description=Ghetto brightness control
ExecStart=~/.cargo/bin/watchexec -w /sys/class/backlight/acpi_video0/brightness /usr/local/bin/ghetto-brightness-control

You might need to expand ~ to the full home path and obviously substitute with the correct path to your script, but the rest should be more or less the same. Save that under ~/.local/share/systemd/user/ghetto-brightness-control.service and then enable it:

$ sudo systemctl --user enable ghetto-brightness-control.service

Well done! Now you can control the brightness of the monitor either by dragging the slider or tapping the multimedia keys.

Other entries in Linux as an alternative to mac for work