DEVICES

PSIONICS FILE - DEVICES
=======================
Device driver interfaces
Last modified 1998-11-06
========================

This document describes all known functions for all known device drivers. It
does not include file IO, even when done through the same interfaces.

The device drivers documented are:
  SND: Sound device
  TIM: Timer device
  ALM: Alarm device
  WLD: World device
  TTY: Serial port device (including IR)
  PAR: Parallel port device
  FRC: Free running counter
  XMD: XModem driver
  YMD: YModem driver
  WLS: Workabout laser scanner
  AIR: AccessIr driver
  Console device


Types of device driver
----------------------
On the Series 3, much functionality, including the filing system, is provided
via device drivers. There are three kinds of device drivers:
* physical device drivers: these drive the hardware directly
* base logical device drivers: these provide a basic abstraction for working
  with logical device drivers
* stacked logical device drivers: these provide higher levels of abstraction
Only logical device drivers need to know about physical device drivers; all
user applications operate through logical device drivers.

For example, the 3-Link pod and cable might be accessed through a physical
device driver called TTY.LNK: (all physical device drivers have a two part
name). This is automatically loaded the first time that the logical device
driver TTY: is opened, and TTY: will use it to actually communicate with the
pod.

When TTY: is opened, the kernel will return a handle. Read and write operations
on that handle will send data directly to and from the port. Alternatively,
the XMD: device driver could be stacked on top of TTY: on that handle. Once
this has been done, read and write on that handle will now be done via the XMD:
driver, which wraps the data in the XModem protocol and calls the TTY: driver
to do the actual output. There is no limit to how many device drivers can be
stacked upon one another.


Opening a handle
----------------
A base logical device driver is opened with the IOOPEN keyword or the IoOpen
system call; a stacked logical device driver is opened with IoOpen. The name is
examined to see whether it has a colon as the fourth character but not the
fifth; if so, it is split into a device name and a channel name. The kernel
then checks that the logical device exists; if not, or if the name does not
have the correct form, it prefixes "FIL:" to the name and tries again (FIL
is the filing system logical device driver). For example:
    "SND:"        device "SND"  channel name ""
    "TTY:A"       device "TTY"  channel name "A"
    "FIL:A:XXX"   device "FIL"  channel name "A:XXX"
    "HELLO.TXT"   device "FIL"  channel name "HELLO.TXT"
    "ROM::XXX"    device "FIL"  channel name "ROM::XXX"
    "FIL:TTY:"    device "FIL"  channel name "TTY:"
    "QXV:"        device "FIL"  channel name "QXV:"
[the last example assumes there is no QXV device driver].

The filing system and the FIL: driver are described in the Psionics file
FILEIO. All other known drivers are described here.

IOOPEN and IoOpen are passed a mode to open the device or file. Drivers other
than the filing system and those specifically mentioning it ignore the mode.
It is recommended that a mode of -1 be used, as this is always rejected by the
filing system; thus an error in the device name or a missing driver will be
detected. Note that the IOOPEN keyword uses a qstr, while the IoOpen system
call uses a cstr.

A driver may refuse to open a given channel name, or all channels, more than
a certain number of times without closing some first. For example, a TTY
driver might only allow one open handle at a time for each port.

In OPL there are two special handles that do not need to be opened:
    -1: the device opened by LOPEN
    -2: the console device (see below)


Using the device driver
-----------------------
Once a device driver has been opened, it is accessed with the keywords IOW,
IOA, and IOC (Series 3a only). These keywords offer the same services, and
differ only in the way completion is indicated.

IOW waits until the operation completes, and then returns. No signal is
    generated.
IOA has an extra status variable argument. The variable is set to -46 at the
    start of the operation, and then to the final result when it completes; a
    signal is generated at this moment (it can be collected with IOWAIT or
    IOWAITSTAT). Note that some operations complete immediately, and so the
    status of -46 is never seen.
IOC is like IOA, but if the operation completes immediately, it places the
    result into the status variable and generates a signal. Thus the code
    making the call can check the result in one place (after collecting the
    signal) rather than two (after the call and after the signal).

Each call is passed a function number and two parameters for passing other
information. The latter identify blocks of memory; the actual argument can be
either the name of an OPL variable (typically the first element of an array),
in which case that variable marks the start of the block, or it can be the #
operator applied to the address of the block. The former is equivalent to
#ADDR(variable).

If the parameter is shown as "unused", then any variable or value can be used,
as it will be ignored; it is often convenient to use #0 as such an argument.

Unless stated otherwise, a successful call returns zero, and an unsuccessful
call some non-zero error code.


Standard functions
------------------

