=======================
A Vivisection of LibGII
=======================

:Author: ric Faurot
:Revision: $Revision: 1.3 $
:Revision date: $Date: 2004/03/02 12:36:24 $

.. contents::
   :depth: 1

Introduction
============

LibGII (General Input Interface Library) is a flexible library for
handling input from a variety of sources, including keyboards, mice,
joysticks, etc.


LibGII is based on the concept of input streams, which virtualize
access to the underlying input drivers.  Events from various input
devices are abstracted into easy-to-use structures.  LibGII also
allows the application to join streams together, receiving input from
an arbitrary combination of devices.


LibGII consists of a main library (`libgii.so`) and a multitude of
dynamic drivers. The library then loads the necessary "drivers" for
the requested input.

LibGII is the result of splitting event functionality from LibGGI in
order to further abstract it.  Thus its design is deliberately similar
to LibGGI, which uses LibGII for input (and LibGG, a library of
LibGGI/LibGII common functions) internally.



The following document is an attempt to give a detailed view of the
reasons behind LibGII's design, and its internal structures and
mechanisms.  All the info reported here result from the author's
reading and (hopefully) understanding of the code. If something is
wrong, incomplete, or ambiguous, feel free to notify the author.


The GII event model
===================


Event semantic
--------------


As GII aims to fully abstract input events on a computer system, it
must provide the developer with a general event model that will
encompass all kinds of event sematic found either in hardware or
software input devices. GII defines the following semantics, or
categories into one of which any event may be classified:

    Key event
        generated by a keyboard device where keys are bound to a code, 
	symbol, or character, and may be pressed and released, possibly with 
	modifiers (SHIFT, CTRL).

    Pointer motion event        
	generated by devices that give a position on several axis and
	reflect the motion of a pointing device. Typically a mouse,
	with at least 2 axes or dimensions.

    Button event
        devices (typically pointer devices) may have a set of buttons
	which can be, just like keys, pressed and released.  However,
	unlike keys, buttons are not bound to a code, symbol, or
	character.

    Exposure event
        This event is specific to visuals and is not directly mapped
	from a physical device. It is sent to an application when part
	of the screen was hidden for any reason and it becomes visible
	again. A part of it might need to be repainted.


    Valuator event
	These events are sent by any kind of captor that measures
	physical quantities.  Typically, these are used to monitor
	sets of thermometers in the fission core of nuclear power
	plants...  (not :-) Valuator events are meant for high
	sampling rates of many variables, but are also useful with any
	device more complicated than a wheel mouse.

    Command and Information event

        This family of events is used to exchange information with
	devices or drivers, and also to issue them commands.  It is
	useful to query or set states on a software-configurable
	device.

Most applications involving user interaction should be happy with
these.


Event types
-----------


Along with the semantic of an event, there are different kind of
actual event that may occur. A key can be pressed or released, for
example, or a pointing device will notify movement, either in relative
or absolute position.  Thus, for each event category, a set of
possible events is defined.

evInformation
    More on these later.

evExpose
    More on this later.

evKeyPress, evKeyRelease, evKeyRepeat    
    These events belong to the key event group. They are delivered
    when a key on a device has changed state.

evPtrRelative, evPtrAbsolute
    These events report pointer (mice, etc.) motion in terms of the x,
    y, z coordinates and the wheel values of the device.  The motion
    described may be relative (offset from the current location) or
    absolute (a specific location on the 'screen'), depending on
    whether the event is of type evPtrRelative or evPtrAbsolute,
    respectively.

    LibGII itself does not attempt to interpolate or keep track of the
    *current* pointer position.  (This is the responsibility of either
    the application itself or LibGII filter library.)  However, in
    some situations LibGII may simultaneously report both relative and
    absolute pointer motion for the same input.

evPtrButtonPress, evPtrButtonRelease
    They belong to the Button event category.

evValRelative, evValAbsolute
    More on those later.


The number of event types is limited to 32, so that they can be
grouped in masks on a 32bits int. Only 12 are used right now.


Event data
----------

Events carry two sets of data, common event data which all events have, and 
type-specific data.


