Jan 112013
 

Customising keyboard maps in Linux is somewhat … confused with lots of different tools and layers to perform the same task. There are a number of tools for performing some form of keyboard mapping, but the most common ones have some disadvantages :-

  •  xkb (which is the modern X way), and xmodmap (which is deprecated but conveniently has a very simple syntax for dealing with a single key) both work fine for ordinary keys but cannot do anything with “unusual” keys not passed into X. Just look online for just how many people have trouble with multimedia keys not being recognised.
  • The PS/2-specific tools of dumpkeys, loadkeys, and setkeycodes which work fine, but are somewhat reluctant to help out with USB keyboards.
  • Plus the desktop environment you are using may well have its own idea of how the keyboard will be used (GNOME has a nasty tendency to grab the menu key away from me).

There is fortunately another way which is rather difficult to find information about. Which is the reason behind this posting of course.

This “other method” is to use the generic input system to perform the keyboard mapping which has certain advantages over other methods. Most of the information to do this came from a README file contained within the source code.

The Example Keyboard

To demonstrate keyboard mapping, it is helpful to have an example keyboard with custom mappings to play with. Many of the keyboards I use this for are rather complex with many mappings, but I also have a mini keyboard with relatively few mappings :-

Original Key new function
Esc Lock screen
`/~ Esc
Caps Lock Control
Insert Delete
Delete `/~

No great mystery as to why I want my keyboard mapped this way – I’m just fussy about keyboards.

The Basic “Tool”

In fact there is just one tool – /lib/udev/keymap – which performs all of the relevant tasks. Before it can do anything, it needs to be provided with the path of the relevant input device. This is easiest done from the console (rather than in X) as root. The easiest way of identifying the device is to unplug the keyboard, reboot the machine, and :-

# ls /dev/input/e* > /var/tmp/old.list
[Plug in keyboard]
# ls /dev/input/e* > /var/tmp/new.list
# diff /var/tmp/old.list /var/tmp/old.list
> /dev/input/event13
> /dev/input/event14

If you are lucky, there will be just one new input device. If not, you will have to try each one in turn. The first job is to record the keycode of each key to be customised in turn. To do this, it is necessary to run keymap with the input device and the “-i” option, and each keystroke will result in some output :-

# /lib/udev/keymap /dev/input/event13 -i
Press ESC to finish, or Control-C if this device is not your primary keyboard
scan code: 0x70029   key code: esc
# /lib/udev/keymap /dev/input/event13 -i
Press ESC to finish, or Control-C if this device is not your primary keyboard
scan code: 0x70035   key code: grave
scan code: 0x70039   key code: capslock
scan code: 0x70049   key code: insert
scan code: 0x7004C   key code: delete

A key can be mapped temporarily using keymap. But before that a list of possible key names is useful to have; there is one to be found in /usr/include/ :-

# grep KEY_ /usr/include/linux/input.h | less

The relevant name would be the part that follows the “KEY_” converted to lower-case.

# /lib/udev/keymap /dev/input/event13 0x70035 esc

But that is rather a temporary solution; it is better by far to create a file containing the necessary mappings to be automatically applied :-

# cat /tmp/custom-filco.map
0x70029 screenlock
#	Original: key code: esc
0x70035 esc
#	Original: key code: grave
0x70039 leftctrl
#	Original: key code: capslock
0x70049 delete
#	Original: key code: insert
0x7004C insert
#	Original: key code: delete

Making The Mappings Permanent

The first step is to obtain some details to uniquely (or as much as possible) identify the keyboard. Run :-

# udevadm info --export-db > /tmp/udev-db.txt

And look through the output for the input device you previously used. Look for a ID_VENDOR_ID and ID_MODEL_ID that you can use.

Next add a rule to /lib/udev/rules.d/95-keymap.rules along the lines of :-

ENV{ID_VENDOR_ID}=="04d9", ENV{ID_MODEL_ID}=="2011", RUN+="keymap $name custom-filco.map"

Once this is working you may want to add it to your version of custom-filco.map as a comment to preserve it for use after upgrades; alternatively you may wish to create a new file that will not get overwritten.

Before activating the new rule, remember to copy /tmp/custom-filco.map into /lib/keymaps/custom-filco.map. And again keep another copy in a safe place to preserve.

As to how to activate, a reboot is probably the simplest way.

Aug 112010
 

Ten years ago? Bloomin’ heck! Still as this still seems to get frequent hits, I suppose quick update is in order – I no longer use the Unicomp “naked” but go through a Soarer converter which is an easier way of mapping the keys and allows macros to be added.

Thanks to these guys (the thread eventually gets to the meaty details), I have changed my Unicomp 122-key keyboard (UB40T56) from a funky “be friendly to Windows IBM Terminal emulators” mode into something a little more interesting. Specifically each key should be sending a unique keycode – which if you select the right model from Unicomp, you’ll get.