These functions apply to all drivers.

Function:   1 (read)
Function:   2 (write)
Argument 1: buffer
Argument 2: count (word)

These functions are equivalent to the IOREAD and IOWRITE keywords. They read
or write up to the specified number of bytes from or to the device; in the
case of function 1, the count is changed to the actual amount read.

These functions can be used with any handle that is using a driver labelled
as a data device (such as the serial port device or the XModem driver).


Function:   3
Argument 1: unused
Argument 2: unused

This will close the handle; it is equivalent to the IOCLOSE keyword.


Function:   4
Argument 1: unused
Argument 2: unused

This will cancel any uncompleted function on the handle; the function will
complete immediately, with the status variable set to -48 ("I/O cancelled").
A signal will still be generated, and must be collected with IOWAITSTAT or
IOWAIT.


Sound device
------------

The sound device has the name "SND:". There are no channel names. Only one
handle can be open at a time, and so the device should be closed as soon as
possible.


Function:   1 (sound channel 1)
Function:   2 (sound channel 2)
Argument 1: note information
Argument 2: word holding number of notes
This function is supported by the HC, MC, and Series 3a only.

This plays a sequence of notes on the specified sound channel. The note
information is an array of words, two per note; the first is the frequency of
the note (in Hz), and the second the duration in beats (see function 7).
The sound will not start until both these functions have been called (thus
ensuring the sound is synchronized on both channels). The function completes
when the specified channel finishes playing, even if the other has not.


Function:   7
Argument 1: 2 byte information block
Argument 2: unused

The characteristics of the sound system are set according to the block:
  Offset  0 (byte): beats per minute (2 to 240, default 120)
  Offset  1 (byte): volume (0 max to 5 min)
The beats per minute is only supported by the HC, MC, and Series 3a. On the
Series 3a, volumes 1 and 2 are identical, as are 4 and 5. On the Series 3t,
volumes 0 and 5 are unavailable.


Function:   8
Argument 1: 2 byte information block
Argument 2: unused

The block is filled in with information about the sound channel, using the
same format as function 7.


Function:   9
Argument 1: alarm type (0 = rings, 1 = chimes)
Argument 2: unused

The specified alarm is played; this function completes when the sound has
completely played.


Function:   10
Argument 1: phone number (cstr)
Argument 2: parameter block

This generates DTMF dialling sounds. The number contains the digits to be
dialled (0 to 9, *, #, and A to F can be used; E is the same as *, and F the
same as #). The parameter block has the format:
  Offset 0 (byte): tone length   )
  Offset 1 (byte): delay length  ) all in 1/32 seconds
  Offset 2 (word): pause length  )



Timer device
------------

The timer device has the name "TIM:". There are no channel names.

Several channels may be opened at the same time by the same process.

Function:   1
Argument 1: delay in 1/10 seconds (long)
Argument 2: unused

This will complete after the specified delay. Time when the machine is switched
off is not counted as part of the delay. Changing the system clock will not
affect the completion of this function.


Function:   2
Argument 1: abstime (long)
Argument 2: unused

This will complete at the specified time. If the machine is switched off at
that time, it will switch back on. Changing the system clock will affect the
completion of this function.


Alarm device
------------

The alarm device has the name "ALM:". There are no channel names.

Function:   1 (display date only)
Function:   2 (display date and time)
Argument 1: time specification block
Argument 2: message (cstr)

This schedules an alarm, which causes a message box to be shown at some later
time. The time specification block has the format:
  Offset  0 (long): abstime when the alarm should sound
  Offset  4 (long): abstime to be displayed in the message box
The message (maximum 64 characters) is shown in the message box.

The function completes when the alarm goes off. If the machine is switched off
at that time, it will switch back on. Changing the system clock will affect the
completion of this function.


Function:   10 (display date only)
Function:   11 (display date and time)
Argument 1: time specification block
Argument 2: message (cstr)
These functions are supported by the Series 3a only.

This schedules an alarm, which causes a message box to be shown at some later
time. The time specification block has the format:
  Offset  0 (long): abstime when the alarm should sound
  Offset  4 (long): abstime to be displayed in the message box
  Offset  8 (qstr): name of alarm sound

These functions are identical to functions 1 and 2, except that the alarm sound
is specified by the call. The sound name may be one of the following:
- the name of a sound file; this is searched for in each of:
    A:\WVE\name.WVE
    B:\WVE\name.WVE
    M:\WVE\name.WVE
    ROM::name.WVE
  [This appears to be the search order, but it is not documented.]
  The Series 3a ROM contains the sounds:
    SYS$AL01   Fanfare
    SYS$AL02   Soft bells
    SYS$AL03   Church bell
- a single byte (thus offset 8 is set to 1) with the value 1 (for rings),
  2 (for chimes), or 16 (for silence).


World device
------------

The world device has the name "WLD:". There are no channel names.

This device gives access to the World database. This includes the built-in
database and any one world file. If the World application is running, this is
the file it currently has open. Otherwise it is the last world file to be open,
or the world file opened with function 21.

World files have a format which varies from version to version of the operating
system, and are limited to 32 entries. This is because the file is mapped into
kernel address space and accessed directly, rather than being loaded in the
usual manner.

Several functions use a "city name block". This is a 42 byte block with the
format:
  Offset  0 to 20: name of a city (cstr)
  Offset 21 to 41: name of a country (cstr)
Unless stated otherwise, the country is that in which the city lies.

Many functions establish or use a searching order. This can be set to:
- all cities, in alphabetical order ("city order")
- capital cities, in alphabetical order of country ("country order")
Search order is cyclic: the last city or country is followed by the first.


Function:   10
Argument 1: clue (cstr)
Argument 2: city name block

This locates a city whose name begins with the clue (the search is done with
folded strings, so "lon" will find London, but "ond" will not). If successful,
the city block is filled in with the city, and city order is set.


Function:   11
Argument 1: clue (cstr)
Argument 2: city name block

This locates a country whose name begins with the clue (the search is done with
folded strings, so "lon" will find London, but "ond" will not). If successful,
the city block is filled in with the capital city of the country, and country
order is set.


Function:   12
Argument 1: city name block
Argument 2: unused

This locates either the city whose name is in the city part of the block, or,
if the city part is an empty string, the capital city of the country whose name
is in the country part of the block (in either case, the string must be exact
after folding). If successful, the block is filled in, and city or country
order (according to what was searched for) is set.


Function:   13 (next city)
Function:   14 (previous city)
Argument 1: city name block
Argument 2: unused

These functions fill the block with the next (or previous) city in the current
search order.


Function:   15
Argument 1: city name block
Argument 2: unused

This function fills the block with the home city; city order is set.


Function:   16
Argument 1: unused
Argument 2: unused

This function sets the home city to the last city returned.


Function:   17
Argument 1: city name block
Argument 2: unused

This function fills the block with the capital city of the default country;
city order is set.


Function:   18
Argument 1: unused
Argument 2: unused

This function sets the default country to that of the last city returned.


Function:   19
Argument 1: original number (cstr)
Argument 2: diallable number (cstr)

This function generates a diallable number (up to 24 characters) from the
original number (up to 128 characters), using the following rules:
- all characters before the first digit are stripped from the number;
- the number then ends at the first character other than a digit, space, or the
  special characters * # , and - (star, hash, comma, and dash);
- if there are any spaces or dashes in the number, they are removed and the
  diallable number is modified as follows:
  * if the first digit was a zero, it is removed;
  * if the home city is not in the default country, the sequence is prefixed
    with the international sequence to dial from the home city to the default
    country;
- if not, the number is precisely those characters left.

For example, "abc,123,456xx789" generates "123,456". Assuming that the default
country is the UK and the default city is in the USA, "abc00-34 56x78"
generates "01144003456".

@David said that this just generates the dial string@
@David implied this also does [country]@


Function:   20
Argument 1: (word) the value 0 (to add) or 1 (to update)
Argument 2: 80 byte information block

Adds or updates the city described by the information block (in the format of
function 22) to the open world file.


Function:   20
Argument 1: (word) the value 2
Argument 2: unused

The current item is deleted from the open world file if it is in it, not the
current home city, and not a capital city of an added country. The function
returns 1 if the entry was hiding an entry in the ROM database, and 0
otherwise.


Function:   20
Argument 1: (word) the value 3
Argument 2: 66 byte information block

Adds or updates the country described by the information block (in the format
of function 23) to the open world file. All cities in the country will have
their GMT offset and DST rule updated to match the data.


Function:   21
Argument 1: (word) mode (0 = open, 1 = create, 2 = replace)
Argument 2: (cstr) filename

This function opens, creates, or replaces a world file for use. The modes have
the meanings described in the Psionics file FILEIO. If the last returned city
is in the database, it is no longer valid (but functions 13, 14, and 25 still
work). The default extension is ".WLD".


Function:   22
Argument 1: 80 byte buffer
Argument 2: unused

This function fills the buffer with information about the last city returned:
  Offset  0 to  20: (cstr) city name
  Offset 21 to  41: (cstr) country name
  Offset 43 (byte): DST rule: 0 = none, 2 = European, 4 = North, 8 = South
  Offset 44 (word): minutes ahead of GMT for city
  Offset 46 (word): city latitude in minutes north (negative means south)
  Offset 48 (word): city longtitude in minutes west (negative means east)
  Offset 50 to  66: (cstr) dial code from home city
  Offset 67 to  75: (cstr) area code of city
  Offset 76 (word): X coordinate of city on map (in pixels)
  Offset 78 (word): Y coordinate of city on map (in pixels)


Function:   23
Argument 1: 66 byte buffer
Argument 2: unused

This function fills the buffer with information about the country of the last
city returned:
  Offset  0 to  20: (cstr) city name
  Offset 21 to  41: (cstr) country name
  Offset 43 (byte): DST rule: 0 = none, 2 = European, 4 = North, 8 = South
  Offset 44 (word): minutes ahead of GMT for capital city
  Offset 46 to  50: (cstr) national dialling code
  Offset 51 to  55: (cstr) international dialling code
  Offset 56 to  64: (cstr) country code


Function:   24
Argument 1: (word) status
Argument 2: 66 byte information block

This function does a calculation on the contents of the information block. The
function should be called with the status set to 1. If it returns successfully,
then, as long as the status is non-zero, it should be called again. When the
status is zero, the calculation has completed. Intermediate stages may use
extra internal memory, so if you wish to abandon the calculation partway, use
function 4 to cancel (this can be done at any time) rather than just stopping.

The initial value of the information block should be:
  Offset 42 (byte): units (0 = miles, 1 = km, 2 = nautical miles)
  Offset 43 (byte): DST rule: 0 = none, 2 = European, 4 = North, 8 = South
  Offset 44 (word): minutes ahead of GMT for city
  Offset 46 (word): point latitude in minutes north (negative means south)
  Offset 48 (word): point longtitude in minutes west (negative means east)

The final value of the information block is:
  Offset  0 (word): distance in stated units from home city to point
  Offset  2 (word): sunrise time at point in minutes past midnight
  Offset  4 (word): sunset  time at point in minutes past midnight
  Offset  6 (word): 0 = times valid, 1 = light all day, -1 = dark all day


Function:   25
Argument 1: city name block
Argument 2: unused

This function returns the next city in the same country as the last city
returned (using city order).


Serial port device (data device)
--------------------------------

The serial port device has the name "TTY:". The channel name is a single
letter from A to Z, identifying the particular port to use. Which ports are
actually provided depends on the specific system.

On the Series 3t and 3a, the two RS-232 ports are channels A and B. On
those machines with an infra-red port, it is channel I.

An open serial port can be read and written with IOREAD and IOWRITE, or with
IOW functions 1 and 2.


Function:   7
Argument 1: 12 byte control block
Argument 2: unused

This function sets various characteristics of the serial port. The control
block has the format:
  Offset  0 (byte): transmit baud rate
  Offset  1 (byte): receive baud rate
    Baud rates are encoded as:
     1 =    50      7 =   600     13 =  4800     19 = 115200
     2 =    75      8 =  1200     14 =  7200
     3 =   110      9 =  1800     15 =  9600
     4 =   134     10 =  2000     16 = 19200
     5 =   150     11 =  2400     17 = 38400
     6 =   300     12 =  3600     18 = 57600
  Offset  2 (byte): framing
    Bits 0 to 3: number of data bits minus 5 (e.g. 3 means 8 bits)
    Bit 4:       clear for 1 stop bit, set for 2 stop bits
    Bit 5:       parity bit enabled if set
  Offset  3 (byte): 0 = no parity, 1 = even parity, 2 = odd parity
  Offset  4 (byte): handshaking
    Bits 0 to 1: 3 = XON handshaking, 0 = no XON handshaking
    Bit 2:       0 = RTS handshaking, 1 = no RTS handshaking
    Bit 3:       1 = DSR handshaking, 0 = no DSR handshaking
    (Any combination of XON, RTS, and DSR can be set at once.)
  Offset  5 (byte): XON character (usually 17)
  Offset  6 (byte): XOFF character (usually 19)
  Offset  7 (byte): flags
    Bit 0: ignore parity errors
  Offset  8 (long): terminating mask
The terminating mask specifies which of the characters with codes 0 to 31
terminate a read. For example, if bits 10 and 13 are set, then a read on the
port will terminate after reading a byte with value 10 or 13.


Function:   8
Argument 1: 12 byte control block
Argument 2: unused

This function fills the control block with the current settings (see function
7).


Function:   9
Argument 1: unused
Argument 2: unused

This function discards any buffered input and any error state. Any handshaking
is set to restart reception.


