| <!doctype linuxdoc system> |
| <article> |
| <title>BrlAPI Reference manual |
| <author> |
| <name>Sébastien Hinderer <tt><htmlurl |
| url="mailto:Sebastien.Hinderer@ens-lyon.org" |
| name="<Sebastien.Hinderer@ens-lyon.org>"></tt><newline></name> |
| <and> |
| <name>Samuel Thibault <tt><htmlurl url="mailto:Samuel.Thibault@ens-lyon.org" |
| name="<Samuel.Thibault@ens-lyon.org>"></tt><newline></name> |
| </author> |
| <date>V1.5, November 2019 |
| <abstract> |
| This document describes <tt>BrlAPI</tt>. |
| </abstract> |
| <toc> |
| |
| <!-- rappel des attributs: |
| <bf/gras/ <em/mis en valeur/ <sf/sans serif/ <sl/slanted/ <tt/machine à écrire |
| <it/italique |
| --> |
| |
| <!----> |
| <sect>Introduction<label id="sec-intro"> |
| <!----> |
| <!-- Seb --> |
| <!-- an introduction explaining very briefly what BrlAPI does, the |
| vocabulary it uses, and how to read this documentation --> |
| <p><em/BrlAPI/ is a service provided by the <em/brltty/ 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 |
| <em/brltty/ 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 <em/brltty/. |
| |
| <sect1>Concepts |
| |
| <p> All throughout this manual, a few terms will be used which are either |
| specific to braille terminals, or introduced because of <em/BrlAPI/. They are defined |
| below. Taking a few minutes to go through this glossary will save a lot |
| of time and questions later. |
| |
| <descrip> |
| |
| <tag/Authorization key/ |
| 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. |
| |
| <tag/Braille display/ |
| The small screen on the braille terminal that is able to display braille text. |
| |
| <tag/Braille keyboard/ |
| The keyboard of the braille terminal. |
| |
| <tag/Braille terminal/ |
| 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. |
| |
| <tag/Brltty/ |
| The background process that gives a blind person access to the console screen |
| thanks to a braille terminal or speech synthetizer. |
| |
| <tag/Client/ |
| An application designed to handle a braille terminal thanks to <em/BrlAPI/. |
| |
| <tag/Command/ |
| A code returned by the driver, indicating an action to do, for instance |
| "go to previous line", "go to next line", etc. |
| |
| <tag/Driver/ |
| 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. |
| |
| <tag/Key/ |
| 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 <em/brltty/), whereas |
| codes used for returning keypresses may vary between drivers. |
| |
| <tag/BrlAPI's Library/ |
| This library helps clients to connect and use <em/BrlAPI/'s |
| server thanks to a series of <tt/brlapi_/-prefixed functions. |
| |
| <tag/Packet/ |
| A sequence of bytes making up the atomic unit in communications, either between |
| braille drivers and braille terminals or between the server and clients. |
| |
| <tag/Raw mode/ |
| 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. |
| |
| <tag/Server/ |
| The part of <em/brltty/ that controls incoming connections and communication |
| between clients and braille drivers. |
| |
| <tag/Suspend mode/ |
| Mode in which the server keeps the device driver closed, so that the client |
| can connect directly to the device. |
| |
| <tag/Tty/ |
| Synonym for console, terminal, ... Linux' console consist of several Virtual |
| Ttys (VTs). The screen program's windows also are Ttys. X-window system's |
| xterms emulate Ttys as well. |
| |
| </descrip> |
| |
| <sect1>How to read this manual |
| |
| <p>This manual is split in five parts. |
| |
| <descrip> |
| |
| <tag><ref id="sec-general" name="General description"></tag> |
| Describes more precisely what <em/BrlAPI/ |
| is and how it works in collaboration with <em/brltty/'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 <em/BrlAPI/ does in |
| reaction to client instructions. These explanations will take place at a |
| user level. |
| |
| <tag><ref id="sec-concurrency" name="Concurrency management"></tag> |
| This part explains how concurrency between <em/BrlAPI/ clients is handled |
| thanks to focus tellers. |
| |
| <tag><ref id="sec-install" name="Installation and configuration"></tag> |
| This part explains in detail how to install and configure the API. For |
| instructions on how to install and configure <em/brltty/, please report to |
| the <em/brltty/ documentation. |
| |
| <tag><ref id="sec-library" name="Library description"></tag> |
| This part describes how client applications |
| can communicate with the server using the <em/BrlAPI/ library that |
| comes with <em/brltty/. Each function will be briefly described, |
| classified by categories. More exhaustive descriptions of every |
| function are available in the corresponding online manual pages. |
| |
| <tag><ref id="sec-drivers" name="Writing braille drivers"></tag> |
| This part describes how the braille drivers included in <em/brltty/ should be |
| written in order to take advantage of <em/BrlAPI/'s services. |
| |
| <tag><ref id="sec-protocol" name="Protocol reference"></tag> |
| This part describes in detail the communication |
| protocol that is used to communicate between server and clients. |
| |
| </descrip> |
| |
| What should be read probably depends on what should be done by applications with |
| <em/BrlAPI/. |
| |
| Reading chapters <ref id="sec-general" name="General description">, <ref |
| id="sec-concurrency" name="Concurrency management"> and <ref id="sec-install" |
| name="Installation and configuration"> is recommended, since they provide |
| useful information and (hopefully) lead to a good understanding of <em/BrlAPI/, |
| for an efficient use. |
| |
| Chapter <ref id="sec-library" Name="Library description"> concerns writing |
| applications that take advantage of braille terminals so as to bring specific |
| (and more useful) information to blind people. |
| |
| Chapter <ref id="sec-drivers" Name="Drivers"> is for braille driver implementation: either adding a braille driver |
| to <em/brltty/ or modifying an existing one so that it can benefit from |
| <em/BrlAPI/'s features, this chapter will be of interest, since it describes |
| exactly what is needed to write a driver for <em/brltty/: the core |
| of drivers interface for instance. |
| |
| Finally, chapter <ref id="sec-protocol" Name="Protocol reference"> is for <em/not using/ the library, but using the <em/BrlAPI/ |
| server directly, when the library might not be sufficient: it describes the |
| underlying protocol that will have to be used to do so. |
| |
| <!----> |
| <sect>General description of <em/BrlAPI/<label id="sec-general"> |
| <!----> |
| <!-- a general documentation, which explains the issue and the design we |
| chose to handle it --> |
| |
| <p>Here is explained what <em/BrlAPI/ is, and what it precisely does. |
| These explanations should be simple enough to be accessible to every user. |
| For a more technical review of <em/BrlAPI/'s functionalities, please see chapter |
| <ref id="sec-library" name="Libary description">. |
| |
| <sect1>Historical notes. |
| |
| <p>Originally, <em/brltty/ 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 <em/BrlAPI/ is to propose an efficient communication |
| mechanism, to control the braille display, read keys from the |
| braille keyboard, or to exchange data with the braille terminal at |
| a lower level (e.g. to write file transfer protocols between |
| braille terminals and Linux systems). |
| |
| <sect1>Why <em/BrlAPI/ is part of <em/brltty/. |
| |
| <p>Instead of rewriting a whole communication program from |
| scratch, we chose to add communication |
| mechanisms to <em/brltty/. This choice has two main justifications. |
| |
| On the one hand, integration to <em/brltty/ allows us to use the |
| increasing number of drivers written for <em/brltty/, 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, |
| <em/brltty/ 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 <em/brltty/ |
| and client applications possible, it seemed easier to add the |
| communication mechanisms to <em/brltty/'s core, instead of writing an |
| external program providing them. |
| |
| <sect1>How it works. |
| |
| <p>We are now going to describe the steps an application should |
| go through to get control of the braille terminal, and what |
| happens on <em/brltty/'s side at each step. This step-by-step |
| description will let us introduce more precisely some |
| concepts that are useful for every <em/BrlAPI/ user. |
| |
| <sect2>Connection. |
| |
| <p>The first thing any client application has to do is to |
| connect (in the Unix sense of the word) to <em/BrlAPI/ 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 <em/brltty/'s |
| side. |
| |
| <sect2>Authorization. |
| |
| <p>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 <em/BrlAPI/ 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, <em/BrlAPI/ requires that each |
| application that wants to control a braille terminal sends an |
| authorization key before doing anything else. The control of |
| the braille terminal will only be possible for the client once |
| it has sent the proper authorization key. What is called |
| authorization 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 |
| authorization key and then be able to send it to <em/BrlAPI/. |
| To see how to do that, please see chapter <ref id="sec-install" name="Installation and configuration">. |
| |
| At the end of this step, the user is authorized to take |
| control of the braille terminal. On <em/brltty/'s side, some data |
| structures are allocated to store information on the client, |
| but this has no user-level side-effect. |
| |
| <sect2>Real use of the braille terminal. |
| |
| <p>Once the client is properly connected and authorized, |
| 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". |
| |
| <sect3>Braille display and braille key presses processing. |
| |
| <p>If the client wants to display something on the braille |
| display or to process braille keys itself, rather than letting |
| <em/brltty/ process them, it has to take control of the Linux |
| terminal it is running on. |
| |
| Once a client has obtained the control of his tty, <em/BrlAPI/ |
| will completely discard <em/brltty/'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, <em/BrlAPI/ 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 <em/brltty/ command. If it is not, the |
| key code is converted into a <em/brltty/ command and returned to |
| <em/brltty/. |
| |
| Once the client is not interested in displaying text |
| or reading braille keys any more, it has to leave the tty, so |
| that either <em/brltty/ can continue its job, or another client can |
| take control of it. |
| |
| <sect3>Parameter handling |
| |
| The server exposes some parameters to the client. Some parameters are global to |
| all clients (e.g. the braille display size), while others are local per client |
| (e.g. retaindots, i.e. whether to send Perkins presses as dot patterns or as |
| letters). Some parameters are read-only (e.g. the braille display size), while |
| others are read-write (e.g. retaindots). Some parameters may change during |
| execution, while others change only when a client set it. |
| |
| Clients can either request the current value of a parameter, or set its value |
| (if it is read-write), or request the server to notify on value change. |
| |
| <sect3>Raw mode. |
| |
| <p>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 <em/BrlAPI/ 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. |
| |
| <sect3>Suspend Mode. |
| |
| <p>Only one client can be in suspend mode at the same time. This mode is also |
| exclusive with raw mode. In this mode, the server keeps the device driver |
| closed, and thus the client can open the device directly by itself. |
| |
| <p><bf/This mode is not recommended/, since the client will then have to |
| reimplement device access. Raw mode should really be preferred, since it lets |
| the client take advantage of server's ability to talk with the device |
| (USB/bluetooth support for instance). |
| |
| <sect3>Remarks. |
| |
| <p> |
| |
| <itemize> |
| |
| <item>The operations described in the three previous |
| subsections are not completely mutually exclusive. An |
| application that controls its current tty can enter raw or suspend |
| mode, provided that no other application already is in this |
| mode. |
| |
| <item>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. |
| |
| <item>Operations previously described 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 <em/BrlAPI/ before |
| each operation. |
| |
| </itemize> |
| |
| <sect2>Disconnection. |
| |
| <p>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. |
| |
| |
| <!----> |
| <sect>Concurrency management between <em/BrlAPI/ clients<label id="sec-concurrency"> |
| <!----> |
| <!-- Sam --> |
| <!-- explain focus tellers, tty tree, & co --> |
| |
| <p> |
| An essential purpose of <em/BrlAPI/ is to manage concurrent access to the |
| braille display between the <em/brltty/ daemon and applications. This |
| concurrency is managed "per Tty". We first describe this with a flat view, and |
| then consider Tty hierarchy. |
| |
| <sect1>VT switching |
| |
| <p> |
| Let's first describe how things work with the simple case of a single series of |
| Virtual Ttys (VTs), the linux console for instance. |
| |
| <p> |
| As described in <ref id="sec-general" name="General Description">, before being able |
| to write output, a <em/BrlAPI/ client has to "get" a tty, i.e. it sends to the |
| <em/BrlAPI/ server the number of the linux' Virtual Tty on which it is running. |
| The <em/BrlAPI/ server uses this information so as to know which client's output |
| should be shown on the braille display, according to the focus teller's |
| information. |
| |
| <p> |
| Let's say some client <em/A/ is running on VT 2. It "got" VT 2 and wrote some |
| output on its <em/BrlAPI/ connection. The focus teller is <em/brltty/ here: it |
| always tells to the <em/BrlAPI/ server which VT is currently shown on the screen |
| and gets usual keyboard presses (it is "active"). |
| |
| <p> |
| Let's say VT 1 is active, then the <em/BrlAPI/ server shows <em/brltty/'s output |
| on the braille display. I.e. the usual <em/brltty/ screen reading appears. |
| Moreover, when braille keys are pressed, they are passed to <em/brltty/, so that |
| usual screen reading can be performed. When the user switches to VT 2, |
| <em/brltty/ (as focus teller) tells it to the <em/BrlAPI/ server, which then |
| remembers that client <em/A/ has got it and has produced some output. The |
| server then displays this output on the braille display. Note that <em/A/ |
| doesn't need to re-submit its output: the server had recorded it so as to be |
| able to show it as soon as the focus switches to VT 2. Whenever some key of the |
| braille device is pressed, <em/BrlAPI/ looks whether it is in the list of keys |
| that client <em/A/ said to be of his interest. If it is, it is passed to <em/A/ |
| (and not to <em/brltty/). If it isn't, it is passed to <em/brltty/ (and not to |
| <em/A/). |
| |
| <p> |
| As a consequence, whenever clients get and release Ttys and the user switches |
| between Ttys, either the <em/brltty/ screen reading or the client's output is |
| automatically shown according to rather natural rules. |
| |
| <sect1>A pile of "paper sheets" |
| |
| <p> |
| Let's look at VT 2 by itself. What is shown on the braille display can be seen |
| as the result of a pile of two paper sheets. <em/brltty/ is represented by the |
| bottom sheet on which its screen reading is written, and client <em/A/ by the |
| top sheet on which its output is written. <em/A/'s sheet hence "covers" |
| <em/brltty/'s sheet: <em/A/'s output "mask" <em/brltty/'s screen reading. |
| |
| <p> |
| <em/A/ may yet want to temporarily let <em/brltty/'s screen reading appear on VT |
| 2, while still receiving some key presses, for instance. For this, it sends a |
| "void" write. The server then clears the recorded output for this connection |
| (in the sheet representation, the sheet becomes "transparent"). As a |
| consequence, <em/brltty/'s output is automatically shown (by transparency in the |
| sheet representation), just like if <em/A/ had released the Tty. |
| |
| <p> |
| Keypresses are handled in a similar way: <em/A/'s desire to get key presses is |
| satisfied first before <em/brltty/. |
| |
| <p> |
| Let's say some other client <em/B/ (probably launched by <em/A/) also gets VT 2 |
| and outputs some text on its <em/BrlAPI/ connection. This adds a third sheet, |
| on top of the two previous ones. It means that the <em/BrlAPI/ server will show |
| <em/B/'s output on the braille device. If <em/A/ then outputs some text, the |
| server will record it (on <em/A/'s sheet which hence becomes opaque again), but |
| it won't be displayed on the braille device, since <em/B/'s sheet is still at |
| the top and opaque (i.e. with some text on it). But if <em/B/ issues a void |
| write, the server clears its ouput buffer (i.e. <em/B/'s sheet becomes |
| transparent), and as a result <em/A/'s output appear on the braille display (by |
| transparency through <em/B/'s sheet). |
| |
| <p> |
| The sheet order is by default determined by the Tty "get"ting order. Clients |
| can however change their priority (which by default is 50) to a higher value in |
| order to show up higher in the pile, or to a lower value in order to hide lower |
| in the pile. |
| |
| <sect1>Hierarchy |
| |
| <p> |
| Now, what happens when running some <em/screen/ program on, say, VT 3? It |
| emulates a series of Ttys, whose output actually appear on the same VT 3. |
| That's where a hierarchy level appears: the focus information is not only the VT |
| number but also, in the case of VT 3, which <em/screen/ window is active. This |
| hence forms a <em/tree/ of Ttys: the "root" being the vga driver's output, whose |
| sons are VTs, and VT 3 has the <em/screen/ windows as sons. <em/Brltty/ is a |
| focus teller for the root, <em/screen/ will have to be a focus teller for VT 3. |
| <em/Screen/ should then get VT 3, not display anything (so that the usual |
| <em/brltty/ screen reading will be shown by transparency), and tell the |
| <em/BrlAPI/ server which <em/screen/ window is active (at startup and at each |
| window switch). This is not implemented directly in <em/screen/ yet, but this |
| may be achieved via a second <em/brltty/ daemon running the Screen driver (but |
| it isn't yet able to get the current window number though) and the <em/BrlAPI/ |
| driver. |
| |
| <p> |
| A <em/BrlAPI/ client <em/C/ running in some <em/screen/ window number 1 would |
| then have to get the Tty path "VT 3 then window 1", which is merely expressed |
| as "3 1". The window number is available in the <tt/WINDOW/ environment |
| variable, set by <em/screen/. The VT number, which actually represents the "path |
| to screen's output" should be available in the <tt/WINDOWPATH/ environment |
| variable, also set by <em/screen/. The client can thus merely concatenate the |
| content of <tt/WINDOWPATH/ (which could hold many levels of window numbers) and |
| of <tt/WINDOW/ and give the result as tty path to the <em/BrlAPI/ server, which |
| then knows precisely where the client's usual output resides. In practice, |
| applications just need to call <tt/brlapi_enterTtyMode(BRLAPI_TTY_DEFAULT)/, and |
| the the <em/BrlAPI/ client library will automatically perform all that. |
| |
| <p> |
| Whenever the user switches to VT 3, the <em/BrlAPI/ server remembers the window |
| that <em/screen/ told to be active. If it was window 1, it then displays |
| <em/C/'s output (if any). Else <em/brltty/'s usual screen reading is shown. |
| Of course, several clients may be run in window 1 as well, and the "sheet pile" |
| mecanism applies: <em/brltty/'s sheet first (at the root of the Ttys tree), then |
| <em/screen/'s sheet (which is transparent, on VT 3), then <em/C/'s sheet (on |
| window 1 of VT 3), then other clients' sheets (on the same window). |
| |
| <p> |
| Ttys are hence organized in a tree, each client adding its sheet at some tty in |
| the tree. |
| |
| <sect1>The X-window case |
| |
| <p> |
| Let's say some X server is running on VT 7 of a Linux system. Xorg's <em/xinit/ |
| and <em/xdm/ commands automatically set the X session's <tt/WINDOWPATH/ |
| environment variable to "7", so that X11 <em/BrlAPI/ clients started from |
| the session just need to call <em/brlapi_enterTtyMode(xid)/ where <em/xid/ |
| is the X-window ID of the window of the client. The <em/BrlAPI/ library |
| will automatically prepend the content of <tt/WINDOWPATH/ to it. |
| |
| <p> |
| For text-based <em/BrlAPI/ clients running in an xterm (which should just call |
| <tt/brlapi_enterTtyMode(BRLAPI_TTY_DEFAULT)/ as explained in the previous |
| section), <em/BrlAPI/ detects the window id thanks to the <tt/WINDOWID/ variable |
| set by xterm. |
| |
| <p> |
| Screen readers are not bound to a particular window, so they should call |
| <em/brlapi_enterTtyModeWithPath(NULL, 0)/ to let the <em/BrlAPI/ library only |
| send the content of <tt/WINDOWPATH/, expressing that screen readers take the |
| whole tty. The user should notably launch <em/xbrlapi/, which is a focus |
| teller for X-window as well as a keyboard simulator (<em/brltty/ can't reliably |
| simulate them at the kernel level in such situation). For accessing AT-SPI |
| contents (like gnome or kde applications), Orca should also be launched. For |
| accessing AT-SPI terminals (like gnome-terminal) in the same way as in the |
| console, a second <em/brltty/ daemon running the at-spi screen driver and the |
| <em/BrlAPI/ driver can also be launched. All three would get the VT of the |
| X session, in that order (for now): <em/xbrlapi/ first, then <em/orca/ and |
| <em/brltty/ at last. When the X focus is on an AT-SPI terminal, <em/brltty/ |
| will hence be able to grab the braille display and key presses. Else <em/orca/ |
| would get them. And <em/xbrlapi/ would finally get remaining key presses and |
| simulate them. |
| |
| <p> |
| Note: old versions of <tt/xinit/, <tt/xdm/, <tt/kdm/ or <tt/gdm/ do not |
| automatically set the <tt/WINDOWPATH/ variable. The user can set it by hand in |
| his <tt>~/.xsession</tt>, <tt>~/.xinitrc</tt>, <tt>~/.gdmrc</tt>... to "7" |
| |
| <p> |
| Note: some Operating Systems like Solaris do not have VTs. In that case |
| <tt/WINDOWPATH/ is empty or not even set. Everything explained above still |
| work fine. |
| |
| <sect1>Detaching |
| |
| <p> |
| Several programs allow detaching: <em/screen/ and <em/VNC/ for instance. In such |
| situation, an intermediate <em/BrlAPI/ server should be run for each such |
| session. Clients would connect to it, and it would prepend the "current tty" |
| path on the fly while forwarding things to the root <em/BrlAPI/ server. This |
| intermediate server is yet to be written (but it is actually relatively close to |
| be). |
| |
| |
| <!----> |
| <sect>Installation and configuration of <em/BrlAPI/<label id="sec-install"> |
| <!----> |
| <!-- Seb --> |
| <!-- an installation and configuration documentation --> |
| <p> |
| <tt/make install/ will install libbrlapi.so in /lib, and include files in |
| /usr/include/brltty. An authorization key will also typically be set in |
| /etc/brlapi.key (if it is not, just create it and put arbitrary data in it), but |
| it won't be readable by anybody else than root. It is up |
| to you to define a group of users who will have the right to read it and hence |
| be able to connect to the server. For instance, you may want to do: |
| |
| <tscreen><code> |
| # addgroup brlapi |
| # chgrp brlapi /etc/brlapi.key |
| # chmod g+r /etc/brlapi.key |
| # addgroup user1 brlapi |
| # addgroup user2 brlapi |
| ... |
| </code></tscreen> |
| |
| |
| <!----> |
| <sect>Library description<label id="sec-library"> |
| <!----> |
| <!-- the library documentation, for those who want to write |
| applications which use it, it should be split in: --> |
| |
| <p> |
| 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. |
| |
| <!-- a basic documentation, which briefly shows |
| how one is supposed to use our library, with trivial examples --> |
| |
| <p> |
| The historical test program for <em/BrlAPI/ was something like: |
| <itemize> |
| <item>connect to <em/BrlAPI/ |
| <item>get driver id |
| <item>get driver name |
| <item>get display size |
| <item>try entering raw mode, immediately leave raw mode. |
| <item>get tty control |
| <item>write something on the display |
| <item>wait for a key press |
| <item>leave tty control |
| <item>disconnect from <em/BrlAPI/ |
| </itemize> |
| |
| It is here rewritten, its working briefly explained. |
| |
| <sect1>Connecting to <em/BrlAPI/ |
| |
| <p>Connection to <em/BrlAPI/ is needed first, thanks to the |
| <tt>brlapi_openConnection</tt> call. For this, a |
| <tt>brlapi_connectionSettings_t</tt> variable must be filled which will hold the |
| settings the library needs to connect to the server. Just giving <tt/NULL/ |
| will work for local use. The other parameter lets you get back the parameters |
| which were actually used to initialize connection. <tt/NULL/ will also be nice |
| for now. |
| |
| <tscreen><code> |
| if (brlapi_openConnection(NULL, NULL)<0) { |
| brlapi_perror("brlapi_openConnection"); |
| exit(1); |
| } |
| </code></tscreen> |
| |
| The connection might fail, so testing is needed. |
| |
| <sect1>Getting driver name |
| |
| <p>Knowing the type of the braille device might be useful: |
| |
| <tscreen><code> |
| char name[BRLAPI_MAXNAMELENGTH+1]; |
| if (brlapi_getDriverName(name, sizeof(name)) < 0) |
| brlapi_perror("brlapi_getDriverName"); |
| else |
| fprintf(stderr, "Driver name: %s\n", name); |
| </code></tscreen> |
| |
| 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. |
| |
| <sect1>Getting display size |
| |
| <p>Before writing on the braille display, the size should be always first |
| checked to be sure everything will hold on it: |
| |
| <tscreen><code> |
| if (brlapi_getDisplaySize(&x, &y) < 0) |
| brlapi_perror("brlapi_getDisplaySize"); |
| else |
| fprintf(stderr, "Braille display has %d line%s of %d column%s\n", |
| y, y>1?"s":"", x, x>1?"s":""); |
| </code></tscreen> |
| |
| <sect1>Entering raw mode, immediately leaving raw mode. |
| |
| <p>Entering raw mode is very simple: |
| |
| <tscreen><code> |
| fprintf(stderr, "Trying to enter in raw mode... "); |
| if (brlapi_enterRawMode(name) < 0) |
| brlapi_perror("brlapi_enterRawMode"); |
| else { |
| fprintf(stderr, "Ok, leaving raw mode immediately\n"); |
| brlapi_leaveRawMode(); |
| } |
| </code></tscreen> |
| |
| Not every driver supports raw mode, so testing is needed. |
| |
| While in raw mode, <tt>brlapi_sendRaw</tt> and <tt>brlapi_recvRaw</tt> |
| 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! |
| |
| <sect1>Getting tty control |
| |
| <p>Let's now display something on the device. control of the tty must be get |
| first: |
| |
| <tscreen><code> |
| fprintf(stderr, "Taking control of the tty... "); |
| if (brlapi_enterTtyMode(BRLAPI_TTY_DEFAULT, NULL) >= 0) |
| { |
| fprintf(stderr, "Ok\n"); |
| </code></tscreen> |
| |
| The first parameter tells the server the number of the tty to take |
| control of. Setting BRLAPI_TTY_DEFAULT lets the library determine it for us. |
| |
| <p>The server is asked to send <em/brltty/ commands, which are device-independent. |
| |
| <p>Getting control might fail if, for instance, another application already took |
| control of this tty, so testing is needed. |
| |
| <p>From now on, the braille display is detached from the screen. |
| |
| <sect1>Writing something on the display |
| |
| <p>The application can now write things on the braille display without |
| altering the screen display: |
| |
| <tscreen><code> |
| fprintf(stderr, "Writing to braille display... "); |
| if (brlapi_writeText(0, "Press a braille key to continue...") >= 0) |
| { |
| fprintf(stderr, "Ok\n"); |
| </code></tscreen> |
| |
| The cursor is also asked <em/not/ to be shown: its position is set to 0. |
| |
| <p>"Writing to braille display... Ok" is now displayed on the screen, and |
| "Press a braille key to continue..." on the braille display. |
| |
| <sect1>Waiting for a key press |
| |
| <p>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: |
| |
| <tscreen><code> |
| fprintf(stderr, "Waiting until a braille key is pressed to continue... "); |
| if (brlapi_readKey(1, &key) > 0) |
| fprintf(stderr, "got it! (code=%"BRLAPI_PRIxKEYCODE")\n", key); |
| </code></tscreen> |
| |
| The command is returned, as described in <tt><brlapi_constants.h></tt> |
| and <tt><brlapi_keycodes.h></tt>. |
| It is not transmitted to <em/brltty/: 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. |
| |
| <sect1>Understanding commands |
| |
| <p>There are two kinds of commands: braille commands (line up/down, top/bottom, |
| etc.) and X Keysyms (i.e. regular keyboard keys). One way to discover which key |
| was pressed is to just use a switch statement: |
| |
| <tscreen><code> |
| switch(key) { |
| case BRLAPI_KEY_TYPE_CMD|BRLAPI_KEY_CMD_LNUP: |
| fprintf(stderr, "line up\n"); |
| break; |
| case BRLAPI_KEY_TYPE_CMD|BRLAPI_KEY_CMD_LNDN: |
| fprintf(stderr, "line down\n"); |
| break; |
| case BRLAPI_KEY_TYPE_SYM|XK_Tab: |
| fprintf(stderr, "tab\n"); |
| break; |
| default: |
| fprintf(stderr, "unknown key\n"); |
| break; |
| } |
| </code></tscreen> |
| |
| Another way is to ask BrlAPI to expand the keycode into separate information |
| parts: |
| |
| <tscreen><code> |
| brlapi_expandedKeyCode_t ekey; |
| brlapi_expandKeyCode(key, &ekey); |
| fprintf(stderr, "type %u, command %u, argument %u, flags %u\n", |
| ekey.type, ekey.command, ekey.argument, ekey.flags); |
| </code></tscreen> |
| |
| Eventually, named equivalents are provided: |
| |
| <tscreen><code> |
| brlapi_describedKeyCode_t dkey; |
| int i; |
| |
| brlapi_describeKeyCode(key, &dkey); |
| fprintf(stderr, "type %s, command %s, argument %u, flags", |
| dkey.type, dkey.command, dkey.argument); |
| for (i = 0; i < dkey.flags; i++) |
| fprintf(stderr, " %s", dkey.flag[i]); |
| fprintf(stderr, "\n"); |
| </code></tscreen> |
| |
| |
| |
| |
| <sect1>Leaving tty control |
| |
| <p>Let's now leave the tty: |
| |
| <tscreen><code> |
| fprintf(stderr, "Leaving tty... "); |
| if (brlapi_leaveTtyMode() >= 0) |
| fprintf(stderr, "Ok\n"); |
| </code></tscreen> |
| |
| But control of another tty can still be get for instance, by calling |
| <tt>brlapi_enterTtyMode()</tt> again... |
| |
| <sect1>Disconnecting from <em/BrlAPI/ |
| |
| <p>Let's disconnect from <em/BrlAPI/: |
| |
| <tscreen><code> |
| brlapi_closeConnection(); |
| </code></tscreen> |
| |
| The application can as well still need to connect to another server on another |
| computer for instance, by calling <tt>brlapi_openConnection()</tt> |
| again... |
| |
| <sect1>Putting everything together... |
| |
| <p> |
| <tscreen><code> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <brlapi.h> |
| |
| int main() |
| { |
| brlapi_keyCode_t key; |
| char name[BRLAPI_MAXNAMELENGTH+1]; |
| unsigned int x, y; |
| |
| /* Connect to BrlAPI */ |
| if (brlapi_openConnection(NULL, NULL)<0) |
| { |
| brlapi_perror("brlapi_openConnection"); |
| exit(1); |
| } |
| |
| /* Get driver name */ |
| if (brlapi_getDriverName(name, sizeof(name)) < 0) |
| brlapi_perror("brlapi_getDriverName"); |
| else |
| fprintf(stderr, "Driver name: %s\n", name); |
| |
| /* Get display size */ |
| if (brlapi_getDisplaySize(&x, &y) < 0) |
| brlapi_perror("brlapi_getDisplaySize"); |
| else |
| fprintf(stderr, "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 */ |
| fprintf(stderr, "Trying to enter in raw mode... "); |
| if (brlapi_enterRawMode(name) < 0) |
| brlapi_perror("brlapi_enterRawMode"); |
| else { |
| fprintf(stderr, "Ok, leaving raw mode immediately\n"); |
| brlapi_leaveRawMode(); |
| } |
| |
| /* Get tty control */ |
| fprintf(stderr, "Taking control of the tty... "); |
| if (brlapi_enterTtyMode(BRLAPI_TTY_DEFAULT, NULL) >= 0) |
| { |
| fprintf(stderr, "Ok\n"); |
| |
| /* Write something on the display */ |
| fprintf(stderr, "Writing to braille display... "); |
| if (brlapi_writeText(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_readKey(1, &key) > 0) { |
| brlapi_expandedKeyCode_t ekey; |
| brlapi_describedKeyCode_t dkey; |
| int i; |
| |
| fprintf(stderr, "got it! (code=%"BRLAPI_PRIxKEYCODE")\n", key); |
| |
| brlapi_expandKeyCode(key, &ekey); |
| fprintf(stderr, "type %u, command %u, argument %u, flags %u\n", |
| ekey.type, ekey.command, ekey.argument, ekey.flags); |
| |
| brlapi_describeKeyCode(key, &dkey); |
| fprintf(stderr, "type %s, command %s, argument %u, flags", |
| dkey.type, dkey.command, dkey.argument); |
| for (i = 0; i < dkey.flags; i++) |
| fprintf(stderr, " %s", dkey.flag[i]); |
| fprintf(stderr, "\n"); |
| } else brlapi_perror("brlapi_readKey"); |
| |
| } else brlapi_perror("brlapi_writeText"); |
| |
| /* Leave tty control */ |
| fprintf(stderr, "Leaving tty... "); |
| if (brlapi_leaveTtyMode() >= 0) |
| fprintf(stderr, "Ok\n"); |
| else brlapi_perror("brlapi_leaveTtyMode"); |
| |
| } else brlapi_perror("brlapi_enterTtyMode"); |
| |
| /* Disconnect from BrlAPI */ |
| brlapi_closeConnection(); |
| return 0; |
| } |
| </code></tscreen> |
| |
| This should compile well thanks to |
| <tt>gcc apiclient.c -o apiclient -lbrlapi</tt> |
| |
| <!----> |
| <sect>Writing (<em/BrlAPI/-compliant) drivers for <em/brltty/<label id="sec-drivers"> |
| <!----> |
| <!-- Seb --> |
| |
| <p>In this chapter, we will describe in details how to write a |
| driver for <em/brltty/. We begin with a general description of the |
| structure the driver should have, before explaining more precisely |
| what each function is supposed to do. |
| |
| <sect1>Overview of the driver's structure |
| |
| <p>A braille driver is in fact a library that is either |
| dynamically loaded by <em/brltty/ at startup, or statically linked to |
| it during the compilation, depending on the options given to the |
| <tt>./configure</tt> 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 <em/BrlAPI/ 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. |
| |
| <sect1>Basic driver structure |
| |
| <p><em>Every</em> <em/brltty/ driver <em>must</em> consist in at least |
| a file called braille.c, located in an appropriate subdirectory of |
| the BrailleDrivers subdirectory. This braille.c file must have the |
| following layout |
| |
| <verb> |
| #include "prologue.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) { ... } |
| </verb> |
| |
| Before giving a detailed description of what each function is |
| supposed to do, we define the <tt>BrailleDisplay</tt> structure, |
| since each function has an argument of type <tt>BrailleDisplay |
| *</tt>. The <tt>BrailleDisplay</tt> structure is defined like this: |
| |
| <verb> |
| 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; |
| </verb> |
| |
| We now describe each function's semantics and calling |
| convention. |
| |
| The <tt/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 <tt/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 <tt/tty/ argument, and to configure the associated communication |
| port. The <tt/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 <tt/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 <tt/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 <tt/brl_writeStatus()/ function is very similar to <tt/brl_writeWindow()/. |
| The only difference is that whereas <tt/brl_writeWindow()/ writes on the |
| main braille display, <tt/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 <tt/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 <em/brltty/'s core, which in turn will process them. |
| The first argument, of type <tt/BrailleDisplay/, is for future use, and |
| can safely be ignored for the moment. The second argument indicates |
| in which context (state) <em/brltty/ is. For instance, it specifies if |
| <em/brltty/ 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 <em/brltty/. For a complete list of available command codes, please |
| have a look at <tt/brl.h/ in the Programs subdirectory. Two codes have special |
| meanings: |
| |
| <descrip> |
| |
| <tag/eof/ specifies that no command is available now, and that |
| no key is waiting to be converted into command in a near future. |
| |
| <tag/CMD_NOOP/ 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. |
| |
| </descrip> |
| |
| <sect1>Enhancements for <em/BrlAPI/ |
| |
| <p>To improve the level of service provided to client |
| applications communicating with braille drivers through <em/BrlAPI/, 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 <em/BrlAPI/: |
| |
| <itemize> |
| <item>reading braille terminal specific key codes, |
| |
| <item>exchanging raw data packets between the braille |
| terminal and a client application running on the PC. |
| </itemize> |
| |
| 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 chapters <ref id="sec-intro" name="Introduction"> and <ref id="sec-general" name="General description">. |
| |
| <sect2>Exchanging raw data packets |
| |
| <p>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: |
| |
| <verb> |
| #define BRL_HAVE_PACKET_IO |
| </verb> |
| |
| The prototypes of the functions the driver should define are: |
| |
| <verb> |
| 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) |
| </verb> |
| |
| <tt>brl_writePacket()</tt> sends a packet of <tt/size/ bytes, stored |
| at <tt/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. |
| |
| <tt>brl_readPacket()</tt> reads a packet of at most <tt/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. |
| |
| <tt>brl_rescue()</tt> is called by <em/BrlAPI/ 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. |
| |
| <sect3>Remarks. |
| |
| <p> |
| <itemize> |
| <item> If the driver provides such functions, every other |
| functions should use them, instead of trying to communicate |
| directly with the braille terminal. For instance, <tt/readCommand()/ |
| should call <tt/readPacket()/, and then extract a key from the packet, |
| rather than reading directly from the communication port's file |
| descriptor. The same applies for <tt/brl_writeWindow()/, which should |
| use <tt/brl_writePacket()/, rather than writing on the communication |
| port's file descriptor. |
| |
| <item> For the moment, the argument of type BrailleDisplay |
| can safely be ignored by the functions described here. |
| |
| </itemize> |
| |
| <!----> |
| <sect>Protocol reference<label id="sec-protocol"> |
| <!----> |
| <!-- a boring documentation, explaining the underlying protocol of the api |
| in detail --> |
| <p> |
| Under some circumstances, it may be preferable to communicate directly with |
| <em/BrlAPI/'s server rather than using <em/BrlAPI/'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. |
| |
| <p> |
| In all the following, <em/integer/ will mean an unsigned 32 bits integer in |
| network byte order (ie most significant bytes first). |
| |
| <sect1>Reliable packet transmission channel |
| |
| <p> |
| The protocol between <em/BrlAPI/'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 <em/BrlAPI/ needs |
| a reliable packet transmission channel. |
| |
| <p> |
| To achieve this, <em/BrlAPI/ uses a TCP-based connection, on which packets |
| are transmitted this way: |
| |
| <itemize> |
| <item>the size in bytes of the packet is transmitted first as an integer, |
| <item>then the type of the packet, as an integer, |
| <item>and finally the packet data. |
| </itemize> |
| |
| <p> |
| 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 <tt/BRLAPI_PACKET_*/ constants defined in <tt/api_protocol.h/. Each type of |
| packet will be further discussed below. |
| |
| <p> |
| <em/BrlAPI/'s library ships two functions to achieve packets sending and receiving |
| using this protocol: <tt/brlapi_writePacket/ and <tt/brlapi_readPacket/. It |
| is a good idea to use these functions rather than rewriting them, since this protocol |
| might change one day in favor of a real reliable packet transmission protocol |
| such as the experimental RDP. |
| |
| <sect1>Responses from the server |
| |
| <p> |
| As described below, many packets are `acknowledged'. It means that upon |
| reception, the server sends either: |
| |
| <itemize> |
| <item>a <tt/BRLAPI_PACKET_ACK/ packet, with no data, which means the operation |
| corresponding to the received packet was successful, |
| <item>or a <tt/BRLAPI_PACKET_ERROR/ packet, the data being an integer |
| which should be one of <tt/BRLAPI_ERROR_*/ constants. This |
| means the operation corresponding to the received packet failed. |
| </itemize> |
| |
| <p> |
| Some other packets need some information as a response. |
| Upon reception, the server will send either: |
| |
| <itemize> |
| <item>a packet of the same type, its data being the response, |
| <item>or a <tt/BRLAPI_PACKET_ERROR/ packet. |
| </itemize> |
| |
| <p> |
| If at some point an ill-formed or non-sense packet is received by the server, |
| and <tt/BRLAPI_PACKET_EXCEPTION/ is returned, holding the guilty packet for |
| further analysis. |
| |
| <sect1>Operating modes |
| <p> |
| The connection between the client and the server can be in either of the |
| four following modes: |
| |
| <itemize> |
| <item>authorization mode: this is the initial mode, when the client hasn't |
| got the authorization to use the server yet. The server first sends a |
| <tt/BRLAPI_PACKET_VERSION/ packet that announces the server version. The client |
| must send back a <tt/BRLAPI_PACKET_VERSION/ for announcing its own version too. |
| The server then sends a <tt/BRLAPI_PACKET_AUTH/ packet that announces |
| which authorization methods are allowed. The client can then send |
| <tt/BRLAPI_PACKET_AUTH/ packets, which makes the connection enter normal mode. |
| If no authorization is needed, the server can announce the <tt/NONE/ method, the |
| client then doesn't need to send a <tt/BRLAPI_PACKET_AUTH/ packet. |
| |
| |
| |
| <item>normal mode: the client is authorized to use the server, but didn't ask for a tty |
| or raw mode. The client can send either of these types of packet: |
| <itemize> |
| <item><tt/BRLAPI_PACKET_GETDRIVERNAME/ |
| or <tt/BRLAPI_PACKET_GETDISPLAYSIZE/ to get pieces of information from the server, |
| <item><tt/BRLAPI_PACKET_ENTERTTYMODE/ to enter tty handling mode, |
| <item><tt/BRLAPI_PACKET_ENTERRAWMODE/ to enter raw mode, |
| </itemize> |
| |
| |
| <item>tty handling mode: the client holds the control of a tty: <em/brltty/ 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: |
| <itemize> |
| <item><tt/BRLAPI_PACKET_LEAVETTYMODE/ to leave tty handling mode and go back to |
| normal mode, |
| <item><tt/BRLAPI_PACKET_IGNOREKEYRANGE/ and <tt/BRLAPI_PACKET_ACCEPTKEYRANGE/ to mask and unmask keys, |
| <item><tt/BRLAPI_PACKET_WRITE/ to display text on this tty, |
| <item><tt/BRLAPI_PACKET_ENTERRAWMODE/ to enter raw mode, |
| <item><tt/BRLAPI_PACKET_GETDRIVERNAME/ |
| or <tt/BRLAPI_PACKET_GETDISPLAYSIZE/ to get pieces of information from the server, |
| </itemize> |
| And the server might send <tt/BRLAPI_PACKET_KEY/ packets to signal key presses. |
| |
| |
| <item>raw mode: the client wants to exchange packets directly with the braille |
| terminal. Only these types of packet will be accepted. |
| <itemize> |
| <item><tt/BRLAPI_PACKET_LEAVERAWMODE/ to get back to previous mode, either normal or |
| tty handling mode. |
| <item><tt/BRLAPI_PACKET_PACKET/ to send a packet to the braille terminal. |
| </itemize> |
| And the server might send <tt/BRLAPI_PACKET_PACKET/ packets to give received packets |
| from the terminal to the client. |
| |
| <item>suspend mode: the client wants to completely drive the braille terminal. |
| The device driver is hence kept closed. No type of packet is allowed except |
| <tt/BRLAPI_PACKET_RESUME/ |
| </itemize> |
| |
| Termination of the connection is initiated by the client in normal mode by |
| simply closing its side of the socket. The server will then close the |
| connection. |
| |
| |
| <sect1>Details for each type of packet |
| |
| <p> |
| Here is described the semantics of each type of packet. Most of them are |
| directly linked to some of <em/BrlAPI/'s library's functions. Reading their |
| online manual page as well will hence be of good help for understanding. |
| |
| <sect2><tt/BRLAPI_PACKET_VERSION/ |
| This must be the first packet ever transmitted from the server to the client and |
| from the client to the server. The server sends one first for letting the client |
| know its protocol version. Data is an integer indicating the protocol version. |
| |
| Then client must then respond the same way for giving its |
| version. If the protocol version can't be handled by the server, a |
| <tt/BRLAPI_ERROR_PROTOCOL_VERSION/ error packet is returned and the connection |
| is closed. |
| |
| <sect2><tt/BRLAPI_PACKET_AUTH/ |
| <p> |
| This must be the second packet ever transmitted from the server to the client |
| and from the client to the server. The server sends one first for letting the |
| client know which authorization methods are available. Data is the allowed |
| authorization types, as integers. |
| |
| If the <tt/NONE/ method is not announced by the server, the client can then try |
| to get authorized by sending packets whose data is the type of authorization |
| that is tried (as an integer), and eventually some data (if the authorization |
| type needs it). |
| |
| If the authorization is successful, the server acknowledges the packet, and |
| other types of packets might be used, other <tt/BRLAPI_PACKET_AUTH/ shouldn't be |
| sent by the client. |
| |
| If the authorization is not successful, the server sends a |
| <tt/BRLAPI_ERROR_AUTHENTICATION/ error, and the client can try another |
| authorization method. |
| |
| Authorization methods are as follow: |
| |
| <itemize> |
| <item><tt/NONE/: the client doesn't need to send an authorization packet. |
| <item><tt/KEY/: data holds a secret key, the authorization is successful only |
| if the key matches the server secret key. |
| <item><tt/CREDENTIALS/: Operating-System-specific credentials are explicitely |
| sent over the socket, the authorization is successful if the server considers |
| the credentials sufficient. |
| </itemize> |
| |
| Note: when the Operating system permits it, the server may use implicit |
| credential check, and then advertise the <tt/none/ method. |
| |
| <sect2><tt/BRLAPI_PACKET_GETDRIVERNAME/ (see <em/brlapi_getDriverName()/) |
| <p> |
| This should be sent by the client when it needs the full name of |
| the current <tt/brltty/ driver. The returned string is \0 terminated. |
| |
| <sect2><tt/BRLAPI_PACKET_GETMODELID/ (see <em/brlapi_getModelIdentifier()/) |
| <p> |
| This should be sent by the client when it needs to identify |
| which model of braille display is currently used by <tt/brltty/. |
| The returned string is \0 terminated. |
| |
| <sect2><tt/BRLAPI_PACKET_GETDISPLAYSIZE/ (see <em/brlapi_getDisplaySize()/) |
| <p> |
| 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. |
| |
| <sect2><tt/BRLAPI_PACKET_ENTERTTYMODE/ (see <em/brlapi_enterTtyMode()/ and |
| <em/brlapi_enterTtyModeWithPath()/) |
| <p> |
| This should be sent by the client to get control of a tty. Sent data are |
| first a series of integers: the first one gives the number of following |
| integers, which are the numbers of ttys that leads to the tty that |
| the application wants to take control of (it can be empty if the tty is |
| one of the machine's VT). The last integer of this series tells the number of |
| the tty to get control of. Finaly, how key presses should be reported is sent: |
| either a driver name or "", preceded by the number of caracters in the driver |
| name (0 in the case of ""), as an unsigned byte. This packet is then |
| acknowledged by the server. |
| |
| <sect2><tt/BRLAPI_PACKET_KEY/ (see <em/brlapi_readKey()/) |
| <p> |
| As soon as the client gets a tty, it must be prepared to handle |
| <tt/BRLAPI_PACKET_KEY/ incoming packets |
| at any time (as soon as the key |
| was pressed on the braille terminal, hopefuly). |
| The data holds a key code as 2 integers, or |
| the key flags then the command code |
| as 2 integers, depending on what has been request in the |
| <tt/BRLAPI_PACKET_ENTERTTYMODE/ packet. |
| |
| <sect2><tt/BRLAPI_PACKET_SETFOCUS/ (see <em/brlapi_setFocus()/) |
| |
| <p> |
| For the server to know which tty is active, one particular client is responsible |
| for sending <tt/BRLAPI_PACKET_SETFOCUS/ packets. They hold a single integer telling |
| the new current tty. For instance, when running an X server on VT 7, the |
| <tt/xbrlapi/ client would have sent a <tt/BRLAPI_PACKET_ENTERTTYMODE(7)/ and will send |
| window IDs whenever X focus changes, allowing display and keypresses switching |
| between xterms. |
| |
| <sect2><tt/BRLAPI_PACKET_LEAVETTYMODE/ (see <em/brlapi_leaveTtyMode()/) |
| <p> |
| This should be sent to free the tty and masked keys lists. |
| This is acknowledged by the server. |
| |
| <sect2><tt/BRLAPI_PACKET_IGNOREKEYRANGE/ and <tt/BRLAPI_PACKET_ACCEPTKEYRANGE/ |
| (see <em/brlapi_ignoreKeyRange()/ and <em/brlapi_acceptKeyRange()/) |
| <p> |
| If the client doesn't want every key press to be signaled to it, but some of |
| them to be given to <tt/brltty/ for normal processing, it can send |
| <tt/BRLAPI_PACKET_IGNOREKEYRANGE/ packets to |
| tell ranges of key codes which shouldn't be |
| sent to it, but given to <tt/brltty/, and <tt/BRLAPI_PACKET_ACCEPTKEYRANGE/ |
| packets to tell ranges |
| of key codes which should be sent to it, and not given to |
| <tt/brltty/. The server keeps a dynamic list of ranges, so that arbitrary |
| sequences of such packets can be sent. |
| A range is composed of 2 keycodes: the "first" and the "last" boundaries. |
| Each keycode is composed of 2 integers: the key flags then the command code. |
| The range expressed by these two keycodes is the set of keycodes whose command |
| codes are between the command code of the "first" keycode and the "last" keycode |
| (inclusive), and whose flags contain at least the flags of the "first" keycode |
| and at most the flags of the "last" keycode. Setting the "first" and "last" |
| keycode to the same value express only one keycode, for instance. Setting the |
| first and last keycode to the same command code but setting no flags in the |
| "first" keycode and setting one flag in the "last" keycode expresses only two |
| keycode, with the same command code and no flags set except possibly the flag |
| that is set in the "last" keycode. Setting one flag <em/i/ in the "first" |
| keycode and setting the same flag plus another flag <em/j/ in the "last" keycode |
| expresses that the keycodes in the range have flag <em/i/ set and possibly flag |
| <em/j/ set, but no other flag. Several such ranges can be provided one after the |
| other. |
| |
| <sect2><tt/BRLAPI_PACKET_WRITE/ (see <em/brlapi_write()/) |
| <p> |
| To display text on the braille terminal and set the position of the cursor, |
| the client can send a <tt/BRLAPI_PACKET_WRITE/ packet. The packet begins |
| with an integer holding flags (see <tt/BRLAPI_WF_*/). These flags indicate |
| which data will then be available, in the following order (corresponding to |
| flag weight): |
| |
| <itemize> |
| <item> A display number can be given as a integer, in case the braille |
| display has several. If not given, usual display is used. |
| <item> A region must be given as two integers indicating the beginning and the |
| number of characters of the part of the braille display which is to be updated, |
| the first cell of the display being numbered 1. For braille displays that have |
| several lines, the first cell of the second line of the display is numbered the |
| length of lines plus one, etc., in other words the display is handled as the |
| concatenation of the lines of the display. |
| If the number is negative, its absolute value is taken into account, and the |
| update is padded or truncated to fill the rest of the display. |
| <item> The text to display can then be given, preceded by its size in bytes |
| expressed as an integer. It will erase the corresponding region in the AND and |
| OR fields. If the region size is positive, the text's length in characters must exactly match the region |
| size. For multibyte text, this is the number of wide characters. Notably, |
| combining and double-width characters count for 1. |
| <item> Then an AND field can be given, one byte per character: the 8-dot |
| representation of the above text will be AND-ed with this field, hence allowing |
| to erase some unwanted parts of characters. Dots are coded as described in |
| ISO/TR 11548-1: dot 1 is set iff bit 0 is set, dot 2 is set iff bit 1 is set, |
| ... dot <em/i+1/ is set if bit <em/i/ is set. This also corresponds to the |
| low-order byte of the coding of unicode's braille row <tt/U+2800/. |
| <item> As well, an OR field may be given, one byte per character: the 8-dot |
| result of the AND operation above (or the 8-dot representation of the text if |
| no AND operation was performed) is OR-ed with this field, hence allowing |
| to set some dots, to underline characters for instance. |
| <item> A cursor position can be specified. 1 representing |
| the first character of the display, 0 turning the cursor off. If not given, |
| the cursor (if any) is left unmodified. |
| <item> Last but not least, the charset of the text can be specified: the length |
| of the name first in one byte, then the name itself in ASCII characters. If the |
| charset is not specified, an 8-bit charset is assumed, and it is assumed to be |
| the same as the server's. Multibyte charsets may be used, AND and OR fields' |
| bytes will correspond to each text's wide <em/character/, be it a combining or a |
| double-width character. |
| </itemize> |
| |
| A <tt/BRLAPI_PACKET_WRITE/ packet without any flag (and hence no data) means a |
| "void" WRITE: the server clears the output buffer for this connection. |
| |
| <sect2><tt/BRLAPI_PACKET_ENTERRAWMODE/ (see <em/brlapi_enterRawMode()/) |
| <p> |
| To enter raw mode, the client must send a <tt/BRLAPI_PACKET_ENTERRAWMODE/ packet, |
| which is acknowledged. Once in raw mode, no other packet than |
| <tt/BRLAPI_PACKET_LEAVERAWMODE/ or <tt/BRLAPI_PACKET_PACKET/ will be accepted. |
| The data must hold the special value <tt/BRLAPI_DEVICE_MAGIC/: <tt/0xdeadbeef/, then |
| the name of the driver (one byte for the length, then the name) to avoid |
| erroneous raw mode activating. |
| |
| <sect2><tt/BRLAPI_PACKET_LEAVERAWMODE/ (see <em/brlapi_leaveRawMode()/) |
| <p> |
| To leave raw mode, the client must send a <tt/BRLAPI_PACKET_LEAVERAWMODE/ packet, which |
| is acknowledged. |
| |
| <sect2><tt/BRLAPI_PACKET_PACKET/ (see <em/brlapi_sendRaw()/ and |
| <em/brlapi_recvRaw()/) |
| <p> |
| While in raw mode, only <tt/BRLAPI_PACKET_PACKET/ packets can be exchanged between |
| the client and the server: to send a packet to the braille terminal, the |
| client merely sends a <tt/BRLAPI_PACKET_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. |
| |
| <sect2><tt/BRLAPI_PACKET_SUSPENDDRIVER/ (see <em/brlapi_suspendDriver()/) |
| <p> |
| To enter suspend mode, the client must send a <tt/BRLAPI_PACKET_SUSPEND/ packet, |
| which is acknowledge. Once in suspend mode, no other packet than |
| <tt/BRLAPI_PACKET_RESUME/ will be accepted. |
| The data must hold the special value <tt/BRLAPI_DEVICE_MAGIC/: <tt/0xdeadbeef/, |
| then the name of the driver (one byte for the length, then the name) to avoid |
| erroneous raw mode activating. |
| |
| <sect2><tt/BRLAPI_PACKET_PARAM_REQUEST/ |
| |
| <p> |
| |
| This packet is sent by the client to request values of parameters. The packet |
| begins with an integer which holds flags (see <tt/BRLAPI_PARAMF_*/) which |
| describe which, how, and when the value should be returned by the server: |
| <itemize> |
| <item> When the <tt/BRLAPI_PARAMF_GLOBAL/ flag is set, the server will |
| return/subscribe the global value instead of the local value. |
| <item> When the <tt/BRLAPI_PARAMF_GET/ flag is set, the server acknowledges the |
| request by returning the latest value with a <tt/BRLAPI_PACKET_PARAM_VALUE/ |
| packet. Otherwise the server acknowledges the request with a |
| <tt/BRLAPI_PACKET_ACK/ packet, without providing the value. |
| <item> When the <tt/BRLAPI_PARAMF_SUBSCRIBE/ flag is set, the server will keep |
| sending asynchronously the value of the parameter whenever it changes, with |
| <tt/BRLAPI_PACKET_PARAM_UPDATE/ packets, until |
| another request packet has the <tt/BRLAPI_PARAMF_UNSUBSCRIBE/ flag set for this |
| parameter. |
| <item> When the <tt/BRLAPI_PARAMF_SELF/ flag is set along |
| <tt/BRLAPI_PARAMF_SUBSCRIBE/, the server will send the value of the parameter |
| when it is changed even by the client itself. |
| <item> When the <tt/BRLAPI_PARAMF_UNSUBSCRIBE/ flag is set, the server |
| will stop sending asynchronously the value of the parameter with |
| <tt/BRLAPI_PACKET_PARAM_UPDATE/ packets. |
| </itemize> |
| |
| It does not make sense to set both the <tt/BRLAPI_PARAMF_SUBSCRIBE/ and |
| <tt/BRLAPI_PARAMF_UNSUBSCRIBE/ flags. |
| |
| Then an integer representing the parameter to be requested. |
| Then two integers that form (in big-endian order) a 64bit value used to |
| subspecify the precise parameter to be requested (e.g. a keycode number). |
| |
| If several <tt/BRLAPI_PARAMF_SUBSCRIBE/ packets are sent by the client, as |
| many <tt/BRLAPI_PARAMF_UNSUBSCRIBE/ packets have to be sent by the client before |
| the server stops sending <tt/BRLAPI_PACKET_PARAM_UPDATE/ packets. |
| |
| <sect2><tt/BRLAPI_PACKET_PARAM_VALUE/ |
| |
| <p> |
| This packet is sent by the client or the server to provide the value of a |
| parameter. The packet begins with an integer which holds flags (see |
| <tt/BRLAPI_PVF_*/) which describe which value is being transmitted: |
| |
| <itemize> |
| <item> When the <tt/BRLAPI_PVF_GLOBAL/ flag is set, the value is the global value |
| instead of the local value. |
| </itemize> |
| |
| Then an integer representing the parameter being transmitted. Then two integers |
| that form (in big-endian order) a 64bit value used to subspecify the precise |
| parameter being transmitted (e.g. a keycode number). Eventually, the packet |
| contains the value. |
| |
| When the packet is sent by the client, it defines the new value of the |
| parameter, and if it is a global value, the server broadcasts the new value to |
| all clients which have subscribed to updates. The packet is then acknowledged by |
| the server on success. If the value can not be changed, the server returns an |
| error (e.g. <tt/BRLAPI_ERROR_READONLY_PARAMETER/). |
| |
| <sect2><tt/BRLAPI_PACKET_PARAM_VALUE/ |
| |
| This packet is sent asynchronously by the server to provide an update of a |
| value of a parameter. This is sent only if the client has previously sent a |
| <tt/BRLAPI_PACKET_PARAM_REQUEST/ packet with the <tt/BRLAPI_PARAMF_SUBSCRIBE/ |
| for the corresponding parameter. |
| |
| It is structured exactly like a <tt/BRLAPI_PACKET_PARAM_VALUE/ packet. |
| |
| <sect2><tt/BRLAPI_PACKET_SYNCHRONIZE/ |
| |
| This packet is sent by the client and just acknowledged by the server. This |
| allows the client to perform a round-try with the server, thus collecting any |
| pending exception notification. |
| |
| </article> |