Keyboards with backlighting are on the rise for both gamers and programmers. Its basic functionality is to illuminate keys in dark environments making it easy to view and type. But how about extending this functionality? In this article I’ll show you how I hacked my Samsung Odyssey’s Backlit Keyboard to “blink” when I receive notifications.

Blink Notification

See the example below:

Visualizar esta foto no Instagram.

 

Uma publicação compartilhada por Micro Hobby (@microhobby) em


The idea was to draw attention beyond the pop up that appears on the screen with the keyboard blinking, or in fade if you prefer this way, when we receive some notification. This is also useful for example when we leave our machine in lockscreen, with this hack if a notification is received, even with lockscreen, the keyboard will blink. So I know if I received something, email, skype, Facebook messenger and etc in that time I did not pay attention to the Notebook.

In my case it was a very useful extension of functionality, because I use an external screen, keyboard and mouse. The notebook’s screen use for less routine functions, I leave the Spotify open, some debugger or terminal, and I rarely use the onboard keyboard.

The Hack

To make this hack what I needed was a Notebook with Backlit Keyboard and a Linux distribution. Here I am using my favorite Linux distro: Mint. The Linux Kernel is very complete and detected the Backlit Keyboard of my Odyssey thus giving me access to some controller functionality by the virtual sysfs of the LEDs subsystem.

Kernel LEDs Subsystem

The Linux kernel has a sub system just to take care of the LEDs. For example, those LEDs on our keyboard, num lock, caps lock and scroll lock are controlled by the LED Subsystem. Doubt? Open the terminal and check the LEDs that the kernel detected on your machine with the following command:

cd /sys/class/leds
ls

Here on my machine Kernel listed me these LEDs:

Each LED that the Kernel detects is a folder so we can enter into them and list. I will use as an example the caps lock of my onboard keyboard:

cd input3::capslock
ls

Here what are listed:

Inside the device folder we will have some files and other folders. What is important now for our hack are the files brightness and max_brightness these “files” are part of the virtual file system of the controller of the LEDs subsystem. What? These files are not really files. What? Yes, as the name already indicated they are virtual. They are mapped in memory and performing “write” and “read” functions in these files actually is as if I were writing to a variable or calling a function of the LED controller. Cool,  no? For example when reading the file max_brightness it will check on the LED controller what maximum brightness this LED can have and return it in a number:

So now I know that my LED can have the maximum brightness of 1. That is, this LED supports the values from 0,  LED off, to 1 of maximum LED brightness. But where do I enter these values? This we can write in the file brightness. Usually our default user does not have write access to the virtual file system, so for writing in it I’m going to use sudo su to run as root:


 

Writing 1 in brightness we turn on the LED of the caps lock, and typing 0 we turn off. Having access to these functionalities give us possibilities to write programs to extend the functionalities of our LEDs.

Scripts

Iside LEDs that my kernel controls are the keyboard backlight of my notebook:

So we can write a script to use the features of this LED:

#!/bin/bash

if [ "$EUID" -ne 0 ]
	then echo "To use LED subsystem bash need to be root"
	exit
fi

if [ $1 = "off" ]; then
	echo 0 > /sys/class/leds/samsung::kbd_backlight/brightness
	exit
fi

while [ 1 ]
do
	# this will do a fade effect in my onboard keyboard backlight
	echo 0 > /sys/class/leds/samsung::kbd_backlight/brightness
	sleep 1.7s
	echo 8 > /sys/class/leds/samsung::kbd_backlight/brightness
	sleep 1.5s
done

This script, which I’ll call blink.sh from now, will generate a fade effect by turning the backlight on and off as if it were pulsing. If we read the max_brightness of this LED we will see that it returns 8, so we can set the brightness from 0 to 8. Another thing I noticed is that even if you can set the brightness in more steps the controller always does the fade effect, dim the brightness . So instead of setting the steps I went from 0, off, to 8 maximum brightness giving a longer time to sleep for the controller itself do the fade effect.

The on and off is within a while running forever, or until we stop the process. There is the possibility that when we stop the process our script is in the part where it is to turn the backlight on, and the light will stay on. For this I put the second “if” that checks an argument “off” that when passed to the script just turns off the backlight and exit the process. This will be useful when we are using blink.sh in our complete hack.

Monitoring Notifications

Ok we already have a script to blink and turn off our keyboard backlight, now let’s put some functionality in it. For our backlight to blink only when we have a new notification, we have to monitor the notifications that arrive on our computer. In graphical interfaces that use the freedesktop.org standard and the dbus to intercommunicate between applications, is the case of Mint Cinnamon, all notifications are messages transmitted by dbus. These messages will be received by the Cinnamon interface which will then make the graphical notification appear on the screen. What we are going to do then is to monitor and filter the messages that will be sent via dbus with dbus-monitor:

#!/bin/bash

if [ "$EUID" -ne 0 ]
	then echo "Please run as root"
	exit
fi

# monitor the notifications
su -c "dbus-monitor \"interface='org.freedesktop.Notifications'\"" castello |
while read LINE; do
	# filter only the member field
	RET=`echo $LINE | grep -o 'member=.*'`

	if [[ $RET == *"Notify"* ]]; then
		echo "new notify"

		# set notification
		if [[ $PID == "" ]]; then
			echo "set backlight"
			./blink.sh &
			PID=$!
		fi
	fi

	if [[ $RET == *"NotificationClosed"* ]]; then
		echo "notify closed"

		# clear notification
		if [[ $PID != "" ]]; then
			echo "turn off backlight"
			kill $PID
			./blink.sh off
			PID=""
		fi
	fi
done

This script has a nice “trick” that we need to pay attention to. As I said above we need to be root for written in the virtual file system of the LEDs subsystem. But if we run the dbus-monitor with root we will not receive the messages of the applications that are running on our default user. So this script asks to be root in the beginning, but, runs the dbus-monitor with its default user:

su -c "dbus-monitor \"interface='org.freedesktop.Notifications'\"" castello

The su command receives the -c argument and the command string, our dbus-monitor with the notifications interface filter, and finally su receives the user with which we want it to run the command. So if you are going to use this script be sure to modify the “castello”, which is the default user on my machine, by your machine default user.

With this trick done dbus-monitor will receive all the messages sent by dbus, and it is a lot of messages. So what we do within the “while” is to get all lines received by the monitor and filter, using grep, looking for messages with the field “member”:

su -c "dbus-monitor \"interface='org.freedesktop.Notifications'\"" castello |
while read LINE; do
	# filter only the member field
	RET=`echo $LINE | grep -o 'member=.*'`

Done this now we have to verify if the messages received contains the “member” Notify field that “member” is sent when we receive a notification:

if [[ $RET == *"Notify"* ]]; then
	echo "new notify"

	# set notification
	if [[ $PID == "" ]]; then
		echo "set backlight"
		./blink.sh
		PID=$!
	fi
fi

If the message contains Notify then I check the PID variable, which saves the process id of the last call to our blink.sh script, if the PID is empty then we can call our blink.sh script to start blinking the keyboard, and save your PID. Why is it important? Because we can receive multiple notifications at once, and there is no need to call multiple processes for our blink.sh script, i]and this may even stick in our script. So we only start a new blink.sh process when it is not actually running.

And when we get a message with the NotificationClosed “member”, it means that some notification has been closed:

if [[ $RET == *"NotificationClosed"* ]]; then
	echo "notify closed"

	# clear notification
	if [[ $PID != "" ]]; then
		echo "turn off backlight"
		kill $PID
		./blink.sh off
		PID=""
	fi
fi

In this case it is the opposite of the previous condition, I check the PID variable if it is not empty. In other words, to clean a process of blink.sh that exists, we have to have a valid PID, which means that blink.sh is running. So I kill PID, blink.sh, clear the PID stored leaving it empty, and call the blink.sh again, but now with the “off” as argument that will just turn off our backlight.

Customizations

On my machine I have extended blink.sh to use effects on all my LEDs, passing an argument to select the LED. Here LEDs from my external keyboard:


I put a frenetic blinking effect of on and off with num lock, caps lock and scroll lock. I also have the caps lock LED on my onboard keyboard:


I’ll leave here the Github link with the complete scripts: https://github.com/microhobby/bashScripts. In this repository you also have the Unit Service to put our scripts to start at boot time with SystemD. To put our script to boot during boot I used the same concepts as the article I wrote for FilipeFlop: Inicialização de Aplicação Durante o Boot com SystemD na Raspberry Pi

Conclusions

Using open standards and an open source Kernel, in case of the Linux Kernel, give us the possibility of Hacks and customizations, the limit is due to their imagination.

Here I used the LED subsystem in conjunction with the notifications, but you can use it for other customizations and automations.

If your Notebook has a Backlit Keyboard, it does not necessarily have to be the Samsung Odyssey, see the list of LEDs detected by the Kernel in /sys/class/leds. If the Kernel detects your backlit keyboard you can apply the same Hack.


Leave a Reply

Your email address will not be published. Required fields are marked *