Function:   10
Argument 1: count (word)
Argument 2: unused

The count is set to the number of bytes buffered and waiting to be read.


Function:   11
Argument 1: 2 byte control block
Argument 2: unused

The first byte of the control block is set to indicate the state of the modem
control lines:
    Bit 0: set if CTS active
    Bit 1: set if DSR active
    Bit 2: set if DCD active

The second byte specifies the new setting for the DTR line:
    0 = leave unchanged
    1 = set DTR active
    2 = set DTR inactive


Function:   12
Argument 1: 6 byte information block
Argument 2: unused

The information block is filled in to indicate which facilites are supported
by the port.
  Offset  0 (long):
    Bit  0: set if supports 50 baud
    Bit  1: set if supports 75 baud
    Bit  2: set if supports 110 baud
    Bit  3: set if supports 134 baud
    Bit  4: set if supports 150 baud
    Bit  5: set if supports 300 baud
    Bit  6: set if supports 600 baud
    Bit  7: set if supports 1200 baud
    Bit  8: set if supports 1800 baud
    Bit  9: set if supports 2000 baud
    Bit 10: set if supports 2400 baud
    Bit 11: set if supports 3600 baud
    Bit 12: set if supports 4800 baud
    Bit 13: set if supports 7200 baud
    Bit 14: set if supports 9600 baud
    Bit 15: set if supports 19200 baud
    Bit 16: set if supports 38400 baud
    Bit 17: set if supports 57600 baud
    Bit 18: set if supports 115200 baud
  Offset  4 (word):
    Bit  0: set if supports 5 bits
    Bit  1: set if supports 6 bits
    Bit  2: set if supports 7 bits
    Bit  3: set if supports 8 bits
    Bit  4: set if supports 2 stop bits
    Bit  5: set if supports even parity
    Bit  6: set if supports odd parity
    Bit  7: set if supports mark parity
    Bit  8: set if supports space parity
    Bit  9: set if supports setting DTR
    Bit 10: set if supports different transmit and receive baud rates
    Bit 11: set if supports soft xon/xoff characters


Parallel port device (data device)
----------------------------------

The parallel port device has the name "PAR:". The channel name is a single
letter from A to Z, identifying the particular port to use. Which ports are
actually provided depends on the specific system. A port will consume power
while open.

An open parallel port can be written with IOWRITE, or with IOW function 2.

No other functions are available on the Series 3.


Free running counter
--------------------

The Free running counter has the name "FRC:". There are no channel names. It
is only available on the Series 3a. Only one process may have the FRC open
at a time, and so it should be closed as soon as possible.

In the following description, an "FRC-tick" is 1/1024 seconds.


Function:   1
Argument 1: (word) set to current count
Argument 2: unused

The current setting of the counter is placed in the word. If the counter is
in mode 1, the count is then reset to zero (the counter continues counting).
This call will not complete while the counter is zero.


Function:   15
Argument 1: (word) operating mode (0 or 1)
Argument 2: (word) step time (10 to 65535)

Starts the counter from zero. Mode 0 means that the counter will increment
every FRC-tick. Mode 1 means that the counter will increment at every N
FRC-ticks, where N is the step time. Any uncompleted function on the counter
will be completed.


XModem and YModem drivers (data device)
---------------------------------------

The XModem driver has the name "XMD:", and the YModem driver the name "YMD:".
There are no channel names. Both are stacked on to another data device.

Once stacked, the driver will use the underlying device to transfer data
using the XModem (single transfer) or YModem (multiple transfer) protocol.
These protocols have a number of variants:
- XModem may use checksums or CRCs on each frame. CRCs are more reliable.
- YModem may use the error correcting or G mode. The G mode does not allow
  errors to be corrected, only detected.
- The transfer may use short frames (128 data bytes) only, or both short and
  long frames (1024 data bytes).

Function 1 is used to receive data. The initial value of the length argument
will be ignored, and a whole frame (128 or 1024) bytes will be placed in the
buffer, which must therefore be large enough. When an end-of-file message is
received, the function will fail with error -36.

Function 2 is used to send data. The length is used as follows:
       0 : an end-of-file message is sent
     128: a short frame is sent
    1024: a long frame is sent
If the length is any other value, the specified amount of data is transferred,
followed by enough $1A bytes to fill a frame (a short frame if the length is
less than 128, and a long frame otherwise).

With YModem, the first frame must be a short frame with the following contents,
in order:
  - (cstr) file name
  - file length in bytes (decimal digits)
  - a single space, then the abstime file last modified (octal digits)
  - a single space, then the file mode, using Unix conventions (octal digits)
  - a single space, then the sending software version number (octal digits)
