Linux KDE RGB keyboard G213
A priori the RGB keyboard appears to be somewhat pointless. Nevertheless, I found myself having an uncontrollable urge to own one. In a review of various models the author pondered what reaction people would have if he could take a current generation RGB keyboard back in time to the late nineties. They could marvel at the progress of computer technology and how far human civilization had progressed 20 years hence.
The model I ended up buying was the Logitech G213 Prodigy. It was available at OfficeWorks around the corner for $79, which is relatively cheap by gaming standards. My application of course is serious software engineering. It's also pretty clear that I've been living in a parallel universe blissfully unaware of the existence of such equipment.
It is also clear from the amount of effort put in here to integrating an RGB KB into KDE that it has a serious deficiency (same for Windows and MacOS). RGB has been around for about 10 years now and is pretty much totally ignored. If human existence is to improve (even further) then RGB must be integrated seemlessly into the window context.
Linux Compatibility
The first issue to adding RGB to a linux keyboard environment is that of software support and compatibility.
Well the good news is that this keyboard will just plug in and run. If you do nothing else you can use the G213's built in ability to run effects directly by ifself. Searching the web and watching Youtube videos, however, will not reveal the needed, pretty much undocumented, key sequences:
- Light button + 1: Color wave left to right
- Light button + 2: Color wave right to left
- Light button + 3: Color wave centre out
- Light button + 4: Breathing effect
- Light button + 5: All color cycle together
- Light button + 0: Fixed color (keep pressing to cycle)
Software drivers
Update
Kubuntu (which has now become the OS of choice on the Ryzen desktop) has the g810-led package as part of the distro!! apt install g810-led it's that easy.
- g213-led -a ff0000
Your keyboard should now be red.
You can still compile everything if desired however.
The very first thing you'll need to do is install
g810-led by
Mat Moul to allow "profiles" to loaded in to the keyboard. After attempting to use alternatives, this is by far and away the easiest and most reliable.
Tips:
- How do I install g++
- How do I install git
- su -
- dnf install hidapi
- dnf install hidapi-devel
- exit
- cd /home/me/my_work_space
- git clone https://github.com/MatMoul/g810-led.git
- cd g810-led
- make
- su
- make install
- g213-led -a 00ff00
Your keyboard should now be green.
* Note: /usr/bin/g213-led is a symlink to /usr/bin/g810-led
Security
Update
Kubuntu no longer needs any fixes to security. g213-led and g810-led now just do their thing.
If you're using Fedora then read on.
The second issue to overcome is that only the root user has sufficient security access to talk to the G213. That's essentially because g213-led tampers with the USB directly. Overcoming that restriction was done by using the trusty linux sudo mechanism.
First, login as the root user and add a group named g213. Then add your userid to the new group.
groupadd g213
usermod -aG g213 myuserid
Use the visudo command as the root user to edit the sudoers file and add this line.
## Allows people in group g213 to run /usr/bin/g810-led
%g213 ALL=(root) NOPASSWD:/usr/bin/g810-led
Essentially it says any user in group g213 can run /usr/bin/g810-led with an effective user id of root.
Profiles
Once users in the g213 group have access to be able to setup the key colors and effects, they can do cool stuff from the commandline.
To run the profiles below use:
sudo /usr/bin/g810-led -p /etc/g810-led/profile.g213.login
All profile files in /etc/g810-led have their permissions set to 755.
Login profile
The first profile needed is for login. This establishes a default keyboard color. For this I selected white for the main keyboard keys, green for the nav keys and blue for the numberics.
This profile is produced by:
/etc/g810-led/profile.g213.login.
# Login profile by groups keys
r 1 ffffff
r 2 ffffff
r 3 ffffff
r 4 00ff00
r 5 0000ff
c # Commit changes
Root login profile
The "root" profile is simply an all red static color. Essentially it means you can do bad things here by accident.
/etc/g810-led/profile.g213.root
# Sample profile by groups keys
a ff0000
c # Commit changes
Sleep profile
Sleep profile uses the g213's breath effect where the keyboard slowly pulses on and off with all keys set to one color. The color is set to green with a moderate breathing speed.
# Sleep profile by groups keys
fx breathing all 00ff00 18
c # Commit changes
CapsLock (new for V2)
CapsLock overwrites the color profile for the main part of the keyboard (with yellow) when the CapsLock key is active. Activation is detected by using xbindkeys (which is now an installation prerequisite).
# Capslock profile by groups keys
r 1 ffff00
r 2 ffff00
r 3 ffff00
c # Commit changes
NumLock (new for V2)
Numlock also overwrites the color profile for the numpad with a sightly light blue.
# Capslock profile by groups keys
r 5 00ffff
c # Commit changes
KDE integration
Once the G213 starts doing stuff the question becomes: how can this be integrated with KDE's desktop to become really cool?
Essentially the color and effects profiles need to be triggered by various system events. The method used here is to use bash shell scripts which are activated by various system mechanisms. The simplest of these is the .bash_profile and .bash_logout with the root user's account.
Root user login and logout color changes
Login as the root user and add this line to the end of /root/.bash_profile to change the keyboard to red.
/usr/bin/g810-led -p /etc/g810-led/profile.g213.root
Similarly add this to /root/.bash_logout to change the keyboard back to the default login colors when the root user logs out of a terminal session:
/usr/bin/g810-led -p /etc/g810-led/profile.g213.login
KDE graphical login and logout color changes
The next step is to get KDE's autostart function to run some bash shell scripts to light up the keyboard on graphical logins.
For login:
/etc/g810-led/g213-led-login.sh
#!/bin/bash
sudo /usr/bin/g810-led -p /etc/g810-led/profile.g213.login
and for logout:
/etc/g810-led/g213-led-logout.sh
#!/bin/bash
# Keyboard sleep (breathing effect).
#
sudo /usr/bin/g810-led -p /etc/g810-led/profile.g213.sleep
# Kill session's dbus monitor as we're logging out.
#
screen -ls | grep 'g213-dbus-monitor' | cut -f 1 -d'.' | tr -d "\t" | xargs -I '{}' kill -SIGTERM {}
ScreenLock mode breathing effect
KDE uses dbus to send messages to various system service providers. One of the subsystems providing services is the screenlock program. It's possible to listen to the dbus and intercept these messages and use them to trigger bash scripts.
A prerequisite for running this script is the ability to background it via "screen". So in Fedora, dnf install screen (or yum install screen for other Linux flavours).
/etc/g810-led/g213-led-dbus-monitor.sh
#!/bin/bash
screen -dmS g213-dbus-monitor '/etc/g810-led/g213-led-screenlock.sh'
/etc/g810-led/g213-led-screenlock.sh
#!/bin/bash
#
# https://unix.stackexchange.com/questions/353998/run-script-on-screen-lock-in-kde
#
dbus-monitor --session "type='signal',interface='org.freedesktop.ScreenSaver'" |
while read x; do
case "$x" in
# You can call your desired script in the following line instead of the echo:
*"boolean true"*) echo "Locked"; sudo /usr/bin/g810-led -p /etc/g810-led/profile.g213.sleep;;
*"boolean false"*) echo "Unlocked"; sudo /usr/bin/g810-led -p /etc/g810-led/profile.g213.login;;
esac
done
xbindkeys: CAPS Lock and NUM Lock
Use xbindkeys to execute g213-led-set-profile.sh with a profile when the CAPS Lock or the NUM Lock is pressed.
- Reference
- dnf install xbindkeys
- Install a custom ~/.xbindkeyssrc
- Add xbindkeys to the KDE autostart menu
# For the benefit of emacs users: -*- shell-script -*-
###########################
# xbindkeys configuration #
###########################
#
# Version: 1.8.5
#
# If you edit this file, do not forget to uncomment any lines
# that you change.
# The pound(#) symbol may be used anywhere for comments.
#
# To specify a key, you can use 'xbindkeys --key' or
# 'xbindkeys --multikey' and put one of the two lines in this file.
#
# The format of a command line is:
# "command to start"
# associated key
#
#
# A list of keys is in /usr/include/X11/keysym.h and in
# /usr/include/X11/keysymdef.h
# The XK_ is not needed.
#
# List of modifier:
# Release, Control, Shift, Mod1 (Alt), Mod2 (NumLock),
# Mod3 (CapsLock), Mod4, Mod5 (Scroll).
#
# The release modifier is not a standard X modifier, but you can
# use it if you want to catch release events instead of press events
# By defaults, xbindkeys does not pay attention with the modifiers
# NumLock, CapsLock and ScrollLock.
# Uncomment the lines above if you want to pay attention to them.
#keystate_numlock = enable
#keystate_capslock = enable
#keystate_scrolllock= enable
# Examples of commands:
#"xbindkeys_show"
# control+shift + q
# set directly keycode (here control + f with my keyboard)
#"xterm"
# c:41 + m:0x4
# specify a mouse button
#"xterm"
# control + b:2
#"xterm -geom 50x20+20+20"
# Shift+Mod2+alt + s
#
## set directly keycode (here control+alt+mod2 + f with my keyboard)
#"xterm"
# alt + c:0x29 + m:4 + mod2
#
## Control+Shift+a release event starts rxvt
#"rxvt"
# release+control+shift + a
#
## Control + mouse button 2 release event starts rxvt
#"rxvt"
# Control + b:2 + Release
#
# Change KB color
#
"/etc/g810-led/g213-led-set-profile.sh xbindkeys"
m:0x2 + c:66
Caps_Lock
#
# Change numpad color
#
"/etc/g810-led/g213-led-set-profile.sh xbindkeys"
m:0x10 + c:77
Mod2 + Num_Lock
##################################
# End of xbindkeys configuration #
##################################
- and for general profile setup (as requested by @Radioactive_Tom, sorry for the ommission):
/etc/g810-led/g213-led-set-profile.sh
#!/bin/bash
#
# Setup G213 keyboard profile.
#
loginid_file="/tmp/g213-loginid.tmp"
#
# Save the optional loginid
#
if [ $# == 1 ]
then
if [ "${1}" == "xbindkeys" ]
then
loginid=`cat "$loginid_file"`
else
loginid=$1
fi
else
loginid=`/usr/bin/whoami`
fi
if [ "${loginid}" != "idle" ]
then
echo -n "${loginid}" > "${loginid_file}"
fi
#
# Get keyboard CapsLock, NumLock and ScrollLock settings
#
if [ "${DISPLAY}ZZZ" != "ZZZ" ]
then
sleep .2
lcKBLocks=`/usr/bin/xset -q | grep Caps`
lcCapsLock=`echo $lcKBLocks | cut -d ' ' -f 4`
lcNumLock=`echo $lcKBLocks | cut -d ' ' -f 8`
lcScrollLock=`echo $lcKBLocks | cut -d ' ' -f 12`
#echo "ShiftLock=$lcCapsLock"
#echo "NumLock=$lcNumLock"
#echo "ScrollLock=$lcScrollLock"
else
lcCapsLock="off"
lcNumLock="off"
lcScrollLock="off"
fi
if [ "${loginid}" == "root" ]
then
#
# Keyboard red.
#
sudo /usr/bin/g810-led -p /etc/g810-led/profile.g213.root
elif [ "${loginid}" == "screenlock" ]
then
#
# Keyboard heatbeat.
#
sudo /usr/bin/g810-led -p /etc/g810-led/profile.g213.sleep
elif [ "${loginid}" == "idle" ]
then
#
# Keyboard heatbeat.
#
sudo /usr/bin/g810-led -p /etc/g810-led/profile.g213.idle
else
#
# Keyboard default.
#
sudo /usr/bin/g810-led -p /etc/g810-led/profile.g213.login
fi
if [ $lcCapsLock != 'off' ]
then
sudo /usr/bin/g810-led -p /etc/g810-led/profile.g213.capslock
fi
if [ $lcNumLock != 'off' ]
then
sudo /usr/bin/g810-led -p /etc/g810-led/profile.g213.numlock
fi
Listen to D-BUS for screen sleep and wake messages
When the keyboard is left idle for a time, make it cycle through rainbow colors. Don't forget to add getIdle to the KDE autostart menu.
getIdle.c (compile to getIdle)
//
// RGB Keyboard timer.
//
// https://unix.stackexchange.com/questions/120957/run-a-command-when-system-is-idle-and-when-is-active-again
//
#include <X11/extensions/scrnsaver.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define IDLE_TIME 50000
int main(void) {
Bool bIsIdle = False;
Bool bWasIdle = False;
int iReturnCode;
Display *dpy = XOpenDisplay(NULL);
if (!dpy) {
return(1);
}
while (True) {
XScreenSaverInfo *info = XScreenSaverAllocInfo();
XScreenSaverQueryInfo(dpy, DefaultRootWindow(dpy), info);
bIsIdle = info->idle > IDLE_TIME;
if ( bIsIdle ) {
if ( !bWasIdle ) {
printf("Idling");
iReturnCode = system("/etc/g810-led/g213-led-set-profile.sh idle");
if ( iReturnCode != 0 ) printf("Failed to idle: %u\n", iReturnCode);
}
} else {
if ( bWasIdle ) {
iReturnCode = system("/etc/g810-led/g213-led-set-profile.sh");
if ( iReturnCode != 0 ) printf("Failed to idle: %u\n", iReturnCode);
}
}
bWasIdle = bIsIdle;
// printf("%u\n", info->idle);
usleep (10000);
}
return(0);
}