<!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.4, December 2006 <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>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 determined by the Tty "get"ting order. Some mecanism will be added in near future for clients to precise "at which level its sheet should be inserted" so as to avoid race conditions on the "get"ting order. <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>Reading braille key codes <p> 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 <em/brltty/. This assumes the existence of a conversion mechanism from key codes to <em/brltty/ 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: <verb> #define BRL_HAVE_KEY_CODES </verb> and the following functions: <verb> static int brl_readKey(BrailleDisplay *) int brl_keyToCommand(BrailleDisplay *brl, DriverCommandContext caller, int code) </verb> The semantics of <tt>brl_readKey()</tt> is very similar to <tt>brl_readCommand()</tt>'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 <tt>brl_keyToCommand()</tt> function's purpose is to convert a key code as delivered by <tt>brl_readKey()</tt> into a <em/brltty/ 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 <em/brltty/. <sect3>Remarks <p>When these two functions are present, the only thing <tt>brl_readCommand()</tt> has to do is to call <tt>brl_readKey()</tt> and then call <tt>brl_keyToCommand()</tt> with the value returned by the first function as argument. <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_GETDRIVERID/, <tt/BRLAPI_PACKET_GETDRIVERNAME/ or <tt/BRLAPI_PACKET_GETDISPLAYSIZE/ to get pieces of information from the server, <item><tt/BRLAPI_PACKET_ENTERTTY/MODE 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_ENTERTY/MODE to switch to another tty, but how key presses should be sent mustn't change, <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_GETDRIVERID/, <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_GETDRIVERID/ (see <em/brlapi_getDriverId()/) <p> This should be sent by the client when it needs the 2-char identifier of the current <tt/brltty/ driver. The returned string is \0 terminated. <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_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. For ranges, Data are 2 pairs of integers: the lower and the upper boundaries; lower and upper must be equal to tell one key, for instance. For Sets, Data simply consists of pairs of integers, one per key in the set. <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. <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. 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. </article>