Name

console-fb-realizer, console-evdev-realizer, console-uugen-hid-realizer, console-uhid-realizer, console-pcat-mouse-realizer, console-pcat-keyboard-realizer, console-ps2-mouse-realizer, console-kvt-realizer — realize a user-space virtual terminal on FBIO, KBIO, USB, evdev, or KVT devices

Synopsis

BSDs

console-ugen-hid-realizer [--mouse-primary] {ugendevicename}

console-uhid-realizer [--mouse-primary] {uhiddevicename}

console-pcat-mouse-realizer [--mouse-primary] {sysmousedevicename}

console-pcat-keyboard-realizer [--mouse-primary] {atkbddevicename}

console-kvt-realizer [--font-light-r filename] [--font-light-o filename] [--font-light-i filename] [--font-medium-r filename] [--font-medium-o filename] [--font-medium-i filename] [--font-demibold-r filename] [--font-demibold-o filename] [--font-demibold-i filename] [--font-bold-r filename] [--font-bold-o filename] [--font-bold-i filename] [--vtfont-faint-r filename] [--vtfont-faint-o filename] [--vtfont-faint-i filename] [--vtfont-normal-r filename] [--vtfont-normal-o filename] [--vtfont-normal-i filename] [--vtfont filename] [--quadrant number] [--wrong-way-up] [--bold-as-colour] [--80-columns] [--mouse-primary]

Linux

console-fb-realizer [--font-light-r filename] [--font-light-o filename] [--font-light-i filename] [--font-medium-r filename] [--font-medium-o filename] [--font-medium-i filename] [--font-demibold-r filename] [--font-demibold-o filename] [--font-demibold-i filename] [--font-bold-r filename] [--font-bold-o filename] [--font-bold-i filename] [--vtfont-faint-r filename] [--vtfont-faint-o filename] [--vtfont-faint-i filename] [--vtfont-normal-r filename] [--vtfont-normal-o filename] [--vtfont-normal-i filename] [--vtfont filename] [--quadrant number] [--wrong-way-up] [--bold-as-colour] [--80-columns] [--mouse-primary] {fbname}

console-evdev-realizer [--mouse-primary] {evdevdevicename}

console-ps2-mouse-realizer [--mouse-primary] {ps2mousedevicename}

console-kvt-realizer [--mouse-primary]

Description

These are the I/O back ends for a (user-space) virtual terminal, that realize that virtual terminal with various input and output devices.

Each one opens the back end interfaces of a user-space virtual terminal and opens the I/O devices (if any) specified by command line options and the particular command. The I/O devices are the concrete devices with which the user-space virtual terminal is to be (partly or wholly) realized. It is the user's responsibility to ensure that these refer to the same, single, physical user station.

They then enter a loop where they simultaneously:

  • write all data received from the input devices to the input FIFO for the virtual terminal, translating to the abstract keyboard and mouse; and

  • render the contents of the character/attribute buffer file for the virtual terminal on any output device.

I/O devices may be shared with other subsystems, or used exclusively.

Mouse and keyboard devices can be aggregated with other mouse and keyboard devices, or separated from them, by choosing whether to share mouse/keyboard state files amongst realizers. Shared keyboard state comprises information about the press, latch, and lock states of the various modifier keys. Sharing this with mouse device realizers enables modifier information to be generated in mouse events; without which all mouse events will have modifier flags set to zero. Shared mouse state comprises information about the mouse position and limits of its various axes, and the instantaneous combined states of buttons and wheels.

Specifying I/O devices

I/O devices are specified by the choice of command, and thus their various command-line options.

The superior (or sole) choices

ugendevicename

This command-line option designates the superior choice of input device on the BSDs. ugendevicename must be the the device file name of a Generic USB device, using the ugen(4) protocol, such as /dev/ugen0.2 for example. console-ugen-uhid-realizer parses the bus and address from the name and actually opens the interface device names such as /dev/usb/0.2.0, /dev/usb/0.2.1, and /dev/usb/0.2.2.

It queries the "type" of the device (e.g. keyboard, tablet, mouse, and so forth) from the device itself, without need for explicitly describing it to the comand. It reads the HID I/O report descriptors from the device and from them decides whether the interface has normal keys, consumer device keys, system keys, keyboard LEDs, relative positioning (mice), and absolute positioning (touchscreen). Any combination of HID I/O in a single USB device can be handled. Multiple keyboard and mice USB interfaces at the given bus+address are combined, and the program acts as if they are a single giant keyboard/mouse.

evdevdevicename

This command-line option designates the superior choice of input device on Linux, the Human Input Devices enumerated by the operating system. On Linux, evdevdevicename must be the device file name of an event device, using the evdev subsystem, such as /dev/input/event0 for example.

console-evdev-realizer queries the "type" of the device (e.g. keyboard, tablet, mouse, and so forth) from the device itself, without need for explicitly describing it to the comand.

