DDCUTIL: controlling the brightness of an external monitor

2021-06-25 13:16:27+09:00

TL;DR

For some time I wondered why external displays can't be controlled from software just like internal ones. I care mostly about free software systems, but the grass doesn't seem greener on gatekeeped platforms.

The good news is that, contrary to what I feared, it's not a hardware limitation. Why is software control for external displays so niche? Maybe the market only cares about laptops and desktops are now an afterthought :-).

Digging a bit on the internet led me first to ddcctl for macOS, then quickly to ddcutil for free platforms. DDC, or Display Data Channel, is a protocol to communicate control information with a monitor. When you plug an external monitor on Linux, you might sometime see new i2c devices appearing as/dev/i2c-*. Note that some monitors appear as usb devices, the procedure is essentially the same.

I2C is a very simple communication bus and one of the /dev/i2c-* devices is a door to connect to your monitor. And ddcutil knows what to tell it. However, read/write access might require some privileges, for a first test, lets use sudo:

# List displays that can be controlled
sudo ddcutil detect
# Decrease brightness
sudo ddcutil setvcp 10 - 25
# Increase brightness
sudo ddcutil setvcp 10 + 25

In these executions, ddcutil will scan all devices to find a monitor then transmit the command. The magic number 10 is the identifier of the brightness property, and the sample commands remove or add 25 to it. More magic on setvcp documentation.

Finally, ddcutil comes with some sample udev rules so that you can use it from a normal account. See ddcutil i2c permissions, or /usr/share/ddcutil/data/45-ddcutil-i2c.rules on Arch.

I just had to bind the two setvcp commands to convenient keys and now I can control both the embedded and the external display from my keyboard (albeit with some latency for the external one). Thanks to the authors of ddcctl and ddcutil!