This can be done by opening up the keyboard and removing the jumper from JP3 (just below a small chip and close to the scroll LED). In addition, it is strongly suggested that you set the kernel parameter “atkbd.softraw=0” which can be done with Ubuntu 10.04 with the following :-

  1. Edit /etc/default/grub and change the variable GRUB_CMDLINE_LINUX_DEFAULT to include “atkbd.softraw=0” at the end of what is already there.
  2. Finish editing and run grub-update and finally reboot.

Without this, showkey -s only shows the scancodes of keys that the kernel knows about – not what scancodes are sent by the keyboard! It is possible to show the unknown scancodes by enabling the i8042 module debug mode, but atkbd.softraw does the same thing more effectively.

This is currently a work in progress, and will need further checking before it can be taken as gospel, but …

Group Key Make Break Keycode
Function Keys
F13 5b db
F14 5c dc 95
F15 5d dd 183
F16 63 e3
F17 64 e4
F18 65 e5
F19 66 e6
F20 67 e7
F21 68 e8
F22 69 e9
F23 6a ea
F24 6b eb
(next row) F1 3b bb 59
F2 3c bc 60
F3 3d bd 61
F4 3e be 62
F5 3f bf 63
F6 40 c0 64
F7 41 c1 65
F8 42 c2 66
F9 43 c3 67
F10 44 c4 68
F11 57 d7 87
F12 58 d8 88
Left Keypad (Top left is “Esc”)
Esc 7e fe 121
Cent 76 f6 85
Print Screen 72 f2
Pause e1 1d 45 e1 9d c5 119
Print 74 f4
Help 6d ed
Record e0 2a e0 37 e0 b7 e0 aa 99
Play 6f ef
GUI (Windows) 75 f5
Menu 6c ec
Editing Pad (between QWERTY and Number Pad)
Backtab 5a da
Insert e0 49 e0 c9 104
PageUp e0 51 e0 d1 109
(next row) Blue Return e0 4f e0 cf 107
Delete e0 52 e0 d2 110
Page Down e0 53 e0 d3 111
(next row) Up Arrow e0 48 e0 c8 103
(next row) Left Arrow e0 4b e0 cb 105
Home e0 47 e0 c7 102
Right Arrow e0 4d e0 cd 106
(next row) Down Arrow e0 50 e0 d0 108
Number Pad
(top row) End 01 81 1
Scroll Lock 46 c6 70
(shifted Scroll Lock) Number Lock 45 c5 69
/ 37 b7 55
* e0 c5 e0 b5 98
(next row) KP-7 47 c7 71
KP-8 48 c8 72
KP-9 49 c9 73
4e ce 78
(next row) KP-4 41 cb 75
KP-5 4c cc 76
KP-6 4d cd 77
+ 4a ca 74
(next row) KP-1 4f cf 79
KP-2 50 d0 80
KP-3 51 d1 81
Enter e0 1c e0 9c 96
(next row) KP-0 52 d2 82
KP-. 53 d3 83
  • Group. To break things up a little, I’ve grouped the keys into the 5 separate parts of the keyboard – the function keys, the keypad to the left, the qwerty pad, the editing pad, and the number pad (“keypad”). The details of the qwerty pad will be the last as the other groups are more interesting (‘qwerty’ keys just work).
  • Key. This is the label on the key on my keyboard. This may be different on different variants so in all cases I have started with the top left, worked left and down (the “qwerty” row before the “asdf” row).
  • Make. This is the scancode produced when the key is pressed.
  • Break. This is the scancode produced when the key is released.
  • Keycode. The configured keycode produced on the Linux console. The red cells are values that are wrong, but in addition many are missing because they are not produced on a keypress. I say wrong because the keycode gives a result that does not match the key legend – in some cases dangerously wrong such as PageDown generating Delete. One thing to be aware of is that you must use “showkey -k” at the console to get the same numbers I have – X seems to add 8 to each keycode.

Three interesting oddities here … F14 and F15 have somehow been graced with keycodes by default; their scan codes must coincide with keys defined on more popular keyboards. And of course Num Lock and Scroll Lock sharing the same key is a little … odd. And lastly the Record key is effectively sending two keystrokes in one.

Fixing The Wrong Keys

The first place to start is to map the keys that return a keycode that represents a key other than that written on the keycap – such as the key marked “End” which thinks it is an “Esc” key. I have left out two of the wrong keys from this group as they fit better into the next section.

The wrong keys can be fixed with the following commands :-

setkeycodes 7e         1    # Esc
setkeycodes e049      82    # Insert
setkeycodes e051     105    # PageUp
setkeycodes e052     111    # Delete
setkeycodes e053     109    # PageDown
setkeycodes 01       107    # End
setkeycodes 37        98    # KP-/
setkeycodes e035      55    # KP-*
setkeycodes 4e        74    # KP--
setkeycodes 4a        78    # KP-+

I have left out a couple of the wrong keys from this section as they do not return dangerously incorrect values, and they fit more logically into the next section (being Record and Blue Return).

Dealing With The Extra Keys

Now onto dealing with the extra keys. The tricky bit here was coming up with new keycodes for these keys that did not conflict with existing keycodes, and were reasonable. This is effectively impossible, as xmodmap -pk appears to show no significant range of unused keycodes although some of the used keycodes are for things like “Shop” buttons!

So I picked a range with a larger number of useless key symbols and some unused ones :-

setkeycodes 5b       222    # F13
setkeycodes 5c       223    # F14
setkeycodes 5d       224    # F15
setkeycodes 63       225    # F16
setkeycodes 64       237    # F17
setkeycodes 65       238    # F18
setkeycodes 66       228    # F19
setkeycodes 67       229    # F20
setkeycodes 68       230    # F21
setkeycodes 69       231    # F22
setkeycodes 6a       232    # F23
setkeycodes 6b       233    # F24
setkeycodes 72        99    # Record (after keyswap)
setkeycodes 74       209    # Print
setkeycodes 6d       138    # Help
setkeycodes 6f       239    # Play
setkeycodes 75       234    # Windows (GUI)
setkeycodes 6c       240    # Menu
setkeycodes 5a       235    # Backtab
setkeycodes e04f     236    # BlueReturn

Once this has run, we can look at fixing the X mappings … which is why F17 and F18 are out of sequence in the above! One key has to be (at least until someone comes up with a better solution!) sorted out with a keycap swap. Take the keycap from the Record key and swap it for the one marked “Print Screen”. This is because the scancode for Record is effectively two scancodes in one and attempting to remap it will result in strange things happening.

Sorting Out X11

Once you have a set of keycodes that don’t do funny things under X (for instance F17 and F18 when in sequence produce not a keystroke under X11 but some other event), you can move onto configuring the X keyboard. The following attempts to map as close to the keycaps as possible without going to extremes :-

xmodmap -e "keycode 230 = F13"
xmodmap -e "keycode 231 = F14"
xmodmap -e "keycode 232 = F15"
xmodmap -e "keycode 233 = F16"
xmodmap -e "keycode 245 = F17"
xmodmap -e "keycode 246 = F18"
xmodmap -e "keycode 236 = F19"
xmodmap -e "keycode 237 = F20"
xmodmap -e "keycode 238 = F21"
xmodmap -e "keycode 239 = F22"
xmodmap -e "keycode 240 = F23"
xmodmap -e "keycode 241 = F24"
xmodmap -e "keycode 217 = Print"
xmodmap -e "keycode 9 = Escape 3270_Attn"
xmodmap -e "keycode  93 = cent bar"
xmodmap -e "keycode 175 = 3270_Record"
xmodmap -e "keycode 175 ="
xmodmap -e "keycode 247 = 3270_Play"
xmodmap -e "keycode 242 = Super_L"
xmodmap -e "keycode 248 = Multi_key"
xmodmap -e "keycode 243 = 3270_BackTab"
xmodmap -e "keycode 118 = Insert 3270_Duplicate"
xmodmap -e "keycode 112 = Prior 3270_Jump"
xmodmap -e "keycode 117 = Next 3270_Rule"

This results in a keyboard that more or less matches the key caps. For some of the blue symbols, you press the key in combination with shift.

The number pad could do with a little more attention in the realm of X-mapping, and there are a few blue symbols on the main qwerty pad that might be usefully mapped, but this is sufficient for my purposes.

Oct 172009
 

If you are old enough to remember a time when if you were really lucky you might have access to a computer over a 9600 baud serial line connecting with a terminal, you may well have encountered the Compose key on DEC serial terminals (or in many other places). If you aren’t, I’ll have to explain what they are …

Imagine you have a US or UK keyboard, and suddenly have a need to enter an accented character (such as ü) – perhaps in a place name or perhaps you simply want to spell “café” properly for once. If you look at your keyboard you’ll find that the relevant characters do not appear anywhere. One of the solutions to this are the “dead letters” where certain symbols (such as “) work by putting the mark on the key over the next letter you type.

This apparently works well enough for those who enter such letters every other word or so, but I’m a monolingual Englishman who does not need them so often and I would rather have my quote key left alone thank you very much.

Now imagine a special key on the keyboard. Let us call it “Compose” for the want of any other name. You press it, and a fourth LED on your keyboard lights up. You can then enter any suitable two character sequence to generate accented characters or other symbols (½, «, ¡, ♯, ə, þ, etc.). Perhaps it might stretch your memory a bit remembering all the sequences, but you soon get used to much of it … it doesn’t take much memory capacity to remember that compose, u, ” becomes a ü, and that if you want anything with an umlaut on it, just use compose, whatever needs an umlaut, and “.

Back when I got started in IT, we had a bewildering variety of different types of keyboards with different layouts (and many of which were better by far for typing than most modern crud). For better or worse the IBM keyboard layout effectively won (the Macintosh keyboard is an IBM one with a few extra function keys and some of the modifiers relabelled). One of the big losses was the lack of a Compose key.

Let’s have it back!

Oh! And if you are going to have an “Alt GR” key to function as a “shift” key to enter funky symbols, please engrave the symbols on the front of the keys. You will notice that where the Shift key produces a different symbol, the different symbol is shown on the key – see the 1 key with ! shown.