Some BSDs have Linux evdev compatibility subsystems, but Generic USB is superior for two reasons. First, the compatibility is incomplete by its nature. Second, even natively evdev hides the extensible nature of the underlying USB HID I/O system.

fbname

This command-line option option designates a framebuffer output device for realizing the user-space virtual terminal's display. fbname must be a device that speaks the "fbio" API to programs. On Linux only framebuffer devices, such as /dev/fb0, speak this protocol. (Remember that "kernel mode setting" device drivers create simple framebuffer devices for programs that use the "fbio" API.) On the BSDs, kernel virtual terminal device speak this protocol, and framebuffers are not directly accessible via separate devices. However, on the BSDs the console-kvt-realizer command is used to employ these.

The framebuffer device need not be the same size or height:width ratio as the virtual terminal display. When it is smaller than the display, the realizer will move the framebuffer around as a "window" onto the virtual terminal display, such that the cursor position is always within the window. When it is larger than the display, the realizer will align the virtual terminal display to one corner of the framebuffer, as specified by the --quadrant command-line option. It will render the parts of the framebuffer outwith the virtual terminal display area as black.

The --wrong-way-up command-line option causes the display to be realized the wrong way up, swapping the direction of increasing line numbers. This is an oft-requested terminal feature, albeit by people who have never actually experienced it.

Inferior choices

uhiddevicename

This command-line option designates an inferior choice of input device on the BSDs, the Human Input Devices enumerated by the operating system or created by uhidd(8). Linux does not have such devices. uhiddeviceename must be the device file name of a USB HID device, using the uhid(4) protocol, such as /dev/uhid0 for example. console-uhid-realizer queries the "type" of the device (e.g. keyboard, tablet, mouse, and so forth) from the device itself, without need for explicitly describing it on the command line.

This is inferior to Generic USB because the kernel and uhidd(8) disagree on what the uhid(4) protocol actually is, and produce devices that are not I/O compatible. Do not use this with devices created by uhidd(8) (which is largely superfluous with these realizers anyway).

sysmousedevicename

This command-line option designates an inferior choice of input device on the BSDs. sysmousedevicesname must be a device that speaks the BSD mouse(4) protocol to programs, such as /dev/sysmouse, or /dev/ums0 (created by the kernel), or /dev/psm0 for examples. BSD mouse devices, while speaking their own idiosyncratic protocols at "mouse level 1" all have a common "mouse level 2" of operation where they all speak this same protocol.

Note

BSD PS/2 mouse devices (psm(4)) speak BSD mouse protocols, not a PS/2 protocol. console-ps2-mouse-realizer is for Linux PS/2 mouse devices, which speak a 3-byte packet PS/2 protocol peculiar to Linux.

However, this common mouse protocol is limited compared to using the USB HID devices directly. It has no support for absolute-position pointing devices, such as USB tablets, because the protocol simply does not support the notion of transmitting absolute position information, only relative pointer movements.

Transparent "mouse integration" under some virtual machine systems requires support for absolute-position pointing devices. (In Oracle VirtualBox, for example, when "mouse integration" is off, host machine mouse input is reported to the guest machine as input from a relative-positioning mouse device; but when "mouse integration" is on, host machine mouse input is reported to the guest machine as input from an absolute-positioning tablet device.) This type of device cannot work with them.

If used at all this is best used only with the mouse concentrator device, /dev/sysmouse, as a backstop catch-all and with PS/2 mice devices.

atkbddevicename

This command-line option designates an inferior choice of input device on the BSDs. filename must be a device that speaks the "kbio" API to programs. On the BSDs, atkbddevicename must be an a kernel virtual terminal device or an atkbd(4) device, such as /dev/atkbd0, /dev/kbdmux0, /dev/ukbd0, or /dev/vkbd0 (created by uhidd(8)) for examples. On Linux, kernel virtual terminal device speak this protocol, and "kbio" devices are not directly accessible via separate devices. However, on Linux the console-kvt-realizer(1) command is used to employ these.

This is inferior because the AT Keyboard model does not include things that are accessible via the USB HID protocol and (to a lesser extent) the Linux input event protocol. Those latter support extra keypads and more keys, including extra extended keys (equals, comma, plus/minus, and brackets on the calculator keypad for examples), consumer device keys (calculator, WWW, and eject for examples), and system keys (power, wake, and sleep).

If used at all this is best used only with the keyboard concentrator device, /dev/kbdmux0, as a backstop catch-all.

ps2mousedevicename

This command-line option designates an inferior choice of input device on Linux. ps2mousdevicename must be a device that speaks the Linux PS/2 mouse protocol to programs, such as /dev/input/mice (a backwards-compatibility mouse concentrator provided by the evdev subsystem) for example.

This is inferior to accessing the mouse via its evdev device. This protocol has no scope for mice wheels, the Z or W axes, or more than 3 buttons. It is also poorly effected in some virtual machine systems, which try to enforce a relationship between "mickeys" in the virtual hardware and pixels on the host display, and do not always do that right.

Kernel VTs and device sharing

The unshared case

All realizers open their respective I/O devices and retain them open for as long as they run. On a system where they do not have to be shared with anything else, and are dedicated to realizing user-space virtual terminals, this just works as-is. One just runs a combination of console-ugen-uhid-realizer, console-evdev-realizer, and console-fb-realizer (and any realizers for old PC/AT or PS/2 devices) that continually realize the user-space virtual terminals. Such a system would be Linux compiled without the CONFIG_VT option and not running an X11 server, for example, or where a secondary framebuffer and a set of input devices are dedicated only to realizing a user-space virtual terminal.

Note

console-kvt-realizer is not used in this case.

The shared case

If more than one thing opens an I/O device, however, exactly what part of the system (say) ends up with a key press event from the keyboard can be unpredictable. This happens when realizers for user-space virtual terminals, the kernel's built-in terminal emulator, the Xorg X11 server, and other things all attempt to use the same I/O devices. Device sharing is a way that these all negotiate sharing I/O devices.

It is done by the participants (console-kvt-realizer and the Xorg server) allocating a (spare) kernel virtual terminal and waiting for acquire and release orders sent by the kernel. On release, it mutes all of its input devices, with EV_DISABLE passed to kevent(2), and notes not to access its output devices. On acquire, it unmutes all of its input devices, with EV_ENABLE passed to kevent(2), and notes that it is permitted to access its output devices. It also tells the kernel's built-in terminal emulator to do the complement, telling it not to draw output on the framebuffer nor to read input from the keyboard when that KVT is active.

console-kvt-realizer uses a kernel virtual terminal (KVT) for device sharing, and also for some I/O devices that they provide. On the BSDs, the "kbio" keyboard input and "fbio" framebuffer output devices are accessible via a KVT, but the mouse input devices are not. On Linux, only the "kbio" keyboard input devices are accessible via a KVT, but the framebuffer output and mouse input devices are not.

Note

The X11 server Xorg(1), in particular its config:devd module, is faulty. It dynamically opens all USB mice as they are attached to the system, but does so exclusively, preventing access to the devices by any other programs. It should just open /dev/sysmouse, and rely upon the mouse device concentration already provided by moused(8) and these realizers. It actually does rely on input concentration for keyboard devices. Xorg(1) interferes both with the operation of the BSD moused(8) and with console-pcat-mouse-realizer.

console-kvt-realizer and the KVT

console-kvt-realizer obtains the name of the KVT device from the value of the TTY environment variable, and assumes that its standard input and standard output are already connected to it. One can invoke the realizer via vc-get-tty(1) or a similar command that obtains a virtual terminal device name from an abbreviation, or just supply the full device name. To open the standard input and output one then chains through open-controlling-tty(1) or a similar command.

Note

When using other commands ensure that the KVT device is set as the controlling terminal. This is a quirk of the operating system kernels themselves, which require this in order for various parts of the mechanism to work.

At startup, console-kvt-realizer switches the virtual terminal display (if it is "fbio") into a suitable graphics mode, configures the ("kbio") input to deliver raw keycodes, and switches the line discipline (of the "kbio" device) to non-canonical input (i.e. "raw") mode (so that the raw keycodes are unmolested by the line discipline); switching all of these back to their saved prior settings upon its termination. The realizer attempts to choose the highest resolution graphics mode available that has a 32-bit or 24-bit colour depth. The --80-columns option constrains its choice to graphics modes that are no wider than 80 columns (1280 pixels).

Autoconfiguration via device paths

Various things are autoconfigured based upon the identity of the I/O device being used:

  • The user-space virtual terminal back end to connect to is autoconfigured with a vcs/ subdirectory of the realizer's working directory. (Conventionally, the vcs/vcname entries in this subdirectory are (symbolic) links to the actual user-space virtual terminal back end directories elsewhere in the filesystem; the actual user-space virtual terminal back end directories are under /run/dev/; and the vcs/ subdirectory itself is a symbolic link to a global /etc/system-control/convert/user-vt/vcs/ directory.) Having opened the appropriate vcs/vcname through autoconfiguration, the program opens the character/attribute buffer file vcs/vcname/display and the input FIFO vcs/vcname/input. These back end interfaces are detailed in console-terminal-emulator(1).

  • The keyboard map file to load is autoconfigured with a kbdmaps/ subdirectory of the realizer's working directory. (Conventionally, the kbdmaps/mapname entries in these subdirectories are not regular files, but are (symbolic or ordinary) links to the actual keyboard map files; the actual keyboard map files are regular files under /etc/system-control/convert/kbdmaps/ or somewhere under /usr/local/share/ that are named after the country code, physical layout, and map options; and the kbdmaps/ subdirectory itself is a symbolic link to a global /etc/system-control/convert/user-vt/kbdmaps/ directory.)

  • The aggregate mouse state file to use is autoconfigured with a mice-aggregate/ subdirectory of the realizer's working directory. (Conventionally, the mice-aggregate/ subdirectory itself is a symbolic link to a global /etc/system-control/convert/user-vt/mice-aggregate/ directory.)

  • The aggregate keyboard state file to load is autoconfigured with a keyboards-aggregate/ subdirectory of the realizer's working directory. (Conventionally, the keyboards-aggregate/ subdirectory itself is a symbolic link to a global /etc/system-control/convert/user-vt/keyboards-aggregate/ directory.)

The realizer uses names derived from device paths to attempt to open the files/directories in those subdirectories, employing progressively shorter versions of the device path in turn, finally falling back to the file/directory name default. This permits different configurations to be specified for individual realized devices, as well as a fallback global configurations for all realized devices.

  • Generic USB (usb-ugen) realizers use a device path that is a combination of the product ID, vendor ID, and (USB) interface number of the keyboard interface, shortened to one that omits the interface number; e.g. usb.03f0:0024:0001 shortened to usb.03f0:0024.

  • The PC/AT keyboard realizer uses a name that is a combination of the EISA PaP ID for a PC/AT keyboard and the device basename, shortened to one that omits the device basename; e.g. eisa.pnp0301.atkbd0 shortened to eisa.pnp0301.

  • The PC/AT mouse realizer uses a name that is a combination of the EISA PaP ID for a PC/AT mouse and the device basename, shortened to one that omits the device basename; e.g. eisa.pnp0F01.psm0 shortened to eisa.pnp0F01.

  • The PS/2 mouse realizer uses a name that is a combination of the EISA PaP ID for a PS/2 mouse and the device basename, shortened to one that omits the device basename; e.g. eisa.pnp0F03.mice shortened to eisa.pnp0F03.

  • The evdev realizer uses a name that is a combination of a prefix and the device basename, shortened to one that omits the device basename; e.g. evdev.event0 shortened to evdev.

  • The framebuffer realizer uses a name that is a combination of an unassigned EISA PaP ID and the device basename, shortened to one that omits the device basename; e.g. eisa.pnpFB00.fb0 shortened to eisa.pnpFB00.

  • USB-HID (uhid) realizers use a fixed device path because no ID information is available from the device driver; e.g. usb.uhid.

  • The KVT realizer uses a name that is a combination of a prefix and the device basename, shortened to one that omits the device basename; e.g. kvt.ttyv1 shortened to kvt.

Display features

Virtual terminal display buffers encompass a "light/dark" screen flag and various kinds of glyph for the cursor and the pointer. All of the cursor and pointer glyph types are supported. The blinking attribute for the cursor is not, however, supported.

As with real DEC VTs, but unlike some terminal emulators, the "light/dark" flag causes foreground and background colours to be swapped when displaying every display cell, i.e. "reverse video". The cursor is not realized by reverse video. Rather, the foreground and background colours of the cell with the cursor are complemented against white.

Fonts

Virtual terminal display buffers have faint, boldface, italic, strikethrough, and underline attributes for character cells. Only faint, boldface, and italic involve font support, mapping to four font weights (light, medium, demibold, and bold) and three slants (upright, italic, and oblique). Strikethrough and underline attributes are rendered not through font selection but by overwriting the non-strikethrough non-underline glyphs with appropriate horizontal lines. If faint and demibold weights are unavailable, the faint attribute is emulated by shading the foreground and background colours towards black. If bold weight is unavailable, the bold attribute is rendered by overlaying a glyph with a shifted copy of itself. (The --bold-as-colour command-line option will as an alternative always render boldface by tinting foreground colours towards white, but this is of limited use with applications that employ 256-colour or true-colour terminal controls, as many do nowadays.) If italic stroke is unavailable, the first fallback is to use an oblique font. (Oblique is not the same as italic, note, and is often an inferior substitute for it.) If neither italic nor oblique are available, the italic attribute is rendered by shifting the upright glyph into an oblique form within the character bounding square if the character size permits.

Fonts are loaded from font files, which may be either in the FreeBSD/TrueOS "vtfont" format or in the straight 8 by 16 unadorned bitmap format used by FreeBSD's "syscons". (To convert an Adobe BDF format font file to "vtfont" format, use the FreeBSD vtfontcvt(1) utility.) Font files are specified by the filename in the various font command-line options: --vtfont-faint-r , --vtfont-faint-o , --vtfont-faint-i , --vtfont-normal-r , --vtfont-normal-o , --vtfont-normal-i , --vtfont , --font-light-r , --font-light-o , --font-light-i , --font-medium-r , --font-medium-o , --font-medium-i , --font-demibold-r , --font-demibold-o , --font-demibold-i , --font-bold-r , --font-bold-o , and --font-bold-i .

