python-kb2macro: A macro script for Linux

Andrew Hall · September 4, 2022

A couple of months ago I started writing a script that allows me to use additional keyboards as macro devices on Linux-based operating systems.

The project in question is python-kb2macro.


I’ve previously wanted to get my hands on one of those macro pads you frequently see on online marketplaces however I’ve encountered two major issues. Either they’re expensive, or they don’t support Linux very well (or at all) if they require special drivers.

So in that case, what could I use that is both cheap as chips, works on Linux and doesn’t require third-party drivers? How about another keyboard?

Now this does pose a slight issue as simply plugging in another keyboard and assigning a macro to it via a tool such as sxhkd (Simple X11 HotKey Daemon) will either block whatever key you’re pressing, or still fire off a keypress when a macro runs. To put it simply, there’s no obvious separation between the keyboard you type on and the one you’re using for macros.

The Hardware

For this project basically any input device will work as long but it’s more intended for USB keyboards and numpads. You can find them for less than 20 dollars on Ebay and work just fine.

Numpad from Ebay

Setting up the Script

Only a few software packages are required and thankfully most of them are found in the majority of distribution repos.

Fetch the repo using git and you’re ready to go. Almost.

One issue with using evdev and event devices in general is that event devices are by default owned by the root user. Now you could just run the script as root, however as this poses a security issue I wouldn’t recommend it. Instead we’ll need to set up a udev rule for the device we want to use that will allow us to gain raw access without needing elevated privileges.

First things first, we’ll need to find the vendor and product id of our USB device. This is done with the lsusb command (with my keypad as an example).

$ lsusb
Bus 001 Device 003: ID 13ba:0001 PCPlay Konig Electronic CMP-KEYPAD12 Numeric Keypad

The part we want from this is 13ba:0001, the vender and product id. This is what we’ll feed this into a udev rules file. Create a file ending in .rules in the /etc/udev/rules.d/ directory, e.g /etc/udev/rules.d/00-my-macro-device.rules.

Next paste in the following line:

SUBSYSTEM=="input", ATTRS{id/vendor}=="xxxx", ATTRS{id/product}=="yyyy", MODE="0660", GROUP="somegroup", SYMLINK+="input/macroN"

We’re not quite there yet however. For the first and second ATTRS, we’ll need to replace xxxx and yyyy with the vendor and product ID we noted down before. Next we’ll change GROUP= to whatever our user group is named (likely the same as your username). Last but not least we’ll set macroN to a nice readable name, in this case macro0. Doing so will ensure the script works every time the original event filename changes.

For example using 13ba:0001 as the device id and andrew as the group name, we should have something like this.

SUBSYSTEM=="input", ATTRS{id/vendor}=="13b1", ATTRS{id/product}=="0001", MODE="0660", GROUP="andrew", SYMLINK+="input/macro0"

Save the file, exit the text editor and run # udevadm control --reload; udevadm trigger. If everything went well you should see a new entry in /dev/input/.

$ ls /dev/input -l
crw-rw---- 1 root andrew 13, 70 Sep  4 13:00 event6
lrwxrwxrwx 1 root root        6 Sep  4 13:00 macro0 -> event6


At this point you should be ready to go. In the next post I will go over how the script is actually used and how macros are set up.

Twitter, Facebook