Keys & Consoles

A Member of the Linux Documentation Project

"The Linux Gazette...making Linux just a little more fun...! "

Copyright (c) 1996 John M. Fisk fiskjm@ctrvax.vanderbilt.edu
The LINUX GAZETTE is a member of the LINUX DOCUMENTATION PROJECT.

Of Keyboards and Consoles...

(The following article was submitted to the Linux Journal for publication and is being presented here with the permission of the publisher of the Linux Journal -- John M. Fisk)


Keyboards, Consoles, and VT Cruising

by
John M. Fisk <fiskjm@ctrvax.vanderbilt.edu>
July 1, 1996

"It's a GUI, GUI, GUI, GUI world!" -- or so the major OS manufacturers would have you belief. Truth is, that while this is increasingly the case, there are times when the command line interface (CLI) is still a very good choice for getting things done. It's fast, generally efficient, and is a good choice on memory or CPU constrained machines. And don't forget that there are still a lot of very nifty things that can be done "at the console."

In this spirit, I'd like to start by following up on a delightful and informative article written by Allesandro Rubini entitled "The Best Without X" that appeared in the November, 1995 (Issue 19) edition of the Linux Journal. Among a wealth of helpful ideas, Allesandro suggested converting the numeric keypad into a "console-switch scratch pad" to allow single key switching from one virtual terminal (VT) to another. We'll begin by looking at how this can be done. We'll also look at:

By the time that you get through tinkering around with these things I think you'll agree that the CLI isn't such a bad place after all :-) Also, the good news is that the programs you'll need for this are standard inclusions in most recent Linux distributions and include:

A listing of Linux FTP archives where these may be found is included at the end of this article.

THE KEYPAD VT-SWITCHER

The numeric keypad is an ideal candidate for remapping into a virtual terminal (VT) switching scratch pad as most of us have never learned to "touch type" using the keypad. In addition, on a 101-key keyboard, its non-numeric functions are already duplicated by the Home, End, Page Up, Page Down, Insert, Delete, and arrow keys. Since there may be occasions in which we still want to use the keypad for numeric input let's see how to set it up as a VT switcher while retaining numeric input ability.

To do this you'll need to have the kbd package installed on your system. The two programs we'll be using for this are the 'showkey' and 'loadkey' programs. To check whether they are installed on your system you can type in:

    % type loadkeys showkey

if you're using the BASH shell, or:

    % which loadkeys showkey

The 'which' program or the BASH shell built-in function 'type' will both print the path to the executable if they exist in the PATH search path. On my machine this produces:

    ~$ type showkey loadkeys
    showkey is /usr/bin/showkey
    loadkeys is /usr/bin/loadkeys

    ~$ which showkey loadkeys
    /usr/bin/showkey
    /usr/bin/loadkeys

If you don't have these programs installed you'll need to get the sources for the kbd package and install it yourself. (This comes as source only but installation is as simple as unachiving it into a temporary directory and typing in 'make && make install').

Converting the keypad into VT switcher involves defining a keyboard mapping and then using loadkeys to actually load this information into the kernel keyboard translation tables. It's a whole lot easier than it sounds although you must keep in mind that indiscriminate tinkering can render your keyboard useless (requiring one of those dreaded cold reboots) and that changing the keyboard translation tables affects ALL VT's, not just the one you're working on.

The kbd package default installation location is under /usr/lib/kbd with the key mapping files in the keytables subdirectory. Change to this directory and make a copy of the defkeymap.map file. This is the default keyboard mapping and is a useful place to start. You can call the new file anything you'd like - e.g.,

    cp defkeymap.map custom.map

Use your favorite editor and load up this file. At this point it's probably helpful to stop for a moment and have a look around. It's rather like visiting one of those fine old curio shops -- look, but don't touch! The first few lines may look something like this:

keycode   1 = Escape  Escape
    alt keycode   1 = Meta_Escape