The weight and slant are encoded via these command-line options, because meta-information about weight and slant is not in a font file itself (it usually being encoded in the filename). Bitmap fonts contain just one glyph set. The "vtfont" format has two glyph sets for a pair of unspecified weights.

  • The "vtfont" command-line options load both sets of glyphs from a "vtfont" format font. "normal" in the option name specifies that the presumed weights of the pair are medium and bold; "faint" specifies that the presumed weights are light and demibold. "r", "o", and "i" specify the presumed slants as upright, oblique, and italic respectively.

  • The "font" command-line options are the only way to load bitmap fonts, and can also be used to load just the first set of glyphs from a "vtfont" format font, providing fine-grained control of what glyphs are used if that is required. Again, "r", "o", and "i" in the option name specify the presumed slants as upright, oblique, and italic respectively. The four presumable weights in the option name are "light", "medium", "demibold", and "bold".

Fonts must be monospace fonts with a height of 8, 14, 15, or 16 and a width of 8, 9, 12, or 16. All glyphs are rendered in a 16 by 16 bounding square, with 8 by 8 pixel fonts doubled to 16 by 16 pixels. 8 by 16 pixel block graphic and box drawing characters are doubled in width. Any "horizontally extendable" characters (such as the em dash) not otherwise extended to 16 pixels wide are extended by overlaying themselves to the right.

With no fonts loaded, and for any characters which cannot be found in the loaded fonts, console-fb-realizer "greeks" its output, falling back to displaying a blank for any whitespace characters, a box for any C0 or C1 control characters, and a block for all other characters. Such "greeking" is of course illegible; and it is recommended that sufficient fonts be loaded in order to render at least the whole of Microsoft's Windows Glyph List 4. (One might be tempted to simply cover the OpenType World Glyph Set 1 character set instead. Bear in mind that the W1G character set does not include line drawing, block, arrow, and other characters that are commonly employed by TUI systems to draw UI widgets; whereas WGL4 does.)

Fonts are loaded at program initialization and remain loaded thereafter. To change fonts, it is necessary to stop and restart console-fb-realizer. This does not, of course, affect the operation of the terminal emulator or the processes using the terminal.

Keyboard mapping

The keyboard input event device provides a sequence of keycode numbers, with attached press/release flags. These are translated to keyboard actions through use of a loadable keyboard map. Unfortunately, Linux and the BSDs do not agree on a single set of keycode numbers, and cannot share one another's keyboard layout definitions. So the realizer first translates the non-portable Linux and BSD keycodes, and USB HID keyboard usages, into a common codeset. It is this common codeset that is actually used in key maps.

The map is stored in a map file in machine-readable form. FreeBSD/TrueOS keymaps can be compiled from the BSD/SCO kbdmap(5) human-readable form to this machine-readable form with the console-convert-kbdmap(1) command.

Map file logical keyboard matrix

In machine-readable form, a map is a simple 2-dimensional array of 96-octet map entries, representing 17 "rows" of 16 "columns" per row, in row-major order. This is the "matrix" of a logical keyboard denoted by the aforementioned common codeset.

These rows are, in order:

ISO 9995 "E" row

An unused position, positions E01 to E12, the additional key from the 106/109-key PC keyboard at E13, one more unused position, then position E14. The language-variant key sometimes found at position E00 is grouped with other similar keys in the third row, where the IBM PC/AT keyboard numbering actually placed it.

ISO 9995 "D" row

Positions D00 to D12, two unused positions, then position D14. The key sometimes found at position D13 is grouped with other similar keys in the third row, where most IBM PC/AT layouts actually place it.

ISO 9995 "C" row

An unused position, positions C01 to C11, the key usually found in position E00 (grave or kanji/zenkaku/hankaku), the key usually found in position C12 (on 102/105-key, 103/106-key, 104/107-key, and 106/109-key PC keyboards) or D13 (on 101/104-key PC keyboards), then two more unused positions.

ISO 9995 "B" row

An unused position, the additional "Europe 2" key from the 102/105-key and 104/107-key PC keyboards at B00, positions B01 to B10, the additional key from the 104/107-key and 106/109-key PC keyboards at B11, and three more unused positions.

Modifiers

1st ⇧ Level 2 shift, 2nd ⇧ Level 2 shift, ⇫ Level 3 shift, an unused position, 1st ⎈ Control, 2nd ⎈ Control, 1st ⌘ Super, 2nd ⌘ Super, 1st ⎇ Alt, three unused positions, ⇬ Caps Lock, Scroll Lock, ⇭ Num Lock, and an unused position.

ISO 9995 "A" row

