Changing keycodes on the hardware level

Topics: Linux, Hardware

This procedure remaps a keyboard scan code using a udev hardware database rule.

Subtopics

Procedure

Test the keycodes for the affected device:

$ sudo evtest
No device specified, trying to scan all of /dev/input/event*
Available devices:
/dev/input/event0:	Sleep Button
/dev/input/event1:	Power Button
/dev/input/event10:	HDA Intel PCH Headphone
/dev/input/event11:	HDA Intel PCH HDMI/DP,pcm=3
/dev/input/event12:	HDA Intel PCH HDMI/DP,pcm=7
/dev/input/event13:	HDA Intel PCH HDMI/DP,pcm=8
/dev/input/event14:	HDA Intel PCH HDMI/DP,pcm=9
/dev/input/event15:	solaar-keyboard
/dev/input/event2:	Lid Switch
/dev/input/event3:	AT Translated Set 2 keyboard
/dev/input/event4:	UNIW0001:00 093A:0255 Mouse
/dev/input/event5:	UNIW0001:00 093A:0255 Touchpad
/dev/input/event6:	Video Bus
/dev/input/event7:	Intel HID events
/dev/input/event8:	PC Speaker
/dev/input/event9:	HDA Intel PCH Mic
Select the device event number [0-15]: 3
Input driver version is 1.0.1
Input device ID: bus 0x11 vendor 0x1 product 0x1 version 0xab83
Input device name: "AT Translated Set 2 keyboard"
Supported events:
  Event type 0 (EV_SYN)
  Event type 1 (EV_KEY)
    Event code 1 (KEY_ESC)
    Event code 2 (KEY_1)
    Event code 3 (KEY_2)
...
Testing ... (interrupt to exit)
Event: time 1705661747.729527, type 4 (EV_MSC), code 4 (MSC_SCAN), value 1c
Event: time 1705661747.729527, type 1 (EV_KEY), code 28 (KEY_ENTER), value 0
Event: time 1705661747.729527, -------------- SYN_REPORT ------------
Event: time 1705661750.396236, type 4 (EV_MSC), code 4 (MSC_SCAN), value 3a
Event: time 1705661750.396236, type 1 (EV_KEY), code 58 (KEY_CAPSLOCK), value 1
Event: time 1705661750.396236, -------------- SYN_REPORT ------------
Event: time 1705661750.396491, type 17 (EV_LED), code 1 (LED_CAPSL), value 1
Event: time 1705661750.396491, -------------- SYN_REPORT ------------
Event: time 1705661750.518530, type 4 (EV_MSC), code 4 (MSC_SCAN), value 3a
Event: time 1705661750.518530, type 1 (EV_KEY), code 58 (KEY_CAPSLOCK), value 0
Event: time 1705661750.518530, -------------- SYN_REPORT ------------
Event: time 1705661752.453338, type 4 (EV_MSC), code 4 (MSC_SCAN), value 1d
Event: time 1705661752.453338, type 1 (EV_KEY), code 29 (KEY_LEFTCTRL), value 1
Event: time 1705661752.453338, -------------- SYN_REPORT ------------
Event: time 1705661752.616397, type 4 (EV_MSC), code 4 (MSC_SCAN), value 1d
Event: time 1705661752.616397, type 1 (EV_KEY), code 29 (KEY_LEFTCTRL), value 0
Event: time 1705661752.616397, -------------- SYN_REPORT ------------

The relevant scan code (EV_MSC) for Caps Lock is 3a.

Get the modalias values for the internal keyboard:

$ cat /sys/class/input/event3/device/modalias | sudo tee /etc/udev/hwdb.d/10-internal-keyboard.hwdb
input:b0011v0001p0001eAB83-e0,1,4,11,14,k71,72,73,74,75,76,77,79,7A,7B,7C,7D,7E,7F,80,8C,8E,8F,9B,9C,9D,9E,9F,A3,A4,A5,A6,AC,AD,B7,B8,B9,D9,E2,ram4,l0,1,2,sfw

Use this information to create a new file /etc/udev/hwdb.d/10-internal-keyboard.hwdb. The modalias line has to be prefixed with evdev: and can be shortened with a wildcard character. Add a line to remap the keyboard scan code. Result:

evdev:input:b0011v0001p0001*
  KEYBOARD_KEY_3a=leftctrl

The device ID can change, presumably after kernel updates. If that happens, cut the ID with the asterisk further to the left.

Finally, enable the change:

$ sudo systemd-hwdb update
$ sudo udevadm trigger

Bookmarks