mirror of
https://gitlab.freedesktop.org/libevdev/libevdev.git
synced 2025-12-21 19:00:06 +01:00
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>
This commit is contained in:
parent
2b0fda32ed
commit
fb480e7d8f
1 changed files with 158 additions and 2 deletions
|
|
@ -52,7 +52,8 @@ extern "C" {
|
||||||
* has been received and that the state of the device is different to what is
|
* 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
|
* 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
|
* 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
|
* Signal safety
|
||||||
* =============
|
* =============
|
||||||
|
|
@ -156,6 +157,159 @@ extern "C" {
|
||||||
* https://bugs.freedesktop.org/enter_bug.cgi?product=libevdev
|
* https://bugs.freedesktop.org/enter_bug.cgi?product=libevdev
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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
|
* @page testing libevdev-internal test suite
|
||||||
*
|
*
|
||||||
|
|
@ -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
|
* @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
|
* 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
|
* 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
|
* @note The implementation of libevdev limits the maximum number of slots
|
||||||
* that can be synched. If your device exceeds the 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
|
* (currently 60), slot indices equal and above this maximum are ignored and
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue