• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<!-- HTML header for doxygen 1.8.8-->
2<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3<html xmlns="http://www.w3.org/1999/xhtml">
4    <head>
5        <meta http-equiv="X-UA-Compatible" content="IE=edge">
6        <!-- For Mobile Devices -->
7        <meta name="viewport" content="width=device-width, initial-scale=1">
8        <meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
9        <meta name="generator" content="Doxygen 1.8.20"/>
10        <script type="text/javascript" src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
11        <title>libevdev: SYN_DROPPED handling</title>
12        <!--<link href="tabs.css" rel="stylesheet" type="text/css"/>-->
13        <script type="text/javascript" src="dynsections.js"></script>
14        <link href="search/search.css" rel="stylesheet" type="text/css"/>
15<script type="text/javascript" src="search/searchdata.js"></script>
16<script type="text/javascript" src="search/search.js"></script>
17        <link href="doxygen.css" rel="stylesheet" type="text/css" />
18        <link href="bootstrap.css" rel="stylesheet" type="text/css"/>
19<link href="customdoxygen.css" rel="stylesheet" type="text/css"/>
20<link href="libevdevdoxygen.css" rel="stylesheet" type="text/css"/>
21        <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
22        <script type="text/javascript" src="doxy-boot.js"></script>
23    </head>
24    <body>
25        <nav class="navbar navbar-default" role="navigation">
26            <div class="container">
27                <div class="navbar-header">
28                    <a class="navbar-brand">libevdev 1.10.0</a>
29                </div>
30            </div>
31        </nav>
32        <div id="top"><!-- do not remove this div, it is closed by doxygen! -->
33            <div class="content" id="content">
34                <div class="container">
35                    <div class="row">
36                        <div class="col-sm-12 panel panel-default" style="padding-bottom: 15px;">
37                            <div style="margin-bottom: 15px;">
38<!-- end header part -->
39<!-- Generated by Doxygen 1.8.20 -->
40<script type="text/javascript">
41/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
42var searchBox = new SearchBox("searchBox", "search",false,'Search');
43/* @license-end */
44</script>
45<script type="text/javascript" src="menudata.js"></script>
46<script type="text/javascript" src="menu.js"></script>
47<script type="text/javascript">
48/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
49$(function() {
50  initMenu('',true,false,'search.php','Search');
51  $(document).ready(function() { init_search(); });
52});
53/* @license-end */</script>
54<div id="main-nav"></div>
55<!-- window showing the filter options -->
56<div id="MSearchSelectWindow"
57     onmouseover="return searchBox.OnSearchSelectShow()"
58     onmouseout="return searchBox.OnSearchSelectHide()"
59     onkeydown="return searchBox.OnSearchSelectKey(event)">
60</div>
61
62<!-- iframe showing the search results (closed by default) -->
63<div id="MSearchResultsWindow">
64<iframe src="javascript:void(0)" frameborder="0"
65        name="MSearchResults" id="MSearchResults">
66</iframe>
67</div>
68
69</div><!-- top -->
70<div class="PageDoc"><div class="header">
71  <div class="headertitle">
72<div class="title">SYN_DROPPED handling </div>  </div>
73</div><!--header-->
74<div class="contents">
75<div class="textblock"><p>This page describes how libevdev handles <code>SYN_DROPPED</code> events.</p>
76<h1><a class="anchor" id="autotoc_md10"></a>
77Receiving &lt;tt&gt;SYN_DROPPED&lt;/tt&gt; events</h1>
78<p>The kernel sends evdev events separated by an event of type <code>EV_SYN</code> and code <code>SYN_REPORT</code>. Such an event marks the end of a frame of hardware events. The number of events between <code>SYN_REPORT</code> events is arbitrary and depends on the hardware. An example event sequence may look like this: </p><div class="fragment"><div class="line">EV_ABS   ABS_X        9</div>
79<div class="line">EV_ABS   ABS_Y        8</div>
80<div class="line">EV_SYN   SYN_REPORT   0</div>
81<div class="line">------------------------</div>
82<div class="line">EV_ABS   ABS_X        10</div>
83<div class="line">EV_ABS   ABS_Y        10</div>
84<div class="line">EV_KEY   BTN_TOUCH    1</div>
85<div class="line">EV_SYN   SYN_REPORT   0</div>
86<div class="line">------------------------</div>
87<div class="line">EV_ABS   ABS_X        11</div>
88<div class="line">EV_SYN   SYN_REPORT   0</div>
89</div><!-- fragment --><p>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 <code>EV_SYN</code> and code <code>SYN_DROPPED</code> 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): </p><div class="fragment"><div class="line">EV_ABS   ABS_X        9</div>
90<div class="line">EV_ABS   ABS_Y        8</div>
91<div class="line">EV_SYN   SYN_REPORT   0</div>
92<div class="line">------------------------</div>
93<div class="line">EV_ABS   ABS_X        10</div>
94<div class="line">EV_ABS   ABS_Y        10</div>
95<div class="line">EV_SYN   SYN_DROPPED  0</div>
96<div class="line">EV_ABS   ABS_Y        15</div>
97<div class="line">EV_SYN   SYN_REPORT   0</div>
98<div class="line">------------------------</div>
99<div class="line">EV_ABS   ABS_X        11</div>
100<div class="line">EV_KEY   BTN_TOUCH    0</div>
101<div class="line">EV_SYN   SYN_REPORT   0</div>
102</div><!-- fragment --><p>A <code>SYN_DROPPED</code> event may be recieved at any time in the event sequence. When a <code>SYN_DROPPED</code> event is received, the client must:</p><ul>
103<li>discard all events since the last <code>SYN_REPORT</code></li>
104<li>discard all events until including the next <code>SYN_REPORT</code> These event are part of incomplete event frames.</li>
105</ul>
106<h1><a class="anchor" id="autotoc_md11"></a>
107Synchronizing the state of the device</h1>
108<p>The handling of the device after a <code>SYN_DROPPED</code> depends on the available event codes. For all event codes of type <code>EV_REL</code>, no handling is necessary, there is no state attached. For all event codes of type <code>EV_KEY</code>, <code>EV_SW</code>, <code>EV_LED</code> and <code>EV_SND</code>, the matching <a class="el" href="ioctls.html">evdev ioctls</a> 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 <a class="el" href="group__events.html#gabb96c864e836c0b98788f4ab771c3a76" title="Get the next event from the device.">libevdev_next_event()</a> if <a class="el" href="group__events.html#gga56c288d9f2e4c1632986c4e218c494e9a1f13a19641d6dafcf01a86a6389800f8">LIBEVDEV_READ_FLAG_SYNC</a> is set.</p>
109<p>For events of type <code>EV_ABS</code> and an event code less than <code>ABS_MT_SLOT</code>, the handling of state changes is as described above. For events between <code>ABS_MT_SLOT</code> and <code>ABS_MAX</code>, 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 <code>ABS_MT_SLOT</code> 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: </p><div class="fragment"><div class="line">EV_ABS   ABS_MT_POSITION_Y   10</div>
110<div class="line">EV_ABS   ABS_MT_SLOT         1</div>
111<div class="line">EV_ABS   ABS_MT_POSITION_X   100</div>
112<div class="line">EV_ABS   ABS_MT_POSITION_Y   80</div>
113<div class="line">EV_SYN   SYN_REPORT          0</div>
114</div><!-- fragment --><p> Note the lack of <code>ABS_MT_SLOT</code>: the first <code>ABS_MT_POSITION_Y</code> applies to a slot opened previously, and is the only axis that changed for that slot. The touchpoint in slot 1 now has position <code>100/80</code>. The kernel does not provide events if a value does not change, and does not send <code>ABS_MT_SLOT</code> 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.</p>
115<p>If a <code>SYN_DROPPED</code> is received, the client must sync all slots individually and update its internal state. libevdev simplifies this by generating multiple events:</p><ul>
116<li>for each slot on the device, libevdev generates an <code>ABS_MT_SLOT</code> event with the value set to the slot number</li>
117<li>for each event code between <code>ABS_MT_SLOT + 1</code> and <code>ABS_MAX</code> that changed state for this slot, libevdev generates an event for the new state</li>
118<li>libevdev sends a final <code>ABS_MT_SLOT</code> event for the current slot as seen by the kernel</li>
119<li>libevdev terminates this sequence with an <code>EV_SYN SYN_REPORT</code> event</li>
120</ul>
121<p>An example event sequence for such a sync may look like this: </p><div class="fragment"><div class="line">EV_ABS   ABS_MT_SLOT         0</div>
122<div class="line">EV_ABS   ABS_MT_POSITION_Y   10</div>
123<div class="line">EV_ABS   ABS_MT_SLOT         1</div>
124<div class="line">EV_ABS   ABS_MT_POSITION_X   100</div>
125<div class="line">EV_ABS   ABS_MT_POSITION_Y   80</div>
126<div class="line">EV_ABS   ABS_MT_SLOT         2</div>
127<div class="line">EV_ABS   ABS_MT_POSITION_Y   8</div>
128<div class="line">EV_ABS   ABS_MT_PRESSURE     12</div>
129<div class="line">EV_ABS   ABS_MT_SLOT         1</div>
130<div class="line">EV_SYN   SYN_REPORT          0</div>
131</div><!-- fragment --><p> Note the terminating <code>ABS_MT_SLOT</code> event, this indicates that the kernel currently has slot 1 active.</p>
132<h1><a class="anchor" id="autotoc_md12"></a>
133Synchronizing ABS_MT_TRACKING_ID</h1>
134<p>The event code <code>ABS_MT_TRACKING_ID</code> is used to denote the start and end of a touch point within a slot. An <code>ABS_MT_TRACKING_ID</code> of zero or greater denotes the start of a touchpoint, an <code>ABS_MT_TRACKING_ID</code> of -1 denotes the end of a touchpoint within this slot. During <code>SYN_DROPPED</code>, a touch point may have ended and re-started within a slot - a client must check the <code>ABS_MT_TRACKING_ID</code>. libevdev simplifies this by emulating extra events if the <code>ABS_MT_TRACKING_ID</code> has changed:</p><ul>
135<li>if the <code>ABS_MT_TRACKING_ID</code> was valid and is -1, libevdev enqueues an <code>ABS_MT_TRACKING_ID</code> event with value -1.</li>
136<li>if the <code>ABS_MT_TRACKING_ID</code> was -1 and is now a valid ID, libevdev enqueues an <code>ABS_MT_TRACKING_ID</code> event with the current value.</li>
137<li>if the <code>ABS_MT_TRACKING_ID</code> was a valid ID and is now a different valid ID, libevev enqueues an <code>ABS_MT_TRACKING_ID</code> event with value -1 and another <code>ABS_MT_TRACKING_ID</code> event with the new value.</li>
138</ul>
139<p>An example event sequence for such a sync may look like this: </p><div class="fragment"><div class="line">EV_ABS   ABS_MT_SLOT         0</div>
140<div class="line">EV_ABS   ABS_MT_TRACKING_ID  -1</div>
141<div class="line">EV_ABS   ABS_MT_SLOT         2</div>
142<div class="line">EV_ABS   ABS_MT_TRACKING_ID  -1</div>
143<div class="line">EV_SYN   SYN_REPORT          0</div>
144<div class="line">------------------------</div>
145<div class="line">EV_ABS   ABS_MT_SLOT         1</div>
146<div class="line">EV_ABS   ABS_MT_POSITION_X   100</div>
147<div class="line">EV_ABS   ABS_MT_POSITION_Y   80</div>
148<div class="line">EV_ABS   ABS_MT_SLOT         2</div>
149<div class="line">EV_ABS   ABS_MT_TRACKING_ID  45</div>
150<div class="line">EV_ABS   ABS_MT_POSITION_Y   8</div>
151<div class="line">EV_ABS   ABS_MT_PRESSURE     12</div>
152<div class="line">EV_ABS   ABS_MT_SLOT         1</div>
153<div class="line">EV_SYN   SYN_REPORT          0</div>
154</div><!-- fragment --><p> Note how the touchpoint in slot 0 was terminated, the touchpoint in slot 2 was terminated and then started with a new <code>ABS_MT_TRACKING_ID</code>. The touchpoint in slot 1 maintained the same <code>ABS_MT_TRACKING_ID</code> and only updated the coordinates. Slot 1 is the currently active slot.</p>
155<p>In the case of a <code>SYN_DROPPED</code> event, a touch point may be invisible to a client if it started after <code>SYN_DROPPED</code> and finished before the client handles events again. The below example shows an example event sequence and what libevdev sees in the case of a <code>SYN_DROPPED</code> event: </p><div class="fragment"><div class="line">          kernel                  |              userspace</div>
156<div class="line">                                  |</div>
157<div class="line">EV_ABS   ABS_MT_SLOT         0    |    EV_ABS   ABS_MT_SLOT         0</div>
158<div class="line">EV_ABS   ABS_MT_TRACKING_ID  -1   |    EV_ABS   ABS_MT_TRACKING_ID  -1</div>
159<div class="line">EV_SYN   SYN_REPORT          0    |    EV_SYN   SYN_REPORT          0</div>
160<div class="line">------------------------          |    ------------------------</div>
161<div class="line">EV_ABS   ABS_MT_TRACKING_ID  30   |</div>
162<div class="line">EV_ABS   ABS_MT_POSITION_X   100  |</div>
163<div class="line">EV_ABS   ABS_MT_POSITION_Y   80   |</div>
164<div class="line">EV_SYN   SYN_REPORT          0    |           SYN_DROPPED</div>
165<div class="line">------------------------          |</div>
166<div class="line">EV_ABS   ABS_MT_TRACKING_ID  -1   |</div>
167<div class="line">EV_SYN   SYN_REPORT          0    |</div>
168<div class="line">------------------------          |    ------------------------</div>
169<div class="line">EV_ABS   ABS_MT_SLOT         1    |    EV_ABS   ABS_MT_SLOT         1</div>
170<div class="line">EV_ABS   ABS_MT_POSITION_X   90   |    EV_ABS   ABS_MT_POSITION_X   90</div>
171<div class="line">EV_ABS   ABS_MT_POSITION_Y   10   |    EV_ABS   ABS_MT_POSITION_Y   10</div>
172<div class="line">EV_SYN   SYN_REPORT          0    |    EV_SYN   SYN_REPORT          0</div>
173</div><!-- fragment --><p> If such an event sequence occurs, libevdev will send all updated axes during the sync process. Axis events may thus be generated for devices without a currently valid <code>ABS_MT_TRACKING_ID</code>. Specifically for the above example, the client would receive the following event sequence: </p><div class="fragment"><div class="line">EV_ABS   ABS_MT_SLOT         0       ← <a class="code" href="group__events.html#gga56c288d9f2e4c1632986c4e218c494e9ac0d6ee19551eecf76f1ede4f36252418">LIBEVDEV_READ_FLAG_NORMAL</a></div>
174<div class="line">EV_ABS   ABS_MT_TRACKING_ID  -1</div>
175<div class="line">EV_SYN   SYN_REPORT          0</div>
176<div class="line">------------------------</div>
177<div class="line">EV_SYN   SYN_DROPPED         0       → <a class="code" href="group__events.html#gga4a96221b3c7f54dfb86035d952154e3aa8d70b14a38204fde4ad433023baa545a">LIBEVDEV_READ_STATUS_SYNC</a></div>
178<div class="line">------------------------</div>
179<div class="line">EV_ABS   ABS_MT_POSITION_X   100     ← <a class="code" href="group__events.html#gga56c288d9f2e4c1632986c4e218c494e9a1f13a19641d6dafcf01a86a6389800f8">LIBEVDEV_READ_FLAG_SYNC</a></div>
180<div class="line">EV_ABS   ABS_MT_POSITION_Y   80</div>
181<div class="line">EV_SYN   SYN_REPORT          0</div>
182<div class="line">-----------------------------        → -EGAIN</div>
183<div class="line">EV_ABS   ABS_MT_SLOT         1       ← <a class="code" href="group__events.html#gga56c288d9f2e4c1632986c4e218c494e9ac0d6ee19551eecf76f1ede4f36252418">LIBEVDEV_READ_FLAG_NORMAL</a></div>
184<div class="line">EV_ABS   ABS_MT_POSITION_X   90</div>
185<div class="line">EV_ABS   ABS_MT_POSITION_Y   10</div>
186<div class="line">EV_SYN   SYN_REPORT          0</div>
187<div class="line">-------------------</div>
188</div><!-- fragment --><p> The axis events do not reflect the position of a current touch point, a client must take care not to generate a new touch point based on those updates.</p>
189<h1><a class="anchor" id="autotoc_md13"></a>
190Discarding events before synchronizing</h1>
191<p>The kernel implements the client buffer as a ring buffer. <code>SYN_DROPPED</code> events are handled when the buffer is full and a new event is received from a device. All existing events are discarded, a <code>SYN_DROPPED</code> is added to the buffer followed by the actual device event. Further events will be appended to the buffer until it is either read by the client, or filled again, at which point the sequence repeats.</p>
192<p>When the client reads the buffer, the buffer will thus always consist of exactly one <code>SYN_DROPPED</code> event followed by an unspecified number of real events. The data the ioctls return is the current state of the device, i.e. the state after all these events have been processed. For example, assume the buffer contains the following sequence:</p>
193<div class="fragment"><div class="line">EV_SYN   SYN_DROPPED</div>
194<div class="line">EV_ABS   ABS_X               1</div>
195<div class="line">EV_SYN   SYN_REPORT          0</div>
196<div class="line">EV_ABS   ABS_X               2</div>
197<div class="line">EV_SYN   SYN_REPORT          0</div>
198<div class="line">EV_ABS   ABS_X               3</div>
199<div class="line">EV_SYN   SYN_REPORT          0</div>
200<div class="line">EV_ABS   ABS_X               4</div>
201<div class="line">EV_SYN   SYN_REPORT          0</div>
202<div class="line">EV_ABS   ABS_X               5</div>
203<div class="line">EV_SYN   SYN_REPORT          0</div>
204<div class="line">EV_ABS   ABS_X               6</div>
205<div class="line">EV_SYN   SYN_REPORT          0</div>
206</div><!-- fragment --><p> An ioctl at any time in this sequence will return a value of 6 for ABS_X.</p>
207<p>libevdev discards all events after a <code>SYN_DROPPED</code> to ensure the events during <a class="el" href="group__events.html#gga56c288d9f2e4c1632986c4e218c494e9a1f13a19641d6dafcf01a86a6389800f8">LIBEVDEV_READ_FLAG_SYNC</a> represent the last known state of the device. This loses some granularity of the events especially as the time between the <code>SYN_DROPPED</code> and the sync process increases. It does however avoid spurious cursor movements. In the above example, the event sequence by libevdev is: </p><div class="fragment"><div class="line">EV_SYN   SYN_DROPPED</div>
208<div class="line">EV_ABS   ABS_X               6</div>
209<div class="line">EV_SYN   SYN_REPORT          0</div>
210</div><!-- fragment --> </div></div><!-- contents -->
211</div><!-- PageDoc -->
212<div class="ttc" id="agroup__events_html_gga4a96221b3c7f54dfb86035d952154e3aa8d70b14a38204fde4ad433023baa545a"><div class="ttname"><a href="group__events.html#gga4a96221b3c7f54dfb86035d952154e3aa8d70b14a38204fde4ad433023baa545a">LIBEVDEV_READ_STATUS_SYNC</a></div><div class="ttdeci">@ LIBEVDEV_READ_STATUS_SYNC</div><div class="ttdoc">Depending on the libevdev_next_event() read flag:</div><div class="ttdef"><b>Definition:</b> libevdev.h:1087</div></div>
213<div class="ttc" id="agroup__events_html_gga56c288d9f2e4c1632986c4e218c494e9ac0d6ee19551eecf76f1ede4f36252418"><div class="ttname"><a href="group__events.html#gga56c288d9f2e4c1632986c4e218c494e9ac0d6ee19551eecf76f1ede4f36252418">LIBEVDEV_READ_FLAG_NORMAL</a></div><div class="ttdeci">@ LIBEVDEV_READ_FLAG_NORMAL</div><div class="ttdoc">Process data in normal mode.</div><div class="ttdef"><b>Definition:</b> libevdev.h:759</div></div>
214<div class="ttc" id="agroup__events_html_gga56c288d9f2e4c1632986c4e218c494e9a1f13a19641d6dafcf01a86a6389800f8"><div class="ttname"><a href="group__events.html#gga56c288d9f2e4c1632986c4e218c494e9a1f13a19641d6dafcf01a86a6389800f8">LIBEVDEV_READ_FLAG_SYNC</a></div><div class="ttdeci">@ LIBEVDEV_READ_FLAG_SYNC</div><div class="ttdoc">Process data in sync mode.</div><div class="ttdef"><b>Definition:</b> libevdev.h:758</div></div>
215<!-- HTML footer for doxygen 1.8.8-->
216<!-- start footer part -->
217</div>
218</div>
219</div>
220</div>
221</div>
222<hr class="footer"/><address class="footer"><small>
223Generated by &#160;<a href="http://www.doxygen.org/index.html">
224<img class="footer" src="doxygen.png" alt="doxygen"/>
225</a> 1.8.20
226</small></address>
227</body>
228</html>
229