Configure unrecognized keys in Linux
En Español  

Occasionally I am presented with keyboards that contain keys that are not recognized by default in Linux. In most cases the fix consist in select a different keyboard layout, modern Linux distributions cover a wide variety of keyboards, but some times there is no keyboard layout available that matches our keyboard and the functionality of some keys is lost. In this post I write about how to detect and map unrecognized keys. I am making the assumption that you are working in a graphical environment and that you want to give it some functionality to the key there.

Topics
What happens when we press a key?
Obtaining the scan code of unrecognized keys
Assing a key code to the scan code
Make a script that runs at boot time

What happens when we press a key?

When we press a key, a scan code is send from the keyboard to the system, the kernel reads this scan code and try to find it in a table that maps this scan codes, the number associated with the scan code in this table is called a key code. In order for a key to work the scan code must have a key code assigned to it. Then, if the environment where we are working on knows what to do with this key code, the key will have a functionality. The functionality in a terminal and the one in a graphical desktop environment may be different, usually multimedia keys don't have a function in a terminal but they do work in the graphical environment.

In most cases, we can assign to this scan code the key code of the functionality that we want, as the X system already support a wide variety of keys and most desktop environments interpret this keys and give them that very same functionality within them. Or we can just give the key any unused key code, and configure in our desktop environment the functionality of said key. This post is primarily about assigning a key code to an unrecognized scan code, and make this change permanent.

Obtaining the scan code of unrecognized keys

When the kernel can't find the scan code of a pressed key in the map of key codes, the kernel produces an error saying that the key is unknown, and indicate us the scan code of the key in question. We can see this error messages by using dmesg or by checking the kernel log file, usually located in /var/log/messages or /var/log/dmesg.

You can press the unrecognized keys and use dmesg to find the scan codes, you would see something similar to this but with your own scan codes:

atkbd.c: Unknown key pressed (translated set 2, code 0xa6 on isa0060/serio0).atkbd.c: Use 'setkeycodes e026 <keycode>' to make it known.atkbd.c: Unknown key released (translated set 2, code 0xa6 on isa0060/serio0).atkbd.c: Use 'setkeycodes e026 <keycode>' to make it known.atkbd.c: Unknown key pressed (translated set 2, code 0xa3 on isa0060/serio0).atkbd.c: Use 'setkeycodes e023 <keycode>' to make it known.atkbd.c: Unknown key released (translated set 2, code 0xa3 on isa0060/serio0).atkbd.c: Use 'setkeycodes e023 <keycode>' to make it known.atkbd.c: Unknown key pressed (translated set 2, code 0x94 on isa0060/serio0).atkbd.c: Use 'setkeycodes e014 <keycode>' to make it known.atkbd.c: Unknown key released (translated set 2, code 0x94 on isa0060/serio0).atkbd.c: Use 'setkeycodes e014 <keycode>' to make it known.

The other option is to use tail -f in the log file of the kernel, again, it may be in /var/log/messages or in /var/log/dmesg, and then press your unrecognized keys, to exit tail use ctrl+c:

tail -f /var/log/messages

By this method you would see the same messages appear when you press said keys, only with the date and the user name in front.

In this example, the scan code of three keys were unrecognized, this is, no key code was found to be associated with the scan code, the important value here appears right next to the setkeycodes command. We have to define e026, e023 and e014.

Assing a key code to the scan code

As I am still assuming that you are planing to give some functionality to this keys in a graphical environment, you can use the command:

xmodmap -pke | less

This command will show you the current layout of the keyboard, in here you can both find unused key codes and well as the key codes of functionality already supported by xmodmap. If this three of the keys corresponded to the volume controls, mute, lower the volume and increase the volume, we will find that this functionality already have a key code associated to it, we will see the following lines:

keycode 121 = XF86AudioMute NoSymbol XF86AudioMute
keycode 122 = XF86AudioLowerVolume NoSymbol XF86AudioLowerVolume
keycode 123 = XF86AudioRaiseVolume NoSymbol XF86AudioRaiseVolume

So, we are going to assign each of the scan codes one of the key codes that we found here. To assign a key code to a key, we use the command setkeycodes. Following our example:

setkeycodes e014 121
setkeycodes e023 122
setkeycodes e026 123

If we don't get error messages then the keys has been correctly set. This should make the keys work. It is a good idea to try the keys individually to check that everything is working well. The worst case scenario is that we assign an invalid number and our keyboard stops working correctly, but this can be easily undone by reloading the session (logging out and logging in) or restarting. This shouldn't happen tho.

Make a script that runs at boot time

Once all is nicely working, we are going to create a script to do this assignation when we boot the computer. We create a file inside /etc/init.d (in some systems it may be in /etc/conf.d, for Ubuntu and variants it's /etc/init.d), I am going to call it keyremap.

sudo gedit /etc/init.d/keyremap

And then add the following lines in this file:

#!/bin/sh
setkeycodes e014 121
setkeycodes e023 122
setkeycodes e026 123

We save the file, and then we make it executable with:

sudo chmod +x /etc/init.d/keyremap

And make it be executed at the start together with the rest of the scripts in /etc/init.d:

update-rc.d keyremap defaults

If we wanted to remove the script from the start, we can use:

update-rc.d -f keyremap remove