Common fields are:

    - size : the size of this event in bytes (limit 256). Note that
      the event structure size is constant. This value only gives the
      number of bytes relevant for this particular event.

    - type: the type of the event (one of the ev* decribed above).

    - origin: the origin of the event (see below).

    - target: the target of the command.

    - error: if an error occured (?? people will want to know moe
      about this - me too)

    - time: A non-monotonic timestamp indicating when the event
      was generated.

Event specific data:

    PtrButton
        the number of the button that was pressed, or released,
	depending on the event type.

    PtrMovement
        the movement in x, y, z and wheel, either absolute or
	relative.

    Key
        the key symbol, value and number, along with the current
	active modifiers (ALT, SHIFT, CTRL,...). The developer doesn't
	have to keep track of the state of these modifiers himself.

    Valuator
	the readings of some or all of the quantities monitored by the
	measuring device.  At most 32 quantities with contiguous
	indices may be reported.  Devices reporting more than 32
	values will generate several events with an index offset set
	accordingly.

    Command/Information
        a code identifying the command or event and specific data, if
        any.


A closer view on input sources
==============================


Input source
------------

In GII, an input source is an abstract link to one or more event
source(s). What we call an event source is a single instance of a GII
module that is able to generate events by some means. Such a module is
in most cases a software driver for a system component, laying between
the application with the GII event model and the system specific event
source with its particular model. For example, the linux keyboard
module can provide a key input source to any GGI application by
knowing two things:

    1. how to invoke the linux keyboard subsystem (/dev/kbd...)
    2. how to map its events into the GII world.


An input source manages an event queue, where events generated by
event sources are... well... queued! The application just has to read
or poll the event sources to get the events one after another.
(Polling should be done at regular intervals by the application to
ensure that the event source is properly processed.)


In the GII input source abstraction, an event source is atomic in the
sense that it refers to a single module instance, usually wrapping a
whole subsystem. But this subsystem can be fairly complex and
subdivided into many software or hardware components. Let us consider
for example linux-evdev LibGII module. Ultimately, all events in the
linux system will be accessed through the evdev interface. So the
single linux-evdev module intance would pass us all events occuring on
the system.  LibGII inputs are written such that this single access
point can address multiple distinct devices that might need to be
identified individually.


This leads us to the notion of device. Devices are the building blocks
for event sources, A single event source may be composed of several
devices. For example, the module wrapping the xlib events has two
devices, the XWin Keyboard and the XWin Mouse. The first will generate
key events, while the second will report both the pointer movement and
button state -- however both kinds of events will enter the
application on the same LibGII handle.


Understanding origin
--------------------


Simple applications usually read events from an input source without
caring much about the actual event sources. They just need to be
notify about mouse motion and key strokes.  LibGII gets more mileage
out of this trivial programming paradigm by allowing multiple handles
to be merged into a single handle.  So, even if two devices use
entirely different LibGII modules, they may be made to appear to an
application to be part of the same unified input handle.


However, there are cases where the application has to know a bit more
about the exact composition of an input source. Suppose that a user
has two mice which are connected to the same input source, typicaly a
touchpad and a serial mouse. The application can simply listen to
pointer events, regardless of their origin, so that the user can
control a single pointer with any of the two mice. In fact the
application itself doesn't even notice that the user has two mice.
This is hidden in the input source.


