The Virtual Terminal Subsystem

The Virtual Terminal Subsystem (vt subsystem) is part of the tty subsystem. It provides means for managing virtual terminals and handling input.

Additionally, it provides a virtual terminal tty (vt tty) driver that implements a tty device that is managed by the vt subsystem.

The VT Subsystem is implemented in

  • os/drivers/tty/vt.c providing basic management

  • os/drivers/tty/vt_con.c providing vt’s console interface

  • os/drivers/tty/vt_insert_char.c take the mapped lower-level input and pass it to the tty

  • os/drivers/tty/vt_kbd.c providing the keyboard input handler

  • os/drivers/tty/vt_keymap.c providing the mapping from keycode + modifier to input character

Overview

The virtual terminal (vt) subsystem is responsible for managing virtual terminals and handling keyboard input for each terminal. See the following diagram for an overview of the interplay between the various components.

../../../_images/ditaa-d146d7e71464e04e188b12819a4c1e1253b11598.svg

The vt subsystem provides a keyboard input handler that registers with the input subsystem to capture and process key events. The subsystem also exposes the console attached to the active virtual terminal to other kernel functions, such as printk().

The keyboard input handler tracks modifier keys like Ctrl, Alt, and Shift, mapping the key events to corresponding input characters. These characters are then passed to the tty subsystem, which forwards them to the active virtual terminal or tty device.

When the input handler detects the Ctrl + Alt + Del key combination, it triggers a system reboot.

Initialization

This subsystem is initialized by calling

void vt_init(void)

Initialize the virtual terminal subsystem.

  • Initialize the vt keyboard event handler.

^ Back to top.

Allocating and Deallocating a Virtual Terminal

A new vt is allocated by calling

vt_t *vt_alloc(void)

Allocate and return a new vt.

The returned virtual terminal will have a new console attached to it. If this is the first virtual terminal, the initial console will be attached to it.

Note

It is currently possible to allocate a single vt, only. This function will panic otherwise.

^ Back to top.

A vt is deallocated by calling

void vt_free(vt_t *vt)

Free a previously allocated vt.

^ Back to top.

Querying the Active Virtual Terminal

The active vt is queried by calling

vt_t *vt_active_vt(void)

Return the active vt.

^ Back to top.

Inserting a character from lower-level input

The VT subsystem receives input characters via

void vt_insert_char(char character)

Insert a character from lower-level input and pass it to the tty associated with the active virtual terminal.

^ Back to top.

The VT Keyboard Handler

The keyboard handler is implemented in os/drivers/tty/vt_kbd.c

Implement the keyboard-facing/-handling part of the virtual terminal driver.

Initialization

The handler is initialized by calling

void vt_kbd_init(void)

Register VT’s event handler to the input subsystem.

^ Back to top.

Key Event Handler Function

The input subsystem passes events to the registered handler

static void __vt_kbd_event(input_event_type_t type, uint16_t code, uint32_t value)

VT’s event handler.

  • track modifiers

  • handle events that VT is responsible for, e.g. Ctrl + Alt + Del

  • others: apply keymapping, pass to vt

Parameters:
  • type – the event type, e.g., EV_KEY

  • code – the key code, e.g., KEY_A

  • value – indicates press (EV_KEY_PRESS) or release (EV_KEY_RELEASE)

^ Back to top.

Tracking Modifier Keys

Modifier keys like Ctrl, Alt, Shift are tracked using the function

static void __vt_track_modifiers(uint16_t code, uint32_t value)

Track the state of the key modifiers.

Track

  • left, right SHIFT

  • left, right CONTROL

  • left, right ALT

Parameters:
  • code – the key code, e.g., KEY_A

  • value – indicates press (EV_KEY_PRESS) or release (EV_KEY_RELEASE)

^ Back to top.

This function in turn relies on the following helper to track an individual modifier key

static inline void __vt_track_modifier(uint16_t code, uint32_t value, uint16_t modifier, bool *state)

Track a modifier.

Parameters:
  • code – : the key code, e.g., KEY_A

  • value – : indicates press (EV_KEY_PRESS) or release (EV_KEY_RELEASE)

  • modifier – : the key code of the modifier to be tracked, e.g., KEY_LEFTCTRL

  • state – : pointer to variable for tracking the state

^ Back to top.

The state of the modifier keys can be queried by calling

static uint8_t __vt_modifiers(void)

Convert VT’s tracked modifiers to keymap modifier mask.

Resetting Modifiers (Testing Only)

For testing purposes, a function resetting all modifiers is provided

void vt_reset_modifiers(void)

Reset modifiers for unit tests.

Note

Available only if the preprocessor macro TESTING is defined.

^ Back to top.

Keymap

The keymap for the keyboard handler is implemented in os/drivers/tty/vt_keymap.c

Mapping a Keycode + Modifiers to a Character

A keycode along with active modifiers is mapped to a character by using the function

char vt_keymap_map(input_keycode_t code, uint8_t modifiers)

Map keycode + modifiers to character.

Parameters:
  • code – the key code defined by the input subsystem

  • modifiers – a modifier mask, e.g., VT_KEYMAP_MOD_SHIFT

^ Back to top.

The modifier keys are encoded by the modifier masks

VT_KEYMAP_MOD_NONE

no modifiers

VT_KEYMAP_MOD_SHIFT

bitmask for SHIFT

VT_KEYMAP_MOD_CTRL

bitmask for CTRL

VT_KEYMAP_MOD_ALT

bitmask for CTRL

The keymap is stored in the array

static char __vt_keymap[KEY_NUM_ENTRIES][VT_KEYMAP_NUM_MOD]

The keymap.

This 2D array maps a key code and modifiers to a character. The first dimension is indexed by the key code – as defined in the enum input_keycode_t (drivers/input/input.h). The second dimension is indexed by the modifier mask.

The VT Console

The virtual terminal subsystem provides a console interface to be used by other system components like, for instance, printk. Any write to vt’s console will write to the console attached to the currently active virtual terminal.

The console implementation of the virtual terminal subsystem can be queried by calling:

console_t *vt_console(void)

Get the console implemented by the vt subsystem.

Data Types Provided by the Subsystem

The vt subsystem provides the following data types.

VT Data Structure

The data structure representing a virtual terminal device, storing the tty device and the respective console.

struct vt_t

Store the mapping of console and tty.

Public Members

tty_t *tty

The tty device representing the virtual terminal.

console_t *con

The console attached to the virtual terminal.

^ Back to top.