References:

Maping keys is pretty simple, and if it's done at the udev level, it's universal, so it doesn't require any X or Wayland specific configuration.

As an example, I map my compose key (menu key) to right meta (aka super, logo, windows, apple, or command key), and CapsLock to left Control.

First, get the scancode(s) of the key(s) you wish to change. Easiest way is to use evteest(1). For each keypress, you'll get information similar to the following:

Event: time 1496690003.603531, -------------- SYN_REPORT ------------
Event: time 1496690003.723467, type 4 (EV_MSC), code 4 (MSC_SCAN), value 70065
Event: time 1496690003.723467, type 1 (EV_KEY), code 127 (KEY_COMPOSE), value 0

The code you will need to use in the udev hwdb config file is the MSC_SCAN value (in this case: 70065).

Next you will need the hardware Vendor and Product ids from lsusb(1). These are two sets of four hexidecimal digits separated by a colon (:) printed right before the device name.

Bus 001 Device 005: ID 258a:1006 <keyboard name here>

In this example, the Vendor ID is 258a, and the Product ID is 1006.

Then create /etc/udev/hwdb.d/61-custom-keyboard.hwdb with the following contents:

evdev:input:b0003v258Ap1006*
 KEYBOARD_KEY_70065=rightmeta
 KEYBOARD_KEY_70039=leftctrl

A few notes on the format of this file:

  • The format for the device identifying line for usb devices is evdev:input:b0003v<Vendor ID>p<ProductID>*.
    • If <Product ID> and <Vendor ID> contain letters, they must be capitalized
    • These scancodes can be quite device-specific, so it is wise to be specific to at least the vendor and product IDs
    • There are methods for identifying atk keyboards as well. Check the Arch Wiki page listed in the references above for more info
  • Defining a key to change is done with KEYBOARD_KEY_<scancode>=<new keycode>
    • <scancode> is the code we pulled from evtest earlier
    • <new keycode> is the keycode we want to emit when the key is pressed. Names of keycodes are listed in /usr/include/linux/input-event-codes.h, and should be all lowercased in your udev config.
  • The filename 61-custom-keyboard.hwdb is somewhat arbitrary, but make sure that you order your file after the existing 60-keyboard.hwdb.

After changing the config files, the hwdb needs to be rebuilt:

# systemd-hwdb update

To start using this new hwdb, either reboot or tell udev to reload:

# udevadm trigger

Note that this will only work for adding or modifying existing key mappings. Deleted key mappings are kept in the kernel until a reboot.

A simple test can be run before trying the keys directly:

# udevadm info /dev/input/by-path/*-usb-*-kbd | grep KEYBOARD_KEY