Hi,
Next revision the pvmouse protocol. It is quite different now, I've
decided to move to a model with one message per updated value, simliar
to the linux input layer. There isn't a "mouse move" message any more.
A mouse move event will be three messages now: one to update X, one to
update Y and a third sync message to mark the end of the message block.
That should be *alot* easier to extend in the future.
Header file is attached. Comments are welcome.
thanks,
Gerd
#ifndef __QEMU_PVMOUSE__
#define __QEMU_PVMOUSE__ 1
/*
* qemu patavirtual mouse/tablet interface
*
* quick overview
* ==============
*
* device initialization
* ---------------------
*
* (1) host sends INIT with supported feature bits
* (2) guests sends ACK to ack the features it is
* able to handle (and willing to use).
* (3) host sends a INFO message for each button and
* each axis supported. More INFO messages might
* follow for features added to the protocol later
* on if enabled by the INIT+ACK handshake.
* A SYNC message marks the end of the device
* information messages.
*
* input event reporting
* ---------------------
*
* host sends one or more BTN_DOWN, BTN_UP and AXIS messages,
* followed by a SYNC. A button press would be just BTN_DOWN+SYNC.
* A mouse move would be two AXIS messages (one for x, one for y)
* followed by SYNC.
*
* multitouch events
* -----------------
*
* Each reported touch point starts with a POINT message, followed by
* multiple AXIS messages (at least x+y, most likely also pressure).
* The whole group is followed by SYNC. A report for two fingers
* would look like this:
*
* POINT
* AXIS x=23
* AXIS y=42
* AXIS pressure=3
* POINT
* AXIS x=78
* AXIS y=56
* AXIS pressure=4
* SYNC
*
* In case the device supports ID tracking the POINT message will
* carry the ID. Updates need only be sent for points which did
* change. IDs are added by using them the first time. IDs are
* invalidated when the finger is lifted (aka pressure=0).
*
* In case the device doesn't support ID tracking each report must
* include all current touch points (in unspecified order).
*
*/
#include <inttypes.h>
/*
* our virtio-serial channel name(s)
*/
#define QEMU_PVMOUSE_FORMAT "org.qemu.pvmouse.%d"
enum qemu_pvmouse_msg_type {
/* feature flag negotiation */
QEMU_PVMOUSE_MSG_INIT,
QEMU_PVMOUSE_MSG_ACK,
/* device information */
QEMU_PVMOUSE_MSG_AXIS_INFO,
QEMU_PVMOUSE_MSG_BUTTON_INFO,
/* device events */
QEMU_PVMOUSE_MSG_BTN_DOWN,
QEMU_PVMOUSE_MSG_BTN_UP,
QEMU_PVMOUSE_MSG_AXIS,
/* message grouping */
QEMU_PVMOUSE_MSG_POINT,
QEMU_PVMOUSE_MSG_SYNC,
};
typedef enum qemu_pvmouse_features {
QEMU_PVMOUSE_FEATURE_MULTITOUCH,
};
/*
* QEMU_PVMOUSE_MSG_INIT, host -> guest
* First message. Sent before any other event.
*/
typedef struct qemu_pvmouse_init {
uint32_t features; /* qemu_pvmouse_features */
} qemu_pvmouse_init;
/*
* QEMU_PVMOUSE_MSG_ACK, guest -> host
* Sent after pvmouse_init. Host will not send
* additional messages until this is received.
*/
typedef struct qemu_pvmouse_ack {
uint32_t features; /* qemu_pvtable_features */
};
enum qemu_pvmouse_axis_type {
/* absolute */
QEMU_PVMOUSE_AXIS_POS_X = 1,
QEMU_PVMOUSE_AXIS_POS_Y,
QEMU_PVMOUSE_AXIS_PRESSURE,
/* relative */
QEMU_PVMOUSE_AXIS_REL_X = 257,
QEMU_PVMOUSE_AXIS_REL_Y,
QEMU_PVMOUSE_AXIS_WHEEL_VERT,
QEMU_PVMOUSE_AXIS_WHEEL_HORIZ,
};
enum qemu_pvmouse_axis_flags {
QEMU_PVMOUSE_AXIS_PEN,
QEMU_PVMOUSE_AXIS_TOUCH,
QEMU_PVMOUSE_AXIS_MULTITOUCH,
QEMU_PVMOUSE_AXIS_POINT_ID,
};
#define QEMU_PVMOUSE_AXIS_MASK_PEN (1 << QEMU_PVMOUSE_AXIS_PEN)
#define QEMU_PVMOUSE_AXIS_MASK_TOUCH (1 << QEMU_PVMOUSE_AXIS_TOUCH)
#define QEMU_PVMOUSE_AXIS_MASK_MULTITOUCH (1 << QEMU_PVMOUSE_AXIS_MULTITOUCH)
#define QEMU_PVMOUSE_AXIS_MASK_POINT_ID (1 << QEMU_PVMOUSE_AXIS_ID)
/*
* QEMU_PVMOUSE_MSG_AXIS_INFO, host -> guest
* Send axis informations.
*/
typedef struct qemu_pvmouse_axis_info {
uint32_t axis_id;
uint32_t type;
uint32_t flags;
int32_t min;
int32_t max;
char label[];
};
/*
* QEMU_PVMOUSE_MSG_AXIS, host -> guest
* Send mouse/pen/finger/wheel move events.
*/
typedef struct qemu_pvmouse_axis_event {
uint32_t axis_id;
int32_t value;
};
/*
* QEMU_PVMOUSE_MSG_BUTTON_INFO, host -> guest
* Send button informations.
*/
typedef struct qemu_pvmouse_button_info {
uint32_t button_id;
char label[];
};
/*
* QEMU_PVMOUSE_MSG_BTN_{DOWN,UP}, host -> guest
* Send button press+release events.
*/
typedef struct qemu_pvmouse_btn_event {
uint32_t button_id;
};
/*
* QEMU_PVMOUSE_MSG_POINT, host -> guest
* marks the start of a point group for multitouch devices.
*/
typedef struct qemu_pvmouse_point {
uint32_t id;
};
/*
* QEMU_PVMOUSE_MSG_SYNC, host -> guest
* Marks the end of a message group which belongs together
* and carries the time stamp for all those events.
*
* The timestamp is specified in nanoseconds. Timebase is undefined.
* This is supposed to be used to figure how much time passed between
* two events, to decide whenever two mouse clicks should be
* interpreted as double click or not and simliar stuff.
*/
typedef struct qemu_pvmouse_sync {
uint64_t timestamp;
};
typedef struct qemu_pvmouse_header {
uint32_t size; /* whole message size */
uint32_t type; /* qemu_pvmouse_type */
} qemu_pvmouse_header;
typedef union qemu_pvmouse_payload {
qemu_pvmouse_init init;
qemu_pvmouse_ack ack;
/* ... */
};
typedef struct qemu_pvmouse_message {
qemu_pvmouse_header hdr;
qemu_pvmouse_payload data;
} qemu_pvmouse_message;
#endif /* __QEMU_PVMOUSE__ */