1c0abf9e6Sopenharmony_ci// SPDX-License-Identifier: MIT
2c0abf9e6Sopenharmony_ci/*
3c0abf9e6Sopenharmony_ci * Copyright © 2013 Red Hat, Inc.
4c0abf9e6Sopenharmony_ci */
5c0abf9e6Sopenharmony_ci
6c0abf9e6Sopenharmony_ci#include "config.h"
7c0abf9e6Sopenharmony_ci#include <linux/input.h>
8c0abf9e6Sopenharmony_ci#include <errno.h>
9c0abf9e6Sopenharmony_ci#include <unistd.h>
10c0abf9e6Sopenharmony_ci#include <stdlib.h>
11c0abf9e6Sopenharmony_ci#include <fcntl.h>
12c0abf9e6Sopenharmony_ci#include <libevdev/libevdev-uinput.h>
13c0abf9e6Sopenharmony_ci
14c0abf9e6Sopenharmony_ci#include "test-common.h"
15c0abf9e6Sopenharmony_ci#define UINPUT_NODE "/dev/uinput"
16c0abf9e6Sopenharmony_ci
17c0abf9e6Sopenharmony_ciSTART_TEST(test_uinput_create_device)
18c0abf9e6Sopenharmony_ci{
19c0abf9e6Sopenharmony_ci	struct libevdev *dev, *dev2;
20c0abf9e6Sopenharmony_ci	struct libevdev_uinput *uidev;
21c0abf9e6Sopenharmony_ci	int fd, uinput_fd;
22c0abf9e6Sopenharmony_ci	unsigned int type, code;
23c0abf9e6Sopenharmony_ci	int rc;
24c0abf9e6Sopenharmony_ci	const char *devnode;
25c0abf9e6Sopenharmony_ci
26c0abf9e6Sopenharmony_ci	dev = libevdev_new();
27c0abf9e6Sopenharmony_ci	ck_assert(dev != NULL);
28c0abf9e6Sopenharmony_ci	libevdev_set_name(dev, TEST_DEVICE_NAME);
29c0abf9e6Sopenharmony_ci	libevdev_enable_event_type(dev, EV_SYN);
30c0abf9e6Sopenharmony_ci	libevdev_enable_event_type(dev, EV_REL);
31c0abf9e6Sopenharmony_ci	libevdev_enable_event_code(dev, EV_REL, REL_X, NULL);
32c0abf9e6Sopenharmony_ci	libevdev_enable_event_code(dev, EV_REL, REL_Y, NULL);
33c0abf9e6Sopenharmony_ci	libevdev_enable_event_code(dev, EV_REL, REL_MAX, NULL);
34c0abf9e6Sopenharmony_ci
35c0abf9e6Sopenharmony_ci	rc = libevdev_uinput_create_from_device(dev, LIBEVDEV_UINPUT_OPEN_MANAGED, &uidev);
36c0abf9e6Sopenharmony_ci	ck_assert_int_eq(rc, 0);
37c0abf9e6Sopenharmony_ci	ck_assert(uidev != NULL);
38c0abf9e6Sopenharmony_ci
39c0abf9e6Sopenharmony_ci	uinput_fd = libevdev_uinput_get_fd(uidev);
40c0abf9e6Sopenharmony_ci	ck_assert_int_gt(uinput_fd, -1);
41c0abf9e6Sopenharmony_ci
42c0abf9e6Sopenharmony_ci	devnode = libevdev_uinput_get_devnode(uidev);
43c0abf9e6Sopenharmony_ci	ck_assert(devnode != NULL);
44c0abf9e6Sopenharmony_ci
45c0abf9e6Sopenharmony_ci	fd = open(devnode, O_RDONLY);
46c0abf9e6Sopenharmony_ci	ck_assert_int_gt(fd, -1);
47c0abf9e6Sopenharmony_ci	rc = libevdev_new_from_fd(fd, &dev2);
48c0abf9e6Sopenharmony_ci	ck_assert_int_eq(rc, 0);
49c0abf9e6Sopenharmony_ci
50c0abf9e6Sopenharmony_ci	for (type = 0; type < EV_CNT; type++) {
51c0abf9e6Sopenharmony_ci		int max = libevdev_event_type_get_max(type);
52c0abf9e6Sopenharmony_ci		if (max == -1)
53c0abf9e6Sopenharmony_ci			continue;
54c0abf9e6Sopenharmony_ci
55c0abf9e6Sopenharmony_ci		for (code = 0; code < (unsigned int)max; code++) {
56c0abf9e6Sopenharmony_ci			ck_assert_int_eq(libevdev_has_event_code(dev, type, code),
57c0abf9e6Sopenharmony_ci					 libevdev_has_event_code(dev2, type, code));
58c0abf9e6Sopenharmony_ci		}
59c0abf9e6Sopenharmony_ci	}
60c0abf9e6Sopenharmony_ci
61c0abf9e6Sopenharmony_ci	libevdev_free(dev);
62c0abf9e6Sopenharmony_ci	libevdev_free(dev2);
63c0abf9e6Sopenharmony_ci	libevdev_uinput_destroy(uidev);
64c0abf9e6Sopenharmony_ci	close(fd);
65c0abf9e6Sopenharmony_ci
66c0abf9e6Sopenharmony_ci	/* uinput fd is managed, so make sure it did get closed */
67c0abf9e6Sopenharmony_ci	ck_assert_int_eq(close(uinput_fd), -1);
68c0abf9e6Sopenharmony_ci	ck_assert_int_eq(errno, EBADF);
69c0abf9e6Sopenharmony_ci
70c0abf9e6Sopenharmony_ci}
71c0abf9e6Sopenharmony_ciEND_TEST
72c0abf9e6Sopenharmony_ci
73c0abf9e6Sopenharmony_ciSTART_TEST(test_uinput_create_device_invalid)
74c0abf9e6Sopenharmony_ci{
75c0abf9e6Sopenharmony_ci	struct libevdev *dev;
76c0abf9e6Sopenharmony_ci	struct libevdev_uinput *uidev = NULL;
77c0abf9e6Sopenharmony_ci	int rc;
78c0abf9e6Sopenharmony_ci
79c0abf9e6Sopenharmony_ci	dev = libevdev_new();
80c0abf9e6Sopenharmony_ci	ck_assert(dev != NULL);
81c0abf9e6Sopenharmony_ci	libevdev_set_name(dev, TEST_DEVICE_NAME);
82c0abf9e6Sopenharmony_ci	libevdev_enable_event_type(dev, EV_SYN);
83c0abf9e6Sopenharmony_ci	libevdev_enable_event_type(dev, EV_REL);
84c0abf9e6Sopenharmony_ci	libevdev_enable_event_code(dev, EV_REL, REL_X, NULL);
85c0abf9e6Sopenharmony_ci	libevdev_enable_event_code(dev, EV_REL, REL_Y, NULL);
86c0abf9e6Sopenharmony_ci
87c0abf9e6Sopenharmony_ci	libevdev_set_log_function(test_logfunc_ignore_error, NULL);
88c0abf9e6Sopenharmony_ci	rc = libevdev_uinput_create_from_device(dev, -1, &uidev);
89c0abf9e6Sopenharmony_ci	ck_assert_int_eq(rc, -EBADF);
90c0abf9e6Sopenharmony_ci	ck_assert(uidev == NULL);
91c0abf9e6Sopenharmony_ci	libevdev_set_log_function(test_logfunc_abort_on_error, NULL);
92c0abf9e6Sopenharmony_ci
93c0abf9e6Sopenharmony_ci	libevdev_free(dev);
94c0abf9e6Sopenharmony_ci}
95c0abf9e6Sopenharmony_ciEND_TEST
96c0abf9e6Sopenharmony_ci
97c0abf9e6Sopenharmony_ciSTART_TEST(test_uinput_create_device_from_fd)
98c0abf9e6Sopenharmony_ci{
99c0abf9e6Sopenharmony_ci	struct libevdev *dev, *dev2;
100c0abf9e6Sopenharmony_ci	struct libevdev_uinput *uidev;
101c0abf9e6Sopenharmony_ci	int fd, fd2;
102c0abf9e6Sopenharmony_ci	unsigned int type, code;
103c0abf9e6Sopenharmony_ci	int rc;
104c0abf9e6Sopenharmony_ci	const char *devnode;
105c0abf9e6Sopenharmony_ci
106c0abf9e6Sopenharmony_ci	dev = libevdev_new();
107c0abf9e6Sopenharmony_ci	ck_assert(dev != NULL);
108c0abf9e6Sopenharmony_ci	libevdev_set_name(dev, TEST_DEVICE_NAME);
109c0abf9e6Sopenharmony_ci	libevdev_enable_event_type(dev, EV_SYN);
110c0abf9e6Sopenharmony_ci	libevdev_enable_event_type(dev, EV_REL);
111c0abf9e6Sopenharmony_ci	libevdev_enable_event_code(dev, EV_REL, REL_X, NULL);
112c0abf9e6Sopenharmony_ci	libevdev_enable_event_code(dev, EV_REL, REL_Y, NULL);
113c0abf9e6Sopenharmony_ci
114c0abf9e6Sopenharmony_ci	fd = open(UINPUT_NODE, O_RDWR);
115c0abf9e6Sopenharmony_ci	ck_assert_int_gt(fd, -1);
116c0abf9e6Sopenharmony_ci
117c0abf9e6Sopenharmony_ci	rc = libevdev_uinput_create_from_device(dev, fd, &uidev);
118c0abf9e6Sopenharmony_ci	ck_assert_int_eq(rc, 0);
119c0abf9e6Sopenharmony_ci	ck_assert(uidev != NULL);
120c0abf9e6Sopenharmony_ci
121c0abf9e6Sopenharmony_ci	ck_assert_int_eq(libevdev_uinput_get_fd(uidev), fd);
122c0abf9e6Sopenharmony_ci
123c0abf9e6Sopenharmony_ci	devnode = libevdev_uinput_get_devnode(uidev);
124c0abf9e6Sopenharmony_ci	ck_assert(devnode != NULL);
125c0abf9e6Sopenharmony_ci
126c0abf9e6Sopenharmony_ci	fd2 = open(devnode, O_RDONLY);
127c0abf9e6Sopenharmony_ci	ck_assert_int_gt(fd2, -1);
128c0abf9e6Sopenharmony_ci	rc = libevdev_new_from_fd(fd2, &dev2);
129c0abf9e6Sopenharmony_ci	ck_assert_int_eq(rc, 0);
130c0abf9e6Sopenharmony_ci
131c0abf9e6Sopenharmony_ci	for (type = 0; type < EV_CNT; type++) {
132c0abf9e6Sopenharmony_ci		int max = libevdev_event_type_get_max(type);
133c0abf9e6Sopenharmony_ci		if (max == -1)
134c0abf9e6Sopenharmony_ci			continue;
135c0abf9e6Sopenharmony_ci
136c0abf9e6Sopenharmony_ci		for (code = 0; code < (unsigned int)max; code++) {
137c0abf9e6Sopenharmony_ci			ck_assert_int_eq(libevdev_has_event_code(dev, type, code),
138c0abf9e6Sopenharmony_ci					 libevdev_has_event_code(dev2, type, code));
139c0abf9e6Sopenharmony_ci		}
140c0abf9e6Sopenharmony_ci	}
141c0abf9e6Sopenharmony_ci
142c0abf9e6Sopenharmony_ci	libevdev_free(dev);
143c0abf9e6Sopenharmony_ci	libevdev_free(dev2);
144c0abf9e6Sopenharmony_ci	libevdev_uinput_destroy(uidev);
145c0abf9e6Sopenharmony_ci	close(fd);
146c0abf9e6Sopenharmony_ci	close(fd2);
147c0abf9e6Sopenharmony_ci}
148c0abf9e6Sopenharmony_ciEND_TEST
149c0abf9e6Sopenharmony_ci
150c0abf9e6Sopenharmony_ci#ifdef __FreeBSD__
151c0abf9e6Sopenharmony_ciSTART_TEST(test_uinput_check_devnode_bsd)
152c0abf9e6Sopenharmony_ci{
153c0abf9e6Sopenharmony_ci	struct libevdev *dev;
154c0abf9e6Sopenharmony_ci	struct libevdev_uinput *uidev, *uidev2;
155c0abf9e6Sopenharmony_ci	const char *devnode, *devnode2;
156c0abf9e6Sopenharmony_ci	int fd, fd2;
157c0abf9e6Sopenharmony_ci	int rc;
158c0abf9e6Sopenharmony_ci
159c0abf9e6Sopenharmony_ci	dev = libevdev_new();
160c0abf9e6Sopenharmony_ci	ck_assert(dev != NULL);
161c0abf9e6Sopenharmony_ci	libevdev_set_name(dev, TEST_DEVICE_NAME);
162c0abf9e6Sopenharmony_ci	libevdev_enable_event_type(dev, EV_SYN);
163c0abf9e6Sopenharmony_ci	libevdev_enable_event_type(dev, EV_REL);
164c0abf9e6Sopenharmony_ci	libevdev_enable_event_code(dev, EV_REL, REL_X, NULL);
165c0abf9e6Sopenharmony_ci	libevdev_enable_event_code(dev, EV_REL, REL_Y, NULL);
166c0abf9e6Sopenharmony_ci
167c0abf9e6Sopenharmony_ci	fd = open(UINPUT_NODE, O_RDWR);
168c0abf9e6Sopenharmony_ci	ck_assert_int_gt(fd, -1);
169c0abf9e6Sopenharmony_ci	fd2 = open(UINPUT_NODE, O_RDWR);
170c0abf9e6Sopenharmony_ci	ck_assert_int_gt(fd2, -1);
171c0abf9e6Sopenharmony_ci
172c0abf9e6Sopenharmony_ci	rc = libevdev_uinput_create_from_device(dev, fd, &uidev);
173c0abf9e6Sopenharmony_ci	ck_assert_int_eq(rc, 0);
174c0abf9e6Sopenharmony_ci
175c0abf9e6Sopenharmony_ci	/* create a second one */
176c0abf9e6Sopenharmony_ci	libevdev_set_name(dev, TEST_DEVICE_NAME " 2");
177c0abf9e6Sopenharmony_ci	rc = libevdev_uinput_create_from_device(dev, fd2, &uidev2);
178c0abf9e6Sopenharmony_ci	ck_assert_int_eq(rc, 0);
179c0abf9e6Sopenharmony_ci
180c0abf9e6Sopenharmony_ci	devnode = libevdev_uinput_get_devnode(uidev);
181c0abf9e6Sopenharmony_ci	ck_assert(devnode != NULL);
182c0abf9e6Sopenharmony_ci
183c0abf9e6Sopenharmony_ci	/* get syspath twice returns same pointer */
184c0abf9e6Sopenharmony_ci	devnode2 = libevdev_uinput_get_devnode(uidev);
185c0abf9e6Sopenharmony_ci	ck_assert(devnode == devnode2);
186c0abf9e6Sopenharmony_ci
187c0abf9e6Sopenharmony_ci	/* second dev has different devnode */
188c0abf9e6Sopenharmony_ci	devnode2 = libevdev_uinput_get_devnode(uidev2);
189c0abf9e6Sopenharmony_ci	ck_assert(strcmp(devnode, devnode2) != 0);
190c0abf9e6Sopenharmony_ci
191c0abf9e6Sopenharmony_ci	libevdev_uinput_destroy(uidev2);
192c0abf9e6Sopenharmony_ci	libevdev_uinput_destroy(uidev);
193c0abf9e6Sopenharmony_ci
194c0abf9e6Sopenharmony_ci	close(fd2);
195c0abf9e6Sopenharmony_ci	close(fd);
196c0abf9e6Sopenharmony_ci
197c0abf9e6Sopenharmony_ci	libevdev_free(dev);
198c0abf9e6Sopenharmony_ci}
199c0abf9e6Sopenharmony_ciEND_TEST
200c0abf9e6Sopenharmony_ci
201c0abf9e6Sopenharmony_ciSTART_TEST(test_uinput_check_syspath_bsd)
202c0abf9e6Sopenharmony_ci{
203c0abf9e6Sopenharmony_ci	struct libevdev *dev;
204c0abf9e6Sopenharmony_ci	struct libevdev_uinput *uidev;
205c0abf9e6Sopenharmony_ci	const char *syspath;
206c0abf9e6Sopenharmony_ci	int fd;
207c0abf9e6Sopenharmony_ci	int rc;
208c0abf9e6Sopenharmony_ci
209c0abf9e6Sopenharmony_ci	dev = libevdev_new();
210c0abf9e6Sopenharmony_ci	ck_assert(dev != NULL);
211c0abf9e6Sopenharmony_ci	libevdev_set_name(dev, TEST_DEVICE_NAME);
212c0abf9e6Sopenharmony_ci	libevdev_enable_event_type(dev, EV_SYN);
213c0abf9e6Sopenharmony_ci	libevdev_enable_event_type(dev, EV_REL);
214c0abf9e6Sopenharmony_ci	libevdev_enable_event_code(dev, EV_REL, REL_X, NULL);
215c0abf9e6Sopenharmony_ci	libevdev_enable_event_code(dev, EV_REL, REL_Y, NULL);
216c0abf9e6Sopenharmony_ci
217c0abf9e6Sopenharmony_ci	fd = open(UINPUT_NODE, O_RDWR);
218c0abf9e6Sopenharmony_ci	ck_assert_int_gt(fd, -1);
219c0abf9e6Sopenharmony_ci
220c0abf9e6Sopenharmony_ci	rc = libevdev_uinput_create_from_device(dev, fd, &uidev);
221c0abf9e6Sopenharmony_ci	ck_assert_int_eq(rc, 0);
222c0abf9e6Sopenharmony_ci
223c0abf9e6Sopenharmony_ci	syspath = libevdev_uinput_get_syspath(uidev);
224c0abf9e6Sopenharmony_ci	/* FreeBSD should always return NULL for libevdev_unput_get_syspath() */
225c0abf9e6Sopenharmony_ci	ck_assert(syspath == NULL);
226c0abf9e6Sopenharmony_ci
227c0abf9e6Sopenharmony_ci	libevdev_uinput_destroy(uidev);
228c0abf9e6Sopenharmony_ci
229c0abf9e6Sopenharmony_ci	close(fd);
230c0abf9e6Sopenharmony_ci
231c0abf9e6Sopenharmony_ci	libevdev_free(dev);
232c0abf9e6Sopenharmony_ci}
233c0abf9e6Sopenharmony_ciEND_TEST
234c0abf9e6Sopenharmony_ci
235c0abf9e6Sopenharmony_ci#else /* !__FreeBSD__ */
236c0abf9e6Sopenharmony_ci
237c0abf9e6Sopenharmony_ciSTART_TEST(test_uinput_check_syspath_time)
238c0abf9e6Sopenharmony_ci{
239c0abf9e6Sopenharmony_ci	struct libevdev *dev;
240c0abf9e6Sopenharmony_ci	struct libevdev_uinput *uidev, *uidev2;
241c0abf9e6Sopenharmony_ci	const char *syspath, *syspath2;
242c0abf9e6Sopenharmony_ci	int fd, fd2;
243c0abf9e6Sopenharmony_ci	int rc;
244c0abf9e6Sopenharmony_ci
245c0abf9e6Sopenharmony_ci	dev = libevdev_new();
246c0abf9e6Sopenharmony_ci	ck_assert(dev != NULL);
247c0abf9e6Sopenharmony_ci	libevdev_set_name(dev, TEST_DEVICE_NAME);
248c0abf9e6Sopenharmony_ci	libevdev_enable_event_type(dev, EV_SYN);
249c0abf9e6Sopenharmony_ci	libevdev_enable_event_type(dev, EV_REL);
250c0abf9e6Sopenharmony_ci	libevdev_enable_event_code(dev, EV_REL, REL_X, NULL);
251c0abf9e6Sopenharmony_ci	libevdev_enable_event_code(dev, EV_REL, REL_Y, NULL);
252c0abf9e6Sopenharmony_ci
253c0abf9e6Sopenharmony_ci	fd = open(UINPUT_NODE, O_RDWR);
254c0abf9e6Sopenharmony_ci	ck_assert_int_gt(fd, -1);
255c0abf9e6Sopenharmony_ci	fd2 = open(UINPUT_NODE, O_RDWR);
256c0abf9e6Sopenharmony_ci	ck_assert_int_gt(fd2, -1);
257c0abf9e6Sopenharmony_ci
258c0abf9e6Sopenharmony_ci	rc = libevdev_uinput_create_from_device(dev, fd, &uidev);
259c0abf9e6Sopenharmony_ci	ck_assert_int_eq(rc, 0);
260c0abf9e6Sopenharmony_ci
261c0abf9e6Sopenharmony_ci	/* sleep for 1.5 seconds. sysfs resolution is 1 second, so
262c0abf9e6Sopenharmony_ci	   creating both devices without delay means
263c0abf9e6Sopenharmony_ci	   libevdev_uinput_get_syspath can't actually differ between
264c0abf9e6Sopenharmony_ci	   them. By waiting, we get different ctime for uidev and uidev2,
265c0abf9e6Sopenharmony_ci	   and exercise that part of the code.
266c0abf9e6Sopenharmony_ci	 */
267c0abf9e6Sopenharmony_ci	usleep(1500000);
268c0abf9e6Sopenharmony_ci
269c0abf9e6Sopenharmony_ci	/* create a second one to test the syspath time filtering code */
270c0abf9e6Sopenharmony_ci	rc = libevdev_uinput_create_from_device(dev, fd2, &uidev2);
271c0abf9e6Sopenharmony_ci	ck_assert_int_eq(rc, 0);
272c0abf9e6Sopenharmony_ci
273c0abf9e6Sopenharmony_ci	syspath = libevdev_uinput_get_syspath(uidev);
274c0abf9e6Sopenharmony_ci	ck_assert(syspath != NULL);
275c0abf9e6Sopenharmony_ci
276c0abf9e6Sopenharmony_ci	/* get syspath twice returns same pointer */
277c0abf9e6Sopenharmony_ci	syspath2 = libevdev_uinput_get_syspath(uidev);
278c0abf9e6Sopenharmony_ci	ck_assert(syspath == syspath2);
279c0abf9e6Sopenharmony_ci
280c0abf9e6Sopenharmony_ci	/* second dev has different syspath */
281c0abf9e6Sopenharmony_ci	syspath2 = libevdev_uinput_get_syspath(uidev2);
282c0abf9e6Sopenharmony_ci	ck_assert(strcmp(syspath, syspath2) != 0);
283c0abf9e6Sopenharmony_ci
284c0abf9e6Sopenharmony_ci	libevdev_free(dev);
285c0abf9e6Sopenharmony_ci	libevdev_uinput_destroy(uidev);
286c0abf9e6Sopenharmony_ci	libevdev_uinput_destroy(uidev2);
287c0abf9e6Sopenharmony_ci
288c0abf9e6Sopenharmony_ci	close(fd);
289c0abf9e6Sopenharmony_ci	close(fd2);
290c0abf9e6Sopenharmony_ci}
291c0abf9e6Sopenharmony_ciEND_TEST
292c0abf9e6Sopenharmony_ci
293c0abf9e6Sopenharmony_ciSTART_TEST(test_uinput_check_syspath_name)
294c0abf9e6Sopenharmony_ci{
295c0abf9e6Sopenharmony_ci	struct libevdev *dev;
296c0abf9e6Sopenharmony_ci	struct libevdev_uinput *uidev, *uidev2;
297c0abf9e6Sopenharmony_ci	const char *syspath, *syspath2;
298c0abf9e6Sopenharmony_ci	int fd, fd2;
299c0abf9e6Sopenharmony_ci	int rc;
300c0abf9e6Sopenharmony_ci
301c0abf9e6Sopenharmony_ci	dev = libevdev_new();
302c0abf9e6Sopenharmony_ci	ck_assert(dev != NULL);
303c0abf9e6Sopenharmony_ci	libevdev_set_name(dev, TEST_DEVICE_NAME);
304c0abf9e6Sopenharmony_ci	libevdev_enable_event_type(dev, EV_SYN);
305c0abf9e6Sopenharmony_ci	libevdev_enable_event_type(dev, EV_REL);
306c0abf9e6Sopenharmony_ci	libevdev_enable_event_code(dev, EV_REL, REL_X, NULL);
307c0abf9e6Sopenharmony_ci	libevdev_enable_event_code(dev, EV_REL, REL_Y, NULL);
308c0abf9e6Sopenharmony_ci
309c0abf9e6Sopenharmony_ci	fd = open(UINPUT_NODE, O_RDWR);
310c0abf9e6Sopenharmony_ci	ck_assert_int_gt(fd, -1);
311c0abf9e6Sopenharmony_ci	fd2 = open(UINPUT_NODE, O_RDWR);
312c0abf9e6Sopenharmony_ci	ck_assert_int_gt(fd2, -1);
313c0abf9e6Sopenharmony_ci
314c0abf9e6Sopenharmony_ci	rc = libevdev_uinput_create_from_device(dev, fd, &uidev);
315c0abf9e6Sopenharmony_ci	ck_assert_int_eq(rc, 0);
316c0abf9e6Sopenharmony_ci
317c0abf9e6Sopenharmony_ci	/* create a second one to stress the syspath filtering code */
318c0abf9e6Sopenharmony_ci	libevdev_set_name(dev, TEST_DEVICE_NAME " 2");
319c0abf9e6Sopenharmony_ci	rc = libevdev_uinput_create_from_device(dev, fd2, &uidev2);
320c0abf9e6Sopenharmony_ci	ck_assert_int_eq(rc, 0);
321c0abf9e6Sopenharmony_ci
322c0abf9e6Sopenharmony_ci	syspath = libevdev_uinput_get_syspath(uidev);
323c0abf9e6Sopenharmony_ci	ck_assert(syspath != NULL);
324c0abf9e6Sopenharmony_ci
325c0abf9e6Sopenharmony_ci	/* get syspath twice returns same pointer */
326c0abf9e6Sopenharmony_ci	syspath2 = libevdev_uinput_get_syspath(uidev);
327c0abf9e6Sopenharmony_ci	ck_assert(syspath == syspath2);
328c0abf9e6Sopenharmony_ci
329c0abf9e6Sopenharmony_ci	/* second dev has different syspath */
330c0abf9e6Sopenharmony_ci	syspath2 = libevdev_uinput_get_syspath(uidev2);
331c0abf9e6Sopenharmony_ci	ck_assert(strcmp(syspath, syspath2) != 0);
332c0abf9e6Sopenharmony_ci
333c0abf9e6Sopenharmony_ci	libevdev_free(dev);
334c0abf9e6Sopenharmony_ci	libevdev_uinput_destroy(uidev);
335c0abf9e6Sopenharmony_ci	libevdev_uinput_destroy(uidev2);
336c0abf9e6Sopenharmony_ci
337c0abf9e6Sopenharmony_ci	close(fd);
338c0abf9e6Sopenharmony_ci	close(fd2);
339c0abf9e6Sopenharmony_ci}
340c0abf9e6Sopenharmony_ciEND_TEST
341c0abf9e6Sopenharmony_ci
342c0abf9e6Sopenharmony_ci#endif /* __FreeBSD __ */
343c0abf9e6Sopenharmony_ci
344c0abf9e6Sopenharmony_ciSTART_TEST(test_uinput_events)
345c0abf9e6Sopenharmony_ci{
346c0abf9e6Sopenharmony_ci	struct libevdev *dev;
347c0abf9e6Sopenharmony_ci	struct libevdev_uinput *uidev;
348c0abf9e6Sopenharmony_ci	int fd, fd2;
349c0abf9e6Sopenharmony_ci	int rc;
350c0abf9e6Sopenharmony_ci	const char *devnode;
351c0abf9e6Sopenharmony_ci	int i;
352c0abf9e6Sopenharmony_ci	const int nevents = 5;
353c0abf9e6Sopenharmony_ci	struct input_event events[] = { {{0, 0}, EV_REL, REL_X, 1},
354c0abf9e6Sopenharmony_ci					{{0, 0}, EV_REL, REL_Y, -1},
355c0abf9e6Sopenharmony_ci					{{0, 0}, EV_SYN, SYN_REPORT, 0},
356c0abf9e6Sopenharmony_ci					{{0, 0}, EV_KEY, BTN_LEFT, 1},
357c0abf9e6Sopenharmony_ci					{{0, 0}, EV_SYN, SYN_REPORT, 0}};
358c0abf9e6Sopenharmony_ci	struct input_event events_read[nevents];
359c0abf9e6Sopenharmony_ci
360c0abf9e6Sopenharmony_ci	dev = libevdev_new();
361c0abf9e6Sopenharmony_ci	ck_assert(dev != NULL);
362c0abf9e6Sopenharmony_ci	libevdev_set_name(dev, TEST_DEVICE_NAME);
363c0abf9e6Sopenharmony_ci	libevdev_enable_event_type(dev, EV_SYN);
364c0abf9e6Sopenharmony_ci	libevdev_enable_event_type(dev, EV_REL);
365c0abf9e6Sopenharmony_ci	libevdev_enable_event_type(dev, EV_KEY);
366c0abf9e6Sopenharmony_ci	libevdev_enable_event_code(dev, EV_REL, REL_X, NULL);
367c0abf9e6Sopenharmony_ci	libevdev_enable_event_code(dev, EV_REL, REL_Y, NULL);
368c0abf9e6Sopenharmony_ci	libevdev_enable_event_code(dev, EV_KEY, BTN_LEFT, NULL);
369c0abf9e6Sopenharmony_ci
370c0abf9e6Sopenharmony_ci	fd = open(UINPUT_NODE, O_RDWR);
371c0abf9e6Sopenharmony_ci	ck_assert_int_gt(fd, -1);
372c0abf9e6Sopenharmony_ci
373c0abf9e6Sopenharmony_ci	rc = libevdev_uinput_create_from_device(dev, fd, &uidev);
374c0abf9e6Sopenharmony_ci	ck_assert_int_eq(rc, 0);
375c0abf9e6Sopenharmony_ci	ck_assert(uidev != NULL);
376c0abf9e6Sopenharmony_ci
377c0abf9e6Sopenharmony_ci	devnode = libevdev_uinput_get_devnode(uidev);
378c0abf9e6Sopenharmony_ci	ck_assert(devnode != NULL);
379c0abf9e6Sopenharmony_ci
380c0abf9e6Sopenharmony_ci	fd2 = open(devnode, O_RDONLY);
381c0abf9e6Sopenharmony_ci
382c0abf9e6Sopenharmony_ci	for (i = 0; i < nevents; i++)
383c0abf9e6Sopenharmony_ci		libevdev_uinput_write_event(uidev, events[i].type, events[i].code, events[i].value);
384c0abf9e6Sopenharmony_ci
385c0abf9e6Sopenharmony_ci	rc = read(fd2, events_read, sizeof(events_read));
386c0abf9e6Sopenharmony_ci	ck_assert_int_eq(rc, sizeof(events_read));
387c0abf9e6Sopenharmony_ci
388c0abf9e6Sopenharmony_ci	for (i = 0; i < nevents; i++) {
389c0abf9e6Sopenharmony_ci		ck_assert_int_eq(events[i].type, events_read[i].type);
390c0abf9e6Sopenharmony_ci		ck_assert_int_eq(events[i].code, events_read[i].code);
391c0abf9e6Sopenharmony_ci		ck_assert_int_eq(events[i].value, events_read[i].value);
392c0abf9e6Sopenharmony_ci	}
393c0abf9e6Sopenharmony_ci
394c0abf9e6Sopenharmony_ci	libevdev_free(dev);
395c0abf9e6Sopenharmony_ci	libevdev_uinput_destroy(uidev);
396c0abf9e6Sopenharmony_ci	close(fd);
397c0abf9e6Sopenharmony_ci	close(fd2);
398c0abf9e6Sopenharmony_ci}
399c0abf9e6Sopenharmony_ciEND_TEST
400c0abf9e6Sopenharmony_ci
401c0abf9e6Sopenharmony_ciSTART_TEST(test_uinput_properties)
402c0abf9e6Sopenharmony_ci{
403c0abf9e6Sopenharmony_ci	struct libevdev *dev, *dev2;
404c0abf9e6Sopenharmony_ci	struct libevdev_uinput *uidev;
405c0abf9e6Sopenharmony_ci	int fd;
406c0abf9e6Sopenharmony_ci	int rc;
407c0abf9e6Sopenharmony_ci	const char *devnode;
408c0abf9e6Sopenharmony_ci
409c0abf9e6Sopenharmony_ci	dev = libevdev_new();
410c0abf9e6Sopenharmony_ci	ck_assert(dev != NULL);
411c0abf9e6Sopenharmony_ci	libevdev_set_name(dev, TEST_DEVICE_NAME);
412c0abf9e6Sopenharmony_ci	libevdev_enable_event_type(dev, EV_SYN);
413c0abf9e6Sopenharmony_ci	libevdev_enable_event_type(dev, EV_REL);
414c0abf9e6Sopenharmony_ci	libevdev_enable_event_type(dev, EV_KEY);
415c0abf9e6Sopenharmony_ci	libevdev_enable_event_code(dev, EV_REL, REL_X, NULL);
416c0abf9e6Sopenharmony_ci	libevdev_enable_event_code(dev, EV_REL, REL_Y, NULL);
417c0abf9e6Sopenharmony_ci	libevdev_enable_event_code(dev, EV_KEY, BTN_LEFT, NULL);
418c0abf9e6Sopenharmony_ci	libevdev_enable_property(dev, INPUT_PROP_BUTTONPAD);
419c0abf9e6Sopenharmony_ci	libevdev_enable_property(dev, INPUT_PROP_MAX);
420c0abf9e6Sopenharmony_ci
421c0abf9e6Sopenharmony_ci	rc = libevdev_uinput_create_from_device(dev, LIBEVDEV_UINPUT_OPEN_MANAGED, &uidev);
422c0abf9e6Sopenharmony_ci	ck_assert_int_eq(rc, 0);
423c0abf9e6Sopenharmony_ci	ck_assert(uidev != NULL);
424c0abf9e6Sopenharmony_ci
425c0abf9e6Sopenharmony_ci	devnode = libevdev_uinput_get_devnode(uidev);
426c0abf9e6Sopenharmony_ci	ck_assert(devnode != NULL);
427c0abf9e6Sopenharmony_ci
428c0abf9e6Sopenharmony_ci	fd = open(devnode, O_RDONLY);
429c0abf9e6Sopenharmony_ci	ck_assert_int_gt(fd, -1);
430c0abf9e6Sopenharmony_ci	rc = libevdev_new_from_fd(fd, &dev2);
431c0abf9e6Sopenharmony_ci	ck_assert_int_eq(rc, 0);
432c0abf9e6Sopenharmony_ci
433c0abf9e6Sopenharmony_ci	ck_assert(libevdev_has_property(dev2, INPUT_PROP_BUTTONPAD));
434c0abf9e6Sopenharmony_ci	ck_assert(libevdev_has_property(dev2, INPUT_PROP_MAX));
435c0abf9e6Sopenharmony_ci
436c0abf9e6Sopenharmony_ci	libevdev_free(dev);
437c0abf9e6Sopenharmony_ci	libevdev_free(dev2);
438c0abf9e6Sopenharmony_ci	libevdev_uinput_destroy(uidev);
439c0abf9e6Sopenharmony_ci	close(fd);
440c0abf9e6Sopenharmony_ci}
441c0abf9e6Sopenharmony_ciEND_TEST
442c0abf9e6Sopenharmony_ci
443c0abf9e6Sopenharmony_ciTEST_SUITE_ROOT_PRIVILEGES(uinput_suite)
444c0abf9e6Sopenharmony_ci{
445c0abf9e6Sopenharmony_ci	Suite *s = suite_create("libevdev uinput device tests");
446c0abf9e6Sopenharmony_ci
447c0abf9e6Sopenharmony_ci	add_test(s, test_uinput_create_device);
448c0abf9e6Sopenharmony_ci	add_test(s, test_uinput_create_device_invalid);
449c0abf9e6Sopenharmony_ci	add_test(s, test_uinput_create_device_from_fd);
450c0abf9e6Sopenharmony_ci#ifdef __FreeBSD__
451c0abf9e6Sopenharmony_ci	add_test(s, test_uinput_check_devnode_bsd);
452c0abf9e6Sopenharmony_ci	add_test(s, test_uinput_check_syspath_bsd);
453c0abf9e6Sopenharmony_ci#else
454c0abf9e6Sopenharmony_ci	add_test(s, test_uinput_check_syspath_time);
455c0abf9e6Sopenharmony_ci	add_test(s, test_uinput_check_syspath_name);
456c0abf9e6Sopenharmony_ci#endif
457c0abf9e6Sopenharmony_ci
458c0abf9e6Sopenharmony_ci	add_test(s, test_uinput_events);
459c0abf9e6Sopenharmony_ci
460c0abf9e6Sopenharmony_ci	add_test(s, test_uinput_properties);
461c0abf9e6Sopenharmony_ci
462c0abf9e6Sopenharmony_ci	return s;
463c0abf9e6Sopenharmony_ci}
464