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.
Code | Name | Description |
---|---|---|
0x1 | DEV_SET | Events 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. |
0x2 | DEV_CONF | This 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. |
0x3 | DEV_RESET | This 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
Code | Name | Description |
---|---|---|
0x0 | SYN_REPORT | This 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. |
0x2 | SYN_MT_REPORT | This is used for less able multitouch devices, to separate multiple sets of X/Y coordinates. We currently have no devices which do this. |
0x3 | SYN_DROPPED | This 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
Code | Name | Description |
---|---|---|
0x00 | REL_X | Movement on the X axis. |
0x01 | REL_Y | Movement on the Y axis. |
0x08 | REL_WHEEL | Vertical wheel movement. |
Type 0x3 ABS: Absolute
Code | Name | Description |
---|---|---|
0x00 | ABS_X | Position on the X axis. |
0x01 | ABS_Y | Position on the Y axis. |
0x18 | ABS_PRESSURE | The pressure the pen/tool is being applied. |
0x2f | ABS_MT_SLOT | Each 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. |
0x35 | ABS_MT_POSITION_X | X coordinate for the current slot. (Finger/pen) |
0x36 | ABS_MT_POSITION_Y | Y coordinate for the current slot. (Finger/pen) |
0x39 | ABS_MT_TRACKING_ID | Unique ID of initiated contact, a value of -1 indicates finger/pen released. |
Type 0x01 KEY: Key/Button
Code | Name | Description |
---|---|---|
0x110 | BTN_LEFT | The left button on a mouse. |
0x111 | BTN_RIGHT | The right button on a mouse. |
0x112 | BTN_MIDDLE | The middle button on a mouse. |
0x113 | BTN_SIDE | The side button on a mouse. |
0x114 | BTN_EXTRA | The extra button on a mouse. |
0x115 | BTN_FORWARD | The forward button on a mouse. |
0x116 | BTN_BACK | The back button on a mouse. |
0x117 | BTN_TASK | The task button on a mouse. |
0x140 | BTN_TOOL_PEN | The current tool is now a pen. |
0x141 | BTN_TOOL_RUBBER | The current tool is now a rubber. |
0x145 | BTN_TOOL_FINGER | The current tool is now a finger. |
0x146 | BTN_TOOL_MOUSE | The current tool is now a mouse. |
0x14a | BTN_TOUCH | The current tool touched the surface. |
0x14b | BTN_STYLUS | The first button on the stylus was pressed. |
0x14c | BTN_STYLUS2 | The 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.