Keyboard configuration and use


I have yet to find good documentation on keyboard support in Linux. The following is cobbled together from various sources using a lot of guesswork - it is very likely to be wrong/misleading/incomplete in many places.

How it works

The kernel contains a keyboard driver, which communicates with the keyboard hardware and generates "input events" for key-presses and key-releases. These events are passed via the "input sub-system" of the kernel and made available to userland processes through the /dev/input/eventX devices (documentation on this is in the file /usr/src/linux/Documentation/input/input.txt). The key codes used in these events are listed (as "#define KEY_...") in the file /usr/src/linux/include/linux/input.h.

Kernel input events can be monitored using the evbug kernel module (see below). Alternatively, the program showkey can display the input-event codes for keys as they are pressed.

X server

The most important userland process that receives and processes input events is the X server, which handles keyboard input for GUI processes. The X-server itself generates an X-event for each input event (key-press and key-release). GUI processes receive keyboard input as these X-events, rather than as kernel input events. The two kinds of events use different codes for the keys: for example the '5' key generates an input event with code 6 (i.e. KEY_5 in /usr/src/linux/include/linux/input.h) and an X-event with code 14. Note that neither of these codes is the same as the ASCII/UTF code, which is 53.

The mapping from X-events to ASCII/UTF8 codes (if done at all) is specific to the GUI application. Command-line programs that are run in an xterm rely on the xterm to do the mapping.

It's possible to monitor X-events using the program xev: just type xev on the command line, and try pressing keys. xev traces ALL X-events, so you will also see events for mouse movements, window resizing, etc.

Virtual terminals

If you are using a virtual terminal rather than the X server, then the keyboard input events are handled within the kernel and provided as ASCII/UTF8 codes via the /dev/ttyX (aka /dev/vc/X) devices.

Keyboard configuration

Kernel

The kernel configuration relevant to keyboard input is under "Device Drivers -> Input Device Support". This won't normally need changing, but there is an "Event Debugging" option, which can be handy if want to see the kernel keyboard events. If you re-build the kernel with this option as a module, you can do:

modprobe evbug

to get all keyboard events logged to /var/log/messages. Do:

rmmod evbug

to turn off the debug output.

For virtual terminals, the mapping from input events to ASCII/UTF8 codes is handled within the kernel. The map used for this is loaded into the kernel using the 'loadkeys' command. This is done automatically at boot time from /etc/rc.d/rc.keymap. If you are having problems with keyboard mapping on a virtual terminal, a first step would be to check that rc.keymap is loading uk.map. The utility 'dumpkeys' will dump the map currently in use by the kernel. The format of kernel keymaps is documented on the 'keymaps' man page.

Laptop keys

The AOpen laptops have some extra keys (e.g. the silver buttons on the left and at the top) that are not recognized by the standard keyboard driver.

acerhk

We used to use the acerhk driver to handle these extra keys, but acerhk is no longer maintained, and it's likely that it will eventually fail to compile with the latest version of the kernel. So far (up to kernel 2.6.27) I've managed to keep it compiling by changing the following line in the acerhk Makefile:

CFLAGS+=-c -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fomit-frame-pointer -fno-strict-aliasing -fno-common -pipe

to:

EXTRA_CFLAGS+=-c -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fomit-frame-pointer -fno-strict-aliasing -fno-common -pipe

Several warnings are also generated when building - I haven't investigated them.

wistron_btns

Kernel 2.6.15 introduced a new module called wistron_btns, which is an alternative acerhk. This was not easily usable until 2.6.21 (or thereabouts), when a generic keymap option was introduced. To use wistron_btns, you need to configure the kernel with 'Device Drivers -> Input device support -> Miscellaneous devices -> x86 Wistron laptop button interface' selected as a module.

To load the wistron_btns module at boot-time add the line:

options wistron_btns keymap=generic

to /etc/modprobe.d/modprobe.conf, and add the line:

/sbin/modprobe -v wistron_btns

to /etc/rc.d/rc.modules.

The extra keys generate the following kernel input keycodes (discovered using evbug - see above) and X-event keycodes (discovered by using xev - see below):

Where Key Input keycode X keycode
"Launch keys" - silver buttons to left of keyboard Wireless 238 KEY_WLAN 243
                         " Mail 155 KEY_MAIL 236
                         " WWW 150 KEY_WWW 130
                         " P1 148 KEY_PROG1 159
                         " P2 149 KEY_PROG2 151
"Audio DJ panel" - silver buttons at top of keyboard Rewind 168 KEY_REWIND 152
                         " Fast forward 159 KEY_FORWARD 233
                         " Play 164 KEY_PLAYPAUSE 162
                         " Stop 166 KEY_STOPCD 164
Function key with Fn held down Fn-F1 138 KEY_HELP 245

Unlike acerhk, wistron_btns (when using the generic keymap) does not automatically turn the WiFI on and off when you press the wireless button. To get this to work, the module needs to be patched. Edit the file /usr/src/linux/drivers/input/misc/wistron_btns.c as follows, and rebuild the kernel:

@@ -565,6 +565,20 @@
        { KE_END, FE_UNTESTED }
 };
 
+static struct key_entry keymap_aopen_1557g[] __initdata = {
+       { KE_KEY, 0x01, {KEY_HELP} },
+       { KE_KEY, 0x11, {KEY_PROG1} },
+       { KE_KEY, 0x12, {KEY_PROG2} },
+       { KE_KEY, 0x22, {KEY_REWIND} },
+       { KE_KEY, 0x23, {KEY_FORWARD} },
+       { KE_KEY, 0x24, {KEY_PLAYPAUSE} },
+       { KE_KEY, 0x25, {KEY_STOPCD} },
+       { KE_WIFI, 0x30 },
+       { KE_KEY, 0x31, {KEY_MAIL} },
+       { KE_KEY, 0x36, {KEY_WWW} },
+       { KE_END, 0 }
+};
+
 static struct key_entry keymap_wistron_generic[] __initdata = {
        { KE_KEY, 0x01, {KEY_HELP} },
        { KE_KEY, 0x02, {KEY_CONFIG} },
+
 static struct key_entry keymap_wistron_generic[] __initdata = {
        { KE_KEY, 0x01, {KEY_HELP} },
        { KE_KEY, 0x02, {KEY_CONFIG} },
@@ -914,6 +928,14 @@
                },
                .driver_data = keymap_fs_amilo_d88x0
        },
+       {
+               .callback = dmi_matched,
+               .ident = "AOpen 1557G",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_SERIAL, "96NDU01G"),
+               },
+               .driver_data = keymap_aopen_1557g
+       },
        { NULL, }
 };

If you use this patch, the module should be loaded without the 'keymap=generic' option.

I've submitted this patch to the author of wistron_btns, so it may eventually find its way into the official kernel.

X server

The X-server uses an amazingly obscure (but supposedly very flexible) mechanism to map input-event key codes to X-event key codes - documentation is in the file /etc/X11/xkb/README.config.

The main place to configure the X-server's keyboard handling is in the file /etc/X11/xorg.conf. This should contain an "InputDevice" section with lines like:

Option "XkbRules"   "xorg"
Option "XkbModel"   "pc104"
Option "XkbLayout"  "gb"
Option "XKbOptions" "compose:rctrl"

The "XkbRules" option should always have the value "xorg".

The "XkbModel" option is supposed to be the model of keyboard that you have. There is a list of these in the file /etc/X11/xkb/rules/xorg.lst, but unless you are lucky your specific keyboard model probably isn't listed. You will then have to guess which of the generic models might work - "pc104" seems OK for the AOpen laptops.

The "XkbLayout" option seems to be a country code. In our case, specifying "gb" enables the "£" key to work.

