[PATCH libevdev 2/4] doc: Add documentation on how SYN_DROPPED is handled

Benjamin Tissoires benjamin.tissoires at gmail.com
Thu Mar 13 06:59:24 PDT 2014


On Tue, Mar 11, 2014 at 8:45 PM, Peter Hutterer
<peter.hutterer at who-t.net> wrote:
> 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 at who-t.net>
> ---

Well, besides the nitpicking at the beginning, I'm ok with that:
Reviewed-by: Benjamin Tissoires <benjamin.tissoires at gmail.com>

In a more general comment, I think that either we should put part of
this in the kernel at Documentation/input/event-codes.txt, or at least
put a link on libevdev in this very same file.
Seeing that BSD is offering a GSoC for implemeting evdev in the input
part of their kernel makes me wonder if they are going to use the
exact same semantic for their evdev protocol
.

>  libevdev/libevdev.h | 158 +++++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 156 insertions(+), 2 deletions(-)
>
> diff --git a/libevdev/libevdev.h b/libevdev/libevdev.h
> index 481e378..5dfe026 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,157 @@ 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 ABS_Y event):
> + * @code
> +   EV_ABS   ABS_X        9
> +   EV_ABS   ABS_Y        8
> +   EV_SYN   SYN_REPORT   0
> +   ------------------------
> +   EV_ABS   ABS_X        10
> +   EV_SYN   SYN_DROPPED  0
> +   EV_KEY   BTN_TOUCH    1
> +   EV_SYN   SYN_REPORT   0
> +   ------------------------
> +   EV_ABS   ABS_X        11
> +   EV_SYN   SYN_REPORT   0
> + * @endcode

<mode bikeshedding on>

This event sequence looks like the kernel just replaced ABS_Y by
SYN_DROPPED. IMO, it would be more convincing if we have at least 1
event repeated before and after the SYN_DROPPED.

how about:

+ * @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        9
+   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

here:
- ABS_Y is sent twice in the second report where SYN_DROPPED is here
- BTN_TOUCH is set to 0 while it's previous state was (or could be) 0,
so we missed this too.

<mode bikeshedding off>

Cheers,
Benjamin

> + *
> + * 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 +850,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
> --
> 1.8.5.3
>
> _______________________________________________
> Input-tools mailing list
> Input-tools at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/input-tools


More information about the Input-tools mailing list