An unused position, the ひらツな/カタカナ/ローマ字 (Hiragana/Katakana/Romaji) key from the 106/109-key PC keyboard, the 半角/全角 (Zenkaku/Hankaku) key (from USB but not a PC keyboard key, and not to be confused with the PC keyboard key at E00), the Hiragana key (from USB but not a PC keyboard key), the Katakana key (from USB but not a PC keyboard key), the 変換 (Henkan or XFER) key from the 106/109-key PC keyboard, the 無変換 (Muhenkan or NFER) key from the 106/109-key PC keyboard, an unused position, the Han/Yeong key from the 103/106-key PC keyboard, the 変換 (Hanja) key from the 103/106-key PC keyboard, three unused positions, Alternate Erase, ⎄ Compose, and ␣ Space.

Cursor/Editing keypad

⇱ Home, Up Arrow, Page Up, Left Arrow, Right Arrow, ⇲ End, Down Arrow, Page Down, Insert, Delete, and 6 unused positions.

Calculator keypad 1

*, 7, 8, 9, -, 4, 5, 6, +, 1, 2, 3, 0, . Decimal Point, Enter, and / Divide.

Calculator keypad 2

, Thousands Separator from the Apple Pro JIS and 107-key PC keyboards, , JP Comma, = from the Apple Pro JIS keyboard, AS/400 =, ± Sign Change, (, ), {, }, and 7 unused positions.

Function row 1

The ⎋ Escape key, then F01 to F15.

Function row 2

F16 to F31.

Function row 3

F32 to F47.

Function row 4

F47 to F63.

System Commands keypad

An unused position, Power, Sleep, Wake, Debug, and 11 more unused positions.

Application Commands keypad 1

Pause, Print Screen, Attention, ⯉ Application, Break, 8 unused posititions, Mute, Volume Down, and Volume Up.

Application Commands keypad 2

An unused position, Execute, Help, Menu, Select, Cancel, Clear, Prior, Return, Separator, Out, Oper, Clear/again, Ex Sel, and 2 more unused positions.

Application Commands keypad 3

An unused position, Stop, Again, Properties, Undo, Redo, Copy, Open, Paste, Find, Cut, and 5 more unused positions.

Consumer keypad 1

Calculator, File Manager, WWW, Home, Refresh, Mail, Bookmarks, Computer, Back, Forward, Lock, CLI, Next Track, Prev Track, Play/Pause, and Stop Playing.

Consumer keypad 2

Record, Rewind, Fast Forward, Eject, New, Exit, and 10 unused positions.

Map file entries

Each 96-octet map entry comprises twenty-four big-endian 32-bit integers.

A map entry describes two things: a set of possible actions to be taken when the key is pressed and released, and how to select which action based upon the momentary keyboard modifier state. A selection class determines how the set of modifiers is reduced to a four-bit action index (giving sixteen possible combinations) by combining modifiers with one another.

Keyboard modifiers comprise (in ISO 9995-1 terminology) modifiers for level 2, level 3, and group 2; for caps, num, and shift locks; and for super, alt, and control. What keys act as these modifiers is of course determined by the keyboard layout: but often the level 2 modifiers are the ⇧ Shift keys; the level 3 modifier is the right ⌥ Option/Closed Apple (Apple keyboards) or ⇮ AltGr (Windows and IBM PC/AT keyboards) key; the alt modifier is the left ⌥ Option/Closed Apple (Apple keyboards) or ⎇ Alt (Windows and IBM PC/AT keyboards) key; and super is the ⌘ Command/Open Apple (Apple keyboards), Meta (Sun keyboards), or Windows (Windows keyboards) key. The initial state of all locks is off.

The selection class code is first in each entry, and the code values are here designated by their UCS-4 code points.

'p' (U+00000070, "plain")

The keyboard modifier state is entirely ignored and the first action is always chosen.

's' (U+00000073, "shiftable")

When selecting an action, the sense of the level2 modifier state is inverted by the shift lock state. Shift lock operates like the typewriter facility of that name, locking on until either level2 modifier key is pressed. This is generally used for non-alphabetic keys that obey shift lock but not caps lock.

'c' (U+00000063, "capsable")

When selecting an action, the sense of the level2 modifier state is inverted by the OR-combined caps lock and shift lock states. This is generally used for alphabetic keys that obey caps lock and shift lock.

'n' (U+0000006E, "numable")

When selecting an action, the sense of the level2 modifier state is inverted by the OR-combined num lock and shift lock states. This is generally used for auxiliary keys that obey num lock and shift lock.

'f' (U+00000066, "funcable")

When selecting an action, the sense of the level2 modifier state is inverted by the shift lock state, and the level3 modifier state is replaced by the alt state. This is generally used for function block keys that obey shift lock but not caps lock.

The next seven 32-bit numbers are reserved, and should be set to zero. The remaining sixteen 32-bit numbers are the actions, chosen according to the selection class. These denote the actions for various combinations of modifiers: none, level2, control, control+level2, level3, level2+level3, control+level3, control+level2+level3, group2, group2+level2, group2+control, group2+control+level2, group2+level3, group2+level2+level3, group2+control+level3, and group2+control+level2+level3, with inversions and replacements as aforementioned.