keycode   2 = one  exclam
    alt keycode   2 = Meta_one
    shift   alt keycode   2 = Meta_exclam
keycode   3 = two   at   at
    control keycode   3 = nul
    shift   control keycode   3 = nul
    alt keycode   3 = Meta_two
    shift   alt keycode   3 = Meta_at

I won't go into all the gory details of how to remap the keyboard except to say that the basic format that we'll use is:

    keycode keynumber = keysym
    modifier keycode keynumber = keysym

in which 'keynumber' is the internal identification number of the key and 'keysym' represents the action to take. Now before you bail out on me let's put this into simple terms. Each key on the keyboard is identified by a unique number which is represented by 'keynumber'. When a key is pressed or released these events are passed to the operating system which responds by performing the appropriate action -- represented here by 'keysym'. The 'modifier' is a key which is held down at the same time that the key is pressed. These 'modifier' keys include the well known control, alt, and shift keys. Being able to define multi-key combinations extends the mapping available for each key.

So, using the example above, pressing the key associated with keynumber 3 actually causes the number '2' to be printed to the screen. If the shift key is held down at the same time as the key is pressed, the '@' sign is printed to the screen, and if the three key combination Shift+Alt+keynumber 3 is pressed, the output is the Meta_at (whatever one of those looks like).

Getting back to the task at hand, what we want to do is change to a specified VT when we press one of the keypad keys: pressing keypad 1 should switch to VT number 1, pressing keypad 2 should switch to VT number 2, and so forth. In your customized key map file find the section that defines the keypad keys -- it should look similar to this:

keycode  71 = KP_7
    alt keycode  71 = Ascii_7
keycode  72 = KP_8
    alt keycode  72 = Ascii_8
keycode  73 = KP_9
    alt keycode  73 = Ascii_9
[...]

Now, edit this section so that it reads something like:

# NUMERIC KEYPAD MAPPING
#
# The section remaps the keypad keys so that they act as a
# VT-switcher:  keypad 1 switches to VT 1, keypad 2 to VT 2,
# and so forth.  Note that pressing Shift+key switches to a VT
# which is 10+ the number of the key (Shift+3 = VT 13) and that
# pressing Alt+key (when Num Lock is on) causes numeric output.
#
# Keypad number 7
#
keycode  71 = Console_7
    shift       keycode  71 = Console_17
    alt         keycode  71 = KP_7
    alt control keycode  71 = Console_7
#
# Keypad number 8
#
keycode  72 = Console_8
    shift       keycode  72 = Console_18
    alt         keycode  72 = KP_8
    alt control keycode  72 = Console_8
#
# Keypad number 9
#
keycode  73 = Console_9
    shift       keycode  73 = Console_19
    alt         keycode  73 = KP_9
    alt control keycode  73 = Console_9
keycode  74 = KP_Subtract
#
# Keypad number 4
#
keycode  75 = Console_4
    shift       keycode  75 = Console_14
    alt         keycode  75 = KP_4
    alt control keycode  75 = Console_4
#
# Keypad number 5
#
keycode  76 = Console_5
    shift       keycode  76 = Console_15
    alt         keycode  76 = KP_5
    alt control keycode  76 = Console_5
#
# Keypad number 6
#
keycode  77 = Console_6
    shift       keycode  77 = Console_16
    alt         keycode  77 = KP_6
    alt control keycode  77 = Console_6
keycode  78 = KP_Add
#
# Keypad number 1
#
keycode  79 = Console_1
    shift       keycode  79 = Console_11
    alt         keycode  79 = KP_1
    alt control keycode  79 = Console_1
#
# Keypad number 2
#
keycode  80 = Console_2
    shift       keycode  80 = Console_12
    alt         keycode  80 = KP_2
    alt control keycode  80 = Console_2
#
# Keypad number 3
#
keycode  81 = Console_3
    shift       keycode  81 = Console_13
    alt         keycode  81 = KP_3
    alt control keycode  81 = Console_3
