XENMOU2 Specification

This page describes the second version of the XenMou protocol. While the first version supported an absolute mouse pointer, this second version is designed to be more flexible, and support a variety of different types of input device, including a mulitouch tablet screen.

As before, XenMou is a PCI device which may be present at any BDF in the system. The Xen PCI Vendor ID 5853 and Device ID C110 will be assigned for this device. It will be an Input Device Class, Mouse Subclass (0x0902).

The device can generate an interrupt.

This PCI device contains 1 BAR: BAR0 is non prefetchable memory of 8k+ bytes (3+ pages) containing MMIO registers and mouse event data.

The pages in BAR0 contain a page for Global registers, one or more pages for event data, and a final page containing a device configuration space. These three sections are described in the three sections below.

Global Registers (Range 0x00000 - 0x00FFF)

The global registers control features of the xenmou adapter that reflect the entire device.

0x00000 - XMOU_MAGIC

Type: Read-Only

Magic number. This register always reads 0x584D4F55

0x00004 - XMOU_REV

Type: Read-Only

Revision number of the back end. This register reads 0x1 until XMOU_CLIENT_REV has been written too, after which it returns it true version (0x2 as of writing). This value should not be used as an indicator of compatibility, as newer versions may be backwards compatible. Please refer to XMOU_CLIENT_REV for use in version compatibility checking.

0x00100 - XMOU_CONTROL

Type: Read-Write

Control register to change backend settings.

 Bit 0:  XMOU_EN Set to enable the xenmou device.
 Bit 1:  INT_EN  Global bit to enable interrupts from the device.
 Bit 2:  MOU_V2  This is no longer supported.  It use to enable version 2 of the xenmou protocol.  XMOU_CLIENT_REV should be used instead.
 Bits 3 - 31: Unused.

0x00104 - XMOU_EVENT_SIZE

Type: Read-Only

Size in bytes of the individual event data structures in the event register range.

0x00108 - XMOU_EVENT_NPAGES

Type: Read-Only

Number of pages that make up the the event register range.

0x0010C - XMOU_ACCELERATION:

Type: Write-Only

Not used.

0x000110 - XMOU_ISR:

Type: Read-Only

Interrupt status register. Write to dismiss interrupt.

 Bit 0:   INT  Indicates if this device is currently generating an interrupt.
 Bits 1 - 31: Unused.

0x00114 - XMOU_CONF_SIZE

Type: Read-Only

This returns the size, in bytes of the XenMou device configuration record (described later under #Device_configuration_space). This value should be used when indexing the array of these records, in place of the size you expect the record to be. This is to allow for expansion, and failing to do so may result in compatibility issues.

0x00118 - XMOU_CLIENT_REV

Type: Read-Write

This should be set on start up, to the version of XenMou spec you expect to use. If not set, the xenmou back end will follow the xenmou version 1 spec. Once you have written the spec version number (0x2 as of writing), you should read this register back. If the value read is not that which was written, then this indicates a fail condition. Reading 0 indicates that the version was rejected, a newer version of the spec may need to be adhered to. Note that newer versions of the back end may still support older versions of the spec - but not necessarily all versions. This register may only be written to before XMOU_EN of the control register, has been enabled. Attempts to change the protocol version, while enabled, will be ignored.

Event Registers (Range 0x01000 - 0x0nFFF)

The event registers occupy XMOU_EVENT_NPAGES pages of 4096 bytes. There are (PAGE_SIZE/XMOU_EVENT_SIZE - 1) individual event data structures per page. The individual event data structures are each XMOU_EVENT_SIZE bits in size (XMOU_EVENT_SIZE is always 64 or greater bits). The first event data structure on the first page is unique in that it holds the read and write pointer indexing into the other event data structures.

0x01000 : XMOU_READ_PTR:

Type: Read-Write

Current read offset index to the next event data structures to read (in XMOU_EVENT_SIZE units).

0x01004 : XMOU_WRITE_PTR:

Type: Read-Only

Current write offset index to the event data structures one beyond the last one written to (in XMOU_EVENT_SIZE units).

0x01000 + (XMOU_EVENT_SIZE) : Event Record Queue

Type: Read-Only


The event registers data structures starting at (0x01000 + XMOU_EVENT_SIZE) form a logical ring spanning XMOU_EVENT_NPAGES pages. The offset pointers above are indices into the ring. If the write pointer is less than the read pointer then the ring has wrapped. When the read pointer is not equal to the write pointer, there are events to read. The pointers being equal always means there are no events to read, that is read == write never means that the ring is full with (PAGE_SIZE/XMOU_EVENT_SIZE - 1) events. A full ring will have a maximum of (PAGE_SIZE/XMOU_EVENT_SIZE - 2) events in it. The ring may wrap at this point, controlled by the underlying virtual HW. When events have been consumed, the xenmou driver software moves the read pointer forward up to the write pointer. Driver software never moves the write pointer. A interrupt is generated when events need the read from the buffer - this is when a SYN_REPORT event (described later) is added. The event record format is described in the next section.

Event Records

Each of the event records are formatted in the following manner:

uint16 type  // Type of record, including KEY (key/button), REL (relative scalar), ABS (absolute scalar), SYN (Synchronization events.) or DEV (Device change events).
uint16 code  // This indicated which item (be it a key or axis) this record represents.
uint32 value // This is the new value for the item indicated by two field above. For a button or key, this would be a Boolean.

The records above are able to accommodate a huge number of different types of event. Furthermore, events are aggregated to form more complex events. Each input device will only be able to send a small subset of the possible events. DEV (device) events are used to indicate which device is emitting the following events, as well as indicating which events are possible. For example a tablet stylus can emit absolute X and Y events, while a traditional mouse emits relative X and Y events.

Below is a small subset of events that are possible. This list should probably be considered the minimum to set to implement. A fuller list can be found here with descriptions here. Detail on the multitouch protocol here.

Type 0x6 DEV: Device

These events describe actions relating to the device emmiting the remaining events. DEV events are not subject to Synchronization events.

CodeNameDescription
0x1DEV_SETEvents after this event belong to the device indicated by <value>. A value of -1 indicates that it is from an unknown source. This number may be referred to as the device's slot number.
0x2DEV_CONFThis indicates that a new device has been created, which from here shall be referred to as <value>. The provided slot number ( <value> ) can be used to find a description of this device, in the configuration space, described later. This information is expected to be considered before attempting to decode events for this device.
0x3DEV_RESETThis indicates that device <value> is no longer valid, and any resources associated with this may be freed. If <value> is 0xFFFF, then all devices are existing invalid - such event is used on start up.

Type 0x0 SYN: Synchronization

CodeNameDescription
0x0SYN_REPORTThis is used as a barrier to indicate that all events of other types (excluding DEV), which occur between the same set of SYN:REPORT events, occurred at the same time. That is to say, events between pairs of SYN:REPORT events are to be aggregated. For example, when moving a mouse, it is common for both the X and Y coordinate to change together, and so an event for each would be emitted, and because they where emmited between a pair of SYN:REPORT events, they would be aggregated. If however, only one axis changed, then only an event for that axis would be emitted. After this event has been added to the buffer, and interrupt is generated.
0x2SYN_MT_REPORTThis is used for less able multitouch devices, to separate multiple sets of X/Y coordinates. We currently have no devices which do this.
0x3SYN_DROPPEDThis informs the client when input events have been dropped from the evdev input buffer due to a buffer overrun.

The client should use this event as a hint to reset its state or ignore all following events until the next packet begins. Client should ignore all events up to and including next SYN_REPORT.

Type 0x2 REL: Relative

CodeNameDescription
0x00REL_XMovement on the X axis.
0x01REL_YMovement on the Y axis.
0x08REL_WHEELVertical wheel movement.

Type 0x3 ABS: Absolute

CodeNameDescription
0x00ABS_XPosition on the X axis.
0x01ABS_YPosition on the Y axis.
0x18ABS_PRESSUREThe pressure the pen/tool is being applied.
0x2fABS_MT_SLOTEach finger/pen in contact with the screen is given a slot number, and this is maintained until it is released. Multitouch events, on the current device, are henceforth for this slot. If only one finger/pen is in contact with the screen, then only one slot in required, and so this event may be omitted. If multiple fingers/pens are in contact with the screen, it would be common for may slot changes to occur during one pair SYN:REPORT events, to indicate each finger moved at the same time.
0x35ABS_MT_POSITION_XX coordinate for the current slot. (Finger/pen)
0x36ABS_MT_POSITION_YY coordinate for the current slot. (Finger/pen)
0x39ABS_MT_TRACKING_IDUnique ID of initiated contact, a value of -1 indicates finger/pen released.

Type 0x01 KEY: Key/Button

CodeNameDescription
0x110BTN_LEFTThe left button on a mouse.
0x111BTN_RIGHTThe right button on a mouse.
0x112BTN_MIDDLEThe middle button on a mouse.
0x113BTN_SIDEThe side button on a mouse.
0x114BTN_EXTRAThe extra button on a mouse.
0x115BTN_FORWARDThe forward button on a mouse.
0x116BTN_BACKThe back button on a mouse.
0x117BTN_TASKThe task button on a mouse.
0x140BTN_TOOL_PENThe current tool is now a pen.
0x141BTN_TOOL_RUBBERThe current tool is now a rubber.
0x145BTN_TOOL_FINGERThe current tool is now a finger.
0x146BTN_TOOL_MOUSEThe current tool is now a mouse.
0x14aBTN_TOUCHThe current tool touched the surface.
0x14bBTN_STYLUSThe first button on the stylus was pressed.
0x14cBTN_STYLUS2The second button on the stylus was pressed.

Example

A stream might look as follows:

DEV_RESET 0xFFFF
DEV_CONF 4              /* The config associated indicates its a stylus */
DEV_CONF 7              /* The config associated indicates its an multi-touch device */
DEV_SET 4

ABS_X 345
ABS_Y 987
BTN_TOOL_PEN 1         /* Pen is hovering over the surface*/
SYN_REPORT

ABS_X 346
SYN_REPORT

ABS_Y 986
SNY_REPORT

ABS_X 344
ABS_Y 985
ABS_PRUSSURE 45
BTN_TOUCH 1          /* Pen touches the surface */
SYN_REPORT

ABS_PRESSURE 48
SYN_REPORT

ABS_X 300
ABS_PRESSURE 20
SYN_REPORT

BTN_TOUCH 0          /* Pen is no longer touching surface */
ABS_X 388
SYN_REPORT

ABS_Y 810
ABS_X 320
BTN_TOOL_PEN 0      /* Pen is no longer hovering over the surface */
SYN_REPORT

DEV_SET 7


ABS_MT_SLOT 0                  /* First finger goes down */
ABS_MT_TRACKING_ID 45
ABS_MT_POSITION_X 200
ABS_MT_POSITION_Y 300
SYN_REPORT

ABS_MT_POSITION_X 210          /* Still slot 0 */
SYN_REPORT

ABS_MT_POSITION_X 220
ABS_MT_POSITION_Y 302
SYN_REPORT

ABS_MT_POSITION_X 225
ABS_MT SLOT 1                  /* Second finger goes down */
ABS_MT_TRACKING_ID 46
ABS_MT_POSITION_X 700
ABS_MT_POSITION_Y 800
SYN_REPORT

ABS_MT_SLOT 0
ABS_MT_POSITION_X 226
ABS_MT_POSITION_Y 308
ABS_MT_SLOT 1
ABS_MT_POSITION_Y 810
SYN_REPORT

ABS_MT_POSITION_Y 815          /* Still on slot 1! */
ABS_MT_POSITION_X 720
SYN_REPORT

ABS_MT_SLOT 0                  /* first finger lifted */
ABS_MT_TRACKING_ID -1
ABS_MT_SLOT 1
ABS_MT_POSITION_X 725
SYN_REPORT

ABS_MT_POSITION_Y 816          /* Still on slot 1! */
ABS_MT_POSITION_X 740
SYN_REPORT

ABS_MT_TRACKING_ID -1          /* Second finger is lifted */
ABS_MT_POSITION_X 741
SYN_REPORT

Device configuration space

After receiving a DEV_CONF event, the details of the new device can be found in this space. The configuration space consists of an array of records in the format described below. The stride of the array should be taken as XMOU_CONF_SIZE, and not a calculation of the size of the device record. Although this may be programmatically inconvenient, it allows for record expansion, without breaking compatibility.

The index into this table is the device's slot number. Not all slots are necessarily filled. Entries into this array may be added or removed in real time, as devices are added or removed to the system. The DEV events are used to indicate when the array has been updated.

This array is located on the page immediately following the event record pages. That is the say it is located at the base address + n * 0x1000, where n = 1 + number of event pages.

Device Record

 char name[40]      // This is the name of the device, in text.
  
 uint32 evbits      // A bit mask indicating which types are used.  Eg, 0xB would indicate SYN events, KEY and ABS events, 
                    // but not REL events (Or any other type).  DEV events are alawys present, and not included in this bit mask.
  
 uint32 absbits[2]  // A bit mask (64 bits) indicating which absolute codes are used.  Each bit corresponds to the code number, 
                    // so 0x3 would indicate ABS_X codes and ABS_Y codes.
  
 uint32 relbits     // A bit mask indicating which relative codes are used. (At present, this is never used)
  
 uint32 btnbits[3]  // A bit mask (96 bits) indicating which button codes are in use.  This bit mask starts at code 0x100, and not 0x0 as for the other bit mask. 
                    // A bit mask of 0xC00 would indicate the device is capable of emitting BTN_LEFT and BTN_RIGHT events

Examples

If a device support ABS_MT_POSITION_X, then that code is ordinal 0x35.

The bitmask that repressents this is 1 << 0x35 = 0x20000000000000


If it support BTN_FORWARD, then that ordinal code is 0x115.

The bitmask that represent this is: 1 << ( 0x115 - 0x100). = 0x200000


ABS_WHEEL (not mentioned in the tables above) is 0x8, so its mask is 0x100.

ABS_GAS (also not mentioned in the tables above) is 0x9, so its mask is 0x200.

If we had ABS_WHEEL and ABS_GAS its bitmask would be 0x100 | 0x200 = 0x300.