Here's how to remap globally keyboard keys with udev's hwdb database, since I couldn't find a single document that documents all the steps correctly (for Ubuntu 14.04).
Motivation: We want some key on some type of keyboard (say F15) to some other pre-defined function (play/pause song) without globally remapping F15 on all keyboards, because that will break all keyboards that actually have a play/pause button.
Overview: We need to find the keyboard scan code for the key, find out the name of the key that we want to turn it into, then compose a mapping (for /just/ that keyboard!) file. Finally, kick udev into recognizing our new mapping.
- Retrieve the keyboard scan code. This can be done by firing up the evtest(1) command.
- Select the device you want to monitor (we'll pick the MS Natural 4000).
- Press the key (here, the zoom out slider). So far, the evtest output looks like this:
# evtest
No device specified, trying to scan all of /dev/input/event*
Available devices:
/dev/input/event0: Power Button
/dev/input/event11: Logitech USB Optical Mouse
/dev/input/event12: Microsoft Natural® Ergonomic Keyboard 4000
/dev/input/event13: Microsoft Natural® Ergonomic Keyboard 4000
/dev/input/event14: HID 05ac:820a
/dev/input/event15: HID 05ac:820b
/dev/input/event16: Apple, Inc. IR Receiver
/dev/input/event17: PWC snapshot button
Select the device event number [0-17]: 13
Input driver version is 1.0.1
Input device ID: bus 0x3 vendor 0x45e product 0xdb version 0x111
Input device name: "Microsoft Natural® Ergonomic Keyboard 4000"
Supported events:
Event type 0 (EV_SYN)
Testing ... (interrupt to exit)
Event: time 1419404672.824579, type 4 (EV_MSC), code 4 (MSC_SCAN), value c022e
Event: time 1419404672.824579, type 1 (EV_KEY), code 153 (KEY_F14), value 1
Event: time 1419404672.824579, -------------- SYN_REPORT ------------
Event: time 1419404672.928509, type 4 (EV_MSC), code 4 (MSC_SCAN), value c022e
Event: time 1419404672.928509, type 1 (EV_KEY), code 153 (KEY_F14), value 0
Event: time 1419404672.928509, -------------- SYN_REPORT ------------
- The keyboard scan code is at the end of the first line in the SYN_REPORT. For the key we want (the zoom out slider), the scan code is 0xC022E.
- Now we need to construct a hardware ID for the keyboard. sysfs will tell us; remembering the number 13 from step 3, we can look it up:
# ls /sys/class/input/input13
lrwxrwxrwx 1 root root 0 Dec 23 22:34 /sys/class/input/input13 -> ../../devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1.3/1-1.3:1.1/0003:045E:00DB.0002/input/input13/
- From this device, we see that the keyboard is USB, the vendor ID is 0x045E (Microsoft) and the product ID is 0x00DB (MS Natural 4000). This enables us to build a hwdb selector: keyboard:usb:v045Ep00DB*. NOTE: As of systemd 205(?) the selector format changed to evdev:input:b0003v045Ep00DB*.
- Now look up the symbolic name of the key event that we want to fire when we press the zoom in key on the keyboard. That list can be found at http://hal.freedesktop.org/quirk/quirk-keymap-list.txt . The key we want is "Previous Song" and its symbolic name is "previoussong".
- Construct the hwdb file /lib/udev/hwdb.d/99-ms-natural.hwdb (the .hwdb extension is critical!) with the following contents:
# Microsoft Natural Ergonomic Keyboard 4000
evdev:input:b0003v045Ep00DB*
KEYBOARD_KEY_c022e=previoussong # KEY_ZOOMOUT
- Regenerate the udev hwdb database: udevadm hwdb --update
- Reboot the system. Occasionally, running udevadm trigger and replugging the device after a few seconds will work.
- Verify correct operation by re-running evtest:
Event: time 1419405734.888026, type 4 (EV_MSC), code 4 (MSC_SCAN), value c022e
Event: time 1419405734.888026, type 1 (EV_KEY), code 165 (KEY_PREVIOUSSONG), value 1
Event: time 1419405734.888026, -------------- SYN_REPORT ------------
Event: time 1419405735.008025, type 4 (EV_MSC), code 4 (MSC_SCAN), value c022e
Event: time 1419405735.008025, type 1 (EV_KEY), code 165 (KEY_PREVIOUSSONG), value 0
Event: time 1419405735.008025, -------------- SYN_REPORT ------------
That should do it!