/*
 * libbrlapi - A library providing access to braille terminals for applications.
 *
 * Copyright (C) 2002-2004 by
 *   Samuel Thibault <Samuel.Thibault@ens-lyon.org>
 *   Sébastien Hinderer <Sebastien.Hinderer@ens-lyon.org>
 * All rights reserved.
 *
 * libbrlapi comes with ABSOLUTELY NO WARRANTY.
 *
 * This is free software, placed under the terms of the
 * GNU Lesser General Public License, as published by the Free Software
 * Foundation; either version 2.1 of the License,
 * or (at your option) any later version.
 * Please see the file COPYING-API for details.
 *
 * Web Page: http://mielke.cc/brltty/
 *
 * This software is maintained by Dave Mielke <dave@mielke.cc>.
 */

/** \file
 * \brief types, defines and functions prototypes for \e BrlAPI's library
 */

#ifndef _BRLAPI_H
#define _BRLAPI_H

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

/* Define this to be a string containing the library version. */
#undef BRLAPI_RELEASE

/* this is for UINT32_MAX */
#include <inttypes.h>
#ifndef UINT32_MAX
#define UINT32_MAX (4294967295U)
#endif /* UINT32_MAX */

/* The type size_t is defined there! */
#include <unistd.h>

/** Maximum packet size for packets exchanged on sockets and with braille
 * terminal */
#define BRLAPI_MAXPACKETSIZE 512

/** \defgroup brlapi_connection Connecting to BrlAPI
 *
 * Before calling any other function of the library, calling
 * brlapi_initializeConnection() is needed to establish a connection to
 * \e BrlAPI 's server.
 * When the connection is not needed any more, brlapi_closeConnection() must be
 * called to close the connection.
 *
 * @{ */

/** Default port number on which connections to \e BrlAPI can be established */
#define BRLAPI_SOCKETPORTNUM 35751
#define BRLAPI_SOCKETPORT "35751"

/** Default unix path on which connections to \e BrlAPI can be established */
#define BRLAPI_SOCKETPATH "/var/lib/BrlAPI/"

/** \e brltty 's settings directory
 *
 * This is where authentication key and driver-dependent key names are found
 * for instance. */
#undef BRLAPI_ETCDIR

/** Default name of the file containing \e BrlAPI 's authentication key
 *
 * This name is relative to BRLAPI_ETCDIR */
#undef BRLAPI_AUTHFILE

/** Final path for default authentication key file */
#define BRLAPI_DEFAUTHPATH BRLAPI_ETCDIR "/" BRLAPI_AUTHFILE

/** \brief Settings structure for \e BrlAPI connection
 *
 * This structure holds every parameter needed to connect to \e BrlAPI: which
 * file the authentication key can be found in and which computer to connect to.
 *
 * \par Examples:
 * \code
 * brlapi_settings_t settings;
 *
 * settings.authKey="/etc/brlapi.key";
 * settings.hostName="foo";
 * \endcode
 *
 * \e libbrlapi will read authentication key from file \p /etc/brlapi.key
 * and connect to the machine called "foo", on the default TCP port.
 *
 * \code
 * settings.hostName="10.1.0.2";
 * \endcode
 *
 * lets directly enter an IP address instead of a machine name.
 *
 * \code
 * settings.hostName=":4321";
 * \endcode
 *
 * lets \e libbrlapi connect to the local computer, on TCP port 4321
 *
 * \sa brlapi_initializeConnection() brlapi_loadAuthKey()
 */
typedef struct {
  /** To get authenticated, \e libbrlapi has to tell the \e BrlAPI server a
   * secret key, for security reasons. This is the path to the file which
   * holds it; it will hence have to be readable by the application.
   *
   * Setting \c NULL defaults it to local installation setup or to the content
   * of the BRLAPI_AUTHPATH environment variable, if it exists. */
  char *authKey;

  /** This tells where the \e BrlAPI server resides: it might be listening on
   * another computer, on any TCP port. It should look like "foo:1234", which
   * means TCP port number 1234 on computer called "foo".
   * \note Please check that resolving this name works before complaining
   *
   * Settings \c NULL defaults it to localhost, using the local installation's
   * default TCP port, or to the content of the BRLAPI_HOSTNAME environment
   * variable, if it exists. */
  char *hostName;
} brlapi_settings_t;

