Setting up the Keyboard in Linux

There are three levels of interpreting symbols that correspond to keys: scancode, keycode and keysym.

Scancode is produced by keyboard as a series for key press or key release.

Keycode can be arbitrary assigned to a scancode.

Keysym is a real character that depends on current layout, Shift state, etc. One keycode corresponds to different keysyms.

This model allows, on the one hand, to swap some keys on the keyboard (changing scancode -> keycode map), and, on the other, to create a keyboard layout (English, Russian, etc.) (changing keycode -> keysym map).

For example, let us change the Shift and Caps Lock issuing as root:

# setkeycodes 2a 58
# setkeycodes 3a 42

and return them back again:

# setkeycodes 2a 42
# setkeycodes 3a 58

If the kernel does not hear scancode, it’s a problem. Years ago my 2.6.17 kernel did not heard special buttons on an Acer notebook such as Launch Mail Client. But an upgrade to 2.6.22 was all that I needed.

By the way, the Power button also generates a scancode (0xe05e) corresponding to keycode 116.

If the kernel hears scancode that is not mapped to a keycode, it usually writes to log (frequently duplicated on the console) something like:

[845.109638] atkbd.c: Unknown key pressed (translated set 2, code 0xb3 on isa0060/serio0).
[845.109793] atkbd.c: Use 'setkeycodes e033' to make it known.
[845.208315] atkbd.c: Unknown key released (translated set 2, code 0xb3 on isa0060/serio0).
[845.208466] atkbd.c: Use 'setkeycodes e033' to make it known.

Just follow the kernel’s instructions 🙂

A list of keycodes can be found at /usr/include/linux/input.h:

#define KEY_RESERVED 0
#define KEY_ESC 1
#define KEY_1 2
#define KEY_2 3
#define KEY_3 4
#define KEY_4 5
...
#define KEY_POWER               116     /* SC System Power Down */
...
#define KEY_MAX 0x1ff
#define KEY_CNT (KEY_MAX+1)

Let’s have some practice.

setkeycodes manages scancode -> keycode association. If the keycode is not assigned, the key won’t work neither in console nor in X Window System. To know scancode, run:

# showkey -s

and press the key you are interested in. To know keycode, just omit -s:

# showkey

.

Both commands should be run in console. Daredevils can try them in X Window in a terminal emulator.

X server has its own keycodes that differ from kernel’s keycodes. X keycodes can be listed running:

$ xev

If kernel keycode is not assigned, the key will not be visible in xev. Curiously, if you assign a special KEY_UNKNOWN = 240 keycode to a key, it won’t be shown by xev.

Keycode -> keysym mapping is configured with xmodmap for X server and with loadkeys for console.

For example, let’s turn Backspace (keycode = 101) into Delete in X:

$ cat .xmodmaprc
keycode 101 = Delete
$ xmodmap .xmodmaprc

loadkeys uses a configuration file like xmodmap, but it’s more powerful since kernel allows to use a sequence of bytes as a keysym. Here is a quote from man loadkeys:

The kernel string table is a sequence of strings
with names like F31. One can make function key F5 (on
an ordinary PC keyboard) produce the text `Hello!’,
and Shift+F5 `Goodbye!’ using lines

keycode 63 = F70 F71
string F70 = “Hello!”
string F71 = “Goodbye!”

We have to go to console and play as root:

# cat mykeys
keycode 63 = F70 F71
string F70 = "Hello!"
string F71 = "Goodbye!"
# loadkeys mykeys

Now press F5!

Leave a comment