The "XkbOptions" option is a way specifying some specific tweaks. By default, "pc104" seems to map the "menu" key (that's the one to the left of the right control key) to the "compose" code. Since I wanted to use the menu key as a menu key, I specified "compose:rctrl" to use the right control key for "compose" instead. The possible values for "XkbOptions" are listed in the file /etc/X11/xkb/rules/xorg.lst.

If you change the settings in xorg.conf you will have to restart the X-server for the settings have an effect. If you want to try out changes without restarting X, you can use the setxkbmap command. For example, the above settings could be specified on the command line using:

setxkbmap -rules xorg -model pc104 -layout gb -option "compose:rctrl"

Once you are happy with the changes you can edit them into xorg.conf to make them permanent.

If you want to do anything more advanced, you could consult the files /etc/X11/xkb/README.config and /etc/X11/xkb/README.enhancing, and the web page Creating custom keyboard layouts for X11 using XKB

Entering unusual characters

There are several ways of entering unusual characters such as '€' (the Euro symbol), '©' (the copyright symbol) and 'é' (e acute):
See Accented Characters for a good explanation of the first two methods, particularly for getting accented characters.
You will probably need to set up Slackware to use Unicode in order for unusual characters to be handled sensibly.

AltGr key

The AltGr key is used like a shift key: hold it down while pressing another key. It may be used on its own or with the normal shift key.

The following table was produced by experimentation using the X server on my laptop:

Key With AltGr With AltGr+Shift
1 ¹  
2 ²
3 ³  
4 ¼
5 ½
6 ¾
7  
8  
9   ±
0   °
-   ¿
. · ÷
,   ×
\   ¦
a æ Æ
c ¢ ©
d ð Ð
f đ ª
g ŋ Ŋ
h ħ Ħ
i ı
k ĸ  
l ł Ł
m µ º
o ø Ø
p þ Þ
q   Ω
r ®
s ß §
t ŧ Ŧ
u
w ł Ł
x »  
y ¥
z «  


AltGr is handled in the kernel for virtual terminals, and by the X server for GUI programs (including xterm). I haven't investigated whether the virtual terminal support for AltGr is the same as the X server's - I think you have to do something to enable it, but I don't know what.

Compose key

To use the compose key, you press (and release) the compose key, and then press two further keys. These two keys are "composed" to produce a single character. For example, pressing <compose> 'a' 'e' produces 'æ', and pressing <compose> '"' 'o' produces 'ö'.

There's a complete list of the compose sequences available under the X server at Linux Compose Key Sequences and in the file /usr/X11R6/lib/X11/locale/en_US.UTF-8/Compose (the compose key is referred to as "Multi_key" in this file).

Some of the more useful composed characters are (together with the AltGr method of typing them, where available):
Unicode Char Compose AltGrAltGr+ShiftComment
00a0   " "   nobreakspace # NO-BREAK SPACE
00a6 ¦ "!^"  \brokenbar # BROKEN BAR
00a7 § "so" "os"   ssection # SECTION SIGN
00a9 © "oc" "oC" "Oc" "OC"  ccopyright # COPYRIGHT SIGN
00ab « "<<" z guillemotleft # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
00ae ® "or" "oR" "Or" "OR"   rregistered # REGISTERED SIGN
00b0 ° "oo"  0degree # DEGREE SIGN
00b1 ± "+-"  9plusminus # PLUS-MINUS SIGN
00b2 ² "^2" 2 SUPERSCRIPT TWO
00b3 ³ "^3" 3 SUPERSCRIPT THREE
00b5 µ "mu" m MICRO SIGN
00b6 "p!" "P!" "PP" r paragraph # PILCROW SIGN
00b7 · ".." . MIDDLE DOT
00b9 ¹ "^1" 1 SUPERSCRIPT ONE
00bb » ">>" x guillemotright # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
00bc ¼ "14"  4VULGAR FRACTION ONE QUARTER
00bd ½ "12" 5 VULGAR FRACTION ONE HALF
00be ¾ "34" 6 VULGAR FRACTION THREE QUARTERS
00d7 × "xx"  ,MULTIPLICATION SIGN
00d8 Ø "/O"  oLATIN CAPITAL LETTER O WITH STROKE
00f7 ÷ ":-" "-:"  .DIVISION SIGN
20ac "C=" "=C" "c=" "=c" "E=" "=E" 4 EuroSign # EURO SIGN
2122 "^TM"  8TRADE MARK SIGN

The compose key is handled in the kernel for virtual terminals, and by the X server for GUI programs (including xterm). I haven't investigated whether the virtual terminal support for the compose key is the same as the X server's - I think you have to do something to enable it, but I don't know what.

Application-specific

In vim, you can enter a Unicode code using Ctrl-V u followed by a 4-digit hex number.

In nvu, thunderird and firefox you can enter a Unicode code by holding down control and shift whilst typing a 4-digit hex number.

Binding actions to special keys

The wistron_btns driver generates key-codes for the special keys on the AOpen laptops, but unless you somehow bind an action to them they don't do anything.

I have a Logitech USB headset, which has "volume control" buttons on it - these also generate key-codes, which do nothing unless you can bind an action to them.

A Google search found an application called xbindkeys, which will intercept X key events and perform actions for them.

Download and installation follows the usual pattern:
tar xvf xbindkeys-1.8.3.tgz
cd xbindkeys-1.8.3
./configure --disable-tk
make
vim description-pak
checkinstall
The "--disable-tk" option stops it installing a useless GUI program that requires TCL/TK.

xbindkeys uses a configuration file called .xbindkeysrc to map X-event key codes to actions. You can use xbindkeys itself to generate entries to go in the configuration file. Type:

xbindkeys -k

on the command line, and then press a key (with control, shift, etc. if required). xbindkeys will print out three lines that look like:

"NoCommand"
    m:0x0 + c:117
    Menu

Copy these lines into the .xbindkeysrc file and edit the "NoCommand" to whatever command you want executed. Repeat the process for each key that you want to associate an action with.

My .xbindkeysrc file looks like this:

"eject"
    m:0x0 + c:151
    NoSymbol

"amixer -c Headset -q set Speaker 5%+"
    m:0x0 + c:176
    NoSymbol

"amixer -c Headset -q set Speaker 5%-"
    m:0x0 + c:174
    NoSymbol

"screenshot"
    m:0x0 + c:111
    Print

"screendump"
    m:0x8 + c:111
    Alt + Print

As you can see, I haven't yet found uses for many of the laptop extra keys yet. The "amixer" commands are for controlling the volume on my USB headset. The "screenshot" and "screendump" commands are for taking screenshots - see Screen Shots.

You can change .xbindkeysrc while xbindkeys is running and it will be re-read automatically.

Any keys that are not assigned actions in .xbindkeysrc will not be intercepted by xbindkeys, and will be available to whatever program has focus.

The final step is to arrange for xbindkeys to be started automatically. This can't be done from /etc/rc.d/rc.local, since xbindkeys needs to connect to the X server, which isn't running at that time. I have a ~/.xinitrc file, so I added the following line to that:
/usr/local/bin/xbindkeys
If you don't already have a .xinitrc file in your home directory, the following should work:

#!/bin/sh
/usr/local/bin/xbindkeys
exec /etc/X11/xdg/xfce4/xinitrc

For reference, my full .xinitrc is:

#!/bin/sh

# Trace commands   

set -x

# Turn off beep
xset b off

# Allow any user/host to connect to X server
# (firewalls will stop unwanted hosts)
xhost +

# Start xbindkeys to handle special keys
/usr/local/bin/xbindkeys

# Start the desktop
exec /etc/X11/xdg/xfce4/xinitrc &> ~/logs/xfce