Linux Support for Funny/Functional Keys

On naming: I am a bit wary about the right name for keys like this, whether to call them Funny Keys or Functional Keys. I coined the term FunKeys as a useful shorthand.

On this page:

Elsewhere:

Supported kernels: Linux 2.2.14 and up, 2.4.2 and up.

This patch is not being actively maintained, unlike my BadRAM patch. There is an alternative that is said to work without kernel patching on current Linux systems. We keep this page around for historic service, especially because the information about keyboard modes is still useful.

Introduction to Keyboard Modes

A keyboard under Linux can be interpreted at four different levels:

Architectural Issues

There are several ways to handle FunKeys. It would be possible to interpret the stream of characters over the console device outside the kernel, intercepting them before they reach the application. This has the disadvantage that the console stream can be at any of the four levels, and the targetted keys need not even be visible at all levels. It also has the potential of slowing down the keyboard feed into an application.

Another option would be to adapt the applications. Since these usually are either XFree86 or the Linux virtual terminals, the set of applications seems limited. A problem here is that XFree86 ignores the scan codes for keys it does not know, and it cannot be trivially altered to handle them. Another disadvantage is that it would require the same settings in two places, leading to maintaince issues and possible inconsistent system behaviour.

But the strongest reason for taking a different approach is that the keys are intended to serve a function rather than a string. This distinguishes them from other keys on the keyboard, although it could be argued that SysRq under Linux gets a similar treatment. Currently, SysRq is hardcoded in the keyboard handler code, and doing this for every volume control whim is a Bad Idea(tm).

For these reasons, it seems best to tap the keyboard codes into a second channel, which is not influenced by the interpretation level of the console stream, and which allowed a concurrent program, like a daemon, to operate on the keycodes in spite of what happened on the desktop.

The keyboard interpretation level transmitted over this secondary keyboard device is also a motivated choice. The scan codes have not only values which are keyboard-specific, but also a structure which is proprietary. The keycodes on the other hand, are almost as raw, but have a standardised structure. Therefore, keycodes lend themselves far better for handling by a daemon than scan codes. The translation to ASCII or UTF-8 seems unsuitable for transmission over the secondary keyboard device because these codes could then also be seen over the console, which is clearly undesirable for FunKeys.

Security Issues

Important information is entered through keyboards, including (root) passwords and possibly confidential information. Constraining the exposure of keystrokes therefore is a Good Thing(tm).

To avoid trojan horses set up by users, we can constrain access to the secondary keyboard device to root only. But to avoid unnoticed tapping of passwords by system administrators, it is useful to avoid that a keystroke ever goes to console and secondary keyboard stream. So, we will split keystrokes in a console stream and a FunKey stream.

This way, an attempt to tap information from the keyboard cannot go unnoticed. Furthermore, this split has the advantage that Fun Keys and plain keys receive a clearly distinct treatment. Whereas the Fun Keys are always handled in the background in spite of desktop activities, the plain keys bounde up and down in interpretation level as deemed useful by the desktop.

Implementation

Keycodes and shifting state are interpreted by the kernel key maps, that translate keycodes to 16 bit numbers, which are normally Unicode/ASCII characters. Unicode values from 0xf000 up are treated specially. The low nibble of the high byte is a keycode type that explains how the low byte is to be handled.

The FunKey kernel patch adds a keycode type for `send to the FunKey device'. That is, keycodes like 0xfe59 mean that keycode 0x59 (MSB reset) must be sent to /dev/funkey when the described key is pressed, and 0xb9 (MSB set) when it is released.

The kernel patch is nothing more than the support for this extra key type and a character device to output it over. All the remaining magic is standard Un*x material, a simple daemon. We give a simple example of such a daemon here, under the name funky, which recognises certain keys and starts a Un*x commond for it. Viva le commandline!

Download Software

Software available here comprises of the kernel patch and a daemon. They work fine on my system, and I would like some test output. So, please tell me about successes as well as about problems! See

What can you download right now?

Installation Instructions

The kernel patch is made for Linux 2.2.14, and it installs on top of the BadRAM patch; otherwise there will probably be a single harmless rejection on the CREDITS file. When configuring the kernel, open the character devices dialog, and mark Support for console on virtual terminal for inclusion.

Make sure that when booting your system, some scripts calls setkeycodes and loadkeys as suggested under Implementation.

After booting the newly built kernel, use setkeycodes to assign keycodes to incoming scancodes. Available scancodes can be found with

	dumpkeys | grep ^keycode | grep =$
For the generated keycodes, you may now enter a FunKey code to submit to the FunKey character device, and add 0xfe00 to it to incur sending through /dev/funkey.

On my RedHat system, I added a few lines

	setkeycodes e020  89 e02e  90 e030  91 e022  92 \
		e024  93 e010  94 e019  95 e05f 120 \
		e06c 121 e065 122 e066 123 e032 124
to /etc/rc.d/init.d/keytable.

Now use the standard utilities loadkeys and dumpkeys can be used to install any translation to FunKey codes in the kernel key maps. For my Logitech Internet Keyboard, I used the following to instruct the kernel to pass a set of keys to /dev/funkey (I simply selected the keycodes as FunKey codes, for no reason at all):

	keycode  89 = U+fe59
	keycode  90 = U+fe5a
	keycode  91 = U+fe5b
	keycode  92 = U+fe5c
	keycode  93 = U+fe5d
	keycode  94 = U+fe5e
	keycode  95 = U+fe5f
	shift keycode 120 = U+fe78
	keycode 121 = U+fe79
	keycode 122 = U+fe7a
	keycode 123 = U+fe7b
	keycode 124 = U+fe7c
where the U+ signifies a Unicode keycode. Note how keycode 120 only works with shift down; that's because it is my halt key ;-). In version 1999.03.02, loadkeys complains about Unicode keycodes, but it handles them well. Perhaps a future version of loadkeys and dumpkeys will provide an enhanced syntax for these forms, something like:
	keycode  89 = funkey 89
	keycode  90 = funkey 90
	shift keycode 120 = funkey 120
and so on. Find the keymap that is loaded for your system and extend it with these settings.

After rebooting the FunKey-patched kernel, find the device major number from /proc/devices. Chances are this is 254; create a device node for it:

	mknod /dev/funkey c 254 0
Now start the daemon. You're in!

How to contact me

If you are interested in this project, you can mail me.

My current snail mail address is:

	Rick van Rein
	Haarlebrink 5
	7544 WP Enschede
	the Netherlands
This overrules the address in the patch and daemon, which is intended as a longer-lasting address.


You're invited at my home page and my Linux page.