Sophie

Sophie

distrib > Fedora > 15 > i386 > by-pkgid > a5192c80b3e1c7afd2b2e9be173d443d > files > 14

brlapi-0.5.6-3.fc15.i686.rpm

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<HTML>
<HEAD>
 <META NAME="GENERATOR" CONTENT="LinuxDoc-Tools 0.9.65">
 <TITLE>BrlAPI Reference manual: Writing (BrlAPI-compliant) drivers for brltty</TITLE>
 <LINK HREF="BrlAPI-7.html" REL=next>
 <LINK HREF="BrlAPI-5.html" REL=previous>
 <LINK HREF="BrlAPI.html#toc6" REL=contents>
</HEAD>
<BODY>
<A HREF="BrlAPI-7.html">Next</A>
<A HREF="BrlAPI-5.html">Previous</A>
<A HREF="BrlAPI.html#toc6">Contents</A>
<HR>
<H2><A NAME="sec-drivers"></A> <A NAME="s6">6.</A> <A HREF="BrlAPI.html#toc6">Writing (<EM>BrlAPI</EM>-compliant) drivers for <EM>brltty</EM></A></H2>

<P>In this chapter, we will describe in details how to write a
driver for <EM>brltty</EM>. We begin with a general description of the
structure the driver should have, before explaining more precisely
what each function is supposed to do.</P>

<H2><A NAME="ss6.1">6.1</A> <A HREF="BrlAPI.html#toc6.1">Overview of the driver's structure</A>
</H2>

<P>A braille driver is in fact a library that is either
dynamically loaded by <EM>brltty</EM> at startup, or statically linked to
it during the compilation, depending on the options given to the
<CODE>./configure</CODE> script.</P>
<P>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</EM> and the service level provided
to client applications.</P>
<P>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.</P>
<P>Moreover, a driver can provide additional functionalities, by
defining some macros asserting that it has these functionalities,
and by defining associated functions.</P>

<H2><A NAME="ss6.2">6.2</A> <A HREF="BrlAPI.html#toc6.2">Basic driver structure</A>
</H2>

<P><EM>Every</EM> <EM>brltty</EM> 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</P>
<P>
<PRE>
    #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) { ... }
</PRE>
</P>
<P>Before giving a detailed description of what each function is
supposed to do, we define the <CODE>BrailleDisplay</CODE> structure,
since each function has an argument of type <CODE>BrailleDisplay
*</CODE>. The <CODE>BrailleDisplay</CODE> structure is defined like this:</P>
<P>
<PRE>
    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;
</PRE>
</P>
<P>We now describe each function's semantics and calling
convention.</P>
<P>The <CODE>brl_identify()</CODE> 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).</P>
<P>The <CODE>brl_open()</CODE> 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 <CODE>tty</CODE> argument, and to configure the associated communication
port. The <CODE>parameters</CODE> 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.</P>
<P>The <CODE>brl_close()</CODE> 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.</P>
<P>The <CODE>brl_writeWindow()</CODE> 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.</P>
<P>The <CODE>brl_writeStatus()</CODE> function is very similar to <CODE>brl_writeWindow()</CODE>.
The only difference is that whereas <CODE>brl_writeWindow()</CODE> writes on the
main braille display, <CODE>brl_writeStatus()</CODE> 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.</P>
<P>The <CODE>brl_readCommand()</CODE> 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</EM>'s core, which in turn will process them.
The first argument, of type <CODE>BrailleDisplay</CODE>, is for future use, and
can safely be ignored for the moment. The second argument indicates
in which context (state) <EM>brltty</EM> is. For instance, it specifies if
<EM>brltty</EM> 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</EM>. For a complete list of available command codes, please
have a look at <CODE>brl.h</CODE> in the Programs subdirectory. Two codes have special
meanings:</P>
<P>
<DL>

<DT><B>eof</B><DD>
<P>specifies that no command is available now, and that
no key is waiting to be converted into command in a near future.</P>

<DT><B>CMD_NOOP</B><DD>
<P>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.</P>

</DL>
</P>

<H2><A NAME="ss6.3">6.3</A> <A HREF="BrlAPI.html#toc6.3">Enhancements for <EM>BrlAPI</EM></A>
</H2>

<P>To improve the level of service provided to client
applications communicating with braille drivers through <EM>BrlAPI</EM>, the
drivers should declare some additional functions that will then be
called by the API when needed.</P>
<P>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</EM>:</P>
<P>
<UL>
<LI>reading braille terminal specific key codes,
</LI>
<LI>exchanging raw data packets between the braille
terminal and a client application running on the PC.</LI>
</UL>
</P>
<P>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 
<A HREF="BrlAPI-1.html#sec-intro">Introduction</A> and 
<A HREF="BrlAPI-2.html#sec-general">General description</A>.</P>

<H3>Reading braille key codes</H3>

<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</EM>. This assumes the existence of a
conversion mechanism from key codes to <EM>brltty</EM> 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:
<PRE>
#define BRL_HAVE_KEY_CODES
</PRE>

and the following functions:
<PRE>
static int brl_readKey(BrailleDisplay *)
int brl_keyToCommand(BrailleDisplay *brl, DriverCommandContext caller, int code)
</PRE>
</P>
<P>The semantics of <CODE>brl_readKey()</CODE> is very similar to
<CODE>brl_readCommand()</CODE>'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.</P>
<P>The <CODE>brl_keyToCommand()</CODE> function's purpose is to convert a key code
as delivered by <CODE>brl_readKey()</CODE> into a <EM>brltty</EM> 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</EM>.</P>

<H3>Remarks</H3>

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

<H3>Exchanging raw data packets</H3>

<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.</P>
<P>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.</P>
<P>The macro that declares that a driver is able to transmit packets
is:</P>
<P>
<PRE>
#define BRL_HAVE_PACKET_IO
</PRE>
</P>
<P>The prototypes of the functions the driver should define are:</P>
<P>
<PRE>
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)
</PRE>
</P>
<P><CODE>brl_writePacket()</CODE> sends a packet of <CODE>size</CODE> bytes, stored
at <CODE>packet</CODE>, 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.</P>
<P><CODE>brl_readPacket()</CODE> reads a packet of at most <CODE>size</CODE> 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.</P>
<P><CODE>brl_rescue()</CODE> is called by <EM>BrlAPI</EM> 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.</P>

<H3>Remarks.</H3>

<P>
<UL>
<LI> If the driver provides such functions, every other
functions should use them, instead of trying to communicate
directly with the braille terminal. For instance, <CODE>readCommand()</CODE>
should call <CODE>readPacket()</CODE>, and then extract a key from the packet,
rather than reading directly from the communication port's file
descriptor. The same applies for <CODE>brl_writeWindow()</CODE>, which should
use <CODE>brl_writePacket()</CODE>, rather than writing on the communication
port's file descriptor.
</LI>
<LI> For the moment, the argument of type BrailleDisplay
can safely be ignored by the functions described here.
</LI>
</UL>
</P>

<HR>
<A HREF="BrlAPI-7.html">Next</A>
<A HREF="BrlAPI-5.html">Previous</A>
<A HREF="BrlAPI.html#toc6">Contents</A>
</BODY>
</HTML>