#
# Keypad number 0
#
keycode  82 = Last_Console
    shift keycode  82 = Console_10
    alt   keycode  82 = KP_0
#
# Keypad '.' key
#
keycode  83 = KP_Period
    altgr control keycode  83 = Boot
      control alt keycode  83 = Boot
keycode  84 = Last_Console

Before going on let's make a couple observations. First, it's not a bad idea to comment the file as you go. What's seems so clear and obvious now quickly fades into obscurity as the weeks pass. Adding comments will help prevent your having to pour back over manual pages, program documentation, and magazine articles looking for the correct syntax or usage.

Second, notice that with each entry there are "sub-stanzas" if you will, that begin with the words "alt keycode" "shift keycode" etc. These are the stanzas that define multi-key combinations in which a "modifier" key is pressed at the same time as the key being defined. A common example of this is the "Ctrl-C" combination that is used to terminate a program in execution.

Finally, you may be asking yourself how you're supposed to know which keynumber is associated with a key. Anyone know off hand what keynumber goes with the " key? The way you find this out is using the 'showkey' program. After you invoke the program, showkey prints the keynumber for any key that you hit (and quits after 10 seconds of no input). So, now that we've already edited the pertinent section in the 'custom.map' file, let's see how we'd arrive at this "from scratch."

The basic steps we'd need to take would be to:

To do this, let's begin by using the 'showkey' program which can be invoked using:

    % showkey

Now, any key that you press causes showkey to print the keynumber. On my machine, invoking showkey and pressing keypad keys 1 through 9 results in the following output:

~$ showkey
kb mode was XLATE

press any key (program terminates after 10s of last key press)...
keycode  79 press
keycode  79 release
keycode  80 press
keycode  80 release
keycode  81 press
keycode  81 release
keycode  75 press
keycode  75 release
keycode  76 press
keycode  76 release
keycode  77 press
keycode  77 release
keycode  71 press
keycode  71 release
keycode  72 press
keycode  72 release
keycode  73 press
keycode  73 release

You can see that both key press and key release events are detected. Also note that the numbering of the keypad keys is not sequential. The numeric keys have the following format:

Actual Key:                 Keynumber:

7    8    9                 71   72   73

4    5    6                 75   76   77

1    2    3                 79   80   81

So that keypad number 1 has keynumber 79, keypad number 2 has keynumber 80, and so forth. Knowing this, we can now set up the appropriate key map entry for each of these keys. The keysym event that we're interested in is Console_x, in which 'x' is the number of the VT to which the view is s asection in the 'custom.map' file, let's see how we'd arrive at this "from scratch."

The basic steps we'd need to take would be to:

To do this, let's begin by using the 'showkey' program which can be invoked using:

    % showkey

Now, any key that you press causes showkey to print the keynumber. On my machine, invoking showkey and pressing keypad keys 1 through 9 results in the following output:

~$ showkey
kb mode was XLATE

press any key (program terminates after 10s of last key press)...
keycode  79 press
keycode  79 release
keycode  80 press
keycode  80 release
keycode  81 press
keycode  81 release
keycode  75 press
keycode  75 release
keycode  76 press
keycode  76 release
keycode  77 press
keycode  77 release
keycode  71 press
keycode  71 release
keycode  72 press
keycode  72 release
keycode  73 press
keycode  73 release

You can see that both key press and key release events are detected. Also note that the numbering of the keypad keys is not sequential. The numeric keys have the following format:

Actual Key:                 Keynumber:

7    8    9                 71   72   73

4    5    6                 75   76   77

1    2    3                 79   80   81

So that keypad number 1 has keynumber 79, keypad number 2 has keynumber 80, and so forth. Knowing this, we can now set up the appropriate key map entry for each of these keys. The keysym event that we're interested in is Console_x, in which 'x' is the number of the VT to which the view is s asection in the 'custom.map' file, let's see how we'd arrive at this "from scratch."

