1 // SPDX-License-Identifier: MIT
2 /*
3 * Copyright © 2013 Red Hat, Inc.
4 */
5
6 #include "config.h"
7 #include <dirent.h>
8 #include <errno.h>
9 #include <fcntl.h>
10 #include <linux/uinput.h>
11 #include <poll.h>
12 #include <stdio.h>
13 #include <string.h>
14 #include <sys/stat.h>
15 #include <time.h>
16 #include <unistd.h>
17
18 #include "libevdev-int.h"
19 #include "libevdev-uinput-int.h"
20 #include "libevdev-uinput.h"
21 #include "libevdev-util.h"
22 #include "libevdev.h"
23
24 #ifndef UINPUT_IOCTL_BASE
25 #define UINPUT_IOCTL_BASE 'U'
26 #endif
27
28 #ifndef UI_SET_PROPBIT
29 #define UI_SET_PROPBIT _IOW(UINPUT_IOCTL_BASE, 110, int)
30 #endif
31
32 static struct libevdev_uinput *
alloc_uinput_device(const char * name)33 alloc_uinput_device(const char *name)
34 {
35 struct libevdev_uinput *uinput_dev;
36
37 uinput_dev = calloc(1, sizeof(struct libevdev_uinput));
38 if (uinput_dev) {
39 uinput_dev->name = strdup(name);
40 uinput_dev->fd = -1;
41 }
42
43 return uinput_dev;
44 }
45
46 static inline int
set_abs(const struct libevdev * dev,int fd,unsigned int code)47 set_abs(const struct libevdev *dev, int fd, unsigned int code)
48 {
49 const struct input_absinfo *abs = libevdev_get_abs_info(dev, code);
50 struct uinput_abs_setup abs_setup = {0};
51 int rc;
52
53 abs_setup.code = code;
54 abs_setup.absinfo = *abs;
55 rc = ioctl(fd, UI_ABS_SETUP, &abs_setup);
56 return rc;
57 }
58
59 static int
set_evbits(const struct libevdev * dev,int fd,struct uinput_user_dev * uidev)60 set_evbits(const struct libevdev *dev, int fd, struct uinput_user_dev *uidev)
61 {
62 int rc = 0;
63 unsigned int type;
64
65 for (type = 0; type < EV_CNT; type++) {
66 unsigned int code;
67 int max;
68 int uinput_bit;
69 const unsigned long *mask;
70
71 if (!libevdev_has_event_type(dev, type))
72 continue;
73
74 rc = ioctl(fd, UI_SET_EVBIT, type);
75 if (rc == -1)
76 break;
77
78 /* uinput can't set EV_REP */
79 if (type == EV_REP)
80 continue;
81
82 max = type_to_mask_const(dev, type, &mask);
83 if (max == -1)
84 continue;
85
86 switch(type) {
87 case EV_KEY: uinput_bit = UI_SET_KEYBIT; break;
88 case EV_REL: uinput_bit = UI_SET_RELBIT; break;
89 case EV_ABS: uinput_bit = UI_SET_ABSBIT; break;
90 case EV_MSC: uinput_bit = UI_SET_MSCBIT; break;
91 case EV_LED: uinput_bit = UI_SET_LEDBIT; break;
92 case EV_SND: uinput_bit = UI_SET_SNDBIT; break;
93 case EV_FF: uinput_bit = UI_SET_FFBIT; break;
94 case EV_SW: uinput_bit = UI_SET_SWBIT; break;
95 default:
96 rc = -1;
97 errno = EINVAL;
98 goto out;
99 }
100
101 for (code = 0; code <= (unsigned int)max; code++) {
102 if (!libevdev_has_event_code(dev, type, code))
103 continue;
104
105 rc = ioctl(fd, uinput_bit, code);
106 if (rc == -1)
107 goto out;
108
109 if (type == EV_ABS) {
110 if (uidev == NULL) {
111 rc = set_abs(dev, fd, code);
112 if (rc != 0)
113 goto out;
114 } else {
115 const struct input_absinfo *abs =
116 libevdev_get_abs_info(dev, code);
117
118 uidev->absmin[code] = abs->minimum;
119 uidev->absmax[code] = abs->maximum;
120 uidev->absfuzz[code] = abs->fuzz;
121 uidev->absflat[code] = abs->flat;
122 /* uinput has no resolution in the
123 * device struct */
124 }
125 }
126 }
127
128 }
129
130 out:
131 return rc;
132 }
133
134 static int
set_props(const struct libevdev * dev,int fd)135 set_props(const struct libevdev *dev, int fd)
136 {
137 unsigned int prop;
138 int rc = 0;
139
140 for (prop = 0; prop <= INPUT_PROP_MAX; prop++) {
141 if (!libevdev_has_property(dev, prop))
142 continue;
143
144 rc = ioctl(fd, UI_SET_PROPBIT, prop);
145 if (rc == -1) {
146 /* If UI_SET_PROPBIT is not supported, treat -EINVAL
147 * as success. The kernel only sends -EINVAL for an
148 * invalid ioctl, invalid INPUT_PROP_MAX or if the
149 * ioctl is called on an already created device. The
150 * last two can't happen here.
151 */
152 if (errno == EINVAL)
153 rc = 0;
154 break;
155 }
156 }
157 return rc;
158 }
159
160 LIBEVDEV_EXPORT int
libevdev_uinput_get_fd(const struct libevdev_uinput * uinput_dev)161 libevdev_uinput_get_fd(const struct libevdev_uinput *uinput_dev)
162 {
163 return uinput_dev->fd;
164 }
165
166 #ifdef __FreeBSD__
167 /*
168 * FreeBSD does not have anything similar to sysfs.
169 * Set libevdev_uinput->syspath to NULL unconditionally.
170 * Look up the device nodes directly instead of via sysfs, as this matches what
171 * is returned by the UI_GET_SYSNAME ioctl() on FreeBSD.
172 */
173 static int
fetch_syspath_and_devnode(struct libevdev_uinput * uinput_dev)174 fetch_syspath_and_devnode(struct libevdev_uinput *uinput_dev)
175 {
176 #define DEV_INPUT_DIR "/dev/input/"
177 int rc;
178 char buf[sizeof(DEV_INPUT_DIR) + 64] = DEV_INPUT_DIR;
179
180 rc = ioctl(uinput_dev->fd,
181 UI_GET_SYSNAME(sizeof(buf) - strlen(DEV_INPUT_DIR)),
182 &buf[strlen(DEV_INPUT_DIR)]);
183 if (rc == -1)
184 return -1;
185
186 uinput_dev->syspath = NULL;
187 uinput_dev->devnode = strdup(buf);
188
189 return 0;
190 #undef DEV_INPUT_DIR
191 }
192
193 #else /* !__FreeBSD__ */
194
is_event_device(const struct dirent * dent)195 static int is_event_device(const struct dirent *dent) {
196 return strncmp("event", dent->d_name, 5) == 0;
197 }
198
199 static char *
fetch_device_node(const char * path)200 fetch_device_node(const char *path)
201 {
202 char *devnode = NULL;
203 struct dirent **namelist;
204 int ndev, i;
205
206 ndev = scandir(path, &namelist, is_event_device, alphasort);
207 if (ndev <= 0)
208 return NULL;
209
210 /* ndev should only ever be 1 */
211
212 for (i = 0; i < ndev; i++) {
213 if (!devnode && asprintf(&devnode, "/dev/input/%s", namelist[i]->d_name) == -1)
214 devnode = NULL;
215 free(namelist[i]);
216 }
217
218 free(namelist);
219
220 return devnode;
221 }
222
is_input_device(const struct dirent * dent)223 static int is_input_device(const struct dirent *dent) {
224 return strncmp("input", dent->d_name, 5) == 0;
225 }
226
227 static int
fetch_syspath_and_devnode(struct libevdev_uinput * uinput_dev)228 fetch_syspath_and_devnode(struct libevdev_uinput *uinput_dev)
229 {
230 #define SYS_INPUT_DIR "/sys/devices/virtual/input/"
231 struct dirent **namelist;
232 int ndev, i;
233 int rc;
234 char buf[sizeof(SYS_INPUT_DIR) + 64] = SYS_INPUT_DIR;
235
236 rc = ioctl(uinput_dev->fd,
237 UI_GET_SYSNAME(sizeof(buf) - strlen(SYS_INPUT_DIR)),
238 &buf[strlen(SYS_INPUT_DIR)]);
239 if (rc != -1) {
240 uinput_dev->syspath = strdup(buf);
241 uinput_dev->devnode = fetch_device_node(buf);
242 return 0;
243 }
244
245 ndev = scandir(SYS_INPUT_DIR, &namelist, is_input_device, alphasort);
246 if (ndev <= 0)
247 return -1;
248
249 for (i = 0; i < ndev; i++) {
250 int fd, len;
251 struct stat st;
252
253 rc = snprintf(buf, sizeof(buf), "%s%s/name",
254 SYS_INPUT_DIR,
255 namelist[i]->d_name);
256 if (rc < 0 || (size_t)rc >= sizeof(buf)) {
257 continue;
258 }
259
260 /* created within time frame */
261 fd = open(buf, O_RDONLY);
262 if (fd < 0)
263 continue;
264
265 /* created before UI_DEV_CREATE, or after it finished */
266 if (fstat(fd, &st) == -1 ||
267 st.st_ctime < uinput_dev->ctime[0] ||
268 st.st_ctime > uinput_dev->ctime[1]) {
269 close(fd);
270 continue;
271 }
272
273 len = read(fd, buf, sizeof(buf));
274 close(fd);
275 if (len <= 0)
276 continue;
277
278 buf[len - 1] = '\0'; /* file contains \n */
279 if (strcmp(buf, uinput_dev->name) == 0) {
280 if (uinput_dev->syspath) {
281 /* FIXME: could descend into bit comparison here */
282 log_info(NULL, "multiple identical devices found. syspath is unreliable\n");
283 break;
284 }
285
286 rc = snprintf(buf, sizeof(buf), "%s%s",
287 SYS_INPUT_DIR,
288 namelist[i]->d_name);
289
290 if (rc < 0 || (size_t)rc >= sizeof(buf)) {
291 log_error(NULL, "Invalid syspath, syspath is unreliable\n");
292 break;
293 }
294
295 uinput_dev->syspath = strdup(buf);
296 uinput_dev->devnode = fetch_device_node(buf);
297 }
298 }
299
300 for (i = 0; i < ndev; i++)
301 free(namelist[i]);
302 free(namelist);
303
304 return uinput_dev->devnode ? 0 : -1;
305 #undef SYS_INPUT_DIR
306 }
307 #endif /* __FreeBSD__*/
308
309 static int
uinput_create_write(const struct libevdev * dev,int fd)310 uinput_create_write(const struct libevdev *dev, int fd)
311 {
312 int rc;
313 struct uinput_user_dev uidev;
314
315 memset(&uidev, 0, sizeof(uidev));
316
317 strncpy(uidev.name, libevdev_get_name(dev), UINPUT_MAX_NAME_SIZE - 1);
318 uidev.id.vendor = libevdev_get_id_vendor(dev);
319 uidev.id.product = libevdev_get_id_product(dev);
320 uidev.id.bustype = libevdev_get_id_bustype(dev);
321 uidev.id.version = libevdev_get_id_version(dev);
322
323 if (set_evbits(dev, fd, &uidev) != 0)
324 goto error;
325 if (set_props(dev, fd) != 0)
326 goto error;
327
328 rc = write(fd, &uidev, sizeof(uidev));
329 if (rc < 0) {
330 goto error;
331 } else if ((size_t)rc < sizeof(uidev)) {
332 errno = EINVAL;
333 goto error;
334 }
335
336 errno = 0;
337
338 error:
339 return -errno;
340 }
341
342 static int
uinput_create_DEV_SETUP(const struct libevdev * dev,int fd,struct libevdev_uinput * new_device)343 uinput_create_DEV_SETUP(const struct libevdev *dev, int fd,
344 struct libevdev_uinput *new_device)
345 {
346 int rc;
347 struct uinput_setup setup;
348
349 if (set_evbits(dev, fd, NULL) != 0)
350 goto error;
351 if (set_props(dev, fd) != 0)
352 goto error;
353
354 memset(&setup, 0, sizeof(setup));
355 strncpy(setup.name, libevdev_get_name(dev), UINPUT_MAX_NAME_SIZE - 1);
356 setup.id.vendor = libevdev_get_id_vendor(dev);
357 setup.id.product = libevdev_get_id_product(dev);
358 setup.id.bustype = libevdev_get_id_bustype(dev);
359 setup.id.version = libevdev_get_id_version(dev);
360 setup.ff_effects_max = libevdev_has_event_type(dev, EV_FF) ? 10 : 0;
361
362 rc = ioctl(fd, UI_DEV_SETUP, &setup);
363 if (rc == 0)
364 errno = 0;
365 error:
366 return -errno;
367 }
368
369 LIBEVDEV_EXPORT int
libevdev_uinput_create_from_device(const struct libevdev * dev,int fd,struct libevdev_uinput ** uinput_dev)370 libevdev_uinput_create_from_device(const struct libevdev *dev, int fd, struct libevdev_uinput** uinput_dev)
371 {
372 int rc;
373 struct libevdev_uinput *new_device;
374 int close_fd_on_error = (fd == LIBEVDEV_UINPUT_OPEN_MANAGED);
375 unsigned int uinput_version = 0;
376
377 new_device = alloc_uinput_device(libevdev_get_name(dev));
378 if (!new_device)
379 return -ENOMEM;
380
381 if (fd == LIBEVDEV_UINPUT_OPEN_MANAGED) {
382 fd = open("/dev/uinput", O_RDWR|O_CLOEXEC);
383 if (fd < 0)
384 goto error;
385
386 new_device->fd_is_managed = 1;
387 } else if (fd < 0) {
388 log_bug(NULL, "Invalid fd %d\n", fd);
389 errno = EBADF;
390 goto error;
391 }
392
393 if (ioctl(fd, UI_GET_VERSION, &uinput_version) == 0 &&
394 uinput_version >= 5)
395 rc = uinput_create_DEV_SETUP(dev, fd, new_device);
396 else
397 rc = uinput_create_write(dev, fd);
398
399 if (rc != 0)
400 goto error;
401
402 /* ctime notes time before/after ioctl to help us filter out devices
403 when traversing /sys/devices/virtual/input to find the device
404 node.
405
406 this is in seconds, so ctime[0]/[1] will almost always be
407 identical but /sys doesn't give us sub-second ctime so...
408 */
409 new_device->ctime[0] = time(NULL);
410
411 rc = ioctl(fd, UI_DEV_CREATE, NULL);
412 if (rc == -1)
413 goto error;
414
415 new_device->ctime[1] = time(NULL);
416 new_device->fd = fd;
417
418 if (fetch_syspath_and_devnode(new_device) == -1) {
419 log_error(NULL, "unable to fetch syspath or device node.\n");
420 errno = ENODEV;
421 goto error;
422 }
423
424 *uinput_dev = new_device;
425
426 return 0;
427
428 error:
429 rc = -errno;
430 libevdev_uinput_destroy(new_device);
431 if (fd != -1 && close_fd_on_error)
432 close(fd);
433 return rc;
434 }
435
436 LIBEVDEV_EXPORT void
libevdev_uinput_destroy(struct libevdev_uinput * uinput_dev)437 libevdev_uinput_destroy(struct libevdev_uinput *uinput_dev)
438 {
439 if (!uinput_dev)
440 return;
441
442 if (uinput_dev->fd >= 0) {
443 (void)ioctl(uinput_dev->fd, UI_DEV_DESTROY, NULL);
444 if (uinput_dev->fd_is_managed)
445 close(uinput_dev->fd);
446 }
447 free(uinput_dev->syspath);
448 free(uinput_dev->devnode);
449 free(uinput_dev->name);
450 free(uinput_dev);
451 }
452
453 LIBEVDEV_EXPORT const char*
libevdev_uinput_get_syspath(struct libevdev_uinput * uinput_dev)454 libevdev_uinput_get_syspath(struct libevdev_uinput *uinput_dev)
455 {
456 return uinput_dev->syspath;
457 }
458
459 LIBEVDEV_EXPORT const char*
libevdev_uinput_get_devnode(struct libevdev_uinput * uinput_dev)460 libevdev_uinput_get_devnode(struct libevdev_uinput *uinput_dev)
461 {
462 return uinput_dev->devnode;
463 }
464
465 LIBEVDEV_EXPORT int
libevdev_uinput_write_event(const struct libevdev_uinput * uinput_dev,unsigned int type,unsigned int code,int value)466 libevdev_uinput_write_event(const struct libevdev_uinput *uinput_dev,
467 unsigned int type,
468 unsigned int code,
469 int value)
470 {
471 struct input_event ev = {type, code, value};
472 int fd = libevdev_uinput_get_fd(uinput_dev);
473 int rc, max;
474
475 if (type > EV_MAX)
476 return -EINVAL;
477
478 max = libevdev_event_type_get_max(type);
479 if (max == -1 || code > (unsigned int)max)
480 return -EINVAL;
481
482 rc = write(fd, &ev, sizeof(ev));
483
484 return rc < 0 ? -errno : 0;
485 }
486