• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2017 James Ye <jye836@gmail.com>
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 <check.h>
27 #include <fcntl.h>
28 #include <libinput.h>
29 
30 #include "libinput-util.h"
31 #include "litest.h"
32 
33 static inline bool
switch_has_lid(struct litest_device * dev)34 switch_has_lid(struct litest_device *dev)
35 {
36 	return libinput_device_switch_has_switch(dev->libinput_device,
37 						 LIBINPUT_SWITCH_LID) > 0;
38 }
39 
40 static inline bool
switch_has_tablet_mode(struct litest_device * dev)41 switch_has_tablet_mode(struct litest_device *dev)
42 {
43 	return libinput_device_switch_has_switch(dev->libinput_device,
44 						 LIBINPUT_SWITCH_TABLET_MODE) > 0;
45 }
46 
START_TEST(switch_has_cap)47 START_TEST(switch_has_cap)
48 {
49 	struct litest_device *dev = litest_current_device();
50 
51 	/* Need to check for this specific device here because the
52 	 * unreliable tablet mode switch removes the capability too */
53 	if (dev->which == LITEST_TABLET_MODE_UNRELIABLE) {
54 		ck_assert(!libinput_device_has_capability(dev->libinput_device,
55 							  LIBINPUT_DEVICE_CAP_SWITCH));
56 		return;
57 	}
58 
59 	ck_assert(libinput_device_has_capability(dev->libinput_device,
60 						 LIBINPUT_DEVICE_CAP_SWITCH));
61 
62 }
63 END_TEST
64 
START_TEST(switch_has_lid_switch)65 START_TEST(switch_has_lid_switch)
66 {
67 	struct litest_device *dev = litest_current_device();
68 
69 	if (!libevdev_has_event_code(dev->evdev, EV_SW, SW_LID))
70 		return;
71 
72 	ck_assert_int_eq(libinput_device_switch_has_switch(dev->libinput_device,
73 							   LIBINPUT_SWITCH_LID),
74 			 1);
75 }
76 END_TEST
77 
78 static bool
tablet_mode_switch_is_reliable(struct litest_device * dev)79 tablet_mode_switch_is_reliable(struct litest_device *dev)
80 {
81 	bool is_unreliable = false;
82 
83        quirks_get_bool(dev->quirks,
84 		QUIRK_MODEL_TABLET_MODE_SWITCH_UNRELIABLE,
85 		&is_unreliable);
86 
87 	return !is_unreliable;
88 }
89 
START_TEST(switch_has_tablet_mode_switch)90 START_TEST(switch_has_tablet_mode_switch)
91 {
92 	struct litest_device *dev = litest_current_device();
93 	int has_switch;
94 
95 	if (!libevdev_has_event_code(dev->evdev, EV_SW, SW_TABLET_MODE))
96 		return;
97 
98 	has_switch = libinput_device_switch_has_switch(dev->libinput_device,
99 						       LIBINPUT_SWITCH_TABLET_MODE);
100 
101 	if (!tablet_mode_switch_is_reliable(dev))
102 		ck_assert_int_ne(has_switch, 1);
103 	else
104 		ck_assert_int_eq(has_switch, 1);
105 }
106 END_TEST
107 
START_TEST(switch_toggle)108 START_TEST(switch_toggle)
109 {
110 	struct litest_device *dev = litest_current_device();
111 	struct libinput *li = dev->libinput;
112 	struct libinput_event *event;
113 	enum libinput_switch sw = _i; /* ranged test */
114 
115 	litest_drain_events(li);
116 
117 	litest_grab_device(dev);
118 	litest_switch_action(dev, sw, LIBINPUT_SWITCH_STATE_ON);
119 	libinput_dispatch(li);
120 
121 	if (libinput_device_switch_has_switch(dev->libinput_device, sw) > 0) {
122 		event = libinput_get_event(li);
123 		litest_is_switch_event(event, sw, LIBINPUT_SWITCH_STATE_ON);
124 		libinput_event_destroy(event);
125 	} else {
126 		litest_assert_empty_queue(li);
127 	}
128 
129 	litest_switch_action(dev, sw, LIBINPUT_SWITCH_STATE_OFF);
130 	libinput_dispatch(li);
131 
132 	if (libinput_device_switch_has_switch(dev->libinput_device, sw) > 0) {
133 		event = libinput_get_event(li);
134 		litest_is_switch_event(event, sw, LIBINPUT_SWITCH_STATE_OFF);
135 		libinput_event_destroy(event);
136 	}
137 
138 	litest_assert_empty_queue(li);
139 	litest_ungrab_device(dev);
140 }
141 END_TEST
142 
START_TEST(switch_toggle_double)143 START_TEST(switch_toggle_double)
144 {
145 	struct litest_device *dev = litest_current_device();
146 	struct libinput *li = dev->libinput;
147 	struct libinput_event *event;
148 	enum libinput_switch sw = _i; /* ranged test */
149 
150 	if (libinput_device_switch_has_switch(dev->libinput_device, sw) <= 0)
151 		return;
152 
153 	litest_drain_events(li);
154 
155 	litest_grab_device(dev);
156 	litest_switch_action(dev, sw, LIBINPUT_SWITCH_STATE_ON);
157 	libinput_dispatch(li);
158 
159 	event = libinput_get_event(li);
160 	litest_is_switch_event(event, sw, LIBINPUT_SWITCH_STATE_ON);
161 	libinput_event_destroy(event);
162 
163 	/* This will be filtered by the kernel, so this test is a bit
164 	 * useless */
165 	litest_switch_action(dev, sw, LIBINPUT_SWITCH_STATE_ON);
166 	libinput_dispatch(li);
167 
168 	litest_assert_empty_queue(li);
169 	litest_ungrab_device(dev);
170 }
171 END_TEST
172 
173 static bool
lid_switch_is_reliable(struct litest_device * dev)174 lid_switch_is_reliable(struct litest_device *dev)
175 {
176 	char *prop;
177 	bool is_reliable = false;
178 
179 	if (quirks_get_string(dev->quirks,
180 			      QUIRK_ATTR_LID_SWITCH_RELIABILITY,
181 			      &prop)) {
182 		is_reliable = streq(prop, "reliable");
183 	}
184 
185 
186 	return is_reliable;
187 }
188 
START_TEST(switch_down_on_init)189 START_TEST(switch_down_on_init)
190 {
191 	struct litest_device *dev = litest_current_device();
192 	struct libinput *li;
193 	struct libinput_event *event;
194 	enum libinput_switch sw = _i; /* ranged test */
195 
196 	if (libinput_device_switch_has_switch(dev->libinput_device, sw) <= 0)
197 		return;
198 
199 	if (sw == LIBINPUT_SWITCH_LID && !lid_switch_is_reliable(dev))
200 		return;
201 
202 	litest_grab_device(dev);
203 	litest_switch_action(dev, sw, LIBINPUT_SWITCH_STATE_ON);
204 	litest_ungrab_device(dev);
205 
206 	/* need separate context to test */
207 	li = litest_create_context();
208 	libinput_path_add_device(li,
209 				 libevdev_uinput_get_devnode(dev->uinput));
210 	libinput_dispatch(li);
211 
212 	litest_wait_for_event_of_type(li, LIBINPUT_EVENT_SWITCH_TOGGLE, -1);
213 	event = libinput_get_event(li);
214 	litest_is_switch_event(event, sw, LIBINPUT_SWITCH_STATE_ON);
215 	libinput_event_destroy(event);
216 
217 	while ((event = libinput_get_event(li))) {
218 		ck_assert_int_ne(libinput_event_get_type(event),
219 				 LIBINPUT_EVENT_SWITCH_TOGGLE);
220 		libinput_event_destroy(event);
221 	}
222 
223 	litest_switch_action(dev, sw, LIBINPUT_SWITCH_STATE_OFF);
224 	libinput_dispatch(li);
225 	event = libinput_get_event(li);
226 	litest_is_switch_event(event, sw, LIBINPUT_SWITCH_STATE_OFF);
227 	libinput_event_destroy(event);
228 	litest_assert_empty_queue(li);
229 
230 	litest_destroy_context(li);
231 }
232 END_TEST
233 
START_TEST(switch_not_down_on_init)234 START_TEST(switch_not_down_on_init)
235 {
236 	struct litest_device *dev = litest_current_device();
237 	struct libinput *li;
238 	struct libinput_event *event;
239 	enum libinput_switch sw = LIBINPUT_SWITCH_LID;
240 
241 	if (libinput_device_switch_has_switch(dev->libinput_device, sw) <= 0)
242 		return;
243 
244 	if (sw == LIBINPUT_SWITCH_LID && lid_switch_is_reliable(dev))
245 		return;
246 
247 	litest_grab_device(dev);
248 	litest_switch_action(dev, sw, LIBINPUT_SWITCH_STATE_ON);
249 	litest_ungrab_device(dev);
250 
251 	/* need separate context to test */
252 	li = litest_create_context();
253 	libinput_path_add_device(li,
254 				 libevdev_uinput_get_devnode(dev->uinput));
255 	libinput_dispatch(li);
256 
257 	while ((event = libinput_get_event(li)) != NULL) {
258 		ck_assert_int_ne(libinput_event_get_type(event),
259 				 LIBINPUT_EVENT_SWITCH_TOGGLE);
260 		libinput_event_destroy(event);
261 	}
262 
263 	litest_switch_action(dev, sw, LIBINPUT_SWITCH_STATE_OFF);
264 	litest_assert_empty_queue(li);
265 	litest_destroy_context(li);
266 }
267 END_TEST
268 
269 static inline struct litest_device *
switch_init_paired_touchpad(struct libinput * li)270 switch_init_paired_touchpad(struct libinput *li)
271 {
272 	enum litest_device_type which = LITEST_SYNAPTICS_I2C;
273 
274 	return litest_add_device(li, which);
275 }
276 
START_TEST(switch_disable_touchpad)277 START_TEST(switch_disable_touchpad)
278 {
279 	struct litest_device *sw = litest_current_device();
280 	struct litest_device *touchpad;
281 	struct libinput *li = sw->libinput;
282 	enum libinput_switch which = _i; /* ranged test */
283 
284 	if (libinput_device_switch_has_switch(sw->libinput_device, which) <= 0)
285 		return;
286 
287 	touchpad = switch_init_paired_touchpad(li);
288 	litest_disable_tap(touchpad->libinput_device);
289 	litest_drain_events(li);
290 
291 	litest_grab_device(sw);
292 
293 	/* switch is on - no events */
294 	litest_switch_action(sw, which, LIBINPUT_SWITCH_STATE_ON);
295 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_SWITCH_TOGGLE);
296 
297 	litest_touch_down(touchpad, 0, 50, 50);
298 	litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10);
299 	litest_touch_up(touchpad, 0);
300 	litest_assert_empty_queue(li);
301 
302 	/* switch is off - motion events */
303 	litest_switch_action(sw, which, LIBINPUT_SWITCH_STATE_OFF);
304 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_SWITCH_TOGGLE);
305 
306 	litest_touch_down(touchpad, 0, 50, 50);
307 	litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10);
308 	litest_touch_up(touchpad, 0);
309 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
310 
311 	litest_delete_device(touchpad);
312 	litest_ungrab_device(sw);
313 }
314 END_TEST
315 
START_TEST(switch_disable_touchpad_during_touch)316 START_TEST(switch_disable_touchpad_during_touch)
317 {
318 	struct litest_device *sw = litest_current_device();
319 	struct litest_device *touchpad;
320 	struct libinput *li = sw->libinput;
321 	enum libinput_switch which = _i; /* ranged test */
322 
323 	if (libinput_device_switch_has_switch(sw->libinput_device, which) <= 0)
324 		return;
325 
326 	touchpad = switch_init_paired_touchpad(li);
327 	litest_disable_tap(touchpad->libinput_device);
328 	litest_drain_events(li);
329 
330 	litest_touch_down(touchpad, 0, 50, 50);
331 	litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 5);
332 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
333 
334 	litest_grab_device(sw);
335 	litest_switch_action(sw, which, LIBINPUT_SWITCH_STATE_ON);
336 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_SWITCH_TOGGLE);
337 	litest_ungrab_device(sw);
338 
339 	litest_touch_move_to(touchpad, 0, 70, 50, 50, 50, 5);
340 	litest_touch_up(touchpad, 0);
341 	litest_assert_empty_queue(li);
342 
343 	litest_delete_device(touchpad);
344 }
345 END_TEST
346 
START_TEST(switch_disable_touchpad_edge_scroll)347 START_TEST(switch_disable_touchpad_edge_scroll)
348 {
349 	struct litest_device *sw = litest_current_device();
350 	struct litest_device *touchpad;
351 	struct libinput *li = sw->libinput;
352 	enum libinput_switch which = _i; /* ranged test */
353 
354 	if (libinput_device_switch_has_switch(sw->libinput_device, which) <= 0)
355 		return;
356 
357 	touchpad = switch_init_paired_touchpad(li);
358 	litest_enable_edge_scroll(touchpad);
359 
360 	litest_drain_events(li);
361 
362 	litest_grab_device(sw);
363 	litest_switch_action(sw, which, LIBINPUT_SWITCH_STATE_ON);
364 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_SWITCH_TOGGLE);
365 	litest_ungrab_device(sw);
366 
367 	litest_touch_down(touchpad, 0, 99, 20);
368 	libinput_dispatch(li);
369 	litest_timeout_edgescroll();
370 	libinput_dispatch(li);
371 	litest_assert_empty_queue(li);
372 
373 	litest_touch_move_to(touchpad, 0, 99, 20, 99, 80, 60);
374 	libinput_dispatch(li);
375 	litest_assert_empty_queue(li);
376 
377 	litest_touch_move_to(touchpad, 0, 99, 80, 99, 20, 60);
378 	litest_touch_up(touchpad, 0);
379 	libinput_dispatch(li);
380 	litest_assert_empty_queue(li);
381 
382 	litest_delete_device(touchpad);
383 }
384 END_TEST
385 
START_TEST(switch_disable_touchpad_edge_scroll_interrupt)386 START_TEST(switch_disable_touchpad_edge_scroll_interrupt)
387 {
388 	struct litest_device *sw = litest_current_device();
389 	struct litest_device *touchpad;
390 	struct libinput *li = sw->libinput;
391 	struct libinput_event *event;
392 	enum libinput_switch which = _i; /* ranged test */
393 
394 	if (libinput_device_switch_has_switch(sw->libinput_device, which) <= 0)
395 		return;
396 
397 	touchpad = switch_init_paired_touchpad(li);
398 	litest_enable_edge_scroll(touchpad);
399 
400 	litest_drain_events(li);
401 
402 	litest_touch_down(touchpad, 0, 99, 20);
403 	libinput_dispatch(li);
404 	litest_timeout_edgescroll();
405 	litest_touch_move_to(touchpad, 0, 99, 20, 99, 30, 10);
406 	libinput_dispatch(li);
407 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS);
408 
409 	litest_grab_device(sw);
410 	litest_switch_action(sw, which, LIBINPUT_SWITCH_STATE_ON);
411 	litest_ungrab_device(sw);
412 	libinput_dispatch(li);
413 
414 	event = libinput_get_event(li);
415 	litest_is_axis_event(event,
416 			     LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL,
417 			     LIBINPUT_POINTER_AXIS_SOURCE_FINGER);
418 	libinput_event_destroy(event);
419 
420 	event = libinput_get_event(li);
421 	litest_is_switch_event(event, which, LIBINPUT_SWITCH_STATE_ON);
422 	libinput_event_destroy(event);
423 
424 	litest_delete_device(touchpad);
425 }
426 END_TEST
427 
START_TEST(switch_disable_touchpad_already_open)428 START_TEST(switch_disable_touchpad_already_open)
429 {
430 	struct litest_device *sw = litest_current_device();
431 	struct litest_device *touchpad;
432 	struct libinput *li = sw->libinput;
433 	enum libinput_switch which = _i; /* ranged test */
434 
435 	if (libinput_device_switch_has_switch(sw->libinput_device, which) <= 0)
436 		return;
437 
438 	touchpad = switch_init_paired_touchpad(li);
439 
440 	litest_disable_tap(touchpad->libinput_device);
441 	litest_drain_events(li);
442 
443 	/* default: switch is off - motion events */
444 	litest_touch_down(touchpad, 0, 50, 50);
445 	litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10);
446 	litest_touch_up(touchpad, 0);
447 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
448 
449 	/* disable switch - motion events */
450 	litest_switch_action(sw, which, LIBINPUT_SWITCH_STATE_OFF);
451 	litest_assert_empty_queue(li);
452 
453 	litest_touch_down(touchpad, 0, 50, 50);
454 	litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10);
455 	litest_touch_up(touchpad, 0);
456 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
457 
458 	litest_delete_device(touchpad);
459 }
460 END_TEST
461 
START_TEST(switch_dont_resume_disabled_touchpad)462 START_TEST(switch_dont_resume_disabled_touchpad)
463 {
464 	struct litest_device *sw = litest_current_device();
465 	struct litest_device *touchpad;
466 	struct libinput *li = sw->libinput;
467 	enum libinput_switch which = _i; /* ranged test */
468 
469 	if (libinput_device_switch_has_switch(sw->libinput_device, which) <= 0)
470 		return;
471 
472 	touchpad = switch_init_paired_touchpad(li);
473 	litest_disable_tap(touchpad->libinput_device);
474 	libinput_device_config_send_events_set_mode(touchpad->libinput_device,
475 						    LIBINPUT_CONFIG_SEND_EVENTS_DISABLED);
476 	litest_drain_events(li);
477 
478 	/* switch is on - no events */
479 	litest_grab_device(sw);
480 	litest_switch_action(sw, which, LIBINPUT_SWITCH_STATE_ON);
481 	litest_ungrab_device(sw);
482 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_SWITCH_TOGGLE);
483 
484 	litest_touch_down(touchpad, 0, 50, 50);
485 	litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10);
486 	litest_touch_up(touchpad, 0);
487 	litest_assert_empty_queue(li);
488 
489 	/* switch is off but but tp is still disabled */
490 	litest_switch_action(sw, which, LIBINPUT_SWITCH_STATE_OFF);
491 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_SWITCH_TOGGLE);
492 
493 	litest_touch_down(touchpad, 0, 50, 50);
494 	litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10);
495 	litest_touch_up(touchpad, 0);
496 	litest_assert_empty_queue(li);
497 
498 	litest_delete_device(touchpad);
499 }
500 END_TEST
501 
START_TEST(switch_dont_resume_disabled_touchpad_external_mouse)502 START_TEST(switch_dont_resume_disabled_touchpad_external_mouse)
503 {
504 	struct litest_device *sw = litest_current_device();
505 	struct litest_device *touchpad, *mouse;
506 	struct libinput *li = sw->libinput;
507 	enum libinput_switch which = _i; /* ranged test */
508 
509 	if (libinput_device_switch_has_switch(sw->libinput_device, which) <= 0)
510 		return;
511 
512 	touchpad = switch_init_paired_touchpad(li);
513 	mouse = litest_add_device(li, LITEST_MOUSE);
514 	litest_disable_tap(touchpad->libinput_device);
515 	libinput_device_config_send_events_set_mode(touchpad->libinput_device,
516 						    LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE);
517 	litest_drain_events(li);
518 
519 	litest_touch_down(touchpad, 0, 50, 50);
520 	litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10);
521 	litest_touch_up(touchpad, 0);
522 	litest_assert_empty_queue(li);
523 
524 	/* switch is on - no events */
525 	litest_grab_device(sw);
526 	litest_switch_action(sw, which, LIBINPUT_SWITCH_STATE_ON);
527 	litest_ungrab_device(sw);
528 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_SWITCH_TOGGLE);
529 
530 	litest_touch_down(touchpad, 0, 50, 50);
531 	litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10);
532 	litest_touch_up(touchpad, 0);
533 	litest_assert_empty_queue(li);
534 
535 	/* switch is off but but tp is still disabled */
536 	litest_switch_action(sw, which, LIBINPUT_SWITCH_STATE_OFF);
537 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_SWITCH_TOGGLE);
538 
539 	litest_touch_down(touchpad, 0, 50, 50);
540 	litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10);
541 	litest_touch_up(touchpad, 0);
542 	litest_assert_empty_queue(li);
543 
544 	litest_delete_device(touchpad);
545 	litest_delete_device(mouse);
546 }
547 END_TEST
548 
START_TEST(lid_open_on_key)549 START_TEST(lid_open_on_key)
550 {
551 	struct litest_device *sw = litest_current_device();
552 	struct litest_device *keyboard;
553 	struct libinput *li = sw->libinput;
554 	struct libinput_event *event;
555 
556 	if (!switch_has_lid(sw))
557 		return;
558 
559 	keyboard = litest_add_device(li, LITEST_KEYBOARD);
560 
561 	litest_grab_device(sw);
562 	for (int i = 0; i < 3; i++) {
563 		litest_switch_action(sw,
564 				     LIBINPUT_SWITCH_LID,
565 				     LIBINPUT_SWITCH_STATE_ON);
566 		litest_drain_events(li);
567 
568 		litest_event(keyboard, EV_KEY, KEY_A, 1);
569 		litest_event(keyboard, EV_SYN, SYN_REPORT, 0);
570 		litest_event(keyboard, EV_KEY, KEY_A, 0);
571 		litest_event(keyboard, EV_SYN, SYN_REPORT, 0);
572 		libinput_dispatch(li);
573 
574 		event = libinput_get_event(li);
575 		litest_is_switch_event(event,
576 				       LIBINPUT_SWITCH_LID,
577 				       LIBINPUT_SWITCH_STATE_OFF);
578 		libinput_event_destroy(event);
579 
580 		litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY);
581 
582 		litest_switch_action(sw,
583 				     LIBINPUT_SWITCH_LID,
584 				     LIBINPUT_SWITCH_STATE_OFF);
585 		litest_assert_empty_queue(li);
586 	}
587 	litest_ungrab_device(sw);
588 
589 	litest_delete_device(keyboard);
590 }
591 END_TEST
592 
START_TEST(lid_open_on_key_touchpad_enabled)593 START_TEST(lid_open_on_key_touchpad_enabled)
594 {
595 	struct litest_device *sw = litest_current_device();
596 	struct litest_device *keyboard, *touchpad;
597 	struct libinput *li = sw->libinput;
598 
599 	if (!switch_has_lid(sw))
600 		return;
601 
602 	keyboard = litest_add_device(li, LITEST_KEYBOARD);
603 	touchpad = litest_add_device(li, LITEST_SYNAPTICS_I2C);
604 
605 	litest_grab_device(sw);
606 	litest_switch_action(sw,
607 			     LIBINPUT_SWITCH_LID,
608 			     LIBINPUT_SWITCH_STATE_ON);
609 	litest_ungrab_device(sw);
610 	litest_drain_events(li);
611 
612 	litest_event(keyboard, EV_KEY, KEY_A, 1);
613 	litest_event(keyboard, EV_SYN, SYN_REPORT, 0);
614 	litest_event(keyboard, EV_KEY, KEY_A, 0);
615 	litest_event(keyboard, EV_SYN, SYN_REPORT, 0);
616 	litest_drain_events(li);
617 	litest_timeout_dwt_long();
618 
619 	litest_touch_down(touchpad, 0, 50, 50);
620 	litest_touch_move_to(touchpad, 0, 50, 50, 70, 70, 10);
621 	litest_touch_up(touchpad, 0);
622 	libinput_dispatch(li);
623 
624 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
625 
626 	litest_delete_device(keyboard);
627 	litest_delete_device(touchpad);
628 }
629 END_TEST
630 
START_TEST(switch_suspend_with_keyboard)631 START_TEST(switch_suspend_with_keyboard)
632 {
633 	struct libinput *li;
634 	struct litest_device *keyboard;
635 	struct litest_device *sw;
636 	enum libinput_switch which = _i; /* ranged test */
637 
638 	li = litest_create_context();
639 
640 	switch(which) {
641 	case LIBINPUT_SWITCH_LID:
642 		sw = litest_add_device(li, LITEST_LID_SWITCH);
643 		break;
644 	case LIBINPUT_SWITCH_TABLET_MODE:
645 		sw = litest_add_device(li, LITEST_THINKPAD_EXTRABUTTONS);
646 		break;
647 	default:
648 		abort();
649 	}
650 
651 	libinput_dispatch(li);
652 
653 	keyboard = litest_add_device(li, LITEST_KEYBOARD);
654 	libinput_dispatch(li);
655 
656 	litest_grab_device(sw);
657 	litest_switch_action(sw, which, LIBINPUT_SWITCH_STATE_ON);
658 	litest_drain_events(li);
659 	litest_switch_action(sw, which, LIBINPUT_SWITCH_STATE_OFF);
660 	litest_drain_events(li);
661 	litest_ungrab_device(sw);
662 
663 	litest_delete_device(keyboard);
664 	litest_drain_events(li);
665 
666 	litest_delete_device(sw);
667 	libinput_dispatch(li);
668 
669 	litest_destroy_context(li);
670 }
671 END_TEST
672 
START_TEST(switch_suspend_with_touchpad)673 START_TEST(switch_suspend_with_touchpad)
674 {
675 	struct libinput *li;
676 	struct litest_device *touchpad, *sw;
677 	enum libinput_switch which = _i; /* ranged test */
678 
679 	li = litest_create_context();
680 
681 	switch(which) {
682 	case LIBINPUT_SWITCH_LID:
683 		sw = litest_add_device(li, LITEST_LID_SWITCH);
684 		break;
685 	case LIBINPUT_SWITCH_TABLET_MODE:
686 		sw = litest_add_device(li, LITEST_THINKPAD_EXTRABUTTONS);
687 		break;
688 	default:
689 		abort();
690 	}
691 
692 	litest_drain_events(li);
693 
694 	touchpad = litest_add_device(li, LITEST_SYNAPTICS_I2C);
695 	litest_drain_events(li);
696 
697 	litest_grab_device(sw);
698 	litest_switch_action(sw, which, LIBINPUT_SWITCH_STATE_ON);
699 	litest_drain_events(li);
700 	litest_switch_action(sw, which, LIBINPUT_SWITCH_STATE_OFF);
701 	litest_drain_events(li);
702 	litest_ungrab_device(sw);
703 
704 	litest_delete_device(sw);
705 	litest_drain_events(li);
706 	litest_delete_device(touchpad);
707 	litest_drain_events(li);
708 
709 	litest_destroy_context(li);
710 }
711 END_TEST
712 
START_TEST(lid_update_hw_on_key)713 START_TEST(lid_update_hw_on_key)
714 {
715 	struct litest_device *sw = litest_current_device();
716 	struct libinput *li = sw->libinput;
717 	struct litest_device *keyboard;
718 	struct libevdev *evdev;
719 	struct input_event event;
720 	int fd;
721 	int rc;
722 
723 	if (!switch_has_lid(sw))
724 		return;
725 
726 	keyboard = litest_add_device(li, LITEST_KEYBOARD);
727 
728 	litest_grab_device(sw);
729 	litest_switch_action(sw,
730 			     LIBINPUT_SWITCH_LID,
731 			     LIBINPUT_SWITCH_STATE_ON);
732 	litest_drain_events(li);
733 	litest_ungrab_device(sw);
734 
735 	/* Separate direct libevdev context to check if the HW event goes
736 	 * through */
737 	fd = open(libevdev_uinput_get_devnode(sw->uinput), O_RDONLY|O_NONBLOCK);
738 	ck_assert_int_ge(fd, 0);
739 	ck_assert_int_eq(libevdev_new_from_fd(fd, &evdev), 0);
740 	ck_assert_int_eq(libevdev_get_event_value(evdev, EV_SW, SW_LID), 1);
741 
742 	/* Typing on the keyboard should trigger a lid open event */
743 	litest_event(keyboard, EV_KEY, KEY_A, 1);
744 	litest_event(keyboard, EV_SYN, SYN_REPORT, 0);
745 	litest_event(keyboard, EV_KEY, KEY_A, 0);
746 	litest_event(keyboard, EV_SYN, SYN_REPORT, 0);
747 	litest_drain_events(li);
748 
749 	rc = libevdev_next_event(evdev, LIBEVDEV_READ_FLAG_NORMAL, &event);
750 	ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SUCCESS);
751 	ck_assert_int_eq(event.type, EV_SW);
752 	ck_assert_int_eq(event.code, SW_LID);
753 	ck_assert_int_eq(event.value, 0);
754 	rc = libevdev_next_event(evdev, LIBEVDEV_READ_FLAG_NORMAL, &event);
755 	ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SUCCESS);
756 	ck_assert_int_eq(event.type, EV_SYN);
757 	ck_assert_int_eq(event.code, SYN_REPORT);
758 	ck_assert_int_eq(event.value, 0);
759 	rc = libevdev_next_event(evdev, LIBEVDEV_READ_FLAG_NORMAL, &event);
760 	ck_assert_int_eq(rc, -EAGAIN);
761 
762 	litest_delete_device(keyboard);
763 	close(fd);
764 	libevdev_free(evdev);
765 }
766 END_TEST
767 
START_TEST(lid_update_hw_on_key_closed_on_init)768 START_TEST(lid_update_hw_on_key_closed_on_init)
769 {
770 	struct litest_device *sw = litest_current_device();
771 	struct libinput *li;
772 	struct litest_device *keyboard;
773 	struct libevdev *evdev = sw->evdev;
774 	struct input_event event;
775 	int fd;
776 	int rc;
777 
778 	litest_grab_device(sw);
779 	litest_switch_action(sw,
780 			     LIBINPUT_SWITCH_LID,
781 			     LIBINPUT_SWITCH_STATE_ON);
782 	litest_ungrab_device(sw);
783 
784 	/* Separate direct libevdev context to check if the HW event goes
785 	 * through */
786 	fd = open(libevdev_uinput_get_devnode(sw->uinput), O_RDONLY|O_NONBLOCK);
787 	ck_assert_int_ge(fd, 0);
788 	ck_assert_int_eq(libevdev_new_from_fd(fd, &evdev), 0);
789 	ck_assert_int_eq(libevdev_get_event_value(evdev, EV_SW, SW_LID), 1);
790 
791 	keyboard = litest_add_device(sw->libinput, LITEST_KEYBOARD);
792 
793 	/* separate context for the right state on init */
794 	li = litest_create_context();
795 	libinput_path_add_device(li,
796 				 libevdev_uinput_get_devnode(sw->uinput));
797 	libinput_path_add_device(li,
798 				 libevdev_uinput_get_devnode(keyboard->uinput));
799 
800 	/* don't expect a switch waiting for us, this is run for an
801 	 * unreliable device */
802 	while (libinput_next_event_type(li) != LIBINPUT_EVENT_NONE) {
803 		ck_assert_int_ne(libinput_next_event_type(li),
804 				 LIBINPUT_EVENT_SWITCH_TOGGLE);
805 		libinput_event_destroy(libinput_get_event(li));
806 	}
807 
808 	litest_event(keyboard, EV_KEY, KEY_A, 1);
809 	litest_event(keyboard, EV_SYN, SYN_REPORT, 0);
810 	litest_event(keyboard, EV_KEY, KEY_A, 0);
811 	litest_event(keyboard, EV_SYN, SYN_REPORT, 0);
812 	/* No switch event, we're still in vanilla (open) state */
813 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY);
814 
815 	/* Make sure kernel state has updated */
816 	rc = libevdev_next_event(evdev, LIBEVDEV_READ_FLAG_NORMAL, &event);
817 	ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SUCCESS);
818 	ck_assert_int_eq(event.type, EV_SW);
819 	ck_assert_int_eq(event.code, SW_LID);
820 	ck_assert_int_eq(event.value, 0);
821 	rc = libevdev_next_event(evdev, LIBEVDEV_READ_FLAG_NORMAL, &event);
822 	ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SUCCESS);
823 	ck_assert_int_eq(event.type, EV_SYN);
824 	ck_assert_int_eq(event.code, SYN_REPORT);
825 	ck_assert_int_eq(event.value, 0);
826 	rc = libevdev_next_event(evdev, LIBEVDEV_READ_FLAG_NORMAL, &event);
827 	ck_assert_int_eq(rc, -EAGAIN);
828 
829 	litest_destroy_context(li);
830 	litest_delete_device(keyboard);
831 	close(fd);
832 	libevdev_free(evdev);
833 }
834 END_TEST
835 
START_TEST(lid_update_hw_on_key_multiple_keyboards)836 START_TEST(lid_update_hw_on_key_multiple_keyboards)
837 {
838 	struct litest_device *sw = litest_current_device();
839 	struct libinput *li = sw->libinput;
840 	struct litest_device *keyboard1, *keyboard2;
841 	struct libevdev *evdev = sw->evdev;
842 	struct input_event event;
843 	int fd;
844 	int rc;
845 
846 	if (!switch_has_lid(sw))
847 		return;
848 
849 	keyboard1 = litest_add_device(li,
850 				LITEST_KEYBOARD_BLADE_STEALTH_VIDEOSWITCH);
851 	libinput_dispatch(li);
852 
853 	keyboard2 = litest_add_device(li, LITEST_KEYBOARD_BLADE_STEALTH);
854 	libinput_dispatch(li);
855 
856 	litest_grab_device(sw);
857 	litest_switch_action(sw,
858 			     LIBINPUT_SWITCH_LID,
859 			     LIBINPUT_SWITCH_STATE_ON);
860 	litest_drain_events(li);
861 	litest_ungrab_device(sw);
862 
863 	/* Separate direct libevdev context to check if the HW event goes
864 	 * through */
865 	fd = open(libevdev_uinput_get_devnode(sw->uinput), O_RDONLY|O_NONBLOCK);
866 	ck_assert_int_ge(fd, 0);
867 	ck_assert_int_eq(libevdev_new_from_fd(fd, &evdev), 0);
868 	ck_assert_int_eq(libevdev_get_event_value(evdev, EV_SW, SW_LID), 1);
869 
870 	/* Typing on the second keyboard should trigger a lid open event */
871 	litest_event(keyboard2, EV_KEY, KEY_A, 1);
872 	litest_event(keyboard2, EV_SYN, SYN_REPORT, 0);
873 	litest_event(keyboard2, EV_KEY, KEY_A, 0);
874 	litest_event(keyboard2, EV_SYN, SYN_REPORT, 0);
875 	litest_drain_events(li);
876 
877 	rc = libevdev_next_event(evdev, LIBEVDEV_READ_FLAG_NORMAL, &event);
878 	ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SUCCESS);
879 	ck_assert_int_eq(event.type, EV_SW);
880 	ck_assert_int_eq(event.code, SW_LID);
881 	ck_assert_int_eq(event.value, 0);
882 	rc = libevdev_next_event(evdev, LIBEVDEV_READ_FLAG_NORMAL, &event);
883 	ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SUCCESS);
884 	ck_assert_int_eq(event.type, EV_SYN);
885 	ck_assert_int_eq(event.code, SYN_REPORT);
886 	ck_assert_int_eq(event.value, 0);
887 	rc = libevdev_next_event(evdev, LIBEVDEV_READ_FLAG_NORMAL, &event);
888 	ck_assert_int_eq(rc, -EAGAIN);
889 
890 	litest_delete_device(keyboard1);
891 	litest_delete_device(keyboard2);
892 	close(fd);
893 	libevdev_free(evdev);
894 }
895 END_TEST
896 
START_TEST(lid_key_press)897 START_TEST(lid_key_press)
898 {
899 	struct litest_device *sw = litest_current_device();
900 	struct libinput *li = sw->libinput;
901 
902 	litest_drain_events(li);
903 
904 	litest_keyboard_key(sw, KEY_VOLUMEUP, true);
905 	litest_keyboard_key(sw, KEY_VOLUMEUP, false);
906 	libinput_dispatch(li);
907 
908 	/* Check that we're routing key events from a lid device too */
909 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY);
910 }
911 END_TEST
912 
START_TEST(tablet_mode_disable_touchpad_on_init)913 START_TEST(tablet_mode_disable_touchpad_on_init)
914 {
915 	struct litest_device *sw = litest_current_device();
916 	struct litest_device *touchpad;
917 	struct libinput *li = sw->libinput;
918 
919 	if (!switch_has_tablet_mode(sw))
920 		return;
921 
922 	litest_grab_device(sw);
923 	litest_switch_action(sw,
924 			     LIBINPUT_SWITCH_TABLET_MODE,
925 			     LIBINPUT_SWITCH_STATE_ON);
926 	litest_drain_events(li);
927 
928 	/* touchpad comes with switch already on - no events */
929 	touchpad = switch_init_paired_touchpad(li);
930 	litest_disable_tap(touchpad->libinput_device);
931 	litest_drain_events(li);
932 
933 	litest_touch_down(touchpad, 0, 50, 50);
934 	litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10);
935 	litest_touch_up(touchpad, 0);
936 	litest_assert_empty_queue(li);
937 
938 	litest_switch_action(sw,
939 			     LIBINPUT_SWITCH_TABLET_MODE,
940 			     LIBINPUT_SWITCH_STATE_OFF);
941 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_SWITCH_TOGGLE);
942 
943 	litest_touch_down(touchpad, 0, 50, 50);
944 	litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10);
945 	litest_touch_up(touchpad, 0);
946 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
947 	litest_ungrab_device(sw);
948 
949 	litest_delete_device(touchpad);
950 }
951 END_TEST
952 
START_TEST(tablet_mode_disable_touchpad_on_resume)953 START_TEST(tablet_mode_disable_touchpad_on_resume)
954 {
955 	struct litest_device *sw = litest_current_device();
956 	struct litest_device *touchpad;
957 	struct libinput *li = sw->libinput;
958 	struct libinput_event *event;
959 	bool have_switch_toggle = false;
960 
961 	if (!switch_has_tablet_mode(sw))
962 		return;
963 
964 	touchpad = switch_init_paired_touchpad(li);
965 	litest_disable_tap(touchpad->libinput_device);
966 	litest_drain_events(li);
967 
968 	libinput_suspend(li);
969 	litest_switch_action(sw,
970 			     LIBINPUT_SWITCH_TABLET_MODE,
971 			     LIBINPUT_SWITCH_STATE_ON);
972 	litest_drain_events(li);
973 	libinput_resume(li);
974 	libinput_dispatch(li);
975 
976 	while ((event = libinput_get_event(li))) {
977 		enum libinput_event_type type;
978 
979 		type = libinput_event_get_type(event);
980 		switch (type) {
981 		case LIBINPUT_EVENT_DEVICE_ADDED:
982 			break;
983 		case LIBINPUT_EVENT_SWITCH_TOGGLE:
984 			litest_is_switch_event(event,
985 					       LIBINPUT_SWITCH_TABLET_MODE,
986 					       LIBINPUT_SWITCH_STATE_ON);
987 			have_switch_toggle = true;
988 			break;
989 		default:
990 			ck_abort();
991 		}
992 		libinput_event_destroy(event);
993 	}
994 
995 	ck_assert(have_switch_toggle);
996 
997 	litest_touch_down(touchpad, 0, 50, 50);
998 	litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10);
999 	litest_touch_up(touchpad, 0);
1000 	litest_assert_empty_queue(li);
1001 
1002 	litest_switch_action(sw,
1003 			     LIBINPUT_SWITCH_TABLET_MODE,
1004 			     LIBINPUT_SWITCH_STATE_OFF);
1005 	libinput_dispatch(li);
1006 	event = libinput_get_event(li);
1007 	litest_is_switch_event(event,
1008 			       LIBINPUT_SWITCH_TABLET_MODE,
1009 			       LIBINPUT_SWITCH_STATE_OFF);
1010 	libinput_event_destroy(event);
1011 
1012 	litest_touch_down(touchpad, 0, 50, 50);
1013 	litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10);
1014 	litest_touch_up(touchpad, 0);
1015 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
1016 
1017 	litest_delete_device(touchpad);
1018 }
1019 END_TEST
1020 
START_TEST(tablet_mode_enable_touchpad_on_resume)1021 START_TEST(tablet_mode_enable_touchpad_on_resume)
1022 {
1023 	struct litest_device *sw = litest_current_device();
1024 	struct litest_device *touchpad;
1025 	struct libinput *li = sw->libinput;
1026 	struct libinput_event *event;
1027 
1028 	if (!switch_has_tablet_mode(sw))
1029 		return;
1030 
1031 	touchpad = switch_init_paired_touchpad(li);
1032 	litest_disable_tap(touchpad->libinput_device);
1033 	litest_drain_events(li);
1034 
1035 	litest_switch_action(sw,
1036 			     LIBINPUT_SWITCH_TABLET_MODE,
1037 			     LIBINPUT_SWITCH_STATE_ON);
1038 	libinput_suspend(li);
1039 	litest_drain_events(li);
1040 
1041 	litest_switch_action(sw,
1042 			     LIBINPUT_SWITCH_TABLET_MODE,
1043 			     LIBINPUT_SWITCH_STATE_OFF);
1044 
1045 	libinput_resume(li);
1046 	libinput_dispatch(li);
1047 
1048 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_DEVICE_ADDED);
1049 
1050 	litest_touch_down(touchpad, 0, 50, 50);
1051 	litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10);
1052 	litest_touch_up(touchpad, 0);
1053 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
1054 
1055 	litest_switch_action(sw,
1056 			     LIBINPUT_SWITCH_TABLET_MODE,
1057 			     LIBINPUT_SWITCH_STATE_ON);
1058 	libinput_dispatch(li);
1059 	event = libinput_get_event(li);
1060 	litest_is_switch_event(event,
1061 			       LIBINPUT_SWITCH_TABLET_MODE,
1062 			       LIBINPUT_SWITCH_STATE_ON);
1063 	libinput_event_destroy(event);
1064 
1065 	litest_touch_down(touchpad, 0, 50, 50);
1066 	litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10);
1067 	litest_touch_up(touchpad, 0);
1068 	litest_assert_empty_queue(li);
1069 
1070 	litest_delete_device(touchpad);
1071 }
1072 END_TEST
1073 
START_TEST(tablet_mode_disable_keyboard)1074 START_TEST(tablet_mode_disable_keyboard)
1075 {
1076 	struct litest_device *sw = litest_current_device();
1077 	struct litest_device *keyboard;
1078 	struct libinput *li = sw->libinput;
1079 
1080 	if (!switch_has_tablet_mode(sw))
1081 		return;
1082 
1083 	keyboard = litest_add_device(li, LITEST_KEYBOARD);
1084 	litest_drain_events(li);
1085 
1086 	litest_keyboard_key(keyboard, KEY_A, true);
1087 	litest_keyboard_key(keyboard, KEY_A, false);
1088 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY);
1089 
1090 	litest_switch_action(sw,
1091 			     LIBINPUT_SWITCH_TABLET_MODE,
1092 			     LIBINPUT_SWITCH_STATE_ON);
1093 	litest_drain_events(li);
1094 
1095 	litest_keyboard_key(keyboard, KEY_A, true);
1096 	litest_keyboard_key(keyboard, KEY_A, false);
1097 	litest_assert_empty_queue(li);
1098 
1099 	litest_switch_action(sw,
1100 			     LIBINPUT_SWITCH_TABLET_MODE,
1101 			     LIBINPUT_SWITCH_STATE_OFF);
1102 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_SWITCH_TOGGLE);
1103 
1104 	litest_keyboard_key(keyboard, KEY_A, true);
1105 	litest_keyboard_key(keyboard, KEY_A, false);
1106 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY);
1107 
1108 	litest_delete_device(keyboard);
1109 }
1110 END_TEST
1111 
START_TEST(tablet_mode_disable_keyboard_on_init)1112 START_TEST(tablet_mode_disable_keyboard_on_init)
1113 {
1114 	struct litest_device *sw = litest_current_device();
1115 	struct litest_device *keyboard;
1116 	struct libinput *li = sw->libinput;
1117 
1118 	if (!switch_has_tablet_mode(sw))
1119 		return;
1120 
1121 	litest_switch_action(sw,
1122 			     LIBINPUT_SWITCH_TABLET_MODE,
1123 			     LIBINPUT_SWITCH_STATE_ON);
1124 	litest_drain_events(li);
1125 
1126 	/* keyboard comes with switch already on - no events */
1127 	keyboard = litest_add_device(li, LITEST_KEYBOARD);
1128 	litest_drain_events(li);
1129 
1130 	litest_keyboard_key(keyboard, KEY_A, true);
1131 	litest_keyboard_key(keyboard, KEY_A, false);
1132 	litest_assert_empty_queue(li);
1133 
1134 	litest_switch_action(sw,
1135 			     LIBINPUT_SWITCH_TABLET_MODE,
1136 			     LIBINPUT_SWITCH_STATE_OFF);
1137 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_SWITCH_TOGGLE);
1138 
1139 	litest_keyboard_key(keyboard, KEY_A, true);
1140 	litest_keyboard_key(keyboard, KEY_A, false);
1141 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY);
1142 
1143 	litest_delete_device(keyboard);
1144 }
1145 END_TEST
1146 
START_TEST(tablet_mode_disable_keyboard_on_resume)1147 START_TEST(tablet_mode_disable_keyboard_on_resume)
1148 {
1149 	struct litest_device *sw = litest_current_device();
1150 	struct litest_device *keyboard;
1151 	struct libinput *li = sw->libinput;
1152 	struct libinput_event *event;
1153 	bool have_switch_toggle = false;
1154 
1155 	if (!switch_has_tablet_mode(sw))
1156 		return;
1157 
1158 	keyboard = litest_add_device(li, LITEST_KEYBOARD);
1159 	litest_drain_events(li);
1160 	libinput_suspend(li);
1161 
1162 	/* We cannot grab this device because libinput doesn't have an open
1163 	 * fd to this device, we need an independent grab.
1164 	 */
1165 	libevdev_grab(sw->evdev, LIBEVDEV_GRAB);
1166 	litest_switch_action(sw,
1167 			     LIBINPUT_SWITCH_TABLET_MODE,
1168 			     LIBINPUT_SWITCH_STATE_ON);
1169 	libevdev_grab(sw->evdev, LIBEVDEV_UNGRAB);
1170 	litest_drain_events(li);
1171 
1172 	libinput_resume(li);
1173 	libinput_dispatch(li);
1174 
1175 	while ((event = libinput_get_event(li))) {
1176 		enum libinput_event_type type;
1177 
1178 		type = libinput_event_get_type(event);
1179 		switch (type) {
1180 		case LIBINPUT_EVENT_DEVICE_ADDED:
1181 			break;
1182 		case LIBINPUT_EVENT_SWITCH_TOGGLE:
1183 			litest_is_switch_event(event,
1184 					       LIBINPUT_SWITCH_TABLET_MODE,
1185 					       LIBINPUT_SWITCH_STATE_ON);
1186 			have_switch_toggle = true;
1187 			break;
1188 		default:
1189 			ck_abort();
1190 		}
1191 		libinput_event_destroy(event);
1192 	}
1193 
1194 	ck_assert(have_switch_toggle);
1195 
1196 	litest_keyboard_key(keyboard, KEY_A, true);
1197 	litest_keyboard_key(keyboard, KEY_A, false);
1198 	litest_assert_empty_queue(li);
1199 
1200 	litest_grab_device(sw);
1201 	litest_switch_action(sw,
1202 			     LIBINPUT_SWITCH_TABLET_MODE,
1203 			     LIBINPUT_SWITCH_STATE_OFF);
1204 	litest_ungrab_device(sw);
1205 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_SWITCH_TOGGLE);
1206 
1207 	litest_keyboard_key(keyboard, KEY_A, true);
1208 	litest_keyboard_key(keyboard, KEY_A, false);
1209 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY);
1210 
1211 	litest_delete_device(keyboard);
1212 }
1213 END_TEST
1214 
START_TEST(tablet_mode_enable_keyboard_on_resume)1215 START_TEST(tablet_mode_enable_keyboard_on_resume)
1216 {
1217 	struct litest_device *sw = litest_current_device();
1218 	struct litest_device *keyboard;
1219 	struct libinput *li = sw->libinput;
1220 
1221 	if (!switch_has_tablet_mode(sw))
1222 		return;
1223 
1224 	keyboard = litest_add_device(li, LITEST_KEYBOARD);
1225 	litest_grab_device(sw);
1226 	litest_switch_action(sw,
1227 			     LIBINPUT_SWITCH_TABLET_MODE,
1228 			     LIBINPUT_SWITCH_STATE_ON);
1229 	litest_drain_events(li);
1230 	litest_ungrab_device(sw);
1231 	libinput_suspend(li);
1232 	litest_drain_events(li);
1233 
1234 	litest_switch_action(sw,
1235 			     LIBINPUT_SWITCH_TABLET_MODE,
1236 			     LIBINPUT_SWITCH_STATE_OFF);
1237 
1238 	libinput_resume(li);
1239 	libinput_dispatch(li);
1240 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_DEVICE_ADDED);
1241 
1242 	litest_keyboard_key(keyboard, KEY_A, true);
1243 	litest_keyboard_key(keyboard, KEY_A, false);
1244 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY);
1245 
1246 	litest_switch_action(sw,
1247 			     LIBINPUT_SWITCH_TABLET_MODE,
1248 			     LIBINPUT_SWITCH_STATE_ON);
1249 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_SWITCH_TOGGLE);
1250 
1251 	litest_keyboard_key(keyboard, KEY_A, true);
1252 	litest_keyboard_key(keyboard, KEY_A, false);
1253 	litest_assert_empty_queue(li);
1254 
1255 	litest_delete_device(keyboard);
1256 }
1257 END_TEST
1258 
START_TEST(tablet_mode_disable_trackpoint)1259 START_TEST(tablet_mode_disable_trackpoint)
1260 {
1261 	struct litest_device *sw = litest_current_device();
1262 	struct litest_device *trackpoint;
1263 	struct libinput *li = sw->libinput;
1264 
1265 	if (!switch_has_tablet_mode(sw))
1266 		return;
1267 
1268 	trackpoint = litest_add_device(li, LITEST_TRACKPOINT);
1269 	litest_drain_events(li);
1270 
1271 	litest_event(trackpoint, EV_REL, REL_Y, -1);
1272 	litest_event(trackpoint, EV_SYN, SYN_REPORT, 0);
1273 	litest_event(trackpoint, EV_REL, REL_Y, -1);
1274 	litest_event(trackpoint, EV_SYN, SYN_REPORT, 0);
1275 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
1276 
1277 	litest_grab_device(sw);
1278 	litest_switch_action(sw,
1279 			     LIBINPUT_SWITCH_TABLET_MODE,
1280 			     LIBINPUT_SWITCH_STATE_ON);
1281 	litest_drain_events(li);
1282 
1283 	litest_event(trackpoint, EV_REL, REL_Y, -1);
1284 	litest_event(trackpoint, EV_SYN, SYN_REPORT, 0);
1285 	litest_event(trackpoint, EV_REL, REL_Y, -1);
1286 	litest_event(trackpoint, EV_SYN, SYN_REPORT, 0);
1287 	litest_assert_empty_queue(li);
1288 
1289 	litest_switch_action(sw,
1290 			     LIBINPUT_SWITCH_TABLET_MODE,
1291 			     LIBINPUT_SWITCH_STATE_OFF);
1292 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_SWITCH_TOGGLE);
1293 
1294 	litest_event(trackpoint, EV_REL, REL_Y, -1);
1295 	litest_event(trackpoint, EV_SYN, SYN_REPORT, 0);
1296 	litest_event(trackpoint, EV_REL, REL_Y, -1);
1297 	litest_event(trackpoint, EV_SYN, SYN_REPORT, 0);
1298 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
1299 	litest_ungrab_device(sw);
1300 
1301 	litest_delete_device(trackpoint);
1302 }
1303 END_TEST
1304 
START_TEST(tablet_mode_disable_trackpoint_on_init)1305 START_TEST(tablet_mode_disable_trackpoint_on_init)
1306 {
1307 	struct litest_device *sw = litest_current_device();
1308 	struct litest_device *trackpoint;
1309 	struct libinput *li = sw->libinput;
1310 
1311 	if (!switch_has_tablet_mode(sw))
1312 		return;
1313 
1314 	litest_grab_device(sw);
1315 	litest_switch_action(sw,
1316 			     LIBINPUT_SWITCH_TABLET_MODE,
1317 			     LIBINPUT_SWITCH_STATE_ON);
1318 	litest_drain_events(li);
1319 
1320 	/* trackpoint comes with switch already on - no events */
1321 	trackpoint = litest_add_device(li, LITEST_TRACKPOINT);
1322 	litest_drain_events(li);
1323 
1324 	litest_event(trackpoint, EV_REL, REL_Y, -1);
1325 	litest_event(trackpoint, EV_SYN, SYN_REPORT, 0);
1326 	litest_event(trackpoint, EV_REL, REL_Y, -1);
1327 	litest_event(trackpoint, EV_SYN, SYN_REPORT, 0);
1328 	litest_assert_empty_queue(li);
1329 
1330 	litest_switch_action(sw,
1331 			     LIBINPUT_SWITCH_TABLET_MODE,
1332 			     LIBINPUT_SWITCH_STATE_OFF);
1333 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_SWITCH_TOGGLE);
1334 
1335 	litest_event(trackpoint, EV_REL, REL_Y, -1);
1336 	litest_event(trackpoint, EV_SYN, SYN_REPORT, 0);
1337 	litest_event(trackpoint, EV_REL, REL_Y, -1);
1338 	litest_event(trackpoint, EV_SYN, SYN_REPORT, 0);
1339 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
1340 	litest_ungrab_device(sw);
1341 
1342 	litest_delete_device(trackpoint);
1343 }
1344 END_TEST
1345 
START_TEST(dock_toggle)1346 START_TEST(dock_toggle)
1347 {
1348 	struct litest_device *sw = litest_current_device();
1349 	struct libinput *li = sw->libinput;
1350 
1351 	if (!libevdev_has_event_code(sw->evdev, EV_SW, SW_DOCK))
1352 		return;
1353 
1354 	litest_drain_events(li);
1355 
1356 	litest_grab_device(sw);
1357 	litest_event(sw, EV_SW, SW_DOCK, 1);
1358 	libinput_dispatch(li);
1359 
1360 	litest_event(sw, EV_SW, SW_DOCK, 0);
1361 	libinput_dispatch(li);
1362 	litest_ungrab_device(sw);
1363 
1364 	litest_assert_empty_queue(li);
1365 }
1366 END_TEST
1367 
TEST_COLLECTION(switch)1368 TEST_COLLECTION(switch)
1369 {
1370 	struct range switches = { LIBINPUT_SWITCH_LID,
1371 				  LIBINPUT_SWITCH_TABLET_MODE + 1};
1372 
1373 	litest_add("switch:has", switch_has_cap, LITEST_SWITCH, LITEST_ANY);
1374 	litest_add("switch:has", switch_has_lid_switch, LITEST_SWITCH, LITEST_ANY);
1375 	litest_add("switch:has", switch_has_tablet_mode_switch, LITEST_SWITCH, LITEST_ANY);
1376 	litest_add_ranged("switch:toggle", switch_toggle, LITEST_SWITCH, LITEST_ANY, &switches);
1377 	litest_add_ranged("switch:toggle", switch_toggle_double, LITEST_SWITCH, LITEST_ANY, &switches);
1378 	litest_add_ranged("switch:toggle", switch_down_on_init, LITEST_SWITCH, LITEST_ANY, &switches);
1379 	litest_add("switch:toggle", switch_not_down_on_init, LITEST_SWITCH, LITEST_ANY);
1380 	litest_add_ranged("switch:touchpad", switch_disable_touchpad, LITEST_SWITCH, LITEST_ANY, &switches);
1381 	litest_add_ranged("switch:touchpad", switch_disable_touchpad_during_touch, LITEST_SWITCH, LITEST_ANY, &switches);
1382 	litest_add_ranged("switch:touchpad", switch_disable_touchpad_edge_scroll, LITEST_SWITCH, LITEST_ANY, &switches);
1383 	litest_add_ranged("switch:touchpad", switch_disable_touchpad_edge_scroll_interrupt, LITEST_SWITCH, LITEST_ANY, &switches);
1384 	litest_add_ranged("switch:touchpad", switch_disable_touchpad_already_open, LITEST_SWITCH, LITEST_ANY, &switches);
1385 	litest_add_ranged("switch:touchpad", switch_dont_resume_disabled_touchpad, LITEST_SWITCH, LITEST_ANY, &switches);
1386 	litest_add_ranged("switch:touchpad", switch_dont_resume_disabled_touchpad_external_mouse, LITEST_SWITCH, LITEST_ANY, &switches);
1387 
1388 	litest_add_ranged_no_device("switch:keyboard", switch_suspend_with_keyboard, &switches);
1389 	litest_add_ranged_no_device("switch:touchpad", switch_suspend_with_touchpad, &switches);
1390 
1391 	litest_add("lid:keyboard", lid_open_on_key, LITEST_SWITCH, LITEST_ANY);
1392 	litest_add("lid:keyboard", lid_open_on_key_touchpad_enabled, LITEST_SWITCH, LITEST_ANY);
1393 	litest_add_for_device("lid:buggy", lid_update_hw_on_key, LITEST_LID_SWITCH_SURFACE3);
1394 	litest_add_for_device("lid:buggy", lid_update_hw_on_key_closed_on_init, LITEST_LID_SWITCH_SURFACE3);
1395 	litest_add_for_device("lid:buggy", lid_update_hw_on_key_multiple_keyboards, LITEST_LID_SWITCH_SURFACE3);
1396 	litest_add_for_device("lid:keypress", lid_key_press, LITEST_GPIO_KEYS);
1397 
1398 	litest_add("tablet-mode:touchpad", tablet_mode_disable_touchpad_on_init, LITEST_SWITCH, LITEST_ANY);
1399 	litest_add("tablet-mode:touchpad", tablet_mode_disable_touchpad_on_resume, LITEST_SWITCH, LITEST_ANY);
1400 	litest_add("tablet-mode:touchpad", tablet_mode_enable_touchpad_on_resume, LITEST_SWITCH, LITEST_ANY);
1401 	litest_add("tablet-mode:keyboard", tablet_mode_disable_keyboard, LITEST_SWITCH, LITEST_ANY);
1402 	litest_add("tablet-mode:keyboard", tablet_mode_disable_keyboard_on_init, LITEST_SWITCH, LITEST_ANY);
1403 	litest_add("tablet-mode:keyboard", tablet_mode_disable_keyboard_on_resume, LITEST_SWITCH, LITEST_ANY);
1404 	litest_add("tablet-mode:keyboard", tablet_mode_enable_keyboard_on_resume, LITEST_SWITCH, LITEST_ANY);
1405 	litest_add("tablet-mode:trackpoint", tablet_mode_disable_trackpoint, LITEST_SWITCH, LITEST_ANY);
1406 	litest_add("tablet-mode:trackpoint", tablet_mode_disable_trackpoint_on_init, LITEST_SWITCH, LITEST_ANY);
1407 
1408 	litest_add("lid:dock", dock_toggle, LITEST_SWITCH, LITEST_ANY);
1409 }
1410