Map file actions

An individual action in a map entry is a big-endian 32-bit integer, which comprises three or four sub-fields.

The most significant byte denotes the action type and the interpretation of the remainder of the action. (These are, intentionally, similar to the input protocol used by console-terminal-emulator(1), aimed at making debugging and trace analysis simpler. They are two distinct and separate protocols, however.)

0x00xxxxxx

No-operation, Take no action. This is used for keys that have no action in the key map.

0x01nnnnnn

UCS-3 key. On press or autorepeat, a Unicode character message for the code point U+00nnnnnn is sent to the input FIFO. If the alt modifier is in effect, a Unicode accelerator message is sent instead.

0x03nnnncc

Modifier key. Modifiers do not autorepeat. On press or release, the modifier key nnnn is enacted against the current keyboard modifier state according to the cc command. Commands are:

0x01

Momentary. The modifier is on when the key is pressed, and off when the key is released.

0x02

Latching. Pressing the key latches the modifier on until a non-modifier key is pressed.

0x03

Locking. Pressing the key locks the modifier on; releasing and pressing it again locks it back off.

0x0Annnnzz

Session selection key. On press or autorepeat, a session selection message for the session number nnnn is sent to the input FIFO. zz is ignored and should be set to zero for upwards compatibility.

0x0Cnnnnzz

Consumer key. On press or autorepeat, a consumer key message for the consumer key number nnnn is sent to the input FIFO. zz is ignored and should be set to zero for upwards compatibility.

0x0Ennnnzz

Extended key. On press or autorepeat, an extended key message for the extended key number nnnn is sent to the input FIFO. zz is ignored and should be set to zero for upwards compatibility.

0x1Ennnnzz

Unshiftable extended key. On press or autorepeat, an extended key message for the extended key number nnnn is sent to the input FIFO. zz is ignored and should be set to zero for upwards compatibility. The accompanying keyboard modifier state does not incorporate the level 2 modifier, which will never be seen by the terminal emulator or processes connected to the terminal. This is used for keyboard layouts where shift inverts the sense of numlock on calculator keys, and that shift is not considered to further modify the key or be visible to applications.

0x0Fnnnnzz

Function key. On press or autorepeat, a function key message for the function key number nnnn is sent. zz is ignored and should be set to zero for upwards compatibility. This is used for keyboard layouts where the function key block has a large number of actual keys. The terminal emulator, and processes connected to the terminal, will see function keys with modifiers.

0x1Fnnnnzz

Unmodifiable function key. On press or autorepeat, a function key message for the function key number nnnn is sent. zz is ignored and should be set to zero for upwards compatibility. The accompanying keyboard modifier state does not incorporate the level or group modifiers, which will never be seen by the terminal emulator or processes connected to the terminal. This is used for keyboard layouts where the function key block has a small number of actual keys and the level+group modifiers are used "locally" (within the realizer) to simulate a larger key block.

Function keys

It is (of course) the keyboard map that handles function key mapping. The function key entries in the matrix represent physical function keys, not composed keys created by combining modifiers with function keys. Those are, after all, represented by the individual actions in each function key's entry.

A keyboard map defines what input messages a combination of modifiers and a function key generates. It will usually be a function key (if the map maps physical function keys straight to terminal emulator function keys, passing the modifier state through to the terminal emulator), an unmodified function key (if the map uses modifiers to extend the function key set, and thus does not pass the modifier state that it has already consumed through to the terminal emulator), or an extended key.

See console-terminal-emulator(1) for why usually keyboard maps map function keys 1 to 5 to the cursor keypad extended keys PAD_F1 to PAD_F5, and not to the F1 to F5 function keys.

Example keyboard map entries

Keyboard maps are tailored, of course, to country, layout (QWERTY, AZERTY, Dvorak, Maltron, and so forth), and the physical layout of the keyboard (104 keys, 109 keys, 124 keys, and so forth). Here are some example keymap entries:

0x00000063, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x01000073, 0x01000053, 0x01000013, 0x01000013, 0x010000DF, 0x010000A7, 0x01000013, 0x01000013. 0x01000073, 0x01000053, 0x01000013, 0x01000013, 0x010000DF, 0x010000A7, 0x01000013, 0x01000013.

'S' on the U.S. International IBM PC/AT keyboard, QWERTY layout. It varies according to caps lock, and produces 'ß' and '§' with the level 3 modifier. The control modifier always produces DC3 (U+0013).

0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0E0F0100, 0x1F000D00, 0x1F001900, 0x1F002500, 0x0A000100, 0x0A000D00, 0x0A001900, 0x0A002500. 0x0E0F0100, 0x1F000D00, 0x1F001900, 0x1F002500, 0x0A000100, 0x0A000D00, 0x0A001900, 0x0A002500.