The basic steps we'd need to take would be to:

To do this, let's begin by using the 'showkey' program which can be invoked using:

    % showkey

Now, any key that you press causes showkey to print the keynumber. On my machine, invoking showkey and pressing keypad keys 1 through 9 results in the following output:

~$ showkey
kb mode was XLATE

press any key (program terminates after 10s of last key press)...
keycode  79 press
keycode  79 release
keycode  80 press
keycode  80 release
keycode  81 press
keycode  81 release
keycode  75 press
keycode  75 release
keycode  76 press
keycode  76 release
keycode  77 press
keycode  77 release
keycode  71 press
keycode  71 release
keycode  72 press
keycode  72 release
keycode  73 press
keycode  73 release

You can see that both key press and key release events are detected. Also note that the numbering of the keypad keys is not sequential. The numeric keys have the following format:

Actual Key:                 Keynumber:

7    8    9                 71   72   73

4    5    6                 75   76   77

1    2    3                 79   80   81

So that keypad number 1 has keynumber 79, keypad number 2 has keynumber 80, and so forth. Knowing this, we can now set up the appropriate key map entry for each of these keys. The keysym event that we're interested in is Console_x, in which 'x' is the number of the VT to which the view is s asection in the 'custom.map' file, let's see how we'd arrive at this "from scratch."

The basic steps we'd need to take would be to:

To do this, let's begin by using the 'showkey' program which can be invoked using:

    % showkey

Now, any key that you press causes showkey to print the keynumber. On my machine, invoking showkey and pressing keypad keys 1 through 9 results in the following output:

~$ showkey
kb mode was XLATE

press any key (program terminates after 10s of last key press)...
keycode  79 press
keycode  79 release
keycode  80 press
keycode  80 release
keycode  81 press
keycode  81 release
keycode  75 press
keycode  75 release
keycode  76 press
keycode  76 release
keycode  77 press
keycode  77 release
keycode  71 press
keycode  71 release
keycode  72 press
keycode  72 release
keycode  73 press
keycode  73 release

You can see that both key press and key release events are detected. Also note that the numbering of the keypad keys is not sequential. The numeric keys have the following format:

Actual Key:                 Keynumber:

7    8    9                 71   72   73

4    5    6                 75   76   77

1    2    3                 79   80   81

So that keypad number 1 has keynumber 79, keypad number 2 has keynumber 80, and so forth. Knowing this, we can now set up the appropriate key map entry for each of these keys. The keysym event that we're interested in is Console_x, in which 'x' is the number of the VT to which the view is s asection in the 'custom.map' file, let's see how we'd arrive at this "from scratch."

The basic steps we'd need to take would be to:

To do this, let's begin by using the 'showkey' program which can be invoked using:

    % showkey

Now, any key that you press causes showkey to print the keynumber. On my machine, invoking showkey and pressing keypad keys 1 through 9 results in the following output:

~$ showkey
kb mode was XLATE

press any key (program terminates after 10s of last key press)...
keycode  79 press
keycode  79 release
keycode  80 press
keycode  80 release
keycode  81 press
keycode  81 release
keycode  75 press
keycode  75 release
keycode  76 press
keycode  76 release
keycode  77 press
keycode  77 release
keycode  71 press
keycode  71 release
keycode  72 press
keycode  72 release
keycode  73 press
keycode  73 release

You can see that both key press and key release events are detected. Also note that the numbering of the keypad keys is not sequential. The numeric keys have the following format:

Actual Key:                 Keynumber:

7    8    9                 71   72   73

4    5    6                 75   76   77

1    2    3                 79   80   81

So that keypad number 1 has keynumber 79, keypad number 2 has keynumber 80, and so forth. Knowing this, we can now set up the appropriate key map entry for each of these keys. The keysym event that we're interested in is Console_x, in which 'x' is the number of the VT to which the view is s asection in the 'custom.map' file, let's see how we'd arrive at this "from scratch."