/* brlapi_initializeConnection */
/** open a socket and connect it to \e BrlAPI 's server
 *
 * This function first loads an authentication key as specified in settings.
 * It then creates a TCP socket and connects it to the specified machine, on
 * the specified port. It writes the authentication key on the socket and
 * waits for acknowledgement.
 *
 * \return the file descriptor, or -1 on error
 *
 * \note The file descriptor is returned in case the client wants to
 * communicate with the server without using \e libbrlapi functions. If it uses
 * them however, it won't have to pass the file descriptor later, since the
 * library keeps a copy of it. But that also means that
 * brlapi_initializeConnection() may be called several times, but \e libbrlapi
 * functions will always work with the last call's descriptor
 *
 * \par Example:
 * \code
 * if (brlapi_initializeConnection(&settings,&settings)<0) {
 *  fprintf(stderr,"couldn't connect to BrlAPI at %s: %s\n",
 *   settings.hostName, brlapi_strerror(brlapi_crrno));
 *  exit(1);
 * }
 * \endcode
 *
 * \par Errors:
 * \e BrlAPI might not be on this TCP port, the host name might not be
 * resolvable, the authentication may fail,...
 *
 * \param clientSettings this gives the connection parameters, as described
 * in brlapi_settings_t. If \c NULL, defaults values are used, so that it is
 * generally a good idea to give \c NULL as default, and only fill a
 * brlapi_settings_t structure when the user gave parameters to the program
 * for instance.
 * \param usedSettings if not \c NULL, parameters which were actually used are
 * stored here, if the application ever needs them.
 *
 * \sa
 * brlapi_settings_t
 * brlapi_loadAuthKey()
 * brlapi_writePacket()
 * brlapi_readPacket()
 */
int brlapi_initializeConnection(const brlapi_settings_t *clientSettings, brlapi_settings_t *usedSettings);

/* brlapi_closeConnection */
/** Cleanly close the socket
 *
 * This function locks until a closing acknowledgement is received from the
 * server. The socket is then freed, so the file descriptor
 * brlapi_initializeConnection() gave has no meaning any more
 */
void brlapi_closeConnection(void);

/* brlapi_loadAuthKey */
/** Load an authentication key from the given file
 *
 * Calling this function shouldn't be needed if brlapi_initializeConnection
 * is used.
 *
 * \param filename gives the full path of the file ;
 * \param authlength gives the size of the \e auth buffer ;
 * \param auth is a buffer where the function will store the authentication key
 *
 * \return 0, -1 on error
 *
 * \sa brlapi_settings_t, brlapi_initializeConnection */
int brlapi_loadAuthKey(const char *filename, size_t *authlength, void *auth);

/** @} */

/** \defgroup brlapi_info Getting Terminal information
 * \brief How to get information about the connected Terminal
 *
 * Before using Raw mode or key codes, the application should always check the
 * type of the connected terminal, to be sure it is really the one it expects.
 *
 * One should also check for display size, so as to adjust further displaying
 * on it.
 * @{
 */

/* brlapi_getDriverId */
/** Identify the driver used by \e brltty
 *
 * This function will fill its argument with the \e brltty 2-chars code of
 * the driver currently in use, to which it adds a '\\0'.
 *
 * \param id is the buffer given by the application
 * \param n is the maximum size of the id buffer
 *
 * \return -1 on error, or a positive value giving the size of the needed
 * buffer, if the supplied one is to small (same as \e snprintf)
*/
int brlapi_getDriverId(unsigned char *id, size_t n);

/* brlapi_getDriverName */
/** return the complete name of the driver used by \e brltty
 *
 * This function fills its argument with the whole name of the braille
 * terminal if available, terminated with a '\\0'.
 *
 * \param name is the buffer given by the application
 * \param n is the maximum size for the name buffer
 *
 * \return -1 on error, or a positive value giving the size of the needed
 * buffer, if the supplied one is to small (same as \e snprintf)
*/
int brlapi_getDriverName(unsigned char *name, size_t n);

/* brlapi_getDisplaySize */
/** return the size of the braille display */
int brlapi_getDisplaySize(unsigned int *x, unsigned int *y);

/** @} */

/** \defgroup brlapi_tty Tty getting & leaving
 * \brief How to take control of ttys for direct braille display / read
 *
 * Before being able to write on the braille display, the application must tell
 * the server which tty it will handle. Some checking is done just to be sure
 * that only one client gets control of each tty.
 *
 * The application must also specify how braille keys will be delivered to it.
 * Two ways are possible: KEYCODES and COMMANDS
 *
 * - KEYCODES are specific to each braille driver, since the raw keycode, as
 *   defined in the driver will be given for each key press.
 *   Using them leads to building highly driver-dependent applications, which
 *   can yet sometimes be useful to mimic existing proprietary applications
 *   for instance.
 * - COMMANDS means that applications will get exactly the same values as
 *   \e brltty. This allows driver-independent clients, which will hopefully
 *   be nice to use with a lot of different terminals
 * \sa brlapi_readKey()
 * @{
 */

/* brlapi_getTty */
/** ask for some tty, with some key mechanism
 *
 * \param tty
 * - If tty>0, application takes control of the specified tty;
 * - if tty<=0, the library first tries to get the tty number by reading
 * /proc/self/stat (on linux). If none is found, it looks at a CONTROLVT
 * environment variable, then WINDOWID is tried (for an xterm case).
 *
 * \param how tells whether the application wants brlapi_readKey() to return
 * keycodes or \e brltty commands: either BRLKEYCODES or BRLCOMMANDS;
 *
 * In an X window environment, CONTROLVT might be useful. XFree86 >=4.4 defines
 * an XFree86_VT root window property which exactly holds the used VT, so that
 * it should be given to brlapi_getTty. If it isn't available, one may,
 * right into .xsession and .xinitrc, grep X's log, for instance:
 *
 * CONTROLVT="$(grep "using VT number" "/var/log/XFree86.$(echo "$DISPLAY" | sed -e "s/^.*::*\([0-9]*\).*$/\1/").log" | sed -e "s/^.*using VT number \([0-9]*\).*$/\1/")"
 *
 * CONTROLVT should also be propagated when running remote applications via ssh,
 * for instance, along with BRLAPI_HOSTNAME and the authentication key.
 *
 * \return the used tty number on success, -1 on error
 *
 * \sa brlapi_leaveTty() brlapi_readKey()
 */
int brlapi_getTty(int tty, int how);

/** ask for \e brltty commands */
#define BRLCOMMANDS 0
/** ask for raw driver keycodes */
#define BRLKEYCODES 1

/* brlapi_leaveTty */
/** stop controlling the tty
 *
 * \return 0 on success, -1 on error.
 *
 * \sa brlapi_getTty()
 */
int brlapi_leaveTty(void);

/* brlapi_setFocus */
/** tell the current tty to brltty
 *
 * This is intended for focus tellers, such as brltty, xbrlapi, screen, ...
 * brlapi_getTty() must have been called beforewards to tell where this focus
 * applies in the tty tree.
 *
 * \return 0 on success, -1 on error.
 *
 * \sa brlapi_getTty() brlapi_leaveTty()
 */
int brlapi_setFocus(int tty);

/** @} */

/** \defgroup brlapi_write Writing on the braille display
 * \brief write text to the braille display
 *
 * Once brlapi_getTty() was called, the application can call brlapi_writeText()
 * to write things on the braille display.
 *
 * \note Be sure to call brlapi_getTty() \e before calling brlapi_write*(), or
 * else you'll get an error. This is particularly not always trivial when
 * writing multithreaded applications.
 *
 * @{ */

/* brlapi_writeText */
/** Write the given \\0-terminated string to the braille display
 *
 * If the string is too long, it is cut. If it's too short, spaces are appended.
 *
 * \param cursor gives the cursor position; if equal to 0, no cursor is shown at
 * all;
 * \param str points on the string to be displayed.
 *
 * \return 0 on success, -1 on error.
 */
int brlapi_writeText(int cursor, const unsigned char *str);

/* brlapi_writeDots */
/** Write the given dots array to the display
 *
 * \param dots points on an array of dot information, one per character. Its
 * size must hence be the same as what brlapi_getDisplaySize() returns.
 *
 * \return 0 on success, -1 on error.
 */
int brlapi_writeDots(const unsigned char *dots);

/* brlapi_writeStruct */
/** Structure containing arguments to be given to brlapi_write() */
typedef struct {
  int displayNumber; /** Display number -1 == unspecified */
  unsigned int regionBegin, regionEnd; /** Region of display to update, 1st character of display is 1 */
  char *text; /** Text to display */
  char *attrAnd; /** And attributes; applied first */
  char *attrOr; /** Or attributes; applied \e after ANDing */
  int cursor; /** -1 == don't touch, 0 == turn off, 1 = 1st char of display, ... */
} brlapi_writeStruct;

/* BRLAPI_WRITESTRUCT_INITIALIZER */
/** Allows to initialize a structure of type \e brlapi_writeStruct *
 * with default values:
 * displayNumber = -1; (unspecified)
 * regionBegin = regionEnd = 0; (update the whole display)
 * text = attrAnd = attrOr = NULL; (no text, no attribute)
 * cursor = -1; (don't touch cursor)
*/
#define BRLAPI_WRITESTRUCT_INITIALIZER \
  { -1, 0, 0, NULL, NULL, NULL, -1};

/* brlapi_write */
/** Update a specific region of the braille display and apply and/or masks
 *
 * \param s gives information necesarry for the update
 *
 * \return 0 on success, -1 on error.
 */
int brlapi_write(const brlapi_writeStruct *s);

/** @} */

/** \defgroup brlapi_keys Reading key presses
 * \brief How to read key presses from the braille terminal
 *
 * Once brlapi_getTty() is called, the application can call brlapi_readKey() to
 * read key presses. Either key codes or commands will be returned, depending
 * on parameters given to brlapi_getTty().
 *
 * key presses are buffered, so that calling brlapi_readKey() in non-blocking
 * mode from times to times should suffice.
 *
 * @{
 */

/** buffer size
 *
 * key presses won't be lost provided no more than BRL_KEYBUF_SIZE key presses
 * are done between two calls to brlapi_read* if a call to another function is
 * done in the meanwhile (which needs somewhere to put them before being able
 * to get responses from the server)
 */
#define BRL_KEYBUF_SIZE 256

/** type for key codes
 *
 * Its size is 32 bits, so driver implementors have to restrict themselves to
 * a 32 bit space. */
typedef uint32_t brl_keycode_t;

/** brl_keycode_t's biggest value
 *
 * As defined in \c <inttypes.h> */
#define BRL_KEYCODE_MAX ((brl_keycode_t) (UINT32_MAX))

/* brlapi_readKey */
/** Read a key from the braille keyboard
 *
 * This function returns one key press's code.
 *
 * If BRLCOMMANDS was given to brlapi_getTty(), a \e brltty command is returned,
 * as described in \c <brltty/brldefs.h> . It is hence pretty
 * driver-independent, and should be used by default when no other option is
 * possible.
 *
 * By default, all commands but those which restart drivers and switch
 * virtual terminals are returned to the application and not to brltty.
 * If the application doesn't want to see some command events,
 * it should call either brlapi_ignoreKeySet() or brlapi_ignoreKeyRange()
 *
 * If BRLKEYCODES was given to brlapi_getTty(), a raw keycode is returned,
 * as specified by the terminal driver, usually in <brltty/brldefs-xy> where xy
 * is the driver's code. It generally corresponds to the very code that the
 * terminal tells to the driver.
 * This should only be used by applications which are dedicated to a particular
 * braille terminal. Hence, checking the terminal type thanks to a call to
 * brlapi_getDriverId() or even brlapi_getDriverName() before getting tty
 * control is a pretty good idea.
 *
 * By default, all the keypresses will be passed to the client, none will go
 * through brltty, so the application will have to handle console switching
 * itself.
 *
 * \param block tells whether the call should block until a key is pressed (1)
 *  or should only probe key presses (0),
 * \param code holds the key code if a key press is indeed read.
 *
 * \return -1 on error and *code is then undefined, 0 if block was 0 and no
 *  key was pressed so far, or 1 and *code holds the key code.
 */
int brlapi_readKey(int block, brl_keycode_t *code);

/* brlapi_ignoreKeyRange */
/** Ignore some key presses from the braille keyboard
 *
 * This function asks the server to give keys between x and y to \e brltty,
 * rather than returning them to the application via
 * brlapi_readKey()
 *
 * \note The given codes are either raw keycodes if BRLKEYCODES was given to
 * brlapi_getTty(), or \e brltty commands if BRLCOMMANDS was given. */
int brlapi_ignoreKeyRange(brl_keycode_t x, brl_keycode_t y);

/* brlapi_ignoreKeySet */
/** Ignore some key presses from the braille keyboard
 *
 * This function asks the server to give the n keys in set s to \e brltty,
 * rather than returning them to the application via
 * brlapi_readKey()
 *
 * \note The given codes are either raw keycodes if BRLKEYCODES was given to
 * brlapi_getTty(), or \e brltty commands if BRLCOMMANDS was given. */
int brlapi_ignoreKeySet(const brl_keycode_t *s, unsigned int n);

/* brlapi_unignoreKeyRange */
/** Unignore some key presses from the braille keyboard
 *
 * This function asks the server to return keys between x and y to the
 * application, and not give them to \e brltty.
 *
 * \note You shouldn't ask the server to give you key presses which are usually
 * used to switch between TTYs, unless you really know what you are doing !
 *
 * \note The given codes are either raw keycodes if BRLKEYCODES was given to
 * brlapi_getTty(), or \e brltty commands if BRLCOMMANDS was given. */
int brlapi_unignoreKeyRange(brl_keycode_t x, brl_keycode_t y);

/* brlapi_unignoreKeySet */
/** Unignore some key presses from the braille keyboard
 *
 * This function asks the server to return all n keys in set s to the
 * application, and not give them to \e brltty.
 *
 * \note You shouldn't ask the server to give you key presses which are usually
 * used to switch between TTYs, unless you really know what you are doing !
 *
 * \note The given codes are either raw keycodes if BRLKEYCODES was given to
 * brlapi_getTty(), or \e brltty commands if BRLCOMMANDS was given. */
int brlapi_unignoreKeySet(const brl_keycode_t *s, unsigned int n);

/** @} */

/** \defgroup brlapi_raw Raw Mode
 * \brief Raw Mode mechanism
 *
 * If the application wants to directly talk to the braille terminal, it should
 * use Raw Mode. In this special mode, the driver gives the whole control of the
 * terminal to it: \e brltty doesn't work any more.
 *
 * For this, it simply has to call brlapi_getRaw(), then brlapi_sendRaw()
 * and brlapi_recvRaw(), and finally give control back thanks to
 * brlapi_leaveRaw()
 *
 * Special care of the terminal should be taken, since one might completely
 * trash the terminal's data, or even lock it ! The application should always
 * check for terminal's type thanks to brlapi_getDriverId().
 *
 * @{
 */

/* brlapi_getRaw */
/** Switch to Raw mode
 * \return 0 on success, -1 on error */
int brlapi_getRaw(void);

/* brlapi_leaveRaw */
/** Leave Raw mode
 * \return 0 on success, -1 on error */
int brlapi_leaveRaw(void);

/* brlapi_sendRaw */
/** Send a Raw Packet
 *
 * \param buf points on the packet;
 * \param size holds the packet size.
 * \return size on success, -1 on error */
ssize_t brlapi_sendRaw(const unsigned char *buf, size_t size);

/* brlapi_recvRaw */
/** Get a Raw packet
 *
 * \param buf points on a buffer where the function will store the received
 * packet;
 * \param size holds the buffer size.
 * \return its size, -1 on error, or -2 on EOF */
ssize_t brlapi_recvRaw(unsigned char *buf, size_t size);

/** @} */

/** \defgroup brlapi_error Error handling
 * \brief how to handle errors which might very well happen
 *
 * When a function fails for some normal error, brlapi_errno will hold an error
 * code to explain why it failed. It is good practice to print it somewhere for
 * the user or the programmer to understand why it failed.
 *
 * When something really wrong was done somewhere, like an out-of-bounds
 * argument, which is really a bug in either the implementation of BrlAPI or
 * in the application, an exception may be sent by the server. As soon as
 * libbrlapi receives it, an error handler prints it and \e exit()s the program,
 * since it means something went really wrong and that we shouldn't go further.
 *
 * This is hopefully a really rare event, but in the case of an editor, for
 * instance, one would surely want to have files saved before actually
 * exit()ing. brlapi_setErrorHandler() lets the programmer to define another
 * exception handler which would save files and then call the default handler
 * brlapi_defaultErrorHandler().
 *
 * @{ */

/* Error codes */
#define BRLERR_SUCCESS                  0  /**< Success */
#define BRLERR_NOMEM                    1  /**< Not enough memory */
#define BRLERR_TTYBUSY                  2  /**< Already a connection running in this tty */
#define BRLERR_RAWMODEBUSY              3  /**< Already a connection using RAW mode */
#define BRLERR_UNKNOWN_INSTRUCTION      4  /**< Not implemented in protocol */
#define BRLERR_ILLEGAL_INSTRUCTION      5  /**< Forbiden in current mode */
#define BRLERR_INVALID_PARAMETER        6  /**< Out of range or have no sense */
#define BRLERR_INVALID_PACKET           7  /**< Invalid size */
#define BRLERR_RAWNOTSUPP               8  /**< Raw mode not supported by loaded driver */
#define BRLERR_KEYSNOTSUPP              9  /**< Reading of key codes not supported by loaded driver */
#define BRLERR_CONNREFUSED             10  /**< Connection refused */
#define BRLERR_OPNOTSUPP               11  /**< Operation not supported */
#define BRLERR_GAIERR                  12  /**< Getaddrinfo error */
#define BRLERR_LIBCERR                 13  /**< Libc error */
#define BRLERR_UNKNOWNTTY              14  /**< Couldn't find out the tty number */
#define BRLERR_PROTOCOL_VERSION        15  /**< Bad protocol version */
#define BRLERR_EOF                     16  /**< Unexpected end of file */
#define BRLERR_TOORECURSE              17  /**< Too many levels of recursion */
#define BRLERR_DRIVERERROR             18  /**< Packet returned by driver too large */

/* brlapi_errlist */
/** Error message list
 *
 * These are the string constants used by brlapi_perror()
 */
extern const char *brlapi_errlist[];

/* brlapi_nerr */
/** Number of error messages */
extern const int brlapi_nerr;

/* brlapi_perror */
/** Print a BrlAPI error message
 *
 * brlapi_perror() reads brlapi_errno, and acts just like perror()
 */
void brlapi_perror(const char *s);

/** Get per-thread errno location
 *
 * In multithreaded software, brlapi_errno is thread specific, so api.h
 * cheats about the brlapi_errno token and actually calls
 * brlapi_errno_location()
 *
 * This gets the thread specific location of global variable brlapi_errno
 */
int *brlapi_errno_location(void);

/** Global variable brlapi_errno
 *
 * brlapi_errno is a global left-value containing the last error code. It is
 * not reset to BRLERR_SUCCESS on success.
 */
extern int brlapi_errno;
/** cheat about the brlapi_errno C token */
#define brlapi_errno (*brlapi_errno_location ())

/* brlapi_strerror */
/** Get plain error message
 *
 * brlapi_strerror() returns the plain error message corresponding to its
 * argument.
 */
const char *brlapi_strerror(int err);

/** Type for packet type. Only unsigned can cross networks, 32bits */
typedef uint32_t brl_type_t;

/* brlapi_packetType */
/** Get plain packet type
 *
 * brlapi_packetType() returns the plain packet type name corresponding to
 * its argument.
 */
const char *brlapi_packetType(brl_type_t ptype);

/* brlapi_errorHandler_t */
/** Type for error handlers
 *
 * Type to give to error handlers which are to be given to
 * brlapi_setErrorHandler()
 *
 * \param err is a BRLERR_ error code
 * \param type is the type of the guilt packet
 * \param buf points to the content of the guilt packet (might be a little bit truncated)
 * \param size gives the guilt packet's size
 */
typedef void (*brlapi_errorHandler_t)(int err, brl_type_t type, const void *buf, size_t size);

/* brlapi_setErrorHandler */
/** Set a new exception handler
 *
 * brlapi_setErrorHandler() replaces the previous error handler by the handler
 * parameter. The previous error handler is returned so that chaining error
 * handlers might be possible.
 *
 * The default handler just prints the error and exit()s
 */
brlapi_errorHandler_t brlapi_setErrorHandler(brlapi_errorHandler_t handler);
void brlapi_defaultErrorHandler(int err, brl_type_t type, const void *buf, size_t size);

/** @} */

#include <pthread.h>

/* brlapi_fd_mutex */
/** Mutex for protecting concurrent fd access
 *
 * In order to regulate concurrent access to the library's file descriptor and
 * requests to / answers from \e BrlAPI server, every function of the library
 * locks this mutex, namely
 *
 * - brlapi_initializeConnection()
 * - brlapi_closeConnection()
 * - brlapi_getRaw()
 * - brlapi_leaveRaw()
 * - brlapi_sendRaw()
 * - brlapi_recvRaw()
 * - brlapi_getDriverId()
 * - brlapi_getDriverName()
 * - brlapi_getDisplaySize()
 * - brlapi_getTty()
 * - brlapi_leaveTty()
 * - brlapi_*write*()
 * - brlapi_(un)?ignorekey(Range|Set)()
 * - brlapi_readKey()
 *
 * If both these functions and brlapi_writePacket() or brlapi_readPacket() are
 * used in a multithreaded application, this mutex must be locked before calling
 * brlapi_writePacket() or brlapi_readPacket(), and unlocked afterwards.
 */
extern pthread_mutex_t brlapi_fd_mutex;

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* _BRLAPI_H */
