Loadkeys, Dumpkeys

    May 10, 2005

You can change the output of the console keyboard with loadkeys. It’s an extremely powerful command, and the man page can be confusing, but for simple use (which is often all we need it for), it’s very easy.

For example, let’s reprogram the F10 key:

echo 'string F10 = "foo" ' | loadkeys

See? That wasn’t difficult. Oops, now what was the original value so we can put it back? Ahh, perhaps a little preparation would have been wise before changing that. The “dumpkeys” command does that:

dumpkeys > myfullkeymap
dumpkeys --funcs-only > funcsonlymap

The “funcs-only” map is short:

string F1 = "\033[[A"
string F2 = "\033[[B"
string F3 = "\033[[C"
string F4 = "\033[[D"
string F5 = "\033[[E"
string F6 = "\033[17~"
string F7 = "\033[18~"
string F8 = "\033[19~"
string F9 = "\033[20~"
string F10 = "\033[21~"
string F11 = "\033[23~"
string F12 = "033[24~"
string F13 = "\033[25~"
string F14 = "\033[26~"
string F15 = "\033[28~"
string F16 = "\033[29~"
string F17 = "\033[31~"
string F18 = "\033[32~"
string F19 = "\033[33~"
string F20 = "\033[34~"
string Find = "\033[1~"
string Insert = "\033[2~"
string Remove = "\033[3~"
string Select = "\033[4~"
string Prior = "\033[5~"
string Next = "\033[6~"
string Macro = "\033[M"
string Pause = "\033[P"

Yours will be different if you reprogrammed F10 above. Do this to put it back:

echo 'string F10 = "\033[21~" ' | loadkeys

If you had previously saved “funcsonlymap”, you could put it all back with “loadkeys funcsonlymap” at any time, or simply use “loadkeys -d”

The full key map is much longer and can be confusing. The first thing you have to understand is how keyboards really work: they actually send a keycode (also called “scancodes”). The “A” key on your keyboard actually sends 30, and F10 sends 68. You can use “showkey” to see what keycodes are really being sent (just stop typing briefly and showkey will exit). In the full keymap dump, you’ll find:

keycode 68 = F10&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp F22&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp Console_22 F34
alt&nbsp&nbsp&nbsp&nbsp keycode&nbsp&nbsp 68 = Console_10
control alt&nbsp&nbsp&nbsp&nbsp keycode&nbsp&nbsp 68 = Console_10

And later in the same file you’ll find:

string F10 = "\033[21~"

The last one is easy to understand, but what does the first part mean? Well, it defines key symbols, “keysms” in the “man keymaps” explanation. It’s position dependent: F10 is the unshifted key, F22 is the shifted F10, but then we start getting confusing. The main page does a lousy job explaining it:

Which of the actions bound to a given key is taken when it is pressed depends on what modifiers are in effect at that moment. The keyboard driver supports 8 modifiers. These modifiers are labeled (completely arbitrarily) Shift, AltGr, Control, Alt, ShiftL, ShiftR, CtrlL and CtrlR. Each of these modifiers has an associated weight of power of two according to the following table:

modifier weight
Shift 1
AltGr 2
Control 4
Alt 8
ShiftL 16
ShiftR 32
ControlL 64
ControlR 128

The effective action of a key is found out by adding up the weights of all the modifiers in effect. By default, no modifiers are in effect, so action number zero, i.e. the one in the first column in a key defini- tion line, is taken when the key is pressed or released. When e.g. Shift and Alt modifiers are in effect, action number nine (from the 10th column) is the effective one.

Changing the state of what modifiers are in effect can be achieved by binding appropriate key actions to desired keys. For example, binding the symbol Shift to a key sets the Shift modifier in effect when that key is pressed and cancels the effect of that modifier when the key is released. Binding AltGr_Lock to a key sets AltGr in effect when the key is pressed and cancels the effect when the key is pressed again. (By default Shift, AltGr, Control and Alt are bound to the keys that bear a similar label; AltGr may denote the right Alt key.)

AltGr is the right hand Alt-Key, by the way. Later on, the man page helpfully tells us:

To find out what keysyms there are available for use in keymaps, use
&nbsp &nbsp &nbsp &nbsp the command

&nbsp &nbsp &nbsp &nbsp &nbsp &nbsp dumpkeys --long-info

Unfortunately, there is currently no description of what each symbol does. It has to be guessed from the name or figured out from the kernel sources.

So, going back to that key 68 definition, it’s easy to see that F22 is the shifted F10, and indeed we can redefine it with:

echo 'string F22 = "Foo" ' | loadkeys

But if you try that with Console_22, you’ll get an error message from loadkeys. That’s because it is one of the “actions” the man page is so vague about. It’s defining the action for the right hand alt key and the function key. I could change it by replacing the keymap definition:

keycode 68 = F10 &nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp F22&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp F100&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp F34

alt &nbsp&nbsp&nbsp keycode&nbsp&nbsp&nbsp 68 = Console_10
control alt &nbsp&nbsp&nbsp keycode&nbsp&nbsp&nbsp 68 = Console_10

And then set F100 to be what I want:

echo 'string F100 = "Foo" ' | loadkeys

And then Right Alt-F10 will send “Foo”. That’s fine. Or, I could leave it as it is and use it for what it is really intended for, but we’ll save that for later. The next position (F34) should be (as I understand the man page ) Shift , Right Alt, and F10. It isn’t. If I program F34, it’s Control F10 that sends what I set F34 to. That makes no sense at all.

Let’s take it slowly: Okey-dokey. It’s binary, calculated back from position, right? Seems to make sense. After F22, position One. which obviously matches Shift, we have Console_22 in position Two. That should mean that it matches the AltGr or Right Alt key and indeed it does: if I enable tty22 in /etc/inittab, the AltGr-F10 will switch me to tty22 on the console.

The next position is Three and it’s F34. I define F34 on the fly

echo 'string F34 = "Key34" ' | loadkeys

because it’s undefined in my default keymap. I would expect, since it is position Three, that the modifiers would be Shift and Altgr – 2 + 1 equals 3, right?

Nope. Actually, Control F10 sends “Key34” after this. How does THAT make any sense?

It doesn’t. And it gets more strange. If I modify that keymapping like this:

keycode 68 = F10&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp F22 &nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp Console_22&nbsp&nbsp&nbsp&nbsp&nbsp F34 F100 F101

and define F34, F100, and F101, it then works exactly as I would expect it to! Right Alt F10 sends the F34 string, Control F10 sends the F100, and Shift Control F10 sends the F101 string..

So why does it work differently by adding two keysyms???

And then I look farther down the table and see more confusion. How the heck can ShiftL (which I assume means Left Shift) be a modifier weight if Shift already is? Do I assume that to use those positions you’d have to NOT define the ordinary shift combination? That might make sense, but the man page doesn’t explain that.

It is easy to get confused (obviously), so they also provide a shortcut:

The “alt keycode 68 = Console_10” is a shorthand way of defining alt plus F10 without stringing out the first keycode line to nine columns. Without that, you’d need nine entries (you can use VoidSymbol as a place holder for key combinations you don’t care about) and you’d need thirteen to define CTRL-ALT-F10. So at the command line you can also do:

echo 'control alt &nbsp&nbsp&nbsp keycode 68 = F100'&nbsp&nbsp | loadkeys

That lets us redefine the key combinations but still doesn’t tell us what the mysterious “Console_” entries mean. The “control alt keycode 68 = Console_10” obviously defines the key that will switch to the “F10” virtual console. Let’s try changing it:

echo 'control alt &nbsp&nbsp&nbsp keycode 68 = Console_3'&nbsp&nbsp&nbsp | loadkeys

With that in place, CTRL-ALT-F10 will switch to tty3. What about Console_22? Yes, that’s a virtual console too – as long as you enable tty22 in inittab. If you have enabled tty22, then with the default keymap shown above, the right alt key and F10 will switch you to a virtual console on tty22.

There’s more to keymaps, but this at least gets you started.

*Originally published at APLawrence.com

A.P. Lawrence provides SCO Unix and Linux consulting services http://www.pcunix.com