Remapping keys with udev

Most of the time I am working on my desk, using my stationary keyboard. But once in a while, and especially during summer time, I like to take my work laptop and sit outside, enjoying the weather while doing some work.

In these moments, the internal keyboard of my Thinkpad P14s drove me nuts. Its Meta and left Alt keys are swapped compared to the keyboard on my desk, which often resulted in a small pause to think about which key to use if I wanted to change to another window, skip a single word during writing etc.

Luckily there is a pretty simple way to remap keys for distributions using udev and systemd (or at least that is the way I can confirm on Arch Linux).

Udev itself has a feature where it maintains a hardware database. It is possible to extend this database with custom configurations, like remapping specific keys on a keyboard.

In my case, that configuration file looks like this:


The first line is the hardware identifier. In this example it has a lot of wildcards, which are catching all keyboards having the same parts in their id. This particular line matches internal Thinkpad keyboards, which I shamelessly copy pasted from the corresponding Arch Linux Wiki article. To get the specific hardware identifier evemu-describe (part of the evemu package on Arch Linux) can be used.

The other two lines are defining what the key remapping looks like. On the left hand side of the =, KEYBOARD_KEY_ is being used with the physical keys scancode being appended to it. On my keyboard, the scancodes (which are in hexadecimal format) are 38 for the physical left alt key, and db for the physical left meta (windows) key. I used evtest to read the scancodes, which are being displayed at the end of the first line after pressing a key, e.g. for left my left meta key:

type 4 (EV_MSC), code 4 (MSC_SCAN), value db

On the right hand side are the keycodes to what the physical keys should be mapped to. There is either a list on freedesktops website or (at least on Arch Linux) at /usr/include/linux/input-event-codes.h (just copy the needed string without the prepended KEY_ part and change it to lowercase. The same string can also be read by using evtest again and pressing the key that you want its value mapped to the other key. This will display the keycode string on the second line.

With all information gathered, I put the configuration into /usr/lib/udev/hwdb.d/10-my_remappings.hwdb and updated udevs hardware database via systemd-hwdb update and reloaded it via udevadm trigger. Ta-da, the keys are remapped and ready to use!

As a final step I added a systemd replacement file so I do not have to manually update and load the hardware database each time. I did so by running systemctl edit systemd-hwdb-update.service which creates the replacement unit and opens an editor to directly edit it. Inside the two specific comment sections which tell you what will be used and what not, I followed the Arch Linux Wiki page and added the described line to it, resulting in the following file content:

### Editing /etc/systemd/system/systemd-hwdb-update.service.d/override.conf
### Anything between here and the comment below will become the contents of the drop-in file

# ConditionNeedsUpdate=/etc

### Edits below this comment will be discarded

With that being set, my muscle memory should be pleased now not to rethink the key mappings everytime I am using my laptop keyboard – hooray!