1 /*
2 * Copyright © 2017 Red Hat, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24 #include "config.h"
25
26 #include "evdev-fallback.h"
27
28 /* Debounce cases to handle
29 P ... button press
30 R ... button release
31 ---| timeout duration
32
33 'normal' .... event sent when it happens
34 'filtered' .. event is not sent (but may be sent later)
35 'delayed' ... event is sent with wall-clock delay
36
37 1) P---| R P normal, R normal
38 2) R---| P R normal, P normal
39 3) P---R--| P P normal, R filtered, delayed, P normal
40 4) R---P--| R R normal, P filtered, delayed, R normal
41 4.1) P---| R--P--| P normal, R filtered
42 5) P--R-P-| R P normal, R filtered, P filtered, R normal
43 6) R--P-R-| P R normal, P filtered, R filtered, P normal
44 7) P--R--|
45 ---P-| P normal, R filtered, P filtered
46 8) R--P--|
47 ---R-| R normal, P filtered, R filtered
48
49 1, 2 are the normal click cases without debouncing taking effect
50 3, 4 are fast clicks where the second event is delivered with a delay
51 5, 6 are contact bounces, fast
52 7, 8 are contact bounces, slow
53
54 4.1 is a special case with the same event sequence as 4 but we want to
55 filter the *release* event out, it's a button losing contact while being
56 held down.
57
58 7 and 8 are cases where the first event happens within the first timeout
59 but the second event is outside that timeout (but within the timeout of
60 the second event). These cases are handled by restarting the timer on every
61 event that could be part of a bouncing sequence, which makes these cases
62 indistinguishable from 5 and 6.
63 */
64
65 enum debounce_event {
66 DEBOUNCE_EVENT_PRESS = 50,
67 DEBOUNCE_EVENT_RELEASE,
68 DEBOUNCE_EVENT_TIMEOUT,
69 DEBOUNCE_EVENT_TIMEOUT_SHORT,
70 DEBOUNCE_EVENT_OTHERBUTTON,
71 };
72
73 static inline const char *
debounce_state_to_str(enum debounce_state state)74 debounce_state_to_str(enum debounce_state state)
75 {
76 switch(state) {
77 CASE_RETURN_STRING(DEBOUNCE_STATE_IS_UP);
78 CASE_RETURN_STRING(DEBOUNCE_STATE_IS_DOWN);
79 CASE_RETURN_STRING(DEBOUNCE_STATE_IS_DOWN_WAITING);
80 CASE_RETURN_STRING(DEBOUNCE_STATE_IS_UP_DELAYING);
81 CASE_RETURN_STRING(DEBOUNCE_STATE_IS_UP_DELAYING_SPURIOUS);
82 CASE_RETURN_STRING(DEBOUNCE_STATE_IS_UP_DETECTING_SPURIOUS);
83 CASE_RETURN_STRING(DEBOUNCE_STATE_IS_DOWN_DETECTING_SPURIOUS);
84 CASE_RETURN_STRING(DEBOUNCE_STATE_IS_UP_WAITING);
85 CASE_RETURN_STRING(DEBOUNCE_STATE_IS_DOWN_DELAYING);
86 CASE_RETURN_STRING(DEBOUNCE_STATE_DISABLED);
87 }
88
89 return NULL;
90 }
91
92 static inline const char*
debounce_event_to_str(enum debounce_event event)93 debounce_event_to_str(enum debounce_event event)
94 {
95 switch(event) {
96 CASE_RETURN_STRING(DEBOUNCE_EVENT_PRESS);
97 CASE_RETURN_STRING(DEBOUNCE_EVENT_RELEASE);
98 CASE_RETURN_STRING(DEBOUNCE_EVENT_TIMEOUT);
99 CASE_RETURN_STRING(DEBOUNCE_EVENT_TIMEOUT_SHORT);
100 CASE_RETURN_STRING(DEBOUNCE_EVENT_OTHERBUTTON);
101 }
102 return NULL;
103 }
104
105 static inline void
log_debounce_bug(struct fallback_dispatch * fallback,enum debounce_event event)106 log_debounce_bug(struct fallback_dispatch *fallback, enum debounce_event event)
107 {
108 evdev_log_bug_libinput(fallback->device,
109 "invalid debounce event %s in state %s\n",
110 debounce_event_to_str(event),
111 debounce_state_to_str(fallback->debounce.state));
112
113 }
114
115 static inline void
debounce_set_state(struct fallback_dispatch * fallback,enum debounce_state new_state)116 debounce_set_state(struct fallback_dispatch *fallback,
117 enum debounce_state new_state)
118 {
119 assert(new_state >= DEBOUNCE_STATE_IS_UP &&
120 new_state <= DEBOUNCE_STATE_IS_DOWN_DELAYING);
121
122 fallback->debounce.state = new_state;
123 }
124
125 static inline void
debounce_set_timer(struct fallback_dispatch * fallback,uint64_t time)126 debounce_set_timer(struct fallback_dispatch *fallback,
127 uint64_t time)
128 {
129 const int DEBOUNCE_TIMEOUT_BOUNCE = ms2us(25);
130
131 libinput_timer_set(&fallback->debounce.timer,
132 time + DEBOUNCE_TIMEOUT_BOUNCE);
133 }
134
135 static inline void
debounce_set_timer_short(struct fallback_dispatch * fallback,uint64_t time)136 debounce_set_timer_short(struct fallback_dispatch *fallback,
137 uint64_t time)
138 {
139 const int DEBOUNCE_TIMEOUT_SPURIOUS = ms2us(12);
140
141 libinput_timer_set(&fallback->debounce.timer_short,
142 time + DEBOUNCE_TIMEOUT_SPURIOUS);
143 }
144
145 static inline void
debounce_cancel_timer(struct fallback_dispatch * fallback)146 debounce_cancel_timer(struct fallback_dispatch *fallback)
147 {
148 libinput_timer_cancel(&fallback->debounce.timer);
149 }
150
151 static inline void
debounce_cancel_timer_short(struct fallback_dispatch * fallback)152 debounce_cancel_timer_short(struct fallback_dispatch *fallback)
153 {
154 libinput_timer_cancel(&fallback->debounce.timer_short);
155 }
156
157 static inline void
debounce_enable_spurious(struct fallback_dispatch * fallback)158 debounce_enable_spurious(struct fallback_dispatch *fallback)
159 {
160 if (fallback->debounce.spurious_enabled)
161 evdev_log_bug_libinput(fallback->device,
162 "tried to enable spurious debouncing twice\n");
163
164 fallback->debounce.spurious_enabled = true;
165 evdev_log_info(fallback->device,
166 "Enabling spurious button debouncing, "
167 "see %s/button-debouncing.html for details\n",
168 HTTP_DOC_LINK);
169 }
170
171 static void
debounce_notify_button(struct fallback_dispatch * fallback,enum libinput_button_state state)172 debounce_notify_button(struct fallback_dispatch *fallback,
173 enum libinput_button_state state)
174 {
175 struct evdev_device *device = fallback->device;
176 unsigned int code = fallback->debounce.button_code;
177 uint64_t time = fallback->debounce.button_time;
178
179 code = evdev_to_left_handed(device, code);
180
181 fallback_notify_physical_button(fallback, device, time, code, state);
182 }
183
184 static void
debounce_is_up_handle_event(struct fallback_dispatch * fallback,enum debounce_event event,uint64_t time)185 debounce_is_up_handle_event(struct fallback_dispatch *fallback, enum debounce_event event, uint64_t time)
186 {
187 switch (event) {
188 case DEBOUNCE_EVENT_PRESS:
189 fallback->debounce.button_time = time;
190 debounce_set_timer(fallback, time);
191 debounce_set_state(fallback, DEBOUNCE_STATE_IS_DOWN_WAITING);
192 debounce_notify_button(fallback,
193 LIBINPUT_BUTTON_STATE_PRESSED);
194 break;
195 case DEBOUNCE_EVENT_RELEASE:
196 case DEBOUNCE_EVENT_TIMEOUT:
197 case DEBOUNCE_EVENT_TIMEOUT_SHORT:
198 log_debounce_bug(fallback, event);
199 break;
200 case DEBOUNCE_EVENT_OTHERBUTTON:
201 break;
202 }
203 }
204
205 static void
debounce_is_down_handle_event(struct fallback_dispatch * fallback,enum debounce_event event,uint64_t time)206 debounce_is_down_handle_event(struct fallback_dispatch *fallback, enum debounce_event event, uint64_t time)
207 {
208 switch (event) {
209 case DEBOUNCE_EVENT_PRESS:
210 log_debounce_bug(fallback, event);
211 break;
212 case DEBOUNCE_EVENT_RELEASE:
213 fallback->debounce.button_time = time;
214 debounce_set_timer(fallback, time);
215 debounce_set_timer_short(fallback, time);
216 if (fallback->debounce.spurious_enabled) {
217 debounce_set_state(fallback, DEBOUNCE_STATE_IS_UP_DELAYING_SPURIOUS);
218 } else {
219 debounce_set_state(fallback, DEBOUNCE_STATE_IS_UP_DETECTING_SPURIOUS);
220 debounce_notify_button(fallback,
221 LIBINPUT_BUTTON_STATE_RELEASED);
222 }
223 break;
224 case DEBOUNCE_EVENT_TIMEOUT:
225 case DEBOUNCE_EVENT_TIMEOUT_SHORT:
226 log_debounce_bug(fallback, event);
227 break;
228 case DEBOUNCE_EVENT_OTHERBUTTON:
229 break;
230 }
231 }
232
233 static void
debounce_is_down_waiting_handle_event(struct fallback_dispatch * fallback,enum debounce_event event,uint64_t time)234 debounce_is_down_waiting_handle_event(struct fallback_dispatch *fallback, enum debounce_event event, uint64_t time)
235 {
236 switch (event) {
237 case DEBOUNCE_EVENT_PRESS:
238 log_debounce_bug(fallback, event);
239 break;
240 case DEBOUNCE_EVENT_RELEASE:
241 debounce_set_timer(fallback, time);
242 debounce_set_state(fallback, DEBOUNCE_STATE_IS_UP_DELAYING);
243 /* Note: In the debouncing RPR case, we use the last
244 * release's time stamp */
245 fallback->debounce.button_time = time;
246 break;
247 case DEBOUNCE_EVENT_TIMEOUT:
248 debounce_set_state(fallback, DEBOUNCE_STATE_IS_DOWN);
249 break;
250 case DEBOUNCE_EVENT_TIMEOUT_SHORT:
251 log_debounce_bug(fallback, event);
252 break;
253 case DEBOUNCE_EVENT_OTHERBUTTON:
254 debounce_set_state(fallback, DEBOUNCE_STATE_IS_DOWN);
255 break;
256 }
257 }
258
259 static void
debounce_is_up_delaying_handle_event(struct fallback_dispatch * fallback,enum debounce_event event,uint64_t time)260 debounce_is_up_delaying_handle_event(struct fallback_dispatch *fallback, enum debounce_event event, uint64_t time)
261 {
262 switch (event) {
263 case DEBOUNCE_EVENT_PRESS:
264 debounce_set_timer(fallback, time);
265 debounce_set_state(fallback, DEBOUNCE_STATE_IS_DOWN_WAITING);
266 break;
267 case DEBOUNCE_EVENT_RELEASE:
268 case DEBOUNCE_EVENT_TIMEOUT_SHORT:
269 log_debounce_bug(fallback, event);
270 break;
271 case DEBOUNCE_EVENT_TIMEOUT:
272 case DEBOUNCE_EVENT_OTHERBUTTON:
273 debounce_set_state(fallback, DEBOUNCE_STATE_IS_UP);
274 debounce_notify_button(fallback,
275 LIBINPUT_BUTTON_STATE_RELEASED);
276 break;
277 }
278 }
279
280 static void
debounce_is_up_delaying_spurious_handle_event(struct fallback_dispatch * fallback,enum debounce_event event,uint64_t time)281 debounce_is_up_delaying_spurious_handle_event(struct fallback_dispatch *fallback, enum debounce_event event, uint64_t time)
282 {
283 switch (event) {
284 case DEBOUNCE_EVENT_PRESS:
285 debounce_set_state(fallback, DEBOUNCE_STATE_IS_DOWN);
286 debounce_cancel_timer(fallback);
287 debounce_cancel_timer_short(fallback);
288 break;
289 case DEBOUNCE_EVENT_RELEASE:
290 case DEBOUNCE_EVENT_TIMEOUT:
291 log_debounce_bug(fallback, event);
292 break;
293 case DEBOUNCE_EVENT_TIMEOUT_SHORT:
294 debounce_set_state(fallback, DEBOUNCE_STATE_IS_UP_WAITING);
295 debounce_notify_button(fallback,
296 LIBINPUT_BUTTON_STATE_RELEASED);
297 break;
298 case DEBOUNCE_EVENT_OTHERBUTTON:
299 debounce_set_state(fallback, DEBOUNCE_STATE_IS_UP);
300 debounce_notify_button(fallback,
301 LIBINPUT_BUTTON_STATE_RELEASED);
302 break;
303 }
304 }
305
306 static void
debounce_is_up_detecting_spurious_handle_event(struct fallback_dispatch * fallback,enum debounce_event event,uint64_t time)307 debounce_is_up_detecting_spurious_handle_event(struct fallback_dispatch *fallback, enum debounce_event event, uint64_t time)
308 {
309 switch (event) {
310 case DEBOUNCE_EVENT_PRESS:
311 debounce_set_timer(fallback, time);
312 debounce_set_timer_short(fallback, time);
313 /* Note: in a bouncing PRP case, we use the last press
314 * event time */
315 fallback->debounce.button_time = time;
316 debounce_set_state(fallback, DEBOUNCE_STATE_IS_DOWN_DETECTING_SPURIOUS);
317 break;
318 case DEBOUNCE_EVENT_RELEASE:
319 log_debounce_bug(fallback, event);
320 break;
321 case DEBOUNCE_EVENT_TIMEOUT:
322 debounce_set_state(fallback, DEBOUNCE_STATE_IS_UP);
323 break;
324 case DEBOUNCE_EVENT_TIMEOUT_SHORT:
325 debounce_set_state(fallback, DEBOUNCE_STATE_IS_UP_WAITING);
326 break;
327 case DEBOUNCE_EVENT_OTHERBUTTON:
328 debounce_set_state(fallback, DEBOUNCE_STATE_IS_UP);
329 break;
330 }
331 }
332
333 static void
debounce_is_down_detecting_spurious_handle_event(struct fallback_dispatch * fallback,enum debounce_event event,uint64_t time)334 debounce_is_down_detecting_spurious_handle_event(struct fallback_dispatch *fallback, enum debounce_event event, uint64_t time)
335 {
336 switch (event) {
337 case DEBOUNCE_EVENT_PRESS:
338 log_debounce_bug(fallback, event);
339 break;
340 case DEBOUNCE_EVENT_RELEASE:
341 debounce_set_timer(fallback, time);
342 debounce_set_timer_short(fallback, time);
343 debounce_set_state(fallback, DEBOUNCE_STATE_IS_UP_DETECTING_SPURIOUS);
344 break;
345 case DEBOUNCE_EVENT_TIMEOUT_SHORT:
346 debounce_cancel_timer(fallback);
347 debounce_set_state(fallback, DEBOUNCE_STATE_IS_DOWN);
348 debounce_enable_spurious(fallback);
349 debounce_notify_button(fallback,
350 LIBINPUT_BUTTON_STATE_PRESSED);
351 break;
352 case DEBOUNCE_EVENT_TIMEOUT:
353 case DEBOUNCE_EVENT_OTHERBUTTON:
354 debounce_set_state(fallback, DEBOUNCE_STATE_IS_DOWN);
355 debounce_notify_button(fallback,
356 LIBINPUT_BUTTON_STATE_PRESSED);
357 break;
358 }
359 }
360
361 static void
debounce_is_up_waiting_handle_event(struct fallback_dispatch * fallback,enum debounce_event event,uint64_t time)362 debounce_is_up_waiting_handle_event(struct fallback_dispatch *fallback, enum debounce_event event, uint64_t time)
363 {
364 switch (event) {
365 case DEBOUNCE_EVENT_PRESS:
366 debounce_set_timer(fallback, time);
367 /* Note: in a debouncing PRP case, we use the last press'
368 * time */
369 fallback->debounce.button_time = time;
370 debounce_set_state(fallback, DEBOUNCE_STATE_IS_DOWN_DELAYING);
371 break;
372 case DEBOUNCE_EVENT_RELEASE:
373 case DEBOUNCE_EVENT_TIMEOUT_SHORT:
374 log_debounce_bug(fallback, event);
375 break;
376 case DEBOUNCE_EVENT_TIMEOUT:
377 case DEBOUNCE_EVENT_OTHERBUTTON:
378 debounce_set_state(fallback, DEBOUNCE_STATE_IS_UP);
379 break;
380 }
381 }
382
383 static void
debounce_is_down_delaying_handle_event(struct fallback_dispatch * fallback,enum debounce_event event,uint64_t time)384 debounce_is_down_delaying_handle_event(struct fallback_dispatch *fallback, enum debounce_event event, uint64_t time)
385 {
386 switch (event) {
387 case DEBOUNCE_EVENT_PRESS:
388 log_debounce_bug(fallback, event);
389 break;
390 case DEBOUNCE_EVENT_RELEASE:
391 debounce_set_timer(fallback, time);
392 debounce_set_state(fallback, DEBOUNCE_STATE_IS_UP_WAITING);
393 break;
394 case DEBOUNCE_EVENT_TIMEOUT_SHORT:
395 log_debounce_bug(fallback, event);
396 break;
397 case DEBOUNCE_EVENT_TIMEOUT:
398 case DEBOUNCE_EVENT_OTHERBUTTON:
399 debounce_set_state(fallback, DEBOUNCE_STATE_IS_DOWN);
400 debounce_notify_button(fallback,
401 LIBINPUT_BUTTON_STATE_PRESSED);
402 break;
403 }
404 }
405
406 static void
debounce_disabled_handle_event(struct fallback_dispatch * fallback,enum debounce_event event,uint64_t time)407 debounce_disabled_handle_event(struct fallback_dispatch *fallback,
408 enum debounce_event event,
409 uint64_t time)
410 {
411 switch (event) {
412 case DEBOUNCE_EVENT_PRESS:
413 fallback->debounce.button_time = time;
414 debounce_notify_button(fallback,
415 LIBINPUT_BUTTON_STATE_PRESSED);
416 break;
417 case DEBOUNCE_EVENT_RELEASE:
418 fallback->debounce.button_time = time;
419 debounce_notify_button(fallback,
420 LIBINPUT_BUTTON_STATE_RELEASED);
421 break;
422 case DEBOUNCE_EVENT_TIMEOUT_SHORT:
423 case DEBOUNCE_EVENT_TIMEOUT:
424 log_debounce_bug(fallback, event);
425 break;
426 case DEBOUNCE_EVENT_OTHERBUTTON:
427 break;
428 }
429 }
430
431 static void
debounce_handle_event(struct fallback_dispatch * fallback,enum debounce_event event,uint64_t time)432 debounce_handle_event(struct fallback_dispatch *fallback,
433 enum debounce_event event,
434 uint64_t time)
435 {
436 enum debounce_state current = fallback->debounce.state;
437
438 if (event == DEBOUNCE_EVENT_OTHERBUTTON) {
439 debounce_cancel_timer(fallback);
440 debounce_cancel_timer_short(fallback);
441 }
442
443 switch(current) {
444 case DEBOUNCE_STATE_IS_UP:
445 debounce_is_up_handle_event(fallback, event, time);
446 break;
447 case DEBOUNCE_STATE_IS_DOWN:
448 debounce_is_down_handle_event(fallback, event, time);
449 break;
450 case DEBOUNCE_STATE_IS_DOWN_WAITING:
451 debounce_is_down_waiting_handle_event(fallback, event, time);
452 break;
453 case DEBOUNCE_STATE_IS_UP_DELAYING:
454 debounce_is_up_delaying_handle_event(fallback, event, time);
455 break;
456 case DEBOUNCE_STATE_IS_UP_DELAYING_SPURIOUS:
457 debounce_is_up_delaying_spurious_handle_event(fallback, event, time);
458 break;
459 case DEBOUNCE_STATE_IS_UP_DETECTING_SPURIOUS:
460 debounce_is_up_detecting_spurious_handle_event(fallback, event, time);
461 break;
462 case DEBOUNCE_STATE_IS_DOWN_DETECTING_SPURIOUS:
463 debounce_is_down_detecting_spurious_handle_event(fallback, event, time);
464 break;
465 case DEBOUNCE_STATE_IS_UP_WAITING:
466 debounce_is_up_waiting_handle_event(fallback, event, time);
467 break;
468 case DEBOUNCE_STATE_IS_DOWN_DELAYING:
469 debounce_is_down_delaying_handle_event(fallback, event, time);
470 break;
471 case DEBOUNCE_STATE_DISABLED:
472 debounce_disabled_handle_event(fallback, event, time);
473 break;
474 }
475
476 evdev_log_debug(fallback->device,
477 "debounce state: %s → %s → %s\n",
478 debounce_state_to_str(current),
479 debounce_event_to_str(event),
480 debounce_state_to_str(fallback->debounce.state));
481 }
482
483 void
fallback_debounce_handle_state(struct fallback_dispatch * dispatch,uint64_t time)484 fallback_debounce_handle_state(struct fallback_dispatch *dispatch,
485 uint64_t time)
486 {
487 unsigned int changed[16] = {0}; /* event codes of changed buttons */
488 size_t nchanged = 0;
489 bool flushed = false;
490
491 for (unsigned int code = 0; code <= KEY_MAX; code++) {
492 if (get_key_type(code) != KEY_TYPE_BUTTON)
493 continue;
494
495 if (hw_key_has_changed(dispatch, code))
496 changed[nchanged++] = code;
497
498 /* If you manage to press more than 16 buttons in the same
499 * frame, we just quietly ignore the rest of them */
500 if (nchanged == ARRAY_LENGTH(changed))
501 break;
502 }
503
504 /* If we have more than one button this frame or a different button,
505 * flush the state machine with otherbutton */
506 if (nchanged > 1 ||
507 changed[0] != dispatch->debounce.button_code) {
508 debounce_handle_event(dispatch,
509 DEBOUNCE_EVENT_OTHERBUTTON,
510 time);
511 flushed = true;
512 }
513
514 /* The state machine has some pre-conditions:
515 * - the IS_DOWN and IS_UP states are neutral entry states without
516 * any timeouts
517 * - a OTHERBUTTON event always flushes the state to IS_DOWN or
518 * IS_UP
519 */
520
521 for (size_t i = 0; i < nchanged; i++) {
522 bool is_down = hw_is_key_down(dispatch, changed[i]);
523
524 if (flushed &&
525 dispatch->debounce.state != DEBOUNCE_STATE_DISABLED) {
526 debounce_set_state(dispatch,
527 !is_down ?
528 DEBOUNCE_STATE_IS_DOWN :
529 DEBOUNCE_STATE_IS_UP);
530 flushed = false;
531 }
532
533 dispatch->debounce.button_code = changed[i];
534 debounce_handle_event(dispatch,
535 is_down ?
536 DEBOUNCE_EVENT_PRESS :
537 DEBOUNCE_EVENT_RELEASE,
538 time);
539
540 /* if we have more than one event, we flush the state
541 * machine immediately after the event itself */
542 if (nchanged > 1) {
543 debounce_handle_event(dispatch,
544 DEBOUNCE_EVENT_OTHERBUTTON,
545 time);
546 flushed = true;
547 }
548
549 }
550 }
551
552 static void
debounce_timeout(uint64_t now,void * data)553 debounce_timeout(uint64_t now, void *data)
554 {
555 struct evdev_device *device = data;
556 struct fallback_dispatch *dispatch =
557 fallback_dispatch(device->dispatch);
558
559 debounce_handle_event(dispatch, DEBOUNCE_EVENT_TIMEOUT, now);
560 }
561
562 static void
debounce_timeout_short(uint64_t now,void * data)563 debounce_timeout_short(uint64_t now, void *data)
564 {
565 struct evdev_device *device = data;
566 struct fallback_dispatch *dispatch =
567 fallback_dispatch(device->dispatch);
568
569 debounce_handle_event(dispatch, DEBOUNCE_EVENT_TIMEOUT_SHORT, now);
570 }
571
572 void
fallback_init_debounce(struct fallback_dispatch * dispatch)573 fallback_init_debounce(struct fallback_dispatch *dispatch)
574 {
575 struct evdev_device *device = dispatch->device;
576 char timer_name[64];
577
578 if (evdev_device_has_model_quirk(device, QUIRK_MODEL_BOUNCING_KEYS)) {
579 dispatch->debounce.state = DEBOUNCE_STATE_DISABLED;
580 return;
581 }
582
583 dispatch->debounce.state = DEBOUNCE_STATE_IS_UP;
584
585 snprintf(timer_name,
586 sizeof(timer_name),
587 "%s debounce short",
588 evdev_device_get_sysname(device));
589 libinput_timer_init(&dispatch->debounce.timer_short,
590 evdev_libinput_context(device),
591 timer_name,
592 debounce_timeout_short,
593 device);
594
595 snprintf(timer_name,
596 sizeof(timer_name),
597 "%s debounce",
598 evdev_device_get_sysname(device));
599 libinput_timer_init(&dispatch->debounce.timer,
600 evdev_libinput_context(device),
601 timer_name,
602 debounce_timeout,
603 device);
604 }
605