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