Being able to change the luminosity of a screen is always something useful, to adjust it when there's more or less light, or even switching it off to keep a laptop processing. This usually works on it's own when we use an environment like KDE or Gnome, but it may not be like this if we don't use certain drivers or if we prefer more configurable environments (like awesome).

If we prefer to do it manually, we can do it through the command line in /sys/class/backlight/. In each devices directory there's a brightness file that sets the current brightness (and that accepts changes), and max_brightness that shows the maximum accepted value, for example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# We look for available devices
$ ls /sys/class/backlight/
radeon_bl0

# Current brightness
$ cat /sys/class/backlight/radeon_bl0/brightness
100

# Maximum brightness
$ cat /sys/class/backlight/radeon_bl0/max_brightness
255

# We set the brightness to max. Notice we need script
$ echo 255 | sudo tee /sys/class/backlight/radeon_bl0/brightness
255

With this, we can set a script up to do it automatically, it should...

List the devices:

1
2
def get_device_list():
    return os.listdir('/sys/class/backlight/')

Show the current and max brightness:

1
2
3
4
5
6
7
def get_brightness(backlight):
    return int(open('/sys/class/backlight/{backlight}/brightness'
                    .format(backlight=backlight), 'rt').read())

def get_max_brightness(backlight):
    return int(open('/sys/class/backlight/{backlight}/max_brightness'
                    .format(backlight=backlight), 'rt').read())

Change the brightness:

1
2
3
def set_brightness(backlight, value):
    return open('/sys/class/backlight/{backlight}/brightness'
                .format(backlight=backlight), 'wt').write(str(value))

Now we can program a couple of functions to make it more and less bright:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
def more(backlight):
    brightness = get_brightness(backlight)
    max_brightness = get_max_brightness(backlight)

    set_brightness(backlight, max(0, brightness + max(1, max_brightness / 10)))


def less(backlight):
    brightness = get_brightness(backlight)
    max_brightness = get_max_brightness(backlight)

    set_brightness(backlight, max(0, brightness - max(1, max_brightness / 10)))

We add a help function, a main and ...

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
def show_help():
    print('''brightness.py (less|more) device

Devices:
    {}'''.format('\n    '.join(get_device_list())))


if __name__ == '__main__':
    if len(sys.argv) == 3 and sys.argv[1] in ('less', 'more'):
        if sys.argv[2] not in get_device_list():
            print('Device {} not found'.format(sys.argv[2]))
        elif sys.argv[1] == 'less':
            less(sys.argv[2])
        elif sys.argv[1] == 'more':
            more(sys.argv[2])

    else:
        show_help()

And the script is ready [ brightness.py ], but there's a problem... to change the brightness we need root privileges. We can run the script with sudo, but it's not needed if we use setuid.

The trick about using setuid with python is that scripts using a #! interpreter are a security issue and it's disabled on modern systems. The solution is to compile the script, for example with cython.

1
2
3
4
5
6
7
8
# Compile the script to a .c
$ cython --embed brightness.py

# Compile the brightness.c to a .o
$ gcc -c brightness.c -I/usr/include/python2.7

# Compile the brightness.o into an executable
$ gcc -o brightness brightness.o -lpython2.7

Notice that gcc doesn't require too many parameters because this program is simple, but it may not be like that. There's more complete Makefiles around.

Once compiled we can setuid it as root:

1
2
3
4
5
# Change the owner to root
$ sudo chown root brightness

# Set setuid
$ sudo chmod +s brightness

And this should be done:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# List the devices
$ ./brightness
brightness.py (less|more) device

Devices:
    radeon_bl0

# Increase the brightness
$ ./brightness more radeon_bl0

# Reduce brightness
$ ./brightness less radeon_bl0

Now we can modify it which any user from the console!

But, what if we have an Awesome windows environment and we want the brightness keys to work? That is pretty easy now, in the rc.lua file there's a clientkeys section, where we can configure it:

1
2
3
4
5
clientkeys = awful.util.table.join(
    awful.key({                   }, "XF86MonBrightnessDown",
     function () awful.util.spawn('PATH/TO/THE/EXECUTABLE/brightness less DEVICE') end),
    awful.key({                   }, "XF86MonBrightnessUp",
     function () awful.util.spawn('PATH/TO/THE/EXECUTABLE/brightness more DEVICE') end),

We're ready and able to set the brightness without any (more :P) extras.

PS: the code, to run make and execute it it's available in GitLab.