The basic steps we'd need to take would be to:

To do this, let's begin by using the 'showkey' program which can be invoked using:

    % showkey

Now, any key that you press causes showkey to print the keynumber. On my machine, invoking showkey and pressing keypad keys 1 through 9 results in the following output:

~$ showkey
kb mode was XLATE

press any key (program terminates after 10s of last key press)...
keycode  79 press
keycode  79 release
keycode  80 press
keycode  80 release
keycode  81 press
keycode  81 release
keycode  75 press
keycode  75 release
keycode  76 press
keycode  76 release
keycode  77 press
keycode  77 release
keycode  71 press
keycode  71 release
keycode  72 press
keycode  72 release
keycode  73 press
keycode  73 release

You can see that both key press and key release events are detected. Also note that the numbering of the keypad keys is not sequential. The numeric keys have the following format:

Actual Key:                 Keynumber:

7    8    9                 71   72   73

4    5    6                 75   76   77

1    2    3                 79   80   81

So that keypad number 1 has keynumber 79, keypad number 2 has keynumber 80, and so forth. Knowing this, we can now set up the appropriate key map entry for each of these keys. The keysym event that we're interested in is Console_x, in which 'x' is the number of the VT to which the view is s asection in the 'custom.map' file, let's see how we'd arrive at this "from scratch."

The basic steps we'd need to take would be to:

To do this, let's begin by using the 'showkey' program which can be invoked using:

    % showkey

Now, any key that you press causes showkey to print the keynumber. On my machine, invoking showkey and pressing keypad keys 1 through 9 results in the following output:

~$ showkey
kb mode was XLATE

press any key (program terminates after 10s of last key press)...
keycode  79 press
keycode  79 release
keycode  80 press
keycode  80 release
keycode  81 press
keycode  81 release
keycode  75 press
keycode  75 release
keycode  76 press
keycode  76 release
keycode  77 press
keycode  77 release
keycode  71 press
keycode  71 release
keycode  72 press
keycode  72 release
keycode  73 press
keycode  73 release

You can see that both key press and key release events are detected. Also note that the numbering of the keypad keys is not sequential. The numeric keys have the following format:

Actual Key:                 Keynumber:

7    8    9                 71   72   73

4    5    6                 75   76   77

1    2    3                 79   80   81

So that keypad number 1 has keynumber 79, keypad number 2 has keynumber 80, and so forth. Knowing this, we can now set up the appropriate key map entry for each of these keys. The keysym event that we're interested in is Console_x, in which 'x' is the number of the VT to which the view is s asection in the 'custom.map' file, let's see how we'd arrive at this "from scratch."

The basic steps we'd need to take would be to:

To do this, let's begin by using the 'showkey' program which can be invoked using:

    % showkey

Now, any key that you press causes showkey to print the keynumber. On my machine, invoking showkey and pressing keypad keys 1 through 9 results in the following output:

~$ showkey
kb mode was XLATE

press any key (program terminates after 10s of last key press)...
keycode  79 press
keycode  79 release
keycode  80 press
keycode  80 release
keycode  81 press
keycode  81 release
keycode  75 press
keycode  75 release
keycode  76 press
keycode  76 release
keycode  77 press
keycode  77 release
keycode  71 press
keycode  71 release
keycode  72 press
keycode  72 release
keycode  73 press
keycode  73 release

You can see that both key press and key release events are detected. Also note that the numbering of the keypad keys is not sequential. The numeric keys have the following format:

Actual Key:                 Keynumber:

7    8    9                 71   72   73

4    5    6                 75   76   77

1    2    3                 79   80   81

So that keypad number 1 has keynumber 79, keypad number 2 has keynumber 80, and so forth. Knowing this, we can now set up the appropriate key map entry for each of these keys. The keysym event that we're interested in is Console_x, in which 'x' is the number of the VT to which the view is s asection in the 'custom.map' fi