Under some circumstances, it may be preferable to communicate directly with BrlAPI's server rather than using 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.
In all the following, integer will mean an unsigned 32 bits integer in network byte order (ie most significant bytes first).
The protocol between 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 BrlAPI needs a reliable packet transmission channel.
To achieve this, BrlAPI uses a TCP-based connection, on which packets are transmitted this way:
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 BRLAPI_PACKET_*
constants defined in api_protocol.h
. Each type of
packet will be further discussed below.
BrlAPI's library ships two functions to achieve packets sending and receiving
using this protocol: brlapi_writePacket
and brlapi_readPacket
. It
is a good idea to use 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.
As described below, many packets are `acknowledged'. It means that upon reception, the server sends either:
BRLAPI_PACKET_ACK
packet, with no data, which means the operation
corresponding to the received packet was successful,BRLAPI_PACKET_ERROR
packet, the data being an integer
which should be one of BRLAPI_ERROR_*
constants. This
means the operation corresponding to the received packet failed.Some other packets need some information as a response. Upon reception, the server will send either:
BRLAPI_PACKET_ERROR
packet.If at some point an ill-formed or non-sense packet is received by the server,
and BRLAPI_PACKET_EXCEPTION
is returned, holding the guilty packet for
further analysis.
The connection between the client and the server can be in either of the four following modes:
BRLAPI_PACKET_VERSION
packet that announces the server version. The client
must send back a BRLAPI_PACKET_VERSION
for announcing its own version too.
The server then sends a BRLAPI_PACKET_AUTH
packet that announces
which authorization methods are allowed. The client can then send
BRLAPI_PACKET_AUTH
packets, which makes the connection enter normal mode.
If no authorization is needed, the server can announce the NONE
method, the
client then doesn't need to send a BRLAPI_PACKET_AUTH
packet.
BRLAPI_PACKET_GETDRIVERNAME
or BRLAPI_PACKET_GETDISPLAYSIZE
to get pieces of information from the server,BRLAPI_PACKET_ENTERTTYMODE
to enter tty handling mode,BRLAPI_PACKET_ENTERRAWMODE
to enter raw mode,BRLAPI_PACKET_LEAVETTYMODE
to leave tty handling mode and go back to
normal mode,BRLAPI_PACKET_IGNOREKEYRANGE
and BRLAPI_PACKET_ACCEPTKEYRANGE
to mask and unmask keys,BRLAPI_PACKET_WRITE
to display text on this tty,BRLAPI_PACKET_ENTERRAWMODE
to enter raw mode,BRLAPI_PACKET_GETDRIVERNAME
or BRLAPI_PACKET_GETDISPLAYSIZE
to get pieces of information from the server,BRLAPI_PACKET_KEY
packets to signal key presses.
BRLAPI_PACKET_LEAVERAWMODE
to get back to previous mode, either normal or
tty handling mode.BRLAPI_PACKET_PACKET
to send a packet to the braille terminal.BRLAPI_PACKET_PACKET
packets to give received packets
from the terminal to the client.
BRLAPI_PACKET_RESUME
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.
Here is described the semantics of each type of packet. Most of them are directly linked to some of BrlAPI's library's functions. Reading their online manual page as well will hence be of good help for understanding.
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 BRLAPI_ERROR_PROTOCOL_VERSION
error packet is returned and the connection is closed.BRLAPI_PACKET_AUTH
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 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 BRLAPI_PACKET_AUTH
shouldn't be
sent by the client.
If the authorization is not successful, the server sends a
BRLAPI_ERROR_AUTHENTICATION
error, and the client can try another
authorization method.
Authorization methods are as follow:
NONE
: the client doesn't need to send an authorization packet.KEY
: data holds a secret key, the authorization is successful only
if the key matches the server secret key.CREDENTIALS
: Operating-System-specific credentials are explicitely
sent over the socket, the authorization is successful if the server considers
the credentials sufficient.Note: when the Operating system permits it, the server may use implicit
credential check, and then advertise the none
method.
BRLAPI_PACKET_GETDRIVERNAME
(see brlapi_getDriverName())This should be sent by the client when it needs the full name of
the current brltty
driver. The returned string is \0 terminated.
BRLAPI_PACKET_GETMODELID
(see brlapi_getModelIdentifier())This should be sent by the client when it needs to identify
which model of braille display is currently used by brltty
.
The returned string is \0 terminated.
BRLAPI_PACKET_GETDISPLAYSIZE
(see brlapi_getDisplaySize())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.
BRLAPI_PACKET_ENTERTTYMODE
(see brlapi_enterTtyMode() and brlapi_enterTtyModeWithPath())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.
BRLAPI_PACKET_KEY
(see brlapi_readKey())As soon as the client gets a tty, it must be prepared to handle
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
BRLAPI_PACKET_ENTERTTYMODE
packet.
BRLAPI_PACKET_SETFOCUS
(see brlapi_setFocus())For the server to know which tty is active, one particular client is responsible
for sending 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
xbrlapi
client would have sent a BRLAPI_PACKET_ENTERTTYMODE(7)
and will send
window IDs whenever X focus changes, allowing display and keypresses switching
between xterms.
BRLAPI_PACKET_LEAVETTYMODE
(see brlapi_leaveTtyMode())This should be sent to free the tty and masked keys lists. This is acknowledged by the server.
BRLAPI_PACKET_IGNOREKEYRANGE
and BRLAPI_PACKET_ACCEPTKEYRANGE
(see brlapi_ignoreKeyRange() and brlapi_acceptKeyRange())If the client doesn't want every key press to be signaled to it, but some of
them to be given to brltty
for normal processing, it can send
BRLAPI_PACKET_IGNOREKEYRANGE
packets to
tell ranges of key codes which shouldn't be
sent to it, but given to brltty
, and BRLAPI_PACKET_ACCEPTKEYRANGE
packets to tell ranges
of key codes which should be sent to it, and not given to
brltty
. The server keeps a dynamic list of ranges, so that arbitrary
sequences of such packets can be sent.
A range is composed of 2 keycodes: the "first" and the "last" boundaries.
Each keycode is composed of 2 integers: the key flags then the command code.
The range expressed by these two keycodes is the set of keycodes whose command
codes are between the command code of the "first" keycode and the "last" keycode
(inclusive), and whose flags contain at least the flags of the "first" keycode
and at most the flags of the "last" keycode. Setting the "first" and "last"
keycode to the same value express only one keycode, for instance. Setting the
first and last keycode to the same command code but setting no flags in the
"first" keycode and setting one flag in the "last" keycode expresses only two
keycode, with the same command code and no flags set except possibly the flag
that is set in the "last" keycode. Setting one flag i in the "first"
keycode and setting the same flag plus another flag j in the "last" keycode
expresses that the keycodes in the range have flag i set and possibly flag
j set, but no other flag. Several such ranges can be provided one after the
other.
BRLAPI_PACKET_WRITE
(see brlapi_write())To display text on the braille terminal and set the position of the cursor,
the client can send a BRLAPI_PACKET_WRITE
packet. The packet begins
with an integer holding flags (see BRLAPI_WF_*
). These flags indicate
which data will then be available, in the following order (corresponding to
flag weight):
U+2800
.A BRLAPI_PACKET_WRITE
packet without any flag (and hence no data) means a
"void" WRITE: the server clears the output buffer for this connection.
BRLAPI_PACKET_ENTERRAWMODE
(see brlapi_enterRawMode())To enter raw mode, the client must send a BRLAPI_PACKET_ENTERRAWMODE
packet,
which is acknowledged. Once in raw mode, no other packet than
BRLAPI_PACKET_LEAVERAWMODE
or BRLAPI_PACKET_PACKET
will be accepted.
The data must hold the special value BRLAPI_DEVICE_MAGIC
: 0xdeadbeef
, then
the name of the driver (one byte for the length, then the name) to avoid
erroneous raw mode activating.
BRLAPI_PACKET_LEAVERAWMODE
(see brlapi_leaveRawMode())To leave raw mode, the client must send a BRLAPI_PACKET_LEAVERAWMODE
packet, which
is acknowledged.
BRLAPI_PACKET_PACKET
(see brlapi_sendRaw() and brlapi_recvRaw())While in raw mode, only 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 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.
BRLAPI_PACKET_SUSPENDDRIVER
(see brlapi_suspendDriver())To enter suspend mode, the client must send a BRLAPI_PACKET_SUSPEND
packet,
which is acknowledge. Once in suspend mode, no other packet than
BRLAPI_PACKET_RESUME
will be accepted.
The data must hold the special value BRLAPI_DEVICE_MAGIC
: 0xdeadbeef
,
then the name of the driver (one byte for the length, then the name) to avoid
erroneous raw mode activating.
BRLAPI_PACKET_PARAM_REQUEST
This packet is sent by the client to request values of parameters. The packet
begins with an integer which holds flags (see BRLAPI_PARAMF_*
) which
describe which, how, and when the value should be returned by the server:
BRLAPI_PARAMF_GLOBAL
flag is set, the server will
return/subscribe the global value instead of the local value.BRLAPI_PARAMF_GET
flag is set, the server acknowledges the
request by returning the latest value with a BRLAPI_PACKET_PARAM_VALUE
packet. Otherwise the server acknowledges the request with a
BRLAPI_PACKET_ACK
packet, without providing the value.BRLAPI_PARAMF_SUBSCRIBE
flag is set, the server will keep
sending asynchronously the value of the parameter whenever it changes, with
BRLAPI_PACKET_PARAM_UPDATE
packets, until
another request packet has the BRLAPI_PARAMF_UNSUBSCRIBE
flag set for this
parameter.BRLAPI_PARAMF_SELF
flag is set along
BRLAPI_PARAMF_SUBSCRIBE
, the server will send the value of the parameter
when it is changed even by the client itself.BRLAPI_PARAMF_UNSUBSCRIBE
flag is set, the server
will stop sending asynchronously the value of the parameter with
BRLAPI_PACKET_PARAM_UPDATE
packets.It does not make sense to set both the BRLAPI_PARAMF_SUBSCRIBE
and
BRLAPI_PARAMF_UNSUBSCRIBE
flags.
Then an integer representing the parameter to be requested. Then two integers that form (in big-endian order) a 64bit value used to subspecify the precise parameter to be requested (e.g. a keycode number).
If several BRLAPI_PARAMF_SUBSCRIBE
packets are sent by the client, as
many BRLAPI_PARAMF_UNSUBSCRIBE
packets have to be sent by the client before
the server stops sending BRLAPI_PACKET_PARAM_UPDATE
packets.
BRLAPI_PACKET_PARAM_VALUE
This packet is sent by the client or the server to provide the value of a
parameter. The packet begins with an integer which holds flags (see
BRLAPI_PVF_*
) which describe which value is being transmitted:
BRLAPI_PVF_GLOBAL
flag is set, the value is the global value
instead of the local value.Then an integer representing the parameter being transmitted. Then two integers that form (in big-endian order) a 64bit value used to subspecify the precise parameter being transmitted (e.g. a keycode number). Eventually, the packet contains the value.
When the packet is sent by the client, it defines the new value of the
parameter, and if it is a global value, the server broadcasts the new value to
all clients which have subscribed to updates. The packet is then acknowledged by
the server on success. If the value can not be changed, the server returns an
error (e.g. BRLAPI_ERROR_READONLY_PARAMETER
).
BRLAPI_PACKET_PARAM_VALUE
This packet is sent asynchronously by the server to provide an update of a value of a parameter. This is sent only if the client has previously sent a BRLAPI_PACKET_PARAM_REQUEST
packet with the BRLAPI_PARAMF_SUBSCRIBE
for the corresponding parameter. It is structured exactly like a BRLAPI_PACKET_PARAM_VALUE
packet.BRLAPI_PACKET_SYNCHRONIZE
This packet is sent by the client and just acknowledged by the server. This allows the client to perform a round-try with the server, thus collecting any pending exception notification.