Keyboards, Consoles, and VT Cruising

There are times when the command line interface is still a very good choice for getting things done.

“It's a GUI, GUI, GUI, GUI world!”—or
so the major OS manufacturers would have you believe. The 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,
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 Alessandro Rubini
entitled “The Best Without X” in the November 1995 issue (#19) of
Linux Journal. Among a wealth of helpful
ideas, Alessandro 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 conversion can be done. We'll also look
at:

Getting from Here to There: handy methods for VT
cruising

The Useful Unused VT: where to put all that logging
information, and where X-Windows really ends up

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 to
do this conversion are standard inclusions in most recent Linux
distributions and include:

kbd 0.91 (keyboard font and utility
programs)

utils 2.5 (Rick Faith's huge collection of
utilities)

GNU shell-utils 1.12 (shell utilities including the
stty program)

A listing of Linux FTP archives where these utilities can be
found is included in the
sidebar.

The Keypad VT-Switcher

The numeric keypad is an ideal candidate for re-mapping into
a virtual terminal-switching scratch pad since most of us have
never learned “ten-key by touch”. In addition, the non-numeric
functions on a 101-key keyboard 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. You'll need to have the kbd
package installed on your system. The two programs we'll be using
are showkey and
loadkey. To check whether they are
installed on your system type:

$ 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:

If you don't have these programs installed, you'll need to
get the the kbd package source, and install it yourself. This
package is available only as source code, but installation is as
simple as un-archiving it into a temporary directory, then
typing:

$make && make install

Converting the keypad into a VT switcher involves defining a
keyboard mapping and using loadkeys to actually load this
information into the kernel keyboard translation tables. It's
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 VTs, not just the one you're
working on. The kbd package's 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, which contains the default keyboard mapping and
is a useful place to begin. You can name the new file anything
you'd like—e.g.,

cp defkeymap.map custom.map

Use your favorite editor and load up the copied file. At this
point it's probably helpful to have a look around at the current
contents. The experience is rather like visiting one of those fine
old curio shops—look, but don't touch! The first few lines may
look something like this:

I won't go into all the gory details of how to re-map the
keyboard except to say that the basic format to 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,
the press or release event is 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. The ability 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-3
is pressed, the output is the Meta_at (whatever that looks
like).

Getting back to the task at hand, we want to change to a
specified VT when we press one of the keypad keys: i.e., pressing
keypad 1 should switch to VT number 1, pressing keypad 2 should
switch to VT number 2, etc. In your customized key map file find
the section that defines the keypad keys—it should look similar to
this:

Before continuing, let's make a couple of observations.
First, it's not a bad idea to comment the file as you go. What
seems clear and obvious now fades into obscurity as the weeks pass.
Adding comments now will prevent your having to pore over manual
pages, program documentation and magazine articles later, looking
for the correct syntax or usage. Second, notice that with each
entry there are sub-stanzas, beginning with
the words alt keycode, shift
keycode, etc. These stanzas 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
crtl-c combination used to terminate a program during
execution.

Finally, you may be asking yourself how you're supposed to
know which keynumber is associated with a key. Does anyone know
off-hand what keynumber goes with the ; key? You
can find this out by using the showkey program. After you invoke
the program, showkey will print the keynumber for any key you press
and will quit after 10 seconds of no input. So, now that we've
edited the pertinent section in the custom.map file, let's see how
we'd arrive at this from scratch. The basic
steps would be:

Find the keynumber for the keypad keys.

Edit the customized mapping for the keys so that
pressing them would change to the appropriate VT.

Edit the customized mapping for the keys so that
the keypad could still be used for numeric input (using a modifier
key combination in this case).

Load the customized mapping and see whether it
works.

Optionally, have the default key mapping loaded at
system boot.

To do this, let's begin by invoking the showkey
program:

$ showkey

Now, any key you press causes showkey to print the keynumber.
On my machine, invoking showkey and pressing keypad keys 1 through
9 results in the output shown in Listing
2. 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 format shown in Table
1:

Table 1

Actual Key: Keynumber:
7 8 9 71 72 73
4 5 6 75 76 77
1 2 3 79 80 81

Table 1 shows that keypad number 1 has keynumber 79, keypad
number 2 has keynumber 80, etc, Knowing this, we can 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 switched. A simple entry to map keypad number 1 to
switching to VT 1 would look like:

keycode 79 = Console_1

If you look at Listing 1,
you'll notice that this is what we've done. Suppose, however, we
wanted to switch to a VT greater than 9—how are we to do that? The
solution is to use a modifier key combination. Looking again at the
example above, using the shift key with the keypad allows us to use
Console_10 through Console_19. We also wanted to be able to use the
numeric keypad as just that—a means of entering numeric data. In
the example above, notice that the modifier alt
was used to do this:

In this stanza for the keypad_7 key, the first entry maps the
keypad_7 key to switch to VT 7. The second line maps shift-keypad_7
to switch to VT 17 and the third line maps the alt-keypad_7
combination to KP_7 which is the keysym for numeric output when num
lock is on. Thus, to use the keypad as a
numeric keypad, press the num lock key so that it toggles to
on, then hold down the alt key while you enter
numbers at the keypad. Note, too, that
alt-crtl-keypad was defined to switch to the
same console as simply pressing the keypad key itself. In this
case, it acts in exactly the same fashion as the
alt-fn (alt-Function_key)
or alt-crtl-fn (alt-crtl-Function
key) combination. You may have noticed that using the
function keys is how one is typically instructed to switch from one
VT to another. Looking at the stanzas for the function keys you'll
notice entries such as the following:

Note that both alt-f1 and alt-crtl-f1 are used to switch to
VT 1. Those of you using X will probably already have found that
switching to a VT from X requires the three key
alt-crtl-fn key combination while the two key
alt-fn key combination is used at the console.
Although you can change this default behavior, it's best not to. At
this point, we've defined mappings for the keypad keys such that
each key acts as a switch to the VT of the same number. Using
shift-keypad_key switches to VT (10 + keypad
number) and using alt-keypad key with the num
lock on outputs the numeric value of the key.
The final step is to actually load the new mapping and give it a
try. The loading is done using loadkeys and can be done without
logging on as root. To load the customized keymap, enter:

$ loadkeys /usr/lib/kbd/keytables/custom.map

This will print a message indicating that the custom.map file
is being loaded. After this, you're all set! Give it a try. To
revert back to the default mapping simply enter:

$ loadkeys /usr/lib/kbd/keytables/defkeymap.map

and the default mappings will be loaded once again. You can
use this edit -> load customized map -> test -> load
default map cycle to obtain the desired mapping. Once you've
created a custom map file and wish to have it loaded at boot, you
can add an entry to one of the rc.* files, such as rc.local, to
have loadkeys automatically load your customized mapping:

This entry ensures that the file is present and readable and
invokes loadkeys to load the file. Again, keep in mind that loading
a key mapping changes the keytable information for
all VTs, not just your current one.