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