173 lines
8.3 KiB
Text
173 lines
8.3 KiB
Text
|
** Svgalib keyboard scancode remapping: the Readme **
|
||
|
|
||
|
** Introduction
|
||
|
|
||
|
After a poll on Slashdot.org about keyboard layouts, I decided to switch from
|
||
|
QWERTY to the Dvorak simplified keyboard. (Such is the power of Slashdot!) It
|
||
|
was easy to switch the keymaps used by the console and X and even LILO, but
|
||
|
svgalib programs that used raw keyboard weren't affected since they interpret
|
||
|
the keyboard scancodes into characters themselves - often assuming a standard
|
||
|
US keyboard with QWERTY layout.
|
||
|
|
||
|
In order for my machine to present a ``unified front'' with a single consistent
|
||
|
keyboard layout, I added to svgalib the ability to remap scancodes. This is
|
||
|
done in keyboard_getevents(), before the event handler is called, so it will
|
||
|
work whether or not a program provides its own handler. Programs that do not
|
||
|
use raw keyboard are not affected, so by setting both the console and svgalib
|
||
|
itself to use the same keymap a consistent keyboard layout is available to all
|
||
|
svgalib programs.
|
||
|
|
||
|
|
||
|
** Background
|
||
|
|
||
|
When you press or release a key on your keyboard, it sends a byte of data to
|
||
|
your computer. The top bit indicates whether the key was pressed or released,
|
||
|
and the lower seven bits hold the scancode, a number that uniquely identifies
|
||
|
the key. A program on the computer interprets these scancodes as representing
|
||
|
characters (`A', `%', etc) or actions to be taken (`Page Up', `Back Space') or
|
||
|
modifiers that alter the interpretation of other keys (`Shift', `Alt', etc).
|
||
|
Most programs do not perform this interpretation themselves, but leave it up
|
||
|
to some other piece of software: the system BIOS, or the operating system,
|
||
|
or the graphical user interface system.
|
||
|
|
||
|
On Linux this is normally done by the kernel or by the X server for X clients,
|
||
|
but this doesn't meet the needs of some programs (especially games) which
|
||
|
care more about whether a key is up or down than what it means and treat the
|
||
|
modifiers the same way as other keys. These programs open the keyboard in `raw'
|
||
|
mode and deal directly with scancodes.
|
||
|
|
||
|
The problem comes because these programs often do need to interpret the keys
|
||
|
into characters, or it is important for a certain key to be identifiable to
|
||
|
the user as being associated with a certain key. For instance, a game player
|
||
|
might need to type a description of a saved game or be directed to press a
|
||
|
certain key to activate a game feature. Interpretation of keyboard scancodes
|
||
|
can be difficult since there are many different keyboard layouts which do not
|
||
|
have the same associations between scancodes, modifiers, characters, and
|
||
|
commands. So the author of the program must choose between writing a complex
|
||
|
and customizable conversion routine that can handle any layout the user might
|
||
|
have, and a simple routine that is hard-coded to use a single layout. In the
|
||
|
latter case, users of other keyboard layouts will encounter numerous
|
||
|
discrepancies between what he or she tries to type and what the program
|
||
|
interprets.
|
||
|
|
||
|
|
||
|
** How it works
|
||
|
|
||
|
Svgalib's scancode conversion is meant to at least partially fill this gap by
|
||
|
converting the scancodes that the keyboard produces to equivalent, or nearly
|
||
|
equivalent, scancodes for the keyboard layout that the program expects. The
|
||
|
program then (hopefully) interprets the new scancode into the intended
|
||
|
character.
|
||
|
|
||
|
As an example, let us consider a US keyboard with Dvorak layout and the game
|
||
|
Quake, which expects a US keyboard with QWERTY layout. Both layouts have the
|
||
|
same scancodes for each physical key, but different characters are produced.
|
||
|
For intance, the first row of letters produces the scancodes 16 through 27, but
|
||
|
on QWERTY this produces the charaters qwertyuiop[] while Dvorak produces
|
||
|
',.pyfgcrl/=. Thus when the Dvorak letter `p' is pressed, the scancode 19
|
||
|
is interpreted by Quake as the letter `r', which occupies scancode 19 on the
|
||
|
QWERTY layout.
|
||
|
|
||
|
The solution lies in the fact that svgalib acts as an intermediary between the
|
||
|
keyboard and the program and has the opportunity to present a different
|
||
|
scancode to the program than the keyboard produced. In this case we tell Quake
|
||
|
that the scancode was not 19 but rather 25, which is the letter `p' in the
|
||
|
QWERTY layout, so when Quake interprets the scancode the correct character is
|
||
|
produced.
|
||
|
|
||
|
|
||
|
** The keymap files
|
||
|
|
||
|
In order to know what scancodes to convert to what other scancodes, a keymap
|
||
|
file is read which lists scancodes produced by the keyboard and their
|
||
|
equivalents in the layout expected by the program.
|
||
|
|
||
|
A program called svgakeymap is provided to generate these maps from the
|
||
|
keytable files in /usr/lib/kbd/keytables; you must have perl for it to work.
|
||
|
Creating a keymap file with svgakeymap is easy; to make a map to convert
|
||
|
scancodes from a US Dvorak keyboard to a US QWERTY keyboard as for our example
|
||
|
above:
|
||
|
|
||
|
svgakeymap dvorak us > dvorak-us.keymap
|
||
|
|
||
|
The path and .map and .gz suffixes are automatically added if necessary. If
|
||
|
your keytables are stored elsewhere, specify a complete path. If only one
|
||
|
keytable is specified, a keymap is generated that performs no conversions but
|
||
|
contains the correct key names so you can specify scancodes used by fake
|
||
|
keyboard and mouse events by name instead of by number. If none are specified,
|
||
|
this is done for the standard US QWERTY layout.
|
||
|
|
||
|
dvorak-us.keymap and default.keymap (the US QWERTY layout) are provided with
|
||
|
the svgalib distribution and can serve as an example if you wish to make your
|
||
|
own keymap files manually or create an improved generator.
|
||
|
|
||
|
|
||
|
** Configuration
|
||
|
|
||
|
You can specify a keymap to use for all svgalib programs (keeping in mind that
|
||
|
only those that use raw keyboard are affected) by putting a line like this into
|
||
|
libvga.config or ~/.svgalibrc:
|
||
|
|
||
|
kbd_keymap /etc/vga/dvorak-us.keymap
|
||
|
|
||
|
You must specify a complete path to the keymap file. If no keymap is specified,
|
||
|
no conversion is performed.
|
||
|
|
||
|
You can also override the global keymap by setting the environment variable
|
||
|
SVGALIB_KEYMAP to point to the appropriate keymap file. This can be useful if
|
||
|
some programs support alternate keymaps directly but not others, or if
|
||
|
different users use their own keyboard layouts based on preference.
|
||
|
|
||
|
|
||
|
** Security issues
|
||
|
|
||
|
It can be dangerous to let users arbitrarily reassign keyboard scancodes; for
|
||
|
instance all keys could be routed to an unused scancode, making the console
|
||
|
unusable. To prevent this, put the option kbd_only_root_keymaps into
|
||
|
libvga.config; only keymaps owned by root will be accepted, so the available
|
||
|
keymaps can be limited to safe ones.
|
||
|
|
||
|
|
||
|
** Bugs and limitations
|
||
|
|
||
|
There are no known bugs, but there probably are some. If you find any please
|
||
|
let me know at brion@pobox.com.
|
||
|
|
||
|
Limitations however we definitely have. The scancode conversion performed is
|
||
|
very simple, and can only achieve 100% success when the keyboard layouts being
|
||
|
converted between differ _only_ in arrangement of keys while producing the same
|
||
|
characters from each key. Example: the de facto standard Dvorak keyboard has
|
||
|
the left and right brackets (`[' and `]') on separate keys, with the curly
|
||
|
braces (`{' and `}') produced by those keys when shifted. The standard QWERTY
|
||
|
keyboard produces those characters the same way, the only difference is that
|
||
|
the keys are a row higher on Dvorak; switching the scancodes around results in
|
||
|
proper character interpretation. However the official ANSI standard Dvorak
|
||
|
layout has tho two brackets on _the same key_, one regular and one shifted.
|
||
|
The curly braces similarly have their own key. These cannot be properly mapped
|
||
|
by scancode to the QWERTY keyboard since they produce different characters
|
||
|
in conjunction with modifiers, and the wrong character is produced by the
|
||
|
program.
|
||
|
|
||
|
This could be worked around by interpreting the modifiers in svgalib and
|
||
|
simulating the proper modifier/character keypress/release sequences, but it
|
||
|
would be very complex and would do nothing to help the situation where
|
||
|
characters on the physical keyboard layout do not exist on the target layout
|
||
|
(quite likely when dealing with national or language-specific keyboards);
|
||
|
they cannot be converted into any key sequence since they do not exist.
|
||
|
|
||
|
Ultimately it might be better to set up a ``medium-rare'' keyboard mode where
|
||
|
keys are interpreted into characters but ``raw''-style non-interpreted key
|
||
|
press and release events are available.
|
||
|
|
||
|
|
||
|
** Further information
|
||
|
|
||
|
There isn't really any further information right now unless you want to Use The
|
||
|
Source... More to come in the future. If it does you'll find it at:
|
||
|
|
||
|
Brion Vibber's Svgalib Stuff - http://pobox.com/~brion/linux/svgalib.html
|
||
|
|
||
|
|
||
|
-- brion vibber (brion@pobox.com)
|
||
|
3 July 1998
|