The last field or fields may be omitted, provided that the name is present.
The rest of the frame must contain only zero bytes. A frame consisting only of
128 zero bytes indicates that there are no more files.


Function:   10
Argument 1: (word) direction: 0 = transmit, 1 = receive
Argument 2: (word) mode

This establishes a connection with the other end of the link. The direction
indicates which way the file transfer will take place. The mode is one of
the following values:
  If long frames are to be rejected while receiving:
    XModem:
      0 = CRC mode if supported by far end, otherwise checksum mode
      1 = CRC mode
      2 = Checksum mode
    YModem:
      3 = Error correcting mode
      4 = G mode
  If long frames are to be accepted while receiving:
    XModem:
      $8001 = CRC mode
    YModem:
      $8003 = Error correcting mode
      $8004 = G mode

With YModem, this function must be called for each file.


Function:   11
Argument 1: unused
Argument 2: unused

This disconnects an existing connection while leaving the driver attached.
With YModem, this function should not be called between files.


Workabout laser scanner
-----------------------

The laser scanner has the device name "WLS:" and channel name "D" (that is,
it is opened as "WLS:D"). Only one handle can be open at a time.
Furthermore, opening the device activates the scanner for 5 seconds, after
which it will no longer read and should be closed; it should also be closed
after a successful read.

Reading from the device returns a string which is not terminated (the
amount of data read gives the length). There are no other IO functions
known.



AccessIR device (data device)
-----------------------------

The AccessIR device has the name "AIR:". There are no channel names. Only
one handle can be open at a time, and so the device should be closed as
soon as possible.

On the Series 3c, the device is built-in to the kernel and is always
available. On the Siena it is provided as a separate file called
ACCESSIR.LDD, and is only available once it has been loaded with system
call DevLoadLDD.

There is a separate IR protocol stack process. This must be started by
executing the program SYS$IRDA.IMG (from ROM:: on the 3c) in the normal
way (system calls FilExecute and ProcResume).

Function 4 has the side effect of disconnecting from the remote machine
if a connection is established.


Function:   5
Argument 1: application name (cstr)
Argument 2: buffer

Waits for a connection from another machine, completing when another
machine connects successfully. If the call is successful, the buffer
is filled with a cstr containing information from the other machine
(up to 56 characters excluding the terminating zero) and the call returns
the maximum amount of data that may be sent in a single write.


Function:   6
Argument 1: information block
Argument 2: maximum number of machines to find

Searches the physical neighbourhood for machines willing to accept an
IrDA connection. The second argument is overwritten with the actual number
of machines found, and 36 bytes are placed in the buffer for each machine:
  Offset  0 (long): @@@@
  Offset  4 (long): machine address
  Offset  8 (long): @@@@
  Offset 12 (cstr): machine nickname (up to 23 characters)


Function:   7
Argument 1: machine address
Argument 2: unused

The device is initialized ready to connect to the specified machine.


Function:   8
Argument 1: application name (cstr)
Argument 2: buffer

Connects to the specified application on the selected machine. If the
connection is successful, the buffer is filled with the information passed
from the other machine (up to 60 bytes). The application name is limited
to 25 characters excluding the terminating zero. If this call is successful,
it returns the maximum amount of data that can be sent in a single write.


Console device
--------------

This is a special device that does not need to be opened; it has the
handle -2.


The console device outputs text in the text area (as set by the SCREEN
keyword), and many of its functions duplicate OPL keywords. Up to 255
characters may be written to the device, and the corresponding text will be
output. Certain characters have the following meaning:
    7 = beep
    9 = go to next tab stop (multiple of 8 characters)
    8 = backspace
   13 = go to start of the line
   10 = go down one line
   11 = ditto
   12 = go down one screen
If the text will not all fit in the current line, what happens depends on the
autowrap and scroll lock flags (defined below). If auto wrap is on, moving
past the end of the line moves to the beginning of the next line. Otherwise
further characters overwrite the last character on the line. If scroll lock is
off, moving down from the bottom line (including because of an auto wrap) will
scroll the screen up one line. Otherwise moving down from the bottom line has
no effect. Writing cannot fail.

Reading from the device ignores the length and always reads exactly 4 bytes,
representing a single keystroke:
  Offset  0 (word): keycode
  Offset  2 (byte): modifiers
    Bit 1: set if SHIFT pressed
    Bit 2: set if CONTROL pressed
    Bit 3: set if PSION pressed
    Bit 4: set if CAPS LOCK in effect
    Bit 5: set if NUM LOCK in effect
  Offset  3 (byte): autorepeat count
The autorepeat count indicates how many keystrokes have been combined into one
return; it will only be greater than 1 if processing of the keystrokes is not
keeping up with the autorepeat.


Function:   7
Argument 1: (word) the value 0
Argument 2: (word) style

This alters the text style as specified:
    Bit 0: bold
    Bit 1: reverse
    Bit 2: underline
    Bit 3: flashing
    Bit 4: italic
Unsupported styles and those requiring a different character width will be
silently ignored. This function cannot fail.


Function:   7
Argument 1: (word) the value 1
Argument 2: control block

This scrolls a rectangle (ignoring the scroll lock flag) by any amount
according to the control block:
  Offset  0 (word): left   edge of rectangle (inclusive)
  Offset  2 (word): top    edge of rectangle (inclusive)
  Offset  4 (word): right  edge of rectangle (exclusive)
  Offset  6 (word): bottom edge of rectangle (exclusive)
  Offset  8 (word): horizontal scroll distance (positive=right, negative=left)
  Offset 10 (word): vertical   scroll distance (positive=down,  negative=up)
The rectangle will be clipped to the text area. This function cannot fail.


Function:   7
Argument 1: (word) the value 2
Argument 2: control block

This clears a rectangular area described by the control block:
  Offset  0 (word): left   edge of rectangle (inclusive)
  Offset  2 (word): top    edge of rectangle (inclusive)
  Offset  4 (word): right  edge of rectangle (exclusive)
  Offset  6 (word): bottom edge of rectangle (exclusive)
The rectangle will be clipped to the text area. This function cannot fail.


Function:   7
Argument 1: (word) the value 3
Argument 2: control block

The cursor moves to the specified location; if that is outside the text area,
it moves to the closest point within. The control block has the format:
  Offset  0 (word): x coordinate
  Offset  2 (word): y coordinate
This function cannot fail.


Function:   7
Argument 1: (word) the value 4
Argument 2: control block

The cursor moves the specified amount, or to the edge of the text area if that
is closer. The control block has the format:
  Offset  0 (word): horizontal distance to move (positive=right, negative=left)
  Offset  2 (word): vertical   distance to move (positive=down,  negative=up)
This function cannot fail.


Function:   7
Argument 1: (word) the value 5
Argument 2: control block

Sets the size of the text area according to the control block:
  Offset  0 (long): must be zero
  Offset  4 (word): new width
  Offset  6 (word): new height


Function:   7
Argument 1: (word) the value 6 (for scroll lock) or 7 (for auto wrap)
Argument 2: (word) 0 for off or 1 for on

Sets the scroll lock or auto wrap flag. This function cannot fail. The initial
state is auto wrap on and scroll lock off.


Function:   7
Argument 1: (word) the value 8
Argument 2: unused

Moves the cursor to the start of the next line, obeying the scroll lock flag.
This function cannot fail.


Function:   7
Argument 1: (word) the value 9
Argument 2: (word) 0 to turn cursor off, 1 to turn it on

Turns the cursor on or off; this has no effect other than altering the
appearance of the cursor on the screen. This function cannot fail.


Function:   7
Argument 1: (word) the value 10
Argument 2: (word) 0 to disable, 1 to enable (default)

Enables or disables exiting via the PSION-ESC key sequence. This function
cannot fail.


Function:   7
Argument 1: (word) the value 11
Argument 2: (word) 0 for buffering, 1 for immediate execution (default)

Enables or disables buffering of commands. When buffering is in effect, calls
to the console are buffered up, and executed only when the buffer is full, a
result is required, or on an explicit flush of the buffer. As a side effect,
errors will be reported to the function causing the buffer contents to be
executed, not the one making the call. This function cannot fail.


Function:   7
Argument 1: (word) the value 12
Argument 2: control block

Sets the text area according to the control block:
  Offset  0 (word): left   edge (inclusive) of the text area
  Offset  2 (word): top    edge (inclusive) of the text area
  Offset  4 (word): right  edge (exclusive) of the text area
  Offset  6 (word): bottom edge (exclusive) of the text area


Function:   7
Argument 1: (word) the value 13 (set up) or 14 (cancel)
Argument 2: control block

Sets up or cancels capturing of a key or combination of keys by this process,
whether or not it is in the foreground. The cancel must specify an identical
control block to the set up. The control block has the format:
  Offset  0 (word): keycode
  Offset  2 (byte): modifiers that must be pressed (if tested)
  Offset  3 (byte): modifiers that are tested
Both modifier values use the bits:
    Bit 1: set if SHIFT pressed
    Bit 2: set if CONTROL pressed
    Bit 3: set if PSION pressed
    Bit 4: set if CAPS LOCK in effect
    Bit 5: set if NUM LOCK in effect
Unused bits must be zero, and a bit must not be set in offset 2 while clear in
offset 3.


Function:   7
Argument 1: (word) the value 15
Argument 2: (word) process id

Moves the indicated process to the foreground. This call cannot fail.


Function:   7
Argument 1: (word) the value 16
Argument 2: (word) 0 for off or 1 for on

Sets the last line wrap flag. This function cannot fail. The initial state of
the flag is off. When off, printing to the bottom right corner of the text area
causes an immediate wrap and scroll. @???@ @Obeys other flags@


Function:   7
Argument 1: (word) the value 17
Argument 2: control block

This sets the font type for the text area, resizing the latter as necessary to
handle the new font, and clears the text area. The control word has the format:
  Offset  0 (word): window server font id
  Offset  2 (word): style
    Bit 0: bold (by double printing)
    Bit 1: underlined
    Bit 2: inverse
    Bit 3: double height
    Bit 4: must be set for proportional fonts, ignored for monospaced fonts
    Bit 5: italic (by printing the top half one pixel to the right)
Note that the console device uses a fixed character grid; if a proportional
font is chosen, bit 4 of the style must be selected, and the characters will be
printed on that grid, and not proportionally.

Window server font ids are $3FFF greater than the OPL font id @CHECK@. The
current system font has id $4099 (widget server) or $9A (OPL).


Function:   7
Argument 1: (word) the value 18
Argument 2: (word) 0 for disabled, 1 for enabled (default)

Enables or disables reads from the console. The console may only be read (via
functions 1, 14, or the equivalent OPL keywords) when enabled. This function
cannot fail.


@@Subs: 19 SET_PRIORITY_CONTROL, 20 COMPATIBILITY, 21 GREY, 22 FONT_EXT ??


Function:   8
Argument 1: 12 byte buffer
Argument 2: must be the same as argument 1

The position of the text area and the current cursor position (as set by the
AT keyword) are written into the buffer.
  Offset  0 (word): set to left   edge (inclusive) of the text area
  Offset  2 (word): set to top    edge (inclusive) of the text area
  Offset  4 (word): set to right  edge (exclusive) of the text area
  Offset  6 (word): set to bottom edge (exclusive) of the text area
  Offset  8 (word): set to cursor x coordinate relative to offset 0
  Offset 10 (word): set to cursor y coordinate relative to offset 2
All coordinates are in character positions. 0,0 is the top left corner of
the screen; note that the bottom and right edges are outside the text area.
This function cannot fail.


Function:   9
Argument 1: unused
Argument 2: unused

This function discards any waiting keypresses. It cannot fail.


Function:   10
Argument 1: word set to 1 if keypresses waiting, and 0 otherwise
Argument 2: unused

This function tests whether there are any keypresses waiting. It cannot fail.


Function:   11
Argument 1: 258 byte control block
Argument 2: word holding maximum length

This function allows the user to edit a string on the screen. The control block
has the following format:
  Offset  0 (byte): unused
  Offset  1 (byte): non-zero allows escape from editing
  Offset  2 to 257: string buffer
The initial value of the string must be placed in the buffer; the resulting
string will also be placed there (in both cases it is a cstr). The length of
the string, excluding the terminating zero, is limited to the specified
maximum. If ESC is pressed with the string currently non-empty, it is cleared.
If ESC is pressed with the string empty and escaping is allowed, the function
will fail; otherwise ESC will be ignored in this circumstance.


Function:   12
Argument 1: 8 byte buffer
Argument 2: unused

The buffer is filled with information about the text area:
  Offset  0 (word): window server id of the console window
  Offset  2 (word): window server id of the console font
  Offset  4 (word): height of a text line in pixels
  Offset  6 (word): width of a text character in pixels
This function cannot fail.


Function:   13
Argument 1: unused
Argument 2: unused

If console buffering is in effect, any buffered commands are executed.
Otherwise this function has no effect. It cannot fail.


Function:   14
Argument 1: 4 byte buffer
Argument 2: unused

This function is equivalent to the GETEVENT keyword. It behaves the same as
reading from the device, except that events other than keypresses can be
returned; for example, foreground, background, and change file events. Unlike
GETEVENT, this function can be called from OPL programs whether or not they
are OPA applications.


Function:   15
Argument 1: word set to 1 if any events waiting, and 0 otherwise
Argument 2: unused

This function is equivalent to the TESTEVENT keyword. It behaves the same as
function 10 except that events other than keypresses are also detected. It
cannot fail.