  BrlAPI Reference manual
  Sbastien Hinderer <sebastien.hinderer@libertysurf.fr>
  Samuel Thibault <samuel.thibault@fnac.net>
  V1.0, June 2003

  This document describes how to use BrlAPI.
  ______________________________________________________________________

  Table of Contents



  1. Introduction
     1.1 Concepts
     1.2 How to read this manual

  2. General description of BrlAPI
     2.1 Historical notes.
     2.2 Why BrlAPI is part of brltty.
     2.3 How it works.
        2.3.1 Connection.
        2.3.2 Authentication.
        2.3.3 Real use of the braille terminal.
           2.3.3.1 Braille display and braille key presses processing.
           2.3.3.2 Raw mode.
           2.3.3.3 Remarks.
        2.3.4 Disconnection.

  3. Installation and configuration BrlAPI
  4. Library description
     4.1 Connecting to BrlAPI
     4.2 Getting driver id and name
     4.3 Getting display size
     4.4 Entering raw mode, immediately leaving raw mode.
     4.5 Getting tty control
     4.6 Writing something on the display
     4.7 Waiting for a key press
     4.8 Leaving tty control
     4.9 Disconnecting from BrlAPI
     4.10 Putting everything together...

  5. Writing (BrlAPI-compliant) drivers for brltty
     5.1 Overview of the driver's structure
     5.2 Basic driver structure
     5.3 Enhancements for BrlAPI
        5.3.1 Reading braille key codes
           5.3.1.1 Remarks
        5.3.2 Exchanging raw data packets
           5.3.2.1 Remarks.

  6. Protocol reference
     6.1 Reliable packet transmission channel
     6.2 Responses from the server
     6.3 Operating modes
     6.4 Details for each type of packet
        6.4.1 BRLPACKET_AUTHKEY (see brlapi_loadAuthKey())
        6.4.2 BRLPACKET_BYE (see brlapi_closeConnection())
        6.4.3 BRLPACKET_GETDRIVERID (see brlapi_getDriverId())
        6.4.4 BRLPACKET_GETDRIVERNAME (see brlapi_getDriverName())
        6.4.5 BRLPACKET_GETDISPLAYSIZE (see brlapi_getDisplaySize())
        6.4.6 BRLPACKET_GETTTY (see brlapi_getTty())
        6.4.7 BRLPACKET_KEY and BRLPACKET_COMMAND (see brlapi_readKey() and brlapi_readCommand())
        6.4.8 BRLPACKET_LEAVETTY (see brlapi_leaveTty())
        6.4.9 BRLPACKET_MASKKEYS and BRLPACKET_UNMASKKEYS (see brlapi_ignoreKeys() and brlapi_unignoreKeys())
        6.4.10 BRLPACKET_WRITE (see brlapi_writeBrl())
        6.4.11 BRLPACKET_WRITEDOTS (see brlapi_writeBrlDots())
        6.4.12 BRLPACKET_STATWRITE
        6.4.13 BRLPACKET_STATWRITEDOTS
        6.4.14 BRLPACKET_GETRAW (see brlapi_getRaw())
        6.4.15 BRLPACKET_LEAVERAW (see brlapi_leaveRaw())
        6.4.16 BRLPACKET_PACKET (see brlapi_sendRaw() and brlapi_recvRaw())


  ______________________________________________________________________



  [1m1.  Introduction[0m

  [4mBrlAPI[24m is a service provided by the [4mbrltty[24m daemon.

  Its purpose is to allow programmers to write applications that take
  advantage of a braille terminal in order to deliver a blind user
  suitable information for his/her specific needs.

  While an application communicates with the braille terminal,
  everything [4mbrltty[24m sends to the braille terminal in the application's
  console is ignored, whereas each piece of data coming from the braille
  terminal is sent to the application, rather than to [4mbrltty[24m.


  [1m1.1.  Concepts[0m

  All throughout this manual, a few terms will be used which are either
  specific to braille terminals, or introduced because of [4mBrlAPI[24m. They
  are defined below. Taking a few minutes to go through this glossary
  will save a lot of time and questions later.



     [1mAuthentication key[0m
        A file containing arbitrary data, that has to be sent to the
        server by the client, to prove it is allowed to establish a
        connection and then control the braille terminal.


     [1mBraille display[0m
        The small screen on the braille terminal that is able to display
        braille text.


     [1mBraille keyboard[0m
        The keyboard of the braille terminal.


     [1mBraille terminal[0m
        A computer designed to display text in braille. In this case,
        the text is supposed to come from another computer running Linux
        or any other Unix system.


     [1mBrltty[0m
        The background process that gives a blind person access to the
        Linux console thanks to a braille terminal or speech
        synthetizer.


     [1mClient[0m
        An application designed to handle a braille terminal thanks to
        [4mBrlAPI[24m.


     [1mCommand[0m
        A code returned by the driver, indicating an action do to, for
        instance "go to previous line", "go to next line", etc.


     [1mDriver[0m
        A library that has functions to communicate with a braille
        terminal.  Basically, a driver has functions to open
        communication with the braille terminal, close the
        communication, write on the braille display, and read keypresses
        from the braille keyboard, plus some special functions that will
        be described in detail in this manual.


     [1mKey[0m
        A code that is returned by the driver when a key is pressed.
        This is different from a command, because the command concept is
        driver-independent (all drivers use the same command codes -
        those defined by [4mbrltty[24m), whereas codes used for returning
        keypresses may vary between drivers.


     [1mBrlAPI's Library[0m
        This library helps clients to connect and use [4mBrlAPI[24m's server
        thanks to a series of brlapi_-prefixed functions.


     [1mPacket[0m
        A sequence of bytes making up the atomic unit in communications,
        either between braille drivers and braille terminals or between
        the server and clients.


     [1mRaw mode[0m
        Mode in which the client application exchanges packets with the
        driver.  Normal operations like sending text for display or
        reading keypresses are not available in this mode. It lets
        applications take advantage of advanced functionalities of the
        driver's communication protocol.


     [1mServer[0m
        The part of [4mbrltty[24m that controls incoming connections and
        communication between clients and braille drivers.



  [1m1.2.  How to read this manual[0m

  This manual is split in five parts.



     [1mGeneral description[0m
        Describes more precisely what [4mBrlAPI[24m is and how it works in
        collaboration with [4mbrltty[24m's core, the braille driver and
        clients. In this part, a "connection-use-disconnection" scenario
        will be described step by step, explaining for each step what
        [4mBrlAPI[24m does in reaction to client instructions. These
        explanations will take place at a user level.


     [1mInstallation and configuration[0m
        This part explains in detail how to install and configure the
        API. For instructions on how to install and configure [4mbrltty[24m,
        please report to the [4mbrltty[24m documentation.


     [1mLibrary description[0m
        This part describes how client applications can communicate with
        the server using the [4mBrlAPI[24m library that comes with [4mbrltty[24m. Each
        function will be briefly described, classified by categories.
        More exhaustive descriptions of every function are available in
        the corresponding online manual pages.



     [1mWriting braille drivers[0m
        This part describes how the braille drivers included in [4mbrltty[0m
        should be written in order to take advantage of [4mBrlAPI[24m's
        services.


     [1mProtocol reference[0m
        This part describes in detail the communication protocol that is
        used to communicate between server and clients.


  What should be read probably depends on what should be done by
  applications with [4mBrlAPI[24m.

  Reading chapters 2 and 3 is recommanded, since they provide useful
  information and (hopefully) lead to a good understanding of [4mBrlAPI[24m,
  for an efficient use.

  Chapter 4 concerns writing applications that take advantage of braille
  terminals so as to bring specific (and more useful) information to
  blind people.

  Chapter 5 is for braille driver implementation: either adding a
  braille driver to [4mbrltty[24m or modifying an existing one so that it can
  benefit from [4mBrlAPI[24m's features, this chapter will be of interest,
  since it describes exactly what is needed to write a driver for
  [4mbrltty[24m: the core of drivers interface for instance.

  Finally, Chapter 6 is for [4mnot[24m [4musing[24m the library, but using the [4mBrlAPI[0m
  server directly, when the library might not be sufficient: it
  describes the underlying protocol that will have to be used to do so.


  [1m2.  General description of BrlAPI[0m

  Here is explained what [4mBrlAPI[24m is, and what it precisely does.  These
  explanations should be simple enough to be accessible to every user.
  For a more technical review of [4mBrlAPI[24m's functionalities, please see
  chapter 4.


  [1m2.1.  Historical notes.[0m

  Originally, [4mbrltty[24m was designed to give access to the Linux console to
  visually impaired people, through a braille terminal or a speech
  synthetizer. At that time, applications running in the console were
  not taking care of the presence of a braille terminal (most
  applications didn't even know what a braille terminal was).

  This situation where applications are not aware of the presence of a
  special device is elegant of course, since it lets use an unlimited
  number of applications which don't need to be specially designed for
  visually impaired people.

  However, it appeared that applications specially designed to take
  advantage of a braille terminal could be wanted, to provide the
  suitable information to blind users, for instance.  The idea of [4mBrlAPI[0m
  is to propose an efficient communication mechanism, to control the
  braille display, read keys from the braille keyboard, or to exhange
  data with the braille terminal at a lower level (e.g. to write file
  transfer protocols between braille terminals and Linux systems).



  [1m2.2.  Why BrlAPI  is part of brltty .[0m

  Instead of rewriting a whole communication program from scratch, we
  chose to add communication mechanisms to [4mbrltty[24m. This choice has two
  main justifications.

  On the one hand, integration to [4mbrltty[24m allows us to use the increasing
  number of drivers written for [4mbrltty[24m, thus handling a large number of
  braille terminals without having to rewrite any piece of existing
  code.

  On the other hand, if an application chooses to send its own
  information to the braille display, and to process braille keys,
  [4mbrltty[24m has to be warned, so that it won't try to communicate with the
  braille terminal while the application already does.  To make this
  synchronzation between [4mbrltty[24m and client applications possible, it
  seemed easier to add the communication mechanisms to [4mbrltty[24m's core,
  instead of writing an external program providing them.


  [1m2.3.  How it works.[0m

  We are now going to describe the steps an application should go
  through to get control of the braille terminal, and what happens on
  [4mbrltty[24m's side at each step. This step-by-step description will let us
  introduce more precisely some concepts that are useful for every
  [4mBrlAPI[24m user.


  [1m2.3.1.  Connection.[0m

  The first thing any client application has to do is to connect (in the
  Unix sense of the word) to [4mBrlAPI[24m which is an mere application server.
  If this is not clear, the only thing to be remembered is that this
  step allows the client application to let the server know about its
  presence. At this stage, nothing special is done on [4mbrltty[24m's side.


  [1m2.3.2.  Authentication.[0m

  Since Unix is designed to allow many users to work on the same
  machine, it's quite possible that there are more than one user
  accounts on the system. Most probably, one doesn't want any user with
  an account on the machine to be able to communicate with the braille
  terminal (just imagine what would happen if, while somebody was
  working with the braille terminal, another user connected to the
  system began to communicate with it, preventing the first one from
  doing his job...). That's why [4mBrlAPI[24m has to provide a way to determine
  whether a user who established a connection is really allowed to
  communicate with the braille terminal. To achieve this, [4mBrlAPI[0m
  requires that each application that wants to control a braille
  terminal sends an authentication key before doing anything else. The
  control of the braille terminal will only be possible for the client
  once it has sent the proper authentication key. What is called
  authentication key is in fact a Unix file containing data (it must be
  non-empty) on your system. All the things you have to do is to give
  read permissions on this file to users that are allowed to communicate
  with the braille terminal, and only to them. This way, only authorized
  users will have access to the authentication key and then be able to
  send it to [4mBrlAPI[24m.  To see how to do that, please see chapter 3.

  At the end of this step, the user is authorized to take control of the
  braille terminal. On [4mbrltty[24m's side, some data structures are allocated
  to store information on the client, but this has no user-level side-
  effect.

  [1m2.3.3.  Real use of the braille terminal.[0m

  Once the client is properly connected and authenticated, there are two
  possible types of communication with the braille terminal. The chosen
  type of communication depends on what the client plans to do. If its
  purpose is to display information on the braille display or to process
  braille keys, it will have to take control of the Linux tty on which
  it is running. If its purpose is to exchange data with the braille
  terminal (e.g. for file transfer), it will enter what is called "raw
  mode".


  [1m2.3.3.1.  Braille display and braille key presses processing.[0m

  If the client wants to display something on the braille display or to
  process braille keys itself, rather than letting [4mbrltty[24m process them,
  it has to take control of the Linux terminal it is running on.

  Each Linux terminal (tty) can be controlled by at most one application
  at a time, that's why [4mBrlAPI[24m will honnor a valid tty control request
  if and only if no other application already controls this tty.

  Once a client has obtained the control of his tty, [4mBrlAPI[24m will
  completely discard [4mbrltty[24m's display on this tty (and only this one),
  leaving the braille display free for the client.

  At the same time, if a key is pressed on the braille keyboard, [4mBrlAPI[0m
  checks whether the client application is interested in this key or
  not. If it is, the key is passed to it, either as a key code or as a
  [4mbrltty[24m command. If it is not, the key code is converted into a [4mbrltty[0m
  command and returned to [4mbrltty[24m.

  Once the client is not interested in displaying text or reading
  braille keys any more, it has to leave the tty, so that either [4mbrltty[0m
  can continue its job, or another client can take control of it.


  [1m2.3.3.2.  Raw mode.[0m

  Only one client can be in raw mode at the same time. In this mode,
  data coming from the braille terminal are checked by the driver (to
  ensure they are valid), but instead of being processed, they are
  delivered "as-is" to the client that is in raw mode.

  In the other direction, packets sent to [4mBrlAPI[24m by the client that is
  in raw mode are passed to the driver which is expected to deliver them
  to the braille terminal without any modification.


  [1m2.3.3.3.  Remarks.[0m



    The operations described in the two previous subsections are not
     completely mutually exclusive. An application that controls its
     current tty can enter raw mode, provided that no other application
     already is in this mode. However, the contrary is not possible: an
     application which has entered raw mode cannot take control of its
     tty before having left raw mode. Indeed, it would make no sense to
     take control of a tty during raw mode since in this mode, braille
     display and reading of braille keys are impossible.

    Not every braille driver supports raw mode. It has to be specially
     (re)written to support it, since it has to provide special
     functions to process incoming and outgoing packets. The same
     restriction is true (but less strong) concerning the ability to
     deliver/convert keycodes into commands: not every driver has this
     ability, it has to be modified to get it.

    Operations described in 3.1 and 3.2 can be repeated.  You can, for
     instance, use raw mode to transfer data onto your braille terminal,
     display text in braille, return to raw mode..., all that without
     having to reconnect to [4mBrlAPI[24m before each operation.


  [1m2.3.4.  Disconnection.[0m

  Once the client has finished using the braille terminal, it has to
  disconnect from the API, so that the memory structures allocated for
  the connection can be freed and eventually used by another client.
  This step is transparent for the user, in the sense that it involves
  no change on the braille display.



  [1m3.  Installation and configuration BrlAPI[0m

  Will be written later with Dave Mielke, the maintainer of [4mbrltty[24m,
  since the precise installation steps are not known yet.


  [1m4.  Library description[0m

  Let's now see how one can write dedicated applications. Basic notions
  will be seen, along with a very simple client. Greater details are
  given as online manual pages.



  The historical test program for [4mBrlAPI[24m was something like:

    connect to [4mBrlAPI[0m

    get driver id

    get driver name

    get display size

    try entering raw mode, immediately leave raw mode.

    get tty control

    write something on the display

    wait for a key press

    leave tty control

    disconnect from [4mBrlAPI[0m

  It is here rewritten, its working briefly explained.


  [1m4.1.  Connecting to BrlAPI[0m

  Connection to [4mBrlAPI[24m is needed first, thanks to the
  brlapi_initializeConnection call. For this, a brlapi_settings_t
  variable must be filled which will hold the settings the library needs
  to connect to the server. Just giving NULL will work for local use.
  The other parameter lets you get back the parameters which were
  actually used to initialize connection. NULL will also be nice for
  now.



       ______________________________________________________________________
        if (brlapi_initializeConnection(NULL,NULL)<0)
        {
         brlapi_perror("brlapi_initializeConnection");
         exit(1);
        }
       ______________________________________________________________________



  The connection might fail, so testing is needed.


  [1m4.2.  Getting driver id and name[0m

  Knowing the type of the braille device might be useful (p is defined
  as char *):



       ______________________________________________________________________
        p = brlapi_getDriverId();
        if (!p)
         brlapi_perror("brlapi_getDriverId");
        else
         printf("Driver id: %s\n",p);

        p = brlapi_getDriverName();
        if (!p)
         brlapi_perror("brlapi_getDriverName");
        else
         printf("Driver name: %s\n",p);
       ______________________________________________________________________



  This is particularly useful before entering raw mode to achieve file
  transfers for instance, just to check that the device is really the
  one expected.


  [1m4.3.  Getting display size[0m

  Before writing on the braille display, the size should be always first
  checked to be sure everything will hold on it:



       ______________________________________________________________________
        if (brlapi_getDisplaySize(&x, &y)<0)
         brlapi_perror("brlapi_getDisplaySize");
        else
         printf("Braille display has %d line%s of %d column%s\n",y,y>1?"s":"",x,x>1?"s":"");
       ______________________________________________________________________



  [1m4.4.  Entering raw mode, immediately leaving raw mode.[0m

  Entering raw mode is very simple:



       ______________________________________________________________________
        fprintf(stderr,"Trying to enter in raw mode... ");
        if (brlapi_getRaw()<0)
         brlapi_perror("brlapi_getRaw");
        else {
         fprintf(stderr,"Ok, leaving raw mode immediately\n");
         brlapi_leaveRaw();
        }
       ______________________________________________________________________



  Not every driver supports raw mode (actually only one does for the
  moment ;-), so testing is needed.

  While in raw mode, brlapi_sendRaw and brlapi_recvRaw can be used to
  send and get data directly to and from the device.  It should be used
  with care, improper use might completely thrash the device !


  [1m4.5.  Getting tty control[0m

  Let's now display something on the device. control of the tty must be
  get first:



       ______________________________________________________________________
        fprintf(stderr,"Taking control of the tty... ");
        if (brlapi_getTty(0,BRLCOMMANDS,NULL)>=0)
        {
         printf("Ok\n");
       ______________________________________________________________________



  The first parameter tells the server the number of the tty to take
  control of. Setting 0 lets the library determine it for us.


  The server is asked to send [4mbrltty[24m commands, which are device-
  independant.  The last parameter might be used when binding keys. This
  is discussed in online manual pages.


  Getting control might fail if, for instance, another application
  already took control of this tty, so testing is needed.


  From now on, the braille display is detached from the screen.


  [1m4.6.  Writing something on the display[0m

  The application can now write things on the braille display without
  altering the screen display:


       ______________________________________________________________________
         fprintf(stderr,"Writing to braille display... ");
         if (brlapi_writeBrl(0,"Press a braille key to continue...")>=0)
         {
          fprintf(stderr,"Ok\n");
       ______________________________________________________________________



  The cursor is also asked [4mnot[24m to be shown: its position is set to 0.


  "Writing to braille display... Ok" is now displayed on the screen, and
  "Press a braille key to continue..." on the braille display.


  [1m4.7.  Waiting for a key press[0m

  To have a break for the user to be able to read these messages, a key
  press (a command here, which is driver-independent) may be waited for:



       ______________________________________________________________________
          fprintf(stderr,"Waiting until a braille key is pressed to continue... ");
          if (brlapi_readCommand(1,&key)>0)
           fprintf(stderr,"got it! (code=%d)\n",key);
       ______________________________________________________________________



  The command code is returned, as described in <brltty/brldefs.h>.  It
  is not transmitted to [4mbrltty[24m: it is up to the application to define
  the behavior, here cleanly exitting, as described below.

  The first parameter tells the lib to block until a key press is indeed
  read.


  [1m4.8.  Leaving tty control[0m

  Let's now leave the tty:



       ______________________________________________________________________
         fprintf(stderr,"Leaving tty... ");
         if (brlapi_leaveTty()>=0)
          fprintf(stderr,"Ok\n");
       ______________________________________________________________________



  But control of another tty can still be get for instance, by calling
  brlapi_getTty() again...


  [1m4.9.  Disconnecting from BrlAPI[0m

  Let's disconnect from [4mBrlAPI[24m:



  ______________________________________________________________________
   brlapi_closeConnection();
  ______________________________________________________________________



  The application can as well still need to connect to another server on
  another computer for instance, by calling
  brlapi_initializeConnection() again...


  [1m4.10.  Putting everything together...[0m



  ______________________________________________________________________
  #include <stdio.h>
  #include <stdlib.h>
  #include <brltty/brlapi.h>

  int main()
  {
   brl_keycode_t key;
   char *p,*c;
   int x, y;

  /* Connect to BrlAPI */
    if (brlapi_initializeConnection(NULL,NULL)<0)
    {
     brlapi_perror("brlapi_initializeConnection");
     exit(1);
    }

  /* Get driver id & name */
   p = brlapi_getDriverId();
   if (!p)
    brlapi_perror("brlapi_getDriverId");
   else
    printf("Driver id: %s\n",p);

   p = brlapi_getDriverName();
   if (!p)
    brlapi_perror("brlapi_getDriverName");
   else
    printf("Driver name: %s\n",p);

  /* Get display size */
   if (brlapi_getDisplaySize(&x, &y)<0)
    brlapi_perror("brlapi_getDisplaySize");
   else
    printf("Braille display has %d line%s of %d column%s\n",y,y>1?"s":"",x,x>1?"s":"");

  /* Try entering raw mode, immediately go out from raw mode */
   printf("Trying to enter in raw mode... ");
   if (brlapi_getRaw()<0)
    brlapi_perror("brlapi_getRaw");
   else {
    printf("Ok, leaving raw mode immediately\n");
    brlapi_leaveRaw();
   }

  /* Get tty control */
   printf("Taking control of the tty... ");
   if (brlapi_getTty(0,BRLCOMMANDS,NULL)>=0)
   {
    printf("Ok\n");

  /* Write something on the display */
    fprintf(stderr,"Writing to braille display... ");
    if (brlapi_writeBrl(0,"Press a braille key to continue...")>=0)
    {
     fprintf(stderr,"Ok\n");

  /* Wait for a key press */
     fprintf(stderr,"Waiting until a braille key is pressed to continue... ");
     if (brlapi_readCommand(1,&key)>0)
      fprintf(stderr,"got it! (code=%d)\n",key);
     else brlapi_perror("brlapi_readCommand");

    } else brlapi_perror("brlapi_writeBrl");

  /* Leave tty control */
    fprintf(stderr,"Leaving tty... ");
    if (brlapi_leaveTty()>=0)
     fprintf(stderr,"Ok\n");
    else brlapi_perror("brlapi_leaveTty");

   } else brlapi_perror("brlapi_getTty");

  /* Disconnect from BrlAPI */
   brlapi_closeConnection();
   return 0;
  }
  ______________________________________________________________________



  This should compile well thanks to gcc apiclient.c -o apiclient
  -lbrlapi


  [1m5.  Writing ( BrlAPI -compliant) drivers for brltty[0m

  In this chapter, we will describe in details how to write a driver for
  [4mbrltty[24m. We begin with a general description of the structure the
  driver should have, before explaining more precisely what each
  function is supposed to do.


  [1m5.1.  Overview of the driver's structure[0m

  A braille driver is in fact a library that is either dynamically
  loaded by [4mbrltty[24m at startup, or statically linked to it during the
  compilation, depending on the options given to the ./configure script.

  This library has to provide every function needed by the core, plus
  some additional functions, that are not mandatory, but which improve
  communication with [4mBrlAPI[24m and the service level provided to client
  applications.

  Basically, a driver library needs to provide a function to open the
  communication with the braille terminal, one to close this
  communication, one to read key codes from the braille keyboard, and
  one to write text on the braille display. As we will see in a moment,
  other functions are required.

  Moreover, a driver can provide additional functionalities, by defining
  some macros asserting that it has these functionalities, and by
  defining associated functions.


  [1m5.2.  Basic driver structure[0m

  [4mEvery[24m [4mbrltty[24m driver [4mmust[24m consist in at least a file called braille.c,
  located in an appropriate subdirectory of the Drivers subdirectory.
  This braille.c file must have the following layout



      #ifdef HAVE_CONFIG_H
      #include "config.h"
      #endif /* HAVE_CONFIG_H */
      /* Include standard C headers */
      #include "Programs/brl.h"
      #include "Programs/misc.h"
      #include "Programs/scr.h"
      #include "Programs/message.h"
      /* Include other files */

      static void brl_identify() { }

      static int brl_open(BrailleDisplay *brl, char **parameters, const char *tty) { ... }

      static void brl_close(BrailleDisplay *brl) { ... }

      static void brl_writeWindow(BrailleDisplay *brl) { ... }

      static void brl_writeStatus(BrailleDisplay *brl) { ... }

      static int brl_readCommand(BrailleDisplay *brl, DriverCommandContext context) { ... }



  Before giving a detailed description of what each function is supposed
  to do, we define the BrailleDisplay structure, since each function has
  an argument of type BrailleDisplay *. The BrailleDisplay structure is
  defined like this:


      typedef struct {

        int x, y; /* The dimensions of the display */

        int helpPage; /* The page number within the help file */

        unsigned char *buffer; /* The contents of the display */

        unsigned isCoreBuffer:1; /* The core allocated the buffer */

        unsigned resizeRequired:1; /* The display size has changed */

        unsigned int writeDelay;

        void (*bufferResized)(int rows, int columns);

      } BrailleDisplay;



  We now describe each function's semantics and calling convention.

  The brl_identify() function takes no argument and returns nothing. It
  is called as soon as the driver is loaded, and its purpose is to print
  some information about the driver in the system log. To achieve this,
  the only thing this function has to do is to call LOG_PRINT with
  appropriate arguments (log level and string to put in the syslog).

  The brl_open() function takes 3 arguments and returns an int. Its
  purpose is to initialize the communication with the braille terminal.
  Generally, this function has to open the file referred to by the tty
  argument, and to configure the associated communication port. The
  parameters argument contains parameters passed to the driver with the
  -B command-line option. It's up to the driver's author to decide
  wether or not he/she wants to use this argument, and what for. The
  function can perform some additional tasks such as trying to identify
  precisely which braille terminal model is connected to the computer,
  by sending it a request and analyzing its answer. The value that is
  finally returned depends on the success of the initialization process.
  If it fails, th function has to return -1. The function returns 0 on
  success.

  The brl_close() function takes just one argument, and returns nothing.
  The name of this function should be self-explanatory; it's goal is to
  close (finish) the communication between the computer and the braille
  terminal. In general, the only thing this function has to do is to
  close the file descriptor associated to the braille terminal's
  communication port.

  The brl_writeWindow() function takes just one argument of type
  BrailleDisplay, and returns nothing. This function displays the
  specified text on the braille window. This routine is the right place
  to check if the text that has to be displayed is not already on the
  braille display, to send it only if necessary. More generally, if the
  braille terminal supports partial refresh of the display, the calculus
  of what exactly has to be sent to the braille display to have a proper
  display, according to what was previously displayed should be done in
  this function.

  The brl_writeStatus() function is very similar to brl_writeWindow().
  The only difference is that whereas brl_writeWindow() writes on the
  main braille display, brl_writeStatus() writes on an auxiliary braille
  display, which occasionaly appears on some braille terminals. The
  remarks that have been done concerning optimizations for refreshing
  the display still apply here.

  The brl_readCommand() function takes two arguments, and returns an
  integer. Its purpose is to read commands from the braille keyboard and
  to pass them to [4mbrltty[24m's core, which in turn will process them.  The
  first argument, of type BrailleDisplay, is for future use, and can
  safely be ignored for the moment. The second argument indicates in
  which context (state) [4mbrltty[24m is. For instance, it specifies if [4mbrltty[0m
  is in a menu, displays a help screen, etc. This information can indeed
  be of some interest when translating a key into a command, especially
  if the keys can have different meanings, depending on the context. So,
  this function has to read keypresses from the braille keyboard, and to
  convert them into commands, according to the given context, these
  commands then being returned to [4mbrltty[24m. For a complete list of
  available command codes, please have a look at brl.h in the Programs
  subdirectory. Two codes have special meanings:



     [1meof[0m
        specifies that no command is available now, and that no key is
        waiting to be converted into command in a near future.


     [1mCMD_NOOP[0m
        specifies that no command is available, but that one will be,
        soon. As a consequence, brl_readCommand will be called again
        immediately. Returning CMD_NOOP is appropriate for instance when
        a key is composed of two consecutive data packets.  When the
        first of them is received, one can expect that the second will
        arrive quickly, so that trying to read it as soon as possible is
        a good idea.



  [1m5.3.  Enhancements for BrlAPI[0m

  To improve the level of service provided to client applications
  communicating with braille drivers through [4mBrlAPI[24m, the drivers should
  declare some additional functions that will then be called by the API
  when needed.

  For each additional feature that has to be implemented in a driver, a
  specific macro must be defined, in addition to the functions
  implementing that feature. For the moment, two features are supported
  by [4mBrlAPI[24m:


    reading braille terminal specific key codes,

    exchanging raw data packets between the braille terminal and a
     client application running on the PC.

  For each feature presented below, only a short description of each
  concerned macro and function will be given. For a more complete
  description of concepts used here, please refer to previous chapters.


  [1m5.3.1.  Reading braille key codes[0m

  When a client takes control of a tty and asks for getting raw key
  codes, it has, like in command mode, the possibility to mask some
  keys. The masked keys will then be passed to [4mbrltty[24m. This assumes the
  existence of a conversion mechanism from key codes to [4mbrltty[24m commands.
  This conversion mechanism can only be implemented by the braille
  driver, since it is the only piece of code that knows about braille
  terminal specific key codes. So, to make it possible for client
  applications to read raw key codes, the driver has to define the
  following macro:

  #define BRL_HAVE_KEY_CODES


  and the following functions:

  static int brl_readKey(BrailleDisplay *)
  int brl_keyToCommand(BrailleDisplay *brl, DriverCommandContext caller, int code)



  The semantics of brl_readKey() is very similar to brl_readCommand()'s,
  with one essential difference: a key code is not context-dependant, so
  no context argument needs to be given to this function. Moreover, the
  code this function returns is driver-specific, and has to be properly
  defined by the driver's author so that client applications can rely on
  it.

  The brl_keyToCommand() function's purpose is to convert a key code as
  delivered by brl_readKey() into a [4mbrltty[24m command. As explained above,
  this function is called by brlapi when a key is pressed on the braille
  keyboard that is ignored by the client application. The corresponding
  command is then returned to [4mbrltty[24m.


  [1m5.3.1.1.  Remarks[0m

  When these two functions are present, the only thing brl_readCommand()
  has to do is to call brl_readKey() and then call brl_keyToCommand()
  with the value returned by the first function as argument.


  [1m5.3.2.  Exchanging raw data packets[0m

  Under some circumstances, an application running on the PC can be
  interested in a raw level communication with the braille terminal. For
  instance, to implement a file transfer protocol, commands to display
  braille or to read keys are not enough. In such a case, one must have
  a way to send raw data to the terminal, and to receive them from it.

  A driver that wants to provide such a mechanism has to define three
  functions: one to send packets, another one to receive them, and the
  last one to reset the communication when problems occur.

  The macro that declares that a driver is able to transmit packets is:


  #define BRL_HAVE_PACKET_IO



  The prototypes of the functions the driver should define are:


  static int brl_writePacket(BrailleDisplay *brl, const unsigned char *packet, int size);
  static int brl_readPacket(BrailleDisplay *brl, unsigned char *p, int size);
  static void brl_rescue(BrailleDisplay *brl)



  brl_writePacket() sends a packet of size bytes, stored at packet, to
  the braille terminal. If the communication protocol allows to
  determined if a packet has been send properly (e.g. the terminal sends
  back an acknowledgement for each packet he receives), then this
  function should wait the acknowledgement, and, if it is not received,
  retransmission of the packet should take place.

  brl_readPacket() reads a packet of at most size bytes, and stores it
  at the specified address. The read must not block. I.e., if no packet
  is available, the function should return immediately, returning 0.

  brl_rescue() is called by [4mBrlAPI[24m when a client application terminates
  without properly leaving the raw mode. This function should restore
  the terminal's state, so that it is able to display text in braille
  again.


  [1m5.3.2.1.  Remarks.[0m


    If the driver provides such functions, every other functions should
     use them, instead of trying to communicate directly with the
     braille terminal. For instance, readCommand() should call
     readPacket(), and then extract a key from the packet, rather than
     reading directly from the communication port's file descriptor. The
     same applies for brl_writeWindow(), which should use
     brl_writePacket(), rather than writing on the communication port's
     file descriptor.

    For the moment, the argument of type BrailleDisplay can safely be
     ignored by the functions described here.


  [1m6.  Protocol reference[0m

  Under some circumstances, it may be preferable to communicate directly
  with [4mBrlAPI[24m's server.avoid rather than using [4mBrlAPI[24m's library. Here
  are the needed details to be able to do this. This chapter is also of
  interest if a precise understanding of how the communication stuff
  works is desired, to be sure to understand how to write multithreaded
  clients, for instance.


  In all the following, [4minteger[24m will mean an unsigned 32 bits integer in
  network byte order (ie most significant bytes first).


  [1m6.1.  Reliable packet transmission channel[0m

  The protocol between [4mBrlAPI[24m's server and clients is based on exchanges
  of packets. So as to avoid locks due to packet loss, these exchanges
  are supposed reliable, and ordering must be preserved, thus [4mBrlAPI[0m
  needs a reliable packet transmission channel.


  To achieve this, [4mBrlAPI[24m uses a TCP-based connection, on which packets
  are transmitted this way:


    the size in bytes of the packet is transmitted first as an integer,

    then the type of the packet, as an integer,

    and finally the packet data.


  The size does not include the { size, type } header, so that packets
  which don't need any data have a size of 0 byte. The type of the
  packet can be either of BRLPACKET_* constants defined in brlapi.h.
  Each type of packet will be further discussed below.


  [4mBrlAPI[24m's library ships two functions to achieve packets sending and
  receiving using this protocol: brlapi_writePacket and
  brlapi_readPacket. It is a good idea to use instead of rewriting them,
  since this protocol might change one day in favor of a real reliable
  packet transmission protocol such as the experimental RDP.


  [1m6.2.  Responses from the server[0m

  As described below, many packets are `acknowledged'. It means that
  upon reception, the server sends either:


    a BRLPACKET_ACK packet, with no data, which means the operation
     corresponding to the received packet was successful,

    or a BRLPACKET_ERROR packet, the data being an integer which should
     be one of BRLERR_* constants. This means the operation
     corresponding to the received packet failed.


  Some other packets need some information as a response.  Upon
  reception, the server will send either:


    a packet of the same type, its data being the response,

    or a BRLPACKET_ERROR packet.



  [1m6.3.  Operating modes[0m

  The connection between the client and the server can be in either of
  the four following modes:


    authentication mode: this is the initial mode, when the client
     hasn't authenticated itself to the server yet. Only one
     BRLPACKET_AUTHKEY packet will be accepted, which makes the
     connection enter normal mode;


    normal mode: the client is authenticated, but didn't ask for a tty
     or raw mode. The client can send either of these types of packet:

       BRLPACKET_GETDRIVERID, BRLPACKET_GETDRIVERNAME or
        BRLPACKET_GETDISPLAYSIZE to get pieces of information from the
        server,

       BRLPACKET_GETTTY to enter tty handling mode,

       BRLPACKET_GETRAW to enter raw mode,

       BRLPACKET_BYE to tell the server it wants to close the
        connection.
     ;


    tty handling mode: the client holds the control of a tty: [4mbrltty[0m
     has no power on it any more, masked keys excepted. It's up to the
     client to manage display and keypresses. For this, it can send
     either of these types of packet:

       BRLPACKET_GETTTY to switch to another tty, but how key presses
        should be sent mustn't change,

       BRLPACKET_LEAVETTY to leave tty handling mode and go back to
        normal mode,

       BRLPACKET_MASKKEY or BRLPACKET_UNMASKKEY to mask and unmask
        keys,

       BRLPACKET_WRITE or BRLPACKET_STATUSWRITE to display text on this
        tty,

       BRLPACKET_GETRAW to enter raw mode,

       BRLPACKET_GETDRIVERID, BRLPACKET_GETDRIVERNAME or
        BRLPACKET_GETDISPLAYSIZE to get pieces of information from the
        server,

       BRLPACKET_BYE to tell the server it wants to close the
        connection.

     And the server might send either BRLPACKET_KEY or BRLPACKET_COMMAND
     packets to signal key presses;


    raw mode: the client wants to exchange packets directly with the
     braille terminal. Only these types of packet will be accepted:

       BRLPACKET_LEAVERAW to get back to previous mode, either normal
        or tty handling mode.

       BRLPACKET_PACKET to send a packet to the braille terminal.

       BRLPACKET_BYE to tell the server it wants to close the
        connection.

     And the server might send BRLPACKET_PACKET packets to give received
     packets from the terminal to the client.


  [1m6.4.  Details for each type of packet[0m

  Here is described the semantics of each type of packet. Most of them
  are directly linked to some of [4mBrlAPI[24m's library's functions. Reading
  their online manual page as well will hence be of good help for
  understanding.


  [1m6.4.1.  BRLPACKET_AUTHKEY  (see brlapi_loadAuthKey() )[0m

  This must be the first packet ever transmitted from the client to the
  server. It lets the client authenticate itself to the server. Data is
  the authentication key itself.

  If the authentication key matches the servers', it is acknowledged,
  and other types of packets might be used, other BRLPACKET_AUTHKEY
  shouldn't be sent by the client.

  If the authentication key doesn't match, the server sends a
  BRLERR_CONNREFUSED and closes the connection.


  [1m6.4.2.  BRLPACKET_BYE  (see brlapi_closeConnection() )[0m

  This should be sent by the client when it doesn't need server's
  services any more, just before disconnecting from it. The server will
  acknowledge this packet and close the connection. It will also clean
  up things like the tty which was got by the application, as well as
  raw mode, by sending a special reset event to the braille device, if
  the brltty driver implements it. But this shouldn't prevent clients
  from cleanly leaving ttys and raw mode before issuing BRLPACKET_BYE !


  [1m6.4.3.  BRLPACKET_GETDRIVERID  (see brlapi_getDriverId() )[0m

  This should be sent by the client when it needs the 2-char identifier
  of the current brltty driver. The returned string is \0 terminated.


  [1m6.4.4.  BRLPACKET_GETDRIVERNAME  (see brlapi_getDriverName() )[0m

  This should be sent by the client when it needs the full name of the
  current brltty driver. The returned string is \0 terminated.


  [1m6.4.5.  BRLPACKET_GETDISPLAYSIZE  (see brlapi_getDisplaySize() )[0m

  This should be sent by the client when it needs to know the braille
  display size. The returned data are two integers: width and then
  height.


  [1m6.4.6.  BRLPACKET_GETTTY  (see brlapi_getTty() )[0m

  This should be sent by the client to get control of a tty. Sent data
  are two integers: the number of the tty to get control of (it mustn't
  be 0), and how key presses should be sent: either BRLKEYCODES or
  BRLCOMMANDS.  This packet is then acknowledged by the server.

  [1m6.4.7.  BRLPACKET_KEY  and BRLPACKET_COMMAND  (see brlapi_readKey()[0m
  [1mand brlapi_readCommand() )[0m

  As soon as the client got a tty, it must be prepared to handle either
  BRLPACKET_KEY or BRLPACKET_COMMAND incoming packets (depending on the
  parameter given in the BRLPACKET_GETTTY packet), at any time (as soon
  as the key was pressed on the braille terminal, hopefuly).  The data
  holds the key press code as an integer, either a raw key code in
  BRLPACKET_KEY packets, or a brltty command code in BRLPACKET_COMMAND
  packets.


  [1m6.4.8.  BRLPACKET_LEAVETTY  (see brlapi_leaveTty() )[0m

  This should be sent to free the tty and masked keys lists.  This is
  acknowledged by the server.


  [1m6.4.9.  BRLPACKET_MASKKEYS  and BRLPACKET_UNMASKKEYS  (see[0m
  [1mbrlapi_ignoreKeys()  and brlapi_unignoreKeys() )[0m

  If the client doesn't want every key press to be signaled to it, but
  some of them to be given to brltty for normal processing, it can send
  BRLPACKET_MASKKEYS packets to tell ranges of key codes which shouldn't
  be sent to it, but given to brltty, and BRLPACKET_UNMASKKEYS packets
  to tell ranges of key codes which should be sent to it, and not given
  to brltty. The server keeps a dynamic list of ranges, so that
  arbitrary sequences of such packets can be sent. Data are 2 integers:
  the lower and the upper boundaries; lower and upper must be equal to
  tell one key, for instance.


  [1m6.4.10.  BRLPACKET_WRITE  (see brlapi_writeBrl() )[0m

  To display text on the braille terminal and set the position of the
  cursor, the client can send a BRLPACKET_WRITE packet. This packet
  holds the cursor position as an integer, and then the text to display,
  one byte per caracter.  The text must exactly fit the braille display,
  ie hold [4mheight[24m*[4mwidth[24m bytes, where [4mheight[24m and [4mwidth[24m must be get by
  sending a BRLPACKET_GETDISPLAYSIZE packet. Moreover, characters are
  expected to be encoded in latin-1. This packet is acknowledged by the
  server.


  [1m6.4.11.  BRLPACKET_WRITEDOTS  (see brlapi_writeBrlDots() )[0m

  Is used the same way as BRLPACKET_WRITE, the only difference being
  that characters are encoded in braille dots.


  [1m6.4.12.  BRLPACKET_STATWRITE[0m

  Some braille terminals have a special status display, whose text is
  independant from normal display's. To display text on it, the client
  can send a BRLPACKET_STATWRITE packet, just like BRLPACKET_WRITE
  packets.


  [1m6.4.13.  BRLPACKET_STATWRITEDOTS[0m

  Is used the same way as BRLPACKET_STATWRITE, the only difference being
  that characters are encoded in braille dots.



  [1m6.4.14.  BRLPACKET_GETRAW  (see brlapi_getRaw() )[0m

  To enter raw mode, the client must send a BRLPACKET_GETRAW packet,
  which is acknowledged. Once in raw mode, no other packet than
  BRLPACKET_LEAVERAW or BRLPACKET_PACKET will be accepted. The data must
  hold the special value BRLRAW_MAGIC: 0xdeadbeef, to avoid erroneous
  raw mode activating.


  [1m6.4.15.  BRLPACKET_LEAVERAW  (see brlapi_leaveRaw() )[0m

  To leave raw mode, the client must send a BRLPACKET_LEAVERAW packet,
  which is acknowledged.


  [1m6.4.16.  BRLPACKET_PACKET  (see brlapi_sendRaw()  and brlapi_recvRaw()[0m
  [1m)[0m

  While in raw mode, only BRLPACKET_PACKET packets can be exchanged
  between the client and the server: to send a packet to the braille
  terminal, the client merely sends a BRLPACKET_PACKET packet, its data
  being the packet to send to the terminal. Whenever its receives a
  packet from the terminal, the server does exactly the same, so that
  packet exchanges between the terminal and the server are exactly
  reproduced between the server and the client.

  Packets' content depend on the braille driver, so that the client
  should check for its id or name thanks to a BRLPACKET_GETDRIVERID
  packet or a BRLPACKET_GETDRIVERNAME packet, prior to sending any
  BRLPACKET_GETRAW packet.