F1 on the U.S. International IBM PC/AT keyboard, QWERTY layout. It ignores level 3, varying according to the level 2, alt, and control modifiers to produce either PAD_F1, F13, F25, and F37 or session switch commands for sessions 1, 13, 25, and 37.

Dead keys

So-called "dead" keys are otherwise ordinary UCS-3 keys in a keyboard map, except that they denote Unicode combining characters; i.e. characters in the "Me" ("Mark, Enclosing") and "Mn" ("Mark, Non-spacing") Unicode code point categories. The keyboard realizers (console-ugen-hid-realizer, console-evdev-realizer, console-uhid-realizer, and console-pcat-keyboard-realizer) remember such "dead" keys, without transmitting them to the input FIFO as they are pressed (or autorepeated). They attempt to combine them with the next non-combining character keypress. In this respect they behave mostly according to ISO/IEC 9995-3 and DIN/EN 2137:

  • The keyboard realizers implement the extra so-called "peculiar" combinations given by the ISO and DIN standards (and also found in several other national keyboard standards). These are applied before attempting any Unicode composition. Most of these involve:

    COMBINING SHORT STROKE OVERLAY (U+0335)

    In ISO 9995-3 keyboard layouts this is Group2+⇫ Level3+C08 (⇧ Shift+⌥ Option, ⌥ Option+K on the U.S. International keyboard). Unicode does not define any compositions using this combining character.

    COMBINING LONG SOLIDUS OVERLAY (U+0338)

    In ISO 9995-3 keyboard layouts this is Group2+⇫ Level3+C09 (⇧ Shift+⌥ Option, ⌥ Option+L on the U.S. International keyboard). Unicode also defines compositions using this combining character. The ISO 9995-3 compositions overlap in only one case, which is the same in both ISO 9995-3 and Unicode.

  • The ISO and DIN standards define "peculiar" combinations with the space character that generate standalone accents. Any sequence of "dead" keys followed by Space generates a sequence of precomposed non-combining accent characters that correspond to the combining characters.

  • The ISO and DIN standards are not specific about Unicode combining characters. The keyboard realizers apply the "canonical" composition rules given by Unicode, attempting to produce a stream of input characters in Unicode Normalized Form C. Any leftover combining characters that cannot be precomposed are treated as if combined with Space, and emitted before the composed character. This differs from Unicode Normalization, where leftover combining characters always follow the "starter" character. Having leftover combining characters precede the composed character both mimicks the existing behaviour of "dead" keys on several systems and is least surprising to the typist as it (roughly) preserves typed order. (Typed order is not entirely preserved; the "dead" keys are sorted by Unicode combining class as a side-effect of NFC composition.)

  • Not all input is in Unicode Normalized Form C. The ISO and DIN standards define a "pass-through" mechanism that allows a typist to enter combining characters as-is: any sequence of "dead" keys followed by the Zero-Width Non-Joiner (entered as Group2+⇧ Level2+A03 in ISO 9995-3 keyboard layouts; which is ⇧ Shift+⌥ Option, ⇧ Shift+␣ Space on the U.S. International keyboard) generates that sequence of non-combining characters in typed order.

  • Full Unicode Normalization is not performed. In particular, if the typist enters a precomposed character after the "dead" keys, it is not decomposed before the composition rules are applied. This is done in order not to surprise the typist. Full Unicode NFD decomposition followed by Unicode NFC composition could result in different leftover combining characters in some cases. It also would perform various one-way transformations.

Security

The realizers only require sufficient privileges to access their various I/O devices, the shared keyboard/mouse state files, the display buffer file (if they are output device realizers), the FIFO (if they are input device realizers). They do not attempt to create the display file or FIFO if they do not exist, because this would create them with the wrong owner and group; and it thus requires no write access to their containing directory. Owner access for any files, directories, FIFOs, or I/O devices is not necessary. The shared keyboard/mouse state files may be owned by the dedicated user, but this is not not a requirement.

Superuser privileges are not necessary for all realizers, which should be invoked without superuser privileges, employing setuidgid(1) or similar as necessary. The recommended configuration is that there be a dedicated unprivileged user or group that owns no files, devices, directories, or FIFOs; that the I/O devices be (as appropriate) readable and writable (but not owned) by that user or group; that the display file and the FIFO are (respectively) readable and writable (but not owned) by that user or group; and that the shared keyboard/mouse state files are both readable and writable (but not owned) by that user or group.

The exception is console-ugen-hid-realizer. That requires superuser access in order to detach any kernel device drivers from ugen(4) devices. After opening its devices and detaching their kernel device drivers, but before attempting to access font files or VT back-ends, it drops privileges in the manner of setuidgid-fromenv(1), and so requires that the appropriate environment variables have been set up via envuidgid(1) or similar.

Author

Jonathan de Boyne Pollard