VC(4) — UNIX Programmer’s Manual
NAME
console, fb, kbd, mouse, ttyv[01] − Video Console devices
DESCRIPTION
The Video Console (VC) driver controls access to all devices involved with the local user interface on ARM based computers running RISC iX. These are the keyboard, the mouse, the video monitor and the loudspeaker. The driver extends the notion of terminal emulation to provide ‘virtual screens’. In effect, there are available for display a number of independent emulated terminals, along with a memory-mapped frame buffer device (for graphics applications and window systems). At any one time, one of these virtual screens will be ‘current’, i.e. selected for display on the physical monitor screen. The user controls the selection from the keyboard using a dedicated key to bring up a ‘selection menu’. On the R140 workstation keyboard the key used for this purpose is the one at the right hand end of the top row of keys, marked ‘Break’.
Each virtual screen has an associated virtual keyboard which is logically attached to the real keyboard when that screen is selected. For the terminal emulation devices (console, ttyv0, ttyv1) the virtual screen and keyboard together behave like a conventional terminal attached by any other means (e.g. serial line): all the normal facilities are available, and the standard tty line disciplines are used. However there are a few differences in detail, and these are described below (see Terminal Emulations). For purposes of selection, the devices /dev/fb (Frame Buffer) and /dev/kbd (KeyBoarD) are paired together as a composite referred to as ‘fb+kbd’ in the selection menu, i.e. when the frame buffer screen is being displayed, the special keyboard device is logically connected to the real keyboard. However, unlike the terminal emulations these two are separate devices, i.e. a call on open(2) is required for each. The mouse device, /dev/mouse is logically independent of the selected screen/keyboard device(s), and is always active when open.
General Interface
The various devices are all implemented as minor devices of the VC major device. The minor numbers are as follows:
0 - console: main system tty
1 - fb: memory-mapped frame buffer
2 - kbd: event-generating keyboard
3 - mouse: event-generating mouse
4 - ttyv0: virtual tty 0
5 - ttyv1: virtual tty 1
Various ioctl(2) calls are provided for individual devices. The definitions for these are accessed by means of:
#include <dev/fbioctl.h>
#include <dev/vcioctl.h>
A further public header file provides macro definitions for use with the event-generating devices (kbd, mouse) and the emulated terminals:
#include <dev/vcio.h>
Each ioctl command is outlined here, but for fuller details of usage, reference should be made to the header files. Two ioctl calls are provided for use on any VC device. The first of these is VCIOCTONE, which allows the generation of a simple sine-wave tone of adjustable amplitude and length. The VCIOCGVDUTYPE call returns a code indicating which of a number of different types of monitor is configured (in CMOS RAM) as being attached to the system. The remaining ioctls are explained as part of the individual device descriptions below.
Terminal Emulations
The devices accessed as /dev/console, /dev/ttyv0, and /dev/ttyv1 are interfaces to distinct terminal emulations which use the single keyboard and screen on the system in a multiplexed fashion; each is treated as an independent terminal device. Functionally they are all similar: the emulated terminals behave in many respects like the DEC VT220 terminal, particularly in respect of the treatment of bytes sent to them for output. There are however some obvious differences, most notably in respect of performance: the effective equivalent baud rate (as a measure of typical display speed) for an emulation varies from around 55Kbaud to over 200Kbaud, depending on various factors. Further information about the terminal emulation is found in avc(4).
The programming interface for the emulations is much like that for typical serial line connections on other systems. In particular, the normal terminal ioctl calls, as documented in tty(4) can all be used. Note however that any call which attempts to treat the line as a real serial line, in terms of hardware features such as modem control, will be ignored or faulted (ENOTTY). Attempts to change the (nominal) speed of the ‘line’ which is fixed at 9600 baud, are also ignored. A further point is that unlike a real terminal, whose display size attributes are not accessible by the driver, the emulated terminal’s dimensions (rows & columns) are controlled by the driver, and hence the terminal window size field of the kernel tty control structure always reflects the emulator’s view of the display size. If the user manually changes the mode (and hence the dimensions) of the screen using the set-up menu, this field will be updated and SIGWINCH will be sent to all processes in the terminal’s current process group. Any attempt by a program (such as stty) to change values in this field, using the TTIOCSWINSZ ioctl, will not have any effect (although the operation is not faulted): instead SIGWINCH will be generated, upon which any process concerned should read the field again using the ioctl TTIOCGWINSZ.
Terminal-specific ioctl commands
There are a total of four ioctl commands specific to the terminal emulation part of the VC driver. The first two, VCIOCGPARAM and VCIOCSPARAM, allow the terminal set-up parameters (normally manipulated interactively via the set-up screen displayed when the ‘Print’ key is pressed) to be read and written. The argument for each is a structure containing two ints, respectively the index of the desired parameter, and its value. The layout of this structure and symbolic names for the various parameters and their possible values are defined in the header file. The driver also allows these parameters to be set (but not, obviously, read back) by means of a control sequence sent to the terminal; in the control sequence the numbers which are sent to identify the parameter and value have the same values as are used in the ioctl commands (see <dev/vcioctl.h>).
The ioctl commands VCIOCSTEXTCOLOURS and VCIOCGTEXTCOLOURS provide the means to set and examine (respectively) the colour values used in displaying the various elements of the screen (border, background, text, bold text, cursor, etc). For each screen polarity (nominal black-on-white and nominal white-on-black) there are ten different elements which can have their colour controlled, although not all of these are accessible in all cases. Particular limitations arise according to the monitor type and screen mode in use.
The Frame Buffer device
The device /dev/fb is an interface to the memory-mapped video display buffer. When used by the terminal emulations, the display memory is controlled exclusively by the VC driver, and is not accessible by user programs. However it is convenient to permit access to it for general window system and graphics use, and the fb device provides the mechanism for this. When the frame buffer is opened, a section of user address space which is normally inaccessible becomes a mapping onto screen memory. A user process modifying this memory directly modifies the visible screen display.
For convenience (and unlike the other displayable devices), the VC driver automatically selects the frame buffer for display as soon as it is opened. If the controlling tty for the process performing the open was one of the VC emulated terminals, the device id is recorded, and if that tty is still open when the frame buffer is closed again, then it is re-selected for display. Otherwise when the frame buffer is closed, the console device becomes the current displayed device. These rules do not apply if the selection menu is being displayed at the time of the open or close of the frame buffer.
Applying the command FBIOGCURINFO to a file descriptor for the open fb device provides information about the current screen format (or subtype), such as the number of bits per pixel, memory organisation, dimensions, etc. and most importantly, the base of the screen memory in the user process address-space. The available subtypes vary according to attached vdu type: for low and medium resolution monitors, more than one format is available. How many subtypes there are for the current vdu type is returned as part of the information. The call FBIOGINFO returns information on a specific subtype, in the range 0..(subtypes-1), which is passed to the driver in the subtype field of the information structure). The FBIOGSUBTYPE call returns just the current subtype number. The call FBIOSSUBTYPE is used to set the display to a specific subtype out of those available.
The two calls VCIOCGPALETTE and VCIOCSPALETTE provide access to the hardware colour palette registers for the frame buffer display. In each case the caller supplies a start-point within the applicable range of palette entries, and a count of the number of entries to be read into the user’s structure (VCIOCGPALETTE) or copied from it into the hardware (VCIOCSPALETTE). The size and interpretation of the palette varies according to the monitor type and frame buffer subtype in use, as described by comments in <dev/vcioctl.h>.
The ioctl call VCIOCGETCURSORINFO provides information to enable a program to control the cursor supported by the video hardware, as follows.
The cursor display is restricted in format: a cursor pattern is always 32 pixels wide; vertically, a cursor pattern may be any height (in units of a raster) up to a limited defined as VC_CURSOR_RASTER_PAIRS ∗ 2. Cursor data is always treated as 2 bits/pixel (and hence a 32-pixel cursor raster occupies 2 ARM words). Logical colour 0 means transparent, i.e. the underlying frame buffer data will be displayed, whereas colours 1, 2 and 3 may be individually defined - see below.
The 32 pixel width restriction seems severe, however a cursor pattern may be defined to appear smaller simply by marking the excess left- or right-hand part of the pattern as transparent. This is done using logical colour 0 (transparent) for each 2-bit pixel. Hardware limitations require that the cursor data should overlap the border area by the smallest possible amount, i.e. when a cursor is displayed overlapping the right-hand edge of the main display area, the right-most non-transparent pixel in the cursor pattern must appear in the right-most pixel position within the pattern; conversely at the left-hand edge the left-most non-transparent pixel must always occur at the left-hand end of the pattern data. On ARM, the left-most pixel is the least significant 2 bits of the lowest-addressed word in the two words of cursor raster data.
Whenever the frame buffer is being displayed, a cursor control block (of type VCCursor) is polled on each vertical flyback interrupt; any change in the block is reflected in the way the cursor is displayed. The control block, like the frame buffer itself, is writable by a user program having the frame buffer open. The VCIOCGETCURSORINFO call is passed the address of a VCCursorInfo structure in which is returned information about the cursor; the information varies according to the frame buffer mode in force, and hence this call should be used after a change of frame buffer sub-type. The most important piece of information is the address of the control block (returned in the base field); also provided are the limits (min_x, min_y, max_x and max_y) of the position of the top-left corner of the cursor image relative to the frame buffer coordinate space. The final item of information is the scale factor for the cursor image. For low- and medium-resolution displays, a pixel in the user-defined cursor image is the same size as a pixel of the main frame buffer display. In high-resolution mode, however, one cursor pixel is as wide as four main display pixels (and there are restrictions on both the cursor pixel values which may be used in the cursor data area, and the cursor ‘colours’ which may be defined). The pixel_scale field of the cursor info structure will contain 1 in the former case and 4 in the latter. Note that the position of the cursor is defined and resolvable in units of a single frame buffer pixel, for all display types, independent of any pixel scaling.
To use the hardware cursor, the display field of the VCCursor structure should be set to contain the index of one of the members of the pattern array. The contents of (part of) the raster_pair array, in conjunction with the size, pos, col1, col2 and col3 and fields of the selected pattern then define the actual cursor image data and image height, the position on the screen where the image will appear, and the three colours which may be displayed within the image. By this mechanism a number of different patterns (up to a limit defined by VC_CURSOR_PATTERNS) may be defined; switching between them is achieved simply by changing the display field. This can be useful for animation purposes.
The special value VC_CURSOR_OFF in the display field disables the cursor display. The value VC_CURSOR_CHANGING means that the cursor display should be left as it was found on the previous poll. A value in the range 0 .. VC_CURSOR_PATTERNS-1 causes that pattern to be displayed; any other value is equivalent to VC_CURSOR_OFF.
The pos field in a pattern defines (in terms of the main frame buffer coordinate system, with (0,0) at the top-left of the display data area) where the top-left pixel of the cursor occurs (note that this pixel need not be visible, it might be transparent). If either of the pos.x and pos.y fields has a value beyond the cursor position limits, it will be treated as if it were at the limit (although the actual field will not be modified by the FB driver).
The three fields col1, col2 and col3 define for each pattern the physical colours which will be displayed by logical cursor pixel values 1, 2 and 3 respectively (colour 0 is transparent). For low- and medium-resolution modes, each field is interpreted as three 4-bit physical colour values for red, green and blue, and one bit indicating colour supremacy (only useful with external video mixing hardware); the red field is bits 0..3, green is 4..7, blue is 8..11 and the supremacy is held in bit 12. In high-resolution mode the colour values are interpreted differently: only colours 1 and 3 may be changed, and if so each must take one of the values 0x010 or 0x030 for black and white respectively; logical colour 2 should not be used in the cursor pattern; supremacy may be used if required.
The size field defines which of the available rasters of cursor image data in the cursor block’s raster_pair array field is/are to be displayed. A cursor pattern must always be aligned to start on a raster-pair boundary; this is enforced by having size.rp_start for each pattern define the data starting point as an index into the raster_pair array. However a pattern may be an arbitary number of rasters in height (defined by the size.r_count field), up to VC_CURSOR_RASTER_PAIRS ∗ 2. Cursor pattern data may overlap, i.e. the same row(s) in the raster_pair array may be referenced by any number of patterns.
The calls VCIOCGETFBBLANKTIME and VCIOCSETFBBLANKTIME give control over the screen blank time period the VC driver uses when the FB device is being displayed. In this case, activity on either the mouse or keyboard input devices will cause the screen blank timeout to be restarted and, if the timer had previously run out, the screen output will be re-enabled. Each call takes as parameter the address of an int which will respectively receive, or be treated as containing, the timeout period measured in seconds. A period of 0 disables the screen blank mechanism for the FB device, i.e. when the frame buffer is selected the screen will stay permanently on.
The Keyboard device
The keyboard device, /dev/kbd is accessible only in conjunction with the frame buffer device, as mentioned in the introduction; i.e. only when the frame buffer device is selected for display (although it need not be open) will input data from the real keyboard be queued for reading from /dev/kbd.
The keyboard is an event-generating device, that is, the data it generates is a sequence of logical event descriptions rather than an ASCII-encoded character stream. Each event is represented in a record constructed as a number of consecutive bytes in the data stream. To maintain synchronisation, all read operations on the stream should be performed with a byte count which is a multiple of the record size (symbolically defined as VC_EVENT_SIZE: currently 5). Although the structure of generated keyboard data is radically different from a typical character device, the driver uses the normal kernel tty mechanisms to handle the data stream. In consequence the standard tty ioctl commands are available to control the stream. However restrictions are placed on what operations may be performed: the commands TIOCOUTQ, TIOCSTOP, TIOCSTART, TIOCSTI, TIOCSETP, and TIOCSETN are all rejected. One special ioctl call is provided, VCIOCEVENTCOUNT, which returns a pointer to a user-readable structure maintained by the kernel. This contains, for each event device, a count of how many events have occured since the device was last opened. A user program can then efficiently detect the presence of new event data by checking the recorded values.
Each event record always contains a type field; further fields vary according to the event type. As mentioned under General Interface, there exists a set of macros for access to the various fields in an event, assuming the bytes comprising the event record are held contiguously in memory in the order they were read. The macro VC_GET_TYPE returns the type field, where the logical keyboard event types are: key-down, key-up, key-repeat and time-high. Macros for the integer values of these types in the event record are defined, named respectively VCEV_KEY_DOWN, VCEV_KEY_UP, VCEV_KEY_REPEAT and VCEV_TIME_HIGH. The first two events describe changes in the state of the physical keyboard: when a key is pressed by the user, a key-down event will be generated; when it is released, a key-up event is generated. Most keys on the keyboard are defined to auto-repeat: for these, if the key is held down for more than a certain time (the ‘start gap’), key-repeat events will be generated at regular intervals (the ‘repeat gap’) thereafter, until the key goes up again. The ioctl commands VCIOC{G,S}AUTORPT, when applied to a file descriptor for the keyboard device, allow examination and setting of the times for the start and repeat gaps. These are specified in units of centiseconds (10ms). If the start gap is set to zero then autorepeat is disabled. The initial values for these times are determined from the CMOS RAM settings used by the main console device. The fourth event type indicates a wrap-round of the timer used to time-stamp events, and is used to keep the process reading an event stream synchronised with the driver.
For each of the key-related event types, three pieces of information are supplied in the event record. The first parameter is a key code (an integer value uniquely tied to the function of the key), the second is an ASCII-encoded character for that key, and the last item is a timestamp. The macros VC_GET_PAR1 and VC_GET_PAR2, and VC_GET_EVSTAMP return these respective fields. For definitions of key codes, see the file <dev/key_table.h>. If a particular key does not generate an ASCII code in normal operation, the second parameter will have the value 0x3FF.
The timestamp for an event is a 16-bit value built using a struct timeval (see gettimeofday(2)) recorded at the time of the event, as follows. The high order 6 bits of the timestamp are the lowest 6 bits of the tv_sec field; the low order 10 bits are derived by taking the tv_usec field and shifting it right by 10 bits: this yields a count in units of 1024 microseconds, within the second. To allow an absolute timestamp to be reconstructed by the process reading events, the time-high event record contains as a single field a 32-bit value of seconds as at the last 64-second wrapround point (i.e. the lowest 6 bits are always 0); the macro VC_GET_TIMEHIGH can be used to extract it. Each normal event can then be given a full timestamp by or’ing the latest time-high value with the 6-bit seconds component from the event’s own timestamp. Note that a time-high event is not generated every 64 seconds; instead it is generated immediately before the first normal event after modulo 64 wrap-round of the system time in seconds. Thus where there is no keyboard activity over a long period, events are not needlessly generated.
There are a number of different types of keyboard which may be attached to the system. These vary in respect of the number and placing of keys, and the combination of key legends on multi-function keys. Whilst the key code parameter in a keyboard event record is intended to be independent of keyboard types, it may be useful to know in advance which key codes may be received. Accordingly the ioctl call VCIOCKBDTYPE allows a user program to determine what type of keyboard is currently attached (although the reader may care to note that it is possible to change the attached keyboard while the system is running).
One further facility provided for convenience on the kbd device is the ability to merge the stream of events generated by the keyboard and mouse devices into a single event channel, accessed by reading from a file-descriptor for the keyboard. The ioctl command VCIOCMOUSELINK takes as parameter the address of an int flag. If this is non-zero, and the mouse device is not open, then events from the mouse (see below) will appear intermixed with events on the existing keyboard stream. The mouse may not thereafter be opened by any caller until either the kbd device is closed or the VCIOCMOUSELINK call to the kbd device has been made again with the flag set to 0, when the link is broken.
The Mouse device
The mouse device is similar in concept to the keyboard device: it generates a stream of event records, describing changes in mouse position, and transitions of the state of the buttons on the mouse. Mouse position changes are marked by events of type mouse-pos (symbolically named as VCEV_MOUSE_POS), and button transitions by key-up and key-down events. All these events are time-stamped; time-high events are used for synchronisation, as on the keyboard. The mouse buttons have their own key codes distinct from any on the keyboard (refer to <dev/key_table.h>), and do not generate an ASCII code (the second event parameter will have value 0x3FF); note also that they do not auto-repeat.
Mouse motion is indicated in relative terms: each mouse-pos event contains a pair of values (dx,dy) indicating movement in the respective directions. The macros VC_GET_RX and VC_GET_RY when applied to an event record return these values as signed integers.
Mouse motion can generate a very high rate of events, and may in extreme cases overload the kernel character-input queues. For this reason a special line-discipline is provided, which accumulates multiple mouse motion events occuring over each short interval and transmits a single event describing the overall change of position. The benefits are that with rapid mouse activity there is less load, both on the system and on the process reading the event stream. The standard ioctl command TIOCSETD should be used on a file descriptor for the mouse device (or the kbd device, if mouse and keyboard events have been merged) to select this line-discipline (MKIDISC, see <sys/ioctl.h>), which is in all other respects the same as the normal one. Note that the user-accessible event counts maintained by the kernel are for raw events, before processing by the line discipline. Care is therefore required in interpreting these.
FILES
/dev/consolemain system console
/dev/fbframe buffer device
/dev/kbdevent-based keyboard interface
/dev/mouseevent-based mouse interface
/dev/ttyv∗virtual terminals
SEE ALSO
BUGS
There ought to be separate virtual mice, one associated with each virtual screen. The frame buffer when open ought to be accessible only by the process which opened it, rather than by all processes.
4th Berkeley Distribution — Revision 1.6 of 12/06/89