But the two mice can also be used to control two separate characters
at the same time in a multiplayer game. So, they need to be
differentiated somehow.  A solution is to separate the input sources
for each player. Problem: you have to poll two input sources in the
application, which tends to complicate the application's codebase. A
more elegant approach (LibGII's approach) is to know which device
generated the event, and act accordingly.


When a module is instantiated, it is given a unique identifier in the
current execution context. This identifier, called the origin, is used
by the application to refer to a specific event source.  If the same
module is instantiated multiple times, each instance will have
different origin.



This origin number refers to the first device in the input source.  A
unique origin is also assigned to each of the device instances in the
event source. In the current implementation, the origin of the n-th
device is the origin of the event source plus n, with a comfortable
limit of 256 devices.  The first device's origin can be seen as a mask
for event sources.  They are always multiples of 256.  When an event
is delivered to the application, the origin field can be checked to
know both the device it came from, and the event source that contains
that device.


The origin is also used to communicate with an event source, for
example to use force feedback in a joystick or steering wheel.


Masks
-----

An event mask is a set of bit flags identifying which categories of
events the application.


Event masks serve two purposes.  The first is to eliminate excess
traffic/system load.  For example as one possible worst case, when you
have an input source which is separated from your application by a
wide area network -- if you are only interested in the keyboard
events, you can stop the mouse events from being sent from the far end
in the first place.  Another worst case is when you have a VERY
talkative device on a slow CPU.



The second is as a convenience, to allow the application to access
only the events which it wants at a particular moment, so, for
example, an application can ask for any keyboard events without having
to process mouse movement event first.  Note that setting the event
mask on an event source does not guarantee that the application will
never find such an event in the event queue... there are various
corner cases where unwanted events may pop up from time to time.  An
application should always ask for exactly the events which it wants to
process.


Filters
-------


The GII filter is a powerful way to interact on the event queue,
without the event sources or the application being aware of it.  A
filter is actually a module, just like a normal event source, but it
does not generate events from the external world. Instead it can
intercept events as they are queued and perform any kind of
modification, including eating the event so it is not passed to any
other filters or to the application.


How can it be used? For example you can invert the directions of your
friend's mouse at no cost, or remap your keyboard. An application
requires a mouse and you don't have one: just put a filter that
intercept keystrokes, and generate fake pointer movements on
Ctrl-Shift-&lt;arrows&gt;.  More generally it can be used to
reconfigure somehow the input of an application that was a bit too
strict about the way it handles inputs, e.g. a game with an annoyingly
large joystick dead-zone.


Other examples are a filter that saves events to a file (for later
playback) or another one that repeats events on network socket to
allow remote monitoring by a third party.


A real case study
-----------------


Santa brought us the latest Santa Claus simulator.  A great game
indeed.  And it uses GII, which makes it even better.


At this point, two scenarii.

    1. We are a hardcore gamer, inclined to get the best out of the
       Santa simulator. Consequently, we choosed the special pack including
       the software, and the latest "Ultimate All-in-One Santa
       AirFight Controller - When Xmas delivery is serious business".
       Let us admire this beauty:

           - 3-axis stick up/down left/right roto, with 4 buttons and
	     force feedback, for precise droppings in extrem
	     conditions.

	   - 4 throttles with 2 buttons on each, for a better control of
	     each reactor (or deer).

	   - An sticker for your car, a field in which GII is irrelevant.

       All these features are used in the game, so there is a one-to-one
       match between them and a game control. This module would
       generate pointer motion and button events, just like any
       joystick. So it could be used transparently as a simple
       joystick by any other application.

       But wait, there is more! It's called the second scenario.

    2. We're a casual gamer. This simulator is probably fun, but the
       pack was definitely overkill.

       However, we have an old joystick and a couple of wheel
       mice. Hey, these wheels would surely make pretty handy
       throttles!  Let's plug that all together, set the GII_INPUT to
       reflect our new configuration and run our simulator.


       Now the application scans through the input source.  The user
       goes to the configuration menu where the app displays all
       available devices with the type of event they generate, and on
       the other side all the controls used in the game.  The user can
       associate devices to controls, provided that they have the
       common semantic: axis are axis, and buttons are buttons. But
       the mapping is up to the user. So he can disable force
       feedback, assign the second mouse wheel to reactor 3 and 4,
       etc... You get the idea.


       Conclusion: The application was designed to map arbitrary event
       sources to controls in the game, allowing any device to be used
       for these controls.  It didn't have to be specially designed
       around the Santa Controller, but can make use of all its
       features. Now the inventive user can come up with a messy set
       of input devices that will cooperate wonderfully on the
       application.

       The application is really not cooperative? So be it. A custom
       filter module will do the job.


Using GII in an application
===========================


Using LibGII as a standalone event library
------------------------------------------

While LibGGI relies on LibGII, the latter can be used independently as
an event library for a non graphic application, or with another
graphic subsystem. LibGGI automatically set LibGII up at
initialization, but if LibGGI is not used, LibGII has to be
initialized by the programmer.

The minimal GII program will look like this::

  #include <ggi/gii.h>

  int main(int ac, char **av) {
  
      if ( giiInit() < 0 )
	      exit(1);
     
      giiExit();

      return 0;  
  }


Most LibGII functions return `0` to indicate success, and a negative
error code to indicate errors.  Return codes greater than `0` are
usually additional hints or other non-negative integer data.


A list of error codes and descriptions can be found in the
`ggi/errors.h` file, which is part of the LibGII/LibGG package.


When using LibGGI, an input source is automatically bound to the
visual, with default devices opened. All the LibGII functions have a
LibGGI equivalent which takes a ggi_visual_t instead of a
gii_input_t. Of course, other inputs can still be opened manually.



Opening
-------

Stay tuned.


Merging and Splitting
---------------------

When an input or filter module is successfully opened (with the
`giiOpen` function), it creates an input source. In the case of a
filter, this input source will hardly provides any event, since the
only time a filter can generate an event is when an other event is
queued on the input source.

As we said earlier, an input source can be composed of several event
generators.  This is achieved by merging input sources together with
the `giiJoinInputs` function. This input source will recieve all
events generated by the inputs and filters it contains, and pass them
through the filters. This allow an application to read all its events
from a single source, regardless of the number and variety of devices
it is actually bound to.


Splitting (with the `giiSplitInputs` function) is necessary when you
want to drop a single source.  A new input source is created, bound
only to the chosen source, which is removed from the former
input. This input can then be closed.


Note that the ggi interface does not allow to split inputs associated
to a visual directly. Additionnal inputs may be joined, but to close
individual inputs, you have to use the `ggiDetachInput` function. This
function remove all inputs from the visual and return a gii_input on
which all gii function apply. Event functions will not work then on
the visual itself.



Event Management - the Lost Art of Polling
------------------------------------------

Stay tuned.




Writing a module
================

Before we describe the module writing process, it is worth taking
a closer look at how GII works internally.

Event queue mechanism
---------------------

Each gii_input maintains a set of event queues, each queue
corresponding to a single event type. All the events of this type will
be queued in that queue. These queues use circular buffers to store
events. When an event is generated by a device, it is queued
appropriately by the library.  Having a separate queue for each event
type prevents events of one type from pushing events of another type
out of the event queue when it fills up -- so your mouse events don't
pile up and delete your keyboard events.



When an application reads an event, these queues are scanned and the
next event, chronologically, is removed and returned to the caller.
It works more or less like a fifo, written to by input modules and
read by applications.


Note that no dynamic memory is ever allocated throughout the process.
Input modules will be given the event structures to fill when they
need to report an event, and the user must provide its own event
structure to read one. Actually, dynamic allocation occurs, but only
when the queues are created, which happens only when the first event
of a kind must be queued and the corresponding queue doesn't exist.
This cuts down on the actual runtime processing requirements of event
sources.


Writing a module
----------------


The first thing you need to do before writing a module is to define
what devices are exposed to GII and what events they generate.


A good separation between a device features is important to allow
applications to have precise handling of there input sources.  For
example, it is a good idea to define two devices for a 2-stick
joystick, so that the application can make a distinction between them
and address them individually. Remember that the origin of a device is
the smallest unit an application can address, so of both sticks have
the same origin (they are the same gii device) and send the same axis
data (x, y, rotation and throttle), the application will not be able
to know which one was moved.


On the other hand, excessive device definitions are not a good thing
either. One could imagine that a mouse input module would define one
device for the axes and one for the buttons, but it makes it more
difficult for a sophistciated application as it has to make a link
between the buttons and movement device for normal pointer operations.


When you define your devices, think of them not only as event
providers, but also as event recievers. Things like joystick
calibration, force feeback notification, etc. imply that events will
need to be targeted at devices, so in our two-joystick example if
there are two separate force feedback mechanisms this is more reason
to identify them with two separate device origins.



Defining your devices
---------------------

Once you know which devices we need for your module, you'll have to
fill in a gii_cmddata_getdevinfo for each of them::

  typedef struct {
	
	char		longname[75];
	char		shortname[5];
	
	gii_event_mask	can_generate;

	uint32		num_buttons;	/* Maximum number of buttons. */
	uint32		num_axes;	/* Maximum number of axes. */
  } gii_cmddata_getdevinfo;


This structure will be sent to the application in a information event
on demand or when the module state changes.


The longname and shortname have a limited size, and must terminate
with `\0`. can_generate is a mask defining what kind of event this
device is able to generate. If the device doesn't have buttons nor
axes, these numbers must be set to 0, or GII_NUM_UNKNOWN if the
numbers are not known.


If the device is a valuator, or can generate valuator events, a
gii_cmddata_getvalinfo must also be defined::


  typedef struct {
	
	uint32		number;		/* Number of the valuator */

	char		longname[75];
	char		shortname[5];

	gii_valrange	range;
	gii_phystype	phystype;

       	sint32	SI_add,SI_mul,SI_div,SI_shift;

  } gii_cmddata_getvalinfo;

  typedef struct gii_valrange {
	sint32		min, center, max;
  } gii_valrange;


The SI_* values are used to compute the floating point value of
the reported values with the formula::

 SI = (float)(SI_add+value[n])*(float)SI_mul/(float)SI_div*pow(2.0,SI_shift)

All these structures can be declared static in the module source.


Defining private data
---------------------


Your module will most probably want to associate private data with an
input, for example a file from wich data is read to produce events,
such as a serial port reading mouse data.  The gii input structure has
a void * priv field that the module is free to use for its specific
needs.


Defining special commands
-------------------------


If your command doesn't carry additional data it must be OR'ed with
GII_CMDFLAG_NODATA. Commands that are private to a specific module
must also have the GII_CMDFLAG_PRIVATE flag set.


Module interface
----------------


The module may define a number of functions that will be called by the
GII library. They are not all required, but a typical module should at
least define GIIclose, GIIeventpoll and GIIeventsend.

::

  int GIIclose(struct gii_input *inp);

This function is used when the device is closed. All you have to do
is to perform any required cleanups like free privately allocated
memory. It is not supposed to fail so the return value doesn't
mean much and will not be checked. Anyway, it is a good practice to
return 0 on normal operation.

::

  int GIIhandler(struct gii_input *inp, gii_event *event);


If a module defines this functions, it is a filter.  Before being
queued, all events will be passed to this function.  It is free to do
whatever it wants, like altering the events, or posting other
events. If this function doesn't return 0, then the event is eaten and
will not be queued. Note that it will also not be delivered to
remaining filters.

::

  int GIIseteventmask(struct gii_input *inp, gii_event_mask evm);


A module may define this function if special internal operations may
or must be performed to optimize event generation in case all event
types are not needed, or new functionality must be invoked. As for
GIIclose, the return value is not kept.  Nonetheless you should return
0 by default or any error code. This should set the cureventmask field
of the input if necessary.

::

  gii_event_mask GIIgeteventmask(struct gii_input *inp);


If the event source mask is subject to change dynamically
(plug and play devices on an USB bus) this function can be
defined to let GII poll the current event mask.

::

  int GIIsendevent(struct gii_input *inp, gii_event *event);

Event are sent to modules via this functions.  The basic behaviour is
to send to correct device or valuator information if required, or
perform any module specific operation, like disabling a device,
applying a force feedback, etc...  When returning the device
information, the event is evCommand and the code is
GII_CMDCODE_GETDEVINFO.

::

  int GIIgetselectfdset(struct gii_input *inp, fd_set *readfds);

If the module must wait on a file descriptor from which it will
generate events, this function must be defined to let GII know about
these descriptors. The expected behaviour is to set readfds to the fd
(see select(2)) on which the source will be waiting, and return the
highest of these descriptors.

::

  gii_event_mask GIIeventpoll(struct gii_input *inp, void *arg);

When this function is called, the module must queue any pending
event. It returns the mask of queued events. This function is
must not be blocking.

::

  int GIIdlinit(gii_input *inp, const char *args, void *argptr);

Whereas all previous functions are usually defined static this one
must be named as is and will be looked for by the libgii dynamic
module loader code. It will be called when a new instance of a module
is opened and bound to a new gii_input.


The args string carries additionnal parameters that the module might
want to use to alter its behaviour or configuration. For example, the
input-tcp module needs a host and a port.

The argptr argument might be used to communicate special binary data
to the module. This is the case for the X11 input module which needs a
hook the xwindow it is listening on.

The function basically works this way:

    1. allocate a private structure
    2. perform any subsystem initialisation (opening a special
       file,...)
    3. register all devices
    4. fill the input structure fields, callbacks and flags
    5. return 0 if everything is ok

The fields that a module can initialize are:

    the callbacks functions
        All the callbacks described above can be set. Only set the
        ones you want to override since they are all set to safe
        defaults. This is especially true for GIIseteventmask,
        GIIgeteventmask and GIIgetselectfd. These are actually only
        necessary to give the module a chance to dynamically invoke or
        dismiss devices dynamically.

    targetcan
        a mask of events the target can produce. If it is not the
	default value is 0, which means that the soure will never be
	polled.

    flags
        The only(?) flag currently defined is GII_FLAGS_HASPOLLED. If
	it is set, it means that the input can't wait for events on a
	file descriptor so select(2) will not work with this input
	since a call will never be interrupted. In this case, GII has
	to emulate blocking call to giiReadEvent or giiPollEvent by
	polling these devices regularly using small timeouts. The
	default value is 10ms but can be changed at compile time. Note
	that this is generally quite bad for overall system
	performance since a lot of CPU cycles will be wasted polling
	devices.


    fdset, maxfd

        the set of file descriptor on which the source is waiting and
	the highest of these descriptor. You don't necessarily have to
	define the GIIgetselectfd function. You can simply set these
	values and if they change, simply call _giiUpdateCache to
	notify GII.  The default callback will be just fine. Remember
	that calling _giiUpdateCache will wake up all other modules in
	the input, so do it only when necessary.


libgii intraface
----------------


LibGII provides a few functions for module developers to
access the internal implementation, that they we'll have to
call in their callbacks.

::

  void _giiEventBlank(gii_event *ev, int size);
  int  _giiEvQueueAdd(gii_input *inp, gii_event *ev);

\_giiEventBlank zeroes an event structure of the given size.  The time
is set to the current time, the origin to GII_EV_ORIGIN_NONE and the
target to GII_EV_TARGET_ALL.

\_giiEvQueueAdd post the given event to the input queue.

These functions are used in the poll callback or when an information
request is submitted to the sendevent callback.

::

  uint32 _giiRegisterDevice(gii_input *inp,
			    gii_cmddata_getdevinfo  *dev,
			    gii_cmddata_getvalinfo  *val);

  int    _giiUnregisterDevice(gii_input *inp, uint32 origin);


These functions are used to define the devices of a module instance.
For each device defined as we've seen before, there should be a call
\_giiRegisterDevice in the GGIdlinit function. The parameters must
refer to static structures in the module code which should not be
altered later on.

There is no need to unregister devices on close. This is done
automatically by libgii. In fact \_giiUnregisterDevice will only be
used in cases where a device is dynamically disabled during the
execution of a program, for example when recieving a special command
event. Most modules will never use it.

\_giiRegisterDevice returns the origin given to this device by GGI. It
is usually a good idea to keep track of this result since it will most
probably be needed to know which device corresponds to the target
found in command events sent to the module.

::

  void _giiUpdateCache(gii_input *inp);</term>

GII caches information about the event sources found in an input, like
flags, event masks and more importantly the set of file descriptors on
which modules are waiting. If for any reasons, one of these changes
for a source, it must call \_giiUpdateCache to force libgii to rescan
all these values.  Note that this will call the GIIgeteventmask and
GIIgetselectfdset functions for the modules that define them. So do
**not** call \_giiUpdateCache in either of those functions.


This is usually used in the poll function if a file is closed and will
not be read anymore. In that case the read fdset should be changed.


A few notes/questions on GII to the maintainers/developers
==========================================================


- Should their be a way to send events to all the devices of a single
  source?
  
  My suggestion is to reserve 0x00 or 0xff in the origin for this.
  right now, origin 0x00 is not assigned to a device.
  This could be seen as adressing the whole source (e.g. for querying
  devices, rather than broadcasting to all sources)


- The poll interval could be modified via an envvar. Actuallly many
  things could be controlled by envvar, like the size of the event
  queues.

- What exactly is the GIIgetfdset suppposed to be there for?  The same
  question holds for GIIgeteventmask.


- How to have gii send a default response to devinfo and devval
  command?  an internal helper could be defined.


- I think GII_EV_TARGET_ALL should pass the event to all module but
  not put it on the queue.


- GII_CMDCODE_GETDEVINFO doesn't carry data on request but also
  doesn't have the GII_CMDFLAG_NODATA bit set. Is it a sane exception?
