summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Hutterer <peter.hutterer@who-t.net>2014-03-11 10:44:10 +1000
committerPeter Hutterer <peter.hutterer@who-t.net>2014-03-14 09:38:18 +1000
commitfb480e7d8fc6450b59da68e06f9f9b79932ece0b (patch)
tree530bd84b3ce6b5806bc43724d39edec3dab5ce54
parent2b0fda32ed531154a8edaeed82eafdb08ca81adf (diff)
downloadlibevdev-fb480e7d8fc6450b59da68e06f9f9b79932ece0b.tar.gz
doc: Add documentation on how SYN_DROPPED is handled
This is getting a bit complex, so add some high-level documentation that we at least know what we're trying to do. Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> Reviewed-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
-rw-r--r--libevdev/libevdev.h160
1 files changed, 158 insertions, 2 deletions
diff --git a/libevdev/libevdev.h b/libevdev/libevdev.h
index 481e378..62fc15f 100644
--- a/libevdev/libevdev.h
+++ b/libevdev/libevdev.h
@@ -52,7 +52,8 @@ extern "C" {
* has been received and that the state of the device is different to what is
* to be expected. It then provides the delta between the previous state and
* the actual state of the device as a set of events. See
- * libevdev_next_event() for more information.
+ * libevdev_next_event() and @ref syn_dropped for more information on how
+ * SYN_DROPPED is handled.
*
* Signal safety
* =============
@@ -157,6 +158,159 @@ extern "C" {
*/
/**
+ * @page syn_dropped SYN_DROPPED handling
+ *
+ * This page describes how libevdev handles SYN_DROPPED events.
+ *
+ * The kernel sends evdev events separated by an event of type EV_SYN and
+ * code SYN_REPORT. Such an event marks the end of a frame of hardware
+ * events. The number of events between SYN_REPORT events is arbitrary and
+ * depends on the hardware. And example event sequence may look like this:
+ * @code
+ EV_ABS ABS_X 9
+ EV_ABS ABS_Y 8
+ EV_SYN SYN_REPORT 0
+ ------------------------
+ EV_ABS ABS_X 10
+ EV_ABS ABS_Y 10
+ EV_KEY BTN_TOUCH 1
+ EV_SYN SYN_REPORT 0
+ ------------------------
+ EV_ABS ABS_X 11
+ EV_SYN SYN_REPORT 0
+ * @endcode
+ *
+ * Events are handed to the client buffer as they appear, the kernel adjusts
+ * the buffer size to handle at least one full event. In the normal case,
+ * the client reads the event and the kernel can place the next event in the
+ * buffer. If the client is not fast enough, the kernel places an event of
+ * type EV_SYN and code SYN_DROPPED into the buffer, effectively notifying
+ * the client that some events were lost. The above example event sequence
+ * may look like this (note the missing/repeated events):
+ * @code
+ EV_ABS ABS_X 9
+ EV_ABS ABS_Y 8
+ EV_SYN SYN_REPORT 0
+ ------------------------
+ EV_ABS ABS_X 10
+ EV_ABS ABS_Y 10
+ EV_SYN SYN_DROPPED 0
+ EV_ABS ABS_Y 15
+ EV_SYN SYN_REPORT 0
+ ------------------------
+ EV_ABS ABS_X 11
+ EV_KEY BTN_TOUCH 0
+ EV_SYN SYN_REPORT 0
+ * @endcode
+ *
+ * A SYN_DROPPED event may be recieved at any time in the event sequence.
+ * When a SYN_DROPPED event is received, the client must:
+ * * discard all events since the last SYN_REPORT
+ * * discard all events until including the next SYN_REPORT
+ * These event are part of incomplete event frames.
+ *
+ * The handling of the device after a SYN_DROPPED depends on the available
+ * event codes. For all event codes of type EV_REL, no handling is
+ * necessary, there is no state attached. For all event codes of type
+ * EV_KEY, EV_SW, EV_LED and EV_SND, the matching @ref ioctls retrieve the
+ * current state. The caller must then compare the last-known state to the
+ * retrieved state and handle the deltas accordingly.
+ * libevdev simplifies this approach: if the state of the device has
+ * changed, libevdev generates an event for each code with the new value and
+ * passes it to the caller during libevdev_next_event() if
+ * LIBEVDEV_READ_FLAG_SYNC is set.
+ *
+ * For events of type EV_ABS and an event code less than ABS_MT_SLOT, the
+ * handling of state changes is as described above. For events between
+ * ABS_MT_SLOT and ABS_MAX, the event handling differs.
+ * Slots are the vehicles to transport information for multiple simultaneous
+ * touchpoints on a device. Slots are re-used once a touchpoint has ended.
+ * The kernel sends an ABS_MT_SLOT event whenever the current slot
+ * changes; any event in the above axis range applies only to the currently
+ * active slot.
+ * Thus, an event sequence from a slot-capable device may look like this:
+ * @code
+ EV_ABS ABS_MT_POSITION_Y 10
+ EV_ABS ABS_MT_SLOT 1
+ EV_ABS ABS_MT_POSITION_X 100
+ EV_ABS ABS_MT_POSITION_Y 80
+ EV_SYN SYN_REPORT 0
+ * @endcode
+ * Note the lack of ABS_MT_SLOT: the first ABS_MT_POSITION_Y applies to
+ * a slot opened previously, and is the only axis that changed for that
+ * slot. The touchpoint in slot 1 now has position 100/80.
+ * The kernel does not provide events if a value does not change, and does
+ * not send ABS_MT_SLOT events if the slot does not change, or none of the
+ * values within a slot changes. A client must thus keep the state for each
+ * slot.
+ *
+ * If a SYN_DROPPED is received, the client must sync all slots
+ * individually and update its internal state. libevdev simplifies this by
+ * generating multiple events:
+ * * for each slot on the device, libevdev generates an
+ * ABS_MT_SLOT event with the value set to the slot number
+ * * for each event code between ABS_MT_SLOT + 1 and ABS_MAX that changed
+ * state for this slot, libevdev generates an event for the new state
+ * * libevdev sends a final ABS_MT_SLOT event for the current slot as
+ * seen by the kernel
+ * * libevdev terminates this sequence with an EV_SYN SYN_REPORT event
+ *
+ * An example event sequence for such a sync may look like this:
+ * @code
+ EV_ABS ABS_MT_SLOT 0
+ EV_ABS ABS_MT_POSITION_Y 10
+ EV_ABS ABS_MT_SLOT 1
+ EV_ABS ABS_MT_POSITION_X 100
+ EV_ABS ABS_MT_POSITION_Y 80
+ EV_ABS ABS_MT_SLOT 2
+ EV_ABS ABS_MT_POSITION_Y 8
+ EV_ABS ABS_MT_PRESSURE 12
+ EV_ABS ABS_MT_SLOT 1
+ EV_SYN SYN_REPORT 0
+ * @endcode
+ * Note the terminating ABS_MT_SLOT event, this indicates that the kernel
+ * currently has slot 1 active.
+ *
+ * The event code ABS_MT_TRACKING_ID is used to denote the start and end of
+ * a touch point within a slot. An ABS_MT_TRACKING_ID of zero or greater
+ * denotes the start of a touchpoint, an ABS_MT_TRACKING_ID of -1 denotes
+ * the end of a touchpoint within this slot. During SYN_DROPPED, a touch
+ * point may have ended and re-started within a slot - a client must check
+ * the ABS_MT_TRACKING_ID. libevdev simplifies this by emulating extra
+ * events if the ABS_MT_TRACKING_ID has changed:
+ * * if the ABS_MT_TRACKING_ID was valid and is -1, libevdev enqueues an
+ * ABS_MT_TRACKING_ID event with value -1.
+ * * if the ABS_MT_TRACKING_ID was -1 and is now a valid ID, libevdev
+ * enqueues an ABS_MT_TRACKING_ID event with the current value.
+ * * if the ABS_MT_TRACKING_ID was a valid ID and is now a different valid
+ * ID, libevev enqueues an ABS_MT_TRACKING_ID event with value -1 and
+ * another ABS_MT_TRACKING_ID event with the new value.
+ * An example event sequence for such a sync may look like this:
+ * @code
+ EV_ABS ABS_MT_SLOT 0
+ EV_ABS ABS_MT_TRACKING_ID -1
+ EV_ABS ABS_MT_SLOT 2
+ EV_ABS ABS_MT_TRACKING_ID -1
+ EV_SYN SYN_REPORT 0
+ ------------------------
+ EV_ABS ABS_MT_SLOT 1
+ EV_ABS ABS_MT_POSITION_X 100
+ EV_ABS ABS_MT_POSITION_Y 80
+ EV_ABS ABS_MT_SLOT 2
+ EV_ABS ABS_MT_TRACKING_ID 45
+ EV_ABS ABS_MT_POSITION_Y 8
+ EV_ABS ABS_MT_PRESSURE 12
+ EV_ABS ABS_MT_SLOT 1
+ EV_SYN SYN_REPORT 0
+ * @endcode
+ * Note how the touchpoint in slot 0 was terminated, the touchpoint in slot
+ * 2 was terminated and then started with a new ABS_MT_TRACKING_ID. The touchpoint
+ * in slot 1 maintained the same ABS_MT_TRACKING_ID and only updated the
+ * coordinates. Slot 1 is the currently active slot.
+ *
+ */
+
+/**
* @page testing libevdev-internal test suite
*
* libevdev's internal test suite uses the
@@ -698,7 +852,9 @@ enum libevdev_read_status {
* @ref LIBEVDEV_READ_FLAG_SYNC flag set, to get the set of events that make up the
* device state delta. This function returns @ref LIBEVDEV_READ_STATUS_SYNC for
* each event part of that delta, until it returns -EAGAIN once all events
- * have been synced.
+ * have been synced. For more details on what libevdev does to sync after a
+ * SYN_DROPPED event, see @ref syn_dropped.
+ *
* @note The implementation of libevdev limits the maximum number of slots
* that can be synched. If your device exceeds the number of slots
* (currently 60), slot indices equal and above this maximum are ignored and