Using ddccontrol as a non-root user
Most modern computer monitors support Display Data Channel which allows the screen brightness/contrast/input to be changed without using the on screen display. Many DDC implementations "just work" over HDMI, DisplayPort, or DVI by creating an i2c interface. Some monitors, like Dell Ultrasharps, also expose a DDC/i2c interface via USB.
Fortunately, several Linux programs exist to interact with the DDC interface. ddcutil is a CLI based program that expects monitors to use the MCCS 2.0 standard. ddccontrol provides a GUI as well as CLI interface. However, ddccontrol
relies on a database of known working monitors. The GUI for ddccontrol
may or may not work if the monitor is not 'officially' supported. Despite these shortcoming, ddccontrol
was able to interface with one of my monitors while ddcutil
was not able to.
Typically only the root
user has access to the i2c devices (/dev/i2c-*
) on a machine meaning gddccontrol
and ddcutil
have to be ran as root. One potential solution to allow non-root users to use DDC is to add them to the i2c
group. However, this means users can access any i2c device, not just monitors supporting i2c, which has been expressed as a security concern.
My solution is to create a new group ddc
that is explicitly granted access to DDC devices via udev
rules. Non-root users can be added to the ddc
group and will only gain write access to the necessary i2c devices for DDC to work.
The first step is to determine the i2c devices representing the DDC interfaces.
# ddccontrol -p
ddccontrol version 0.4.2
Copyright 2004-2005 Oleg I. Vdovikin (oleg@cs.msu.su)
Copyright 2004-2006 Nicolas Boichat (nicolas@boichat.ch)
This program comes with ABSOLUTELY NO WARRANTY.
You may redistribute copies of this program under the terms of the GNU General Public License.
Probing for available monitors...............
Detected monitors :
- Device: dev:/dev/i2c-18
DDC/CI supported: Yes
Monitor Name: Dell U2518D
Input type: Digital
(Automatically selected)
- Device: dev:/dev/i2c-10
DDC/CI supported: Yes
Monitor Name: LG IPS226V-PN
Input type: Digital
...
ddccontrol
found two monitors on /dev/i2c-18
and /dev/i2c-10
. It can be useful to double check the devices are supported by udev with:
$ udevadm info -q path -n /dev/i2c-18
/devices/pci0000:00/0000:00:03.1/0000:0c:00.0/i2c-18/i2c-dev/i2c-18
$ udevadm info -q path -n /dev/i2c-10
/devices/pci0000:00/0000:00:03.1/0000:0c:00.0/i2c-10/i2c-dev/i2c-10
To write the necessary udev rules the KERNEL
and SUBSYSTEM
need to be known:
$ udevadm info -a -p $(udevadm info -q path -n /dev/i2c-18)
looking at device '/devices/pci0000:00/0000:00:03.1/0000:0c:00.0/i2c-18/i2c-dev/i2c-18':
KERNEL=="i2c-18"
SUBSYSTEM=="i2c-dev"
DRIVER==""
ATTR{name}=="0000:0c:00.0"
looking at parent device '/devices/pci0000:00/0000:00:03.1/0000:0c:00.0/i2c-18':
KERNELS=="i2c-18"
SUBSYSTEMS=="i2c"
DRIVERS==""
ATTRS{name}=="0000:0c:00.0"
With the KERNEL
and SUBSYSTEM
known, it is possible to write a udev rule changing the i2c device's owner to the ddc
group.
# vim /etc/udev/rules.d/98-ddc.rules
KERNEL=="i2c-10", SUBSYSTEM=="i2c-dev", GROUP=="ddc", MODE="0660"
KERNEL=="i2c-18", SUBSYSTEM=="i2c-dev", GROUP=="ddc", MODE="0660"
For the udev rules to be applied, udev must be stopped, the rules reloaded, and then restarted. It may also be necessary to reload the i2c-dev
kernel module:
# service udev stop
# udevadm control --reload-rules && udevadm trigger
# service udev start
# modprobe -r i2c-dev
# modprobe i2c-dev
Verifying the udev rule worked is straightforward:
$ ls -l /dev/ | grep i2c
...
crw-rw---- 1 root ddc 89, 10 Jan 20 15:49 i2c-10
...
crw-rw---- 1 root ddc 89, 18 Jan 20 15:49 i2c-18
...
All that is left is to add the non-root user to the ddc
group:
# groupadd ddc
# usermod -a -G ddc userName
$ su - userName
Now the user can set the brightness without being root:
$ ddccontrol -r 0x10 -w 50 dev:/dev/i2c-18
Did this information improve the security of your box? Say thanks and help keep this site ad & analytics free by using my Amazon Affilliate URL. I'll receive a small commission on purchased made in the next 24 hours. Or, consider donating some ETH (0xf3c4a78c24D34E111f272Ac2AC72b1f01ba52DF3
).