1 /*
2 * Copyright (c) 2015, 2021 Vladimir Kondratyev <vladimir@kondratyev.su>
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 */
25
26 #include "config.h"
27
28 #include <sys/param.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #ifdef HAVE_SYSCTLBYNAME
32 #include <sys/sysctl.h>
33 #endif
34
35 #include <assert.h>
36 #include <fcntl.h>
37 #include <fnmatch.h>
38 #include <stdbool.h>
39 #include <stdint.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <unistd.h>
44
45 #ifdef HAVE_DEV_HID_HIDRAW_H
46 #include <dev/hid/hidraw.h>
47 #endif
48 #ifdef HAVE_LINUX_INPUT_H
49 #include <linux/input.h>
50 #endif
51
52 #include "libudev.h"
53 #include "udev-device.h"
54 #include "udev-list.h"
55 #include "udev-utils.h"
56 #include "utils.h"
57 #ifdef ENABLE_GPL
58 #include "utils-gpl.h"
59 #endif
60
61 #ifdef HAVE_LINUX_INPUT_H
62 #ifndef BTN_DPAD_UP
63 #define BTN_DPAD_UP 0x220
64 #endif
65 #ifndef BTN_DPAD_RIGHT
66 #define BTN_DPAD_RIGHT 0x223
67 #endif
68 #ifndef BTN_SOUTH
69 #define BTN_SOUTH 0x130
70 #endif
71 #else /* !HAVE_LINUX_INPUT_H */
72 #define BUS_PCI 0x01
73 #define BUS_USB 0x03
74 #define BUS_VIRTUAL 0x06
75 #define BUS_ISA 0x10
76 #define BUS_I8042 0x11
77 #endif /* !HAVE_LINUX_INPUT_H */
78
79 #define PS2_KEYBOARD_VENDOR 0x001
80 #define PS2_KEYBOARD_PRODUCT 0x001
81 #define PS2_MOUSE_VENDOR 0x002
82 #define PS2_MOUSE_GENERIC_PRODUCT 0x001
83
84 typedef void (create_node_handler_t)(struct udev_device *udev_device);
85
86 #if defined(HAVE_LINUX_INPUT_H) || defined(HAVE_DEV_HID_HIDRAW_H)
87 static const char *virtual_sysname = "uinput";
88 #endif
89
90 #ifdef HAVE_LINUX_INPUT_H
91 static create_node_handler_t create_evdev_handler;
92 #endif
93 static create_node_handler_t create_keyboard_handler;
94 static create_node_handler_t create_mouse_handler;
95 static create_node_handler_t create_joystick_handler;
96 static create_node_handler_t create_touchpad_handler;
97 static create_node_handler_t create_touchscreen_handler;
98 static create_node_handler_t create_sysmouse_handler;
99 static create_node_handler_t create_kbdmux_handler;
100 static create_node_handler_t create_drm_handler;
101 #ifdef HAVE_DEV_HID_HIDRAW_H
102 static create_node_handler_t create_hidraw_handler;
103 #endif
104
105 struct devnum_scan_args {
106 dev_t devnum;
107 char * pattern;
108 char * path;
109 size_t len;
110 };
111
112 struct subsystem_config {
113 char *subsystem;
114 char *syspath;
115 char *symlink; /* If syspath is symlink, path it refers to */
116 int flags; /* See SCFLAG_* below. */
117 create_node_handler_t *create_handler;
118 };
119
120 enum {
121 IT_NONE,
122 IT_KEYBOARD,
123 IT_MOUSE,
124 IT_TOUCHPAD,
125 IT_TOUCHSCREEN,
126 IT_JOYSTICK,
127 IT_TABLET,
128 IT_ACCELEROMETER,
129 IT_SWITCH,
130 };
131
132 /* Flag which in indicates a device should be skipped because it's
133 * already exposed through EVDEV when it's enabled. */
134 #define SCFLAG_SKIP_IF_EVDEV 0x01
135
136 static const struct subsystem_config subsystems[] = {
137 {
138 #ifdef HAVE_LINUX_INPUT_H
139 .subsystem = "input",
140 .syspath = DEV_PATH_ROOT "/input/event[0-9]*",
141 .create_handler = create_evdev_handler
142 }, {
143 #endif
144 .subsystem = "input",
145 .syspath = DEV_PATH_ROOT "/ukbd[0-9]*",
146 .flags = SCFLAG_SKIP_IF_EVDEV,
147 .create_handler = create_keyboard_handler,
148 }, {
149 .subsystem = "input",
150 .syspath = DEV_PATH_ROOT "/atkbd[0-9]*",
151 .flags = SCFLAG_SKIP_IF_EVDEV,
152 .create_handler = create_keyboard_handler,
153 }, {
154 .subsystem = "input",
155 .syspath = DEV_PATH_ROOT "/kbdmux[0-9]*",
156 .flags = SCFLAG_SKIP_IF_EVDEV,
157 .create_handler = create_kbdmux_handler,
158 }, {
159 .subsystem = "input",
160 .syspath = DEV_PATH_ROOT "/ums[0-9]*",
161 .flags = SCFLAG_SKIP_IF_EVDEV,
162 .create_handler = create_mouse_handler,
163 }, {
164 .subsystem = "input",
165 .syspath = DEV_PATH_ROOT "/psm[0-9]*",
166 .flags = SCFLAG_SKIP_IF_EVDEV,
167 .create_handler = create_mouse_handler,
168 }, {
169 .subsystem = "input",
170 .syspath = DEV_PATH_ROOT "/joy[0-9]*",
171 .create_handler = create_joystick_handler,
172 }, {
173 .subsystem = "input",
174 .syspath = DEV_PATH_ROOT "/atp[0-9]*",
175 .create_handler = create_touchpad_handler,
176 }, {
177 .subsystem = "input",
178 .syspath = DEV_PATH_ROOT "/wsp[0-9]*",
179 .create_handler = create_touchpad_handler,
180 }, {
181 .subsystem = "input",
182 .syspath = DEV_PATH_ROOT "/uep[0-9]*",
183 .create_handler = create_touchscreen_handler,
184 }, {
185 .subsystem = "input",
186 .syspath = DEV_PATH_ROOT "/sysmouse",
187 .flags = SCFLAG_SKIP_IF_EVDEV,
188 .create_handler = create_sysmouse_handler,
189 }, {
190 .subsystem = "input",
191 .syspath = DEV_PATH_ROOT "/vboxguest",
192 .create_handler = create_mouse_handler,
193 }, {
194 .subsystem = "drm",
195 .syspath = DEV_PATH_ROOT "/dri/card[0-9]*",
196 .symlink = DEV_PATH_ROOT "/drm/[0-9]*",
197 .create_handler = create_drm_handler,
198 },
199 #ifdef HAVE_DEV_HID_HIDRAW_H
200 {
201 .subsystem = "hidraw",
202 .syspath = DEV_PATH_ROOT "/hidraw[0-9]*",
203 .create_handler = create_hidraw_handler,
204 },
205 #endif
206 };
207
208 static const struct subsystem_config *
get_subsystem_config_by_syspath(const char * path)209 get_subsystem_config_by_syspath(const char *path)
210 {
211 size_t i;
212
213 for (i = 0; i < nitems(subsystems); i++)
214 if (fnmatch(subsystems[i].syspath, path, 0) == 0)
215 return (&subsystems[i]);
216
217 return (NULL);
218 }
219
220 static bool
kernel_has_evdev_enabled()221 kernel_has_evdev_enabled()
222 {
223 static int enabled = -1;
224 #ifdef HAVE_SYSCTLBYNAME
225 size_t len;
226 #endif
227
228 if (enabled != -1)
229 return (enabled);
230
231 #ifdef HAVE_SYSCTLBYNAME
232 if (sysctlbyname("kern.features.evdev_support", &enabled, &len, NULL, 0) < 0)
233 return (0);
234 #else
235 enabled = 1;
236 #endif
237
238 TRC("() EVDEV enabled: %s", enabled ? "true" : "false");
239 return (enabled);
240 }
241
242 const char *
get_subsystem_by_syspath(const char * syspath)243 get_subsystem_by_syspath(const char *syspath)
244 {
245 const struct subsystem_config *sc;
246
247 sc = get_subsystem_config_by_syspath(syspath);
248 if (sc == NULL)
249 return (UNKNOWN_SUBSYSTEM);
250 if (sc->flags & SCFLAG_SKIP_IF_EVDEV && kernel_has_evdev_enabled()) {
251 TRC("(%s) EVDEV enabled -> skipping device", syspath);
252 return (UNKNOWN_SUBSYSTEM);
253 }
254
255 return (sc->subsystem);
256 }
257
258 const char *
get_sysname_by_syspath(const char * syspath)259 get_sysname_by_syspath(const char *syspath)
260 {
261
262 return (strbase(syspath));
263 }
264
265 const char *
get_devpath_by_syspath(const char * syspath)266 get_devpath_by_syspath(const char *syspath)
267 {
268
269 return (syspath);
270 }
271
272 const char *
get_syspath_by_devpath(const char * devpath)273 get_syspath_by_devpath(const char *devpath)
274 {
275
276 return (devpath);
277 }
278
279 static int
get_syspath_by_devnum_cb(const char * path,mode_t type,void * args)280 get_syspath_by_devnum_cb(const char *path, mode_t type, void *args)
281 {
282 struct devnum_scan_args *sa = args;
283 struct stat st;
284
285 if (S_ISLNK(type) &&
286 fnmatch(sa->pattern, path, 0) == 0 &&
287 stat(path, &st) == 0 &&
288 st.ST_RDEV == sa->devnum) {
289 strlcpy(sa->path, path, sa->len);
290 return (-1);
291 }
292 return (0);
293 }
294
295 const char *
get_syspath_by_devnum(dev_t devnum)296 get_syspath_by_devnum(dev_t devnum)
297 {
298 char devpath[DEV_PATH_MAX] = DEV_PATH_ROOT "/";
299 char linkdir[DEV_PATH_MAX];
300 struct stat st;
301 struct scan_ctx ctx;
302 struct devnum_scan_args args;
303 const char *linkbase;
304 size_t dev_len, linkdir_len, i;
305
306 dev_len = strlen(devpath);
307 devname_r(devnum, S_IFCHR, devpath + dev_len, sizeof(devpath) - dev_len);
308 /* Recheck path as devname_r returns zero-terminated garbage on error */
309 if (stat(devpath, &st) != 0 || st.ST_RDEV != devnum) {
310 TRC("(%d) -> failed", (int)devnum);
311 return NULL;
312 }
313 TRC("(%d) -> %s", (int)devnum, devpath);
314
315 /* Resolve symlink in reverse direction if necessary */
316 for (i = 0; i < nitems(subsystems); i++) {
317 if (subsystems[i].symlink != NULL &&
318 fnmatch(subsystems[i].symlink, devpath, 0) == 0) {
319 linkbase = strbase(subsystems[i].syspath);
320 assert(linkbase != NULL);
321 linkdir_len = linkbase - subsystems[i].syspath;
322 if (linkdir_len >= sizeof(linkdir))
323 linkdir_len = sizeof(linkdir);
324 strlcpy(linkdir, subsystems[i].syspath, linkdir_len + 1);
325 args = (struct devnum_scan_args) {
326 .devnum = devnum,
327 .pattern = subsystems[i].syspath,
328 .path = devpath,
329 .len = sizeof(devpath),
330 };
331 ctx = (struct scan_ctx) {
332 .recursive = false,
333 .cb = get_syspath_by_devnum_cb,
334 .args = &args,
335 };
336 if (scandir_recursive(linkdir, sizeof(linkdir), &ctx) == -1)
337 break;
338 }
339 }
340
341 return (strdup(devpath));
342 }
343
344 void
invoke_create_handler(struct udev_device * ud)345 invoke_create_handler(struct udev_device *ud)
346 {
347 const char *path;
348 const struct subsystem_config *sc;
349
350 path = udev_device_get_syspath(ud);
351 sc = get_subsystem_config_by_syspath(path);
352 if (sc == NULL || sc->create_handler == NULL)
353 return;
354 if (sc->flags & SCFLAG_SKIP_IF_EVDEV && kernel_has_evdev_enabled()) {
355 TRC("(%p) EVDEV enabled -> skipping device", ud);
356 return;
357 }
358
359 sc->create_handler(ud);
360 }
361
362 static int
set_input_device_type(struct udev_device * ud,int input_type)363 set_input_device_type(struct udev_device *ud, int input_type)
364 {
365 struct udev_list *ul;
366
367 ul = udev_device_get_properties_list(ud);
368 if (udev_list_insert(ul, "ID_INPUT", "1") < 0)
369 return (-1);
370 switch (input_type) {
371 case IT_KEYBOARD:
372 udev_list_insert(ul, "ID_INPUT_KEY", "1");
373 udev_list_insert(ul, "ID_INPUT_KEYBOARD", "1");
374 break;
375 case IT_MOUSE:
376 udev_list_insert(ul, "ID_INPUT_MOUSE", "1");
377 break;
378 case IT_TOUCHPAD:
379 udev_list_insert(ul, "ID_INPUT_MOUSE", "1");
380 udev_list_insert(ul, "ID_INPUT_TOUCHPAD", "1");
381 break;
382 case IT_TOUCHSCREEN:
383 udev_list_insert(ul, "ID_INPUT_TOUCHSCREEN", "1");
384 break;
385 case IT_JOYSTICK:
386 udev_list_insert(ul, "ID_INPUT_JOYSTICK", "1");
387 break;
388 case IT_TABLET:
389 udev_list_insert(ul, "ID_INPUT_TABLET", "1");
390 break;
391 case IT_ACCELEROMETER:
392 udev_list_insert(ul, "ID_INPUT_ACCELEROMETER", "1");
393 break;
394 case IT_SWITCH:
395 udev_list_insert(ul, "ID_INPUT_SWITCH", "1");
396 break;
397 }
398 return (0);
399 }
400
401 static struct udev_device *
create_xorg_parent(struct udev_device * ud,const char * sysname,const char * name,const char * product,const char * pnp_id)402 create_xorg_parent(struct udev_device *ud, const char* sysname,
403 const char *name, const char *product, const char *pnp_id)
404 {
405 struct udev_device *parent;
406 struct udev *udev;
407 struct udev_list *props, *sysattrs;
408
409 /* xorg-server gets device name and vendor string from parent device */
410 udev = udev_device_get_udev(ud);
411 parent = udev_device_new_common(udev, sysname, UD_ACTION_NONE);
412 if (parent == NULL)
413 return NULL;
414
415 props = udev_device_get_properties_list(parent);
416 sysattrs = udev_device_get_sysattr_list(parent);
417 udev_list_insert(props, "NAME", name);
418 udev_list_insert(sysattrs, "name", name);
419 if (product != NULL)
420 udev_list_insert(props, "PRODUCT", product);
421 if (pnp_id != NULL)
422 udev_list_insert(sysattrs, "id", product);
423
424 return (parent);
425 }
426
427 #ifdef HAVE_LINUX_INPUT_H
428
429 #define LONG_BITS (sizeof(long) * 8)
430 #define NLONGS(x) (((x) + LONG_BITS - 1) / LONG_BITS)
431
432 static inline bool
bit_is_set(const unsigned long * array,int bit)433 bit_is_set(const unsigned long *array, int bit)
434 {
435 return !!(array[bit / LONG_BITS] & (1LL << (bit % LONG_BITS)));
436 }
437
438 static inline bool
bit_find(const unsigned long * array,int start,int stop)439 bit_find(const unsigned long *array, int start, int stop)
440 {
441 int i;
442
443 for (i = start; i < stop; i++)
444 if (bit_is_set(array, i))
445 return true;
446
447 return false;
448 }
449
450 static void
create_evdev_handler(struct udev_device * ud)451 create_evdev_handler(struct udev_device *ud)
452 {
453 struct udev_device *parent;
454 const char *sysname;
455 char name[80], product[80], phys[80];
456 int fd = -1, input_type = IT_NONE;
457 bool opened = false;
458 bool has_keys, has_buttons, has_lmr, has_dpad, has_joy_axes;
459 bool has_rel_axes, has_abs_axes, has_mt, has_switches;
460 unsigned long key_bits[NLONGS(KEY_CNT)];
461 unsigned long rel_bits[NLONGS(REL_CNT)];
462 unsigned long abs_bits[NLONGS(ABS_CNT)];
463 unsigned long sw_bits[NLONGS(SW_CNT)];
464 unsigned long prp_bits[NLONGS(INPUT_PROP_CNT)];
465 struct input_id id;
466 #ifdef HAVE_SYSCTLBYNAME
467 const char *unit;
468 char mib[32];
469 size_t len;
470
471 sysname = udev_device_get_sysname(ud);
472 len = syspathlen_wo_units(sysname);
473 unit = sysname + len;
474
475 snprintf(mib, sizeof(mib), "kern.evdev.input.%s.name", unit);
476 len = sizeof(name);
477 if (sysctlbyname(mib, name, &len, NULL, 0) < 0)
478 goto use_ioctl;
479
480 snprintf(mib, sizeof(mib), "kern.evdev.input.%s.phys", unit);
481 len = sizeof(phys);
482 if (sysctlbyname(mib, phys, &len, NULL, 0) < 0)
483 goto use_ioctl;
484
485 snprintf(mib, sizeof(mib), "kern.evdev.input.%s.id", unit);
486 len = sizeof(id);
487 if (sysctlbyname(mib, &id, &len, NULL, 0) < 0)
488 goto use_ioctl;
489
490 snprintf(mib, sizeof(mib), "kern.evdev.input.%s.key_bits", unit);
491 len = sizeof(key_bits);
492 if (sysctlbyname(mib, key_bits, &len, NULL, 0) < 0)
493 goto use_ioctl;
494
495 snprintf(mib, sizeof(mib), "kern.evdev.input.%s.rel_bits", unit);
496 len = sizeof(rel_bits);
497 if (sysctlbyname(mib, rel_bits, &len, NULL, 0) < 0)
498 goto use_ioctl;
499
500 snprintf(mib, sizeof(mib), "kern.evdev.input.%s.abs_bits", unit);
501 len = sizeof(abs_bits);
502 if (sysctlbyname(mib, abs_bits, &len, NULL, 0) < 0)
503 goto use_ioctl;
504
505 snprintf(mib, sizeof(mib), "kern.evdev.input.%s.sw_bits", unit);
506 len = sizeof(sw_bits);
507 if (sysctlbyname(mib, sw_bits, &len, NULL, 0) < 0)
508 goto use_ioctl;
509
510 snprintf(mib, sizeof(mib), "kern.evdev.input.%s.props", unit);
511 len = sizeof(prp_bits);
512 if (sysctlbyname(mib, prp_bits, &len, NULL, 0) < 0)
513 goto use_ioctl;
514
515 goto found_values;
516
517 use_ioctl:
518 ERR("sysctl not found, opening device and using ioctl");
519 #endif
520
521 fd = open(udev_device_get_devnode(ud), O_RDONLY | O_CLOEXEC);
522 if (fd == -1) {
523 fd = path_to_fd(udev_device_get_devnode(ud));
524 } else {
525 opened = true;
526 }
527 if (fd == -1)
528 return;
529
530 if (ioctl(fd, EVIOCGNAME(sizeof(name)), name) < 0 ||
531 (ioctl(fd, EVIOCGPHYS(sizeof(phys)), phys) < 0 && errno != ENOENT) ||
532 ioctl(fd, EVIOCGID, &id) < 0 ||
533 ioctl(fd, EVIOCGBIT(EV_REL, sizeof(rel_bits)), rel_bits) < 0 ||
534 ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_bits)), abs_bits) < 0 ||
535 ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(key_bits)), key_bits) < 0 ||
536 ioctl(fd, EVIOCGBIT(EV_SW, sizeof(sw_bits)), sw_bits) < 0 ||
537 ioctl(fd, EVIOCGPROP(sizeof(prp_bits)), prp_bits) < 0) {
538 ERR("could not query evdev");
539 goto bail_out;
540 }
541
542 #ifdef HAVE_SYSCTLBYNAME
543 found_values:
544 #endif
545 /* Derived from EvdevProbe() function of xf86-input-evdev driver */
546 has_keys = bit_find(key_bits, 0, BTN_MISC);
547 has_buttons = bit_find(key_bits, BTN_MISC, BTN_JOYSTICK);
548 has_lmr = bit_find(key_bits, BTN_LEFT, BTN_MIDDLE + 1);
549 has_dpad = bit_find(key_bits, BTN_DPAD_UP, BTN_DPAD_RIGHT + 1);
550 has_joy_axes = bit_find(abs_bits, ABS_RX, ABS_HAT3Y + 1);
551 has_rel_axes = bit_find(rel_bits, 0, REL_CNT);
552 has_abs_axes = bit_find(abs_bits, 0, ABS_CNT);
553 has_switches = bit_find(sw_bits, 0, SW_CNT);
554 has_mt = bit_find(abs_bits, ABS_MT_SLOT, ABS_CNT);
555
556 if (has_abs_axes) {
557 if (has_mt && !has_buttons) {
558 if (bit_is_set(key_bits, BTN_JOYSTICK)) {
559 input_type = IT_JOYSTICK;
560 goto detected;
561 } else {
562 has_buttons = true;
563 }
564 }
565
566 if (bit_is_set(abs_bits, ABS_X) &&
567 bit_is_set(abs_bits, ABS_Y)) {
568 if (bit_is_set(key_bits, BTN_TOOL_PEN) ||
569 bit_is_set(key_bits, BTN_STYLUS) ||
570 bit_is_set(key_bits, BTN_STYLUS2)) {
571 input_type = IT_TABLET;
572 goto detected;
573 } else if (has_joy_axes ||
574 bit_is_set(key_bits, BTN_JOYSTICK)) {
575 /* Device is a joystick */
576 input_type = IT_JOYSTICK;
577 goto detected;
578 } else if (bit_is_set(key_bits, BTN_SOUTH) ||
579 has_dpad ||
580 bit_is_set(abs_bits, ABS_HAT0X) ||
581 bit_is_set(abs_bits, ABS_HAT0Y) ||
582 bit_is_set(key_bits, BTN_THUMBL) ||
583 bit_is_set(key_bits, BTN_THUMBR)) {
584 /* Device is a gamepad */
585 input_type = IT_JOYSTICK;
586 goto detected;
587 } else if (bit_is_set(abs_bits, ABS_PRESSURE) ||
588 bit_is_set(key_bits, BTN_TOUCH)) {
589 if (has_lmr ||
590 bit_is_set(key_bits, BTN_TOOL_FINGER)) {
591 input_type = IT_TOUCHPAD;
592 } else {
593 input_type = IT_TOUCHSCREEN;
594 }
595 goto detected;
596 } else if (!(bit_is_set(rel_bits, REL_X) &&
597 bit_is_set(rel_bits, REL_Y)) &&
598 has_lmr) {
599 input_type = IT_MOUSE;
600 goto detected;
601 }
602 }
603 }
604
605 if (bit_is_set(prp_bits, INPUT_PROP_ACCELEROMETER))
606 input_type = IT_ACCELEROMETER;
607 else if (has_keys)
608 input_type = IT_KEYBOARD;
609 else if (bit_is_set(prp_bits, INPUT_PROP_POINTER) || has_rel_axes || has_abs_axes || has_buttons)
610 input_type = IT_MOUSE;
611 else if (has_switches)
612 input_type = IT_SWITCH;
613
614 if (input_type == IT_NONE)
615 goto bail_out;
616
617 detected:
618 set_input_device_type(ud, input_type);
619
620 sysname = phys[0] == 0 ? virtual_sysname : phys;
621
622 *(strchrnul(name, ',')) = '\0'; /* strip name */
623
624 snprintf(product, sizeof(product), "%x/%x/%x/%x",
625 id.bustype, id.vendor, id.product, id.version);
626
627 parent = create_xorg_parent(ud, sysname, name, product, NULL);
628 if (parent != NULL)
629 udev_device_set_parent(ud, parent);
630
631 bail_out:
632 if (opened)
633 close(fd);
634 }
635 #endif
636
637 size_t
syspathlen_wo_units(const char * path)638 syspathlen_wo_units(const char *path) {
639 size_t len;
640
641 len = strlen(path);
642 while (len > 0) {
643 if (path[len-1] < '0' || path[len-1] > '9')
644 break;
645 --len;
646 }
647 return len;
648 }
649
650 static void
set_parent(struct udev_device * ud)651 set_parent(struct udev_device *ud)
652 {
653 struct udev_device *parent;
654 const char *sysname;
655 char product[80], name[80];
656 char *pnp_id = NULL;
657 size_t len;
658 uint32_t bus = BUS_VIRTUAL, prod = 0, vendor = 0;
659 #ifdef HAVE_SYSCTLBYNAME
660 char devname[DEV_PATH_MAX], mib[32], pnpinfo[1024], parentname[80];
661 const char *unit, *vendorstr, *prodstr, *devicestr;
662 size_t vendorlen, prodlen, devicelen, pnplen;
663 #endif
664
665 sysname = udev_device_get_sysname(ud);
666 len = syspathlen_wo_units(sysname);
667 /* Check if device unit number found */
668 if (strlen(sysname) == len)
669 return;
670
671 #ifdef HAVE_SYSCTLBYNAME
672 snprintf(devname, len + 1, "%s", sysname);
673 unit = sysname + len;
674
675 snprintf(mib, sizeof(mib), "dev.%.17s.%.3s.%%desc", devname, unit);
676 len = sizeof(name);
677 if (sysctlbyname(mib, name, &len, NULL, 0) < 0)
678 return;
679 *(strchrnul(name, ',')) = '\0'; /* strip name */
680
681 snprintf(mib, sizeof(mib), "dev.%.14s.%.3s.%%pnpinfo", devname, unit);
682 len = sizeof(pnpinfo);
683 if (sysctlbyname(mib, pnpinfo, &len, NULL, 0) < 0)
684 return;
685
686 snprintf(mib, sizeof(mib), "dev.%.15s.%.3s.%%parent", devname, unit);
687 len = sizeof(parentname);
688 if (sysctlbyname(mib, parentname, &len, NULL, 0) < 0)
689 return;
690
691 vendorstr = get_kern_prop_value(pnpinfo, "vendor", &vendorlen);
692 prodstr = get_kern_prop_value(pnpinfo, "product", &prodlen);
693 devicestr = get_kern_prop_value(pnpinfo, "device", &devicelen);
694 pnp_id = get_kern_prop_value(pnpinfo, "_HID", &pnplen);
695 if (pnp_id != NULL && pnplen == 4 && strncmp(pnp_id, "none", 4) == 0)
696 pnp_id = NULL;
697 if (pnp_id != NULL)
698 pnp_id[pnplen] = '\0';
699 if (prodstr != NULL && vendorstr != NULL) {
700 /* XXX: should parent be compared to uhub* to detect usb? */
701 vendor = strtol(vendorstr, NULL, 0);
702 prod = strtol(prodstr, NULL, 0);
703 bus = BUS_USB;
704 } else if (devicestr != NULL && vendorstr != NULL) {
705 vendor = strtol(vendorstr, NULL, 0);
706 prod = strtol(devicestr, NULL, 0);
707 bus = BUS_PCI;
708 } else if (strcmp(parentname, "atkbdc0") == 0) {
709 if (strcmp(devname, "atkbd") == 0) {
710 vendor = PS2_KEYBOARD_VENDOR;
711 prod = PS2_KEYBOARD_PRODUCT;
712 } else if (strcmp(devname, "psm") == 0) {
713 vendor = PS2_MOUSE_VENDOR;
714 prod = PS2_MOUSE_GENERIC_PRODUCT;
715 } else {
716 vendor = 0;
717 prod = 0;
718 }
719 bus = BUS_I8042;
720 }
721 #else
722 strlcpy(name, sysname, sizeof(name));
723 #endif
724 snprintf(product, sizeof(product), "%x/%x/%x/0", bus, vendor, prod);
725 parent = create_xorg_parent(ud, sysname, name, product, pnp_id);
726 if (parent != NULL)
727 udev_device_set_parent(ud, parent);
728
729 return;
730 }
731
732 static void
create_keyboard_handler(struct udev_device * ud)733 create_keyboard_handler(struct udev_device *ud)
734 {
735
736 set_input_device_type(ud, IT_KEYBOARD);
737 set_parent(ud);
738 }
739
740 static void
create_mouse_handler(struct udev_device * ud)741 create_mouse_handler(struct udev_device *ud)
742 {
743
744 set_input_device_type(ud, IT_MOUSE);
745 set_parent(ud);
746 }
747
748 static void
create_kbdmux_handler(struct udev_device * ud)749 create_kbdmux_handler(struct udev_device *ud)
750 {
751 struct udev_device *parent;
752 const char* sysname;
753
754 set_input_device_type(ud, IT_KEYBOARD);
755 sysname = udev_device_get_sysname(ud);
756 parent = create_xorg_parent(ud, sysname,
757 "System keyboard multiplexor", "6/1/1/0", NULL);
758 if (parent != NULL)
759 udev_device_set_parent(ud, parent);
760 }
761
762 static void
create_sysmouse_handler(struct udev_device * ud)763 create_sysmouse_handler(struct udev_device *ud)
764 {
765 struct udev_device *parent;
766 const char* sysname;
767
768 set_input_device_type(ud, IT_MOUSE);
769 sysname = udev_device_get_sysname(ud);
770 parent = create_xorg_parent(ud, sysname,
771 "System mouse", "6/2/1/0", NULL);
772 if (parent != NULL)
773 udev_device_set_parent(ud, parent);
774 }
775
776 static void
create_joystick_handler(struct udev_device * ud)777 create_joystick_handler(struct udev_device *ud)
778 {
779
780 set_input_device_type(ud, IT_JOYSTICK);
781 set_parent(ud);
782 }
783
784 static void
create_touchpad_handler(struct udev_device * ud)785 create_touchpad_handler(struct udev_device *ud)
786 {
787
788 set_input_device_type(ud, IT_TOUCHPAD);
789 set_parent(ud);
790 }
791
792 static void
create_touchscreen_handler(struct udev_device * ud)793 create_touchscreen_handler(struct udev_device *ud)
794 {
795
796 set_input_device_type(ud, IT_TOUCHSCREEN);
797 set_parent(ud);
798 }
799
800 static void
create_drm_handler(struct udev_device * ud)801 create_drm_handler(struct udev_device *ud)
802 {
803 const char *sysname, *devpath;
804 struct udev_device *parent;
805 #ifdef HAVE_SYSCTLBYNAME
806 char devbuf[PATH_MAX], buf[32], *devbufptr;
807 size_t buflen = sizeof(devbuf);
808 #endif
809
810 udev_list_insert(udev_device_get_properties_list(ud), "HOTPLUG", "1");
811 devpath = udev_device_get_devnode(ud);
812 if (devpath == NULL)
813 return;
814
815 sysname = udev_device_get_sysname(ud);
816 parent = create_xorg_parent(ud, sysname, "drm parent", NULL, NULL);
817 if (parent == NULL)
818 return;
819
820 udev_device_set_parent(ud, parent);
821
822 #ifdef HAVE_SYSCTLBYNAME
823 realpath(devpath, devbuf);
824 devbufptr = devbuf + 1;
825 devbufptr = strchrnul(devbufptr, '/');
826 while (*devbufptr != '\0') {
827 *devbufptr = '.';
828 devbufptr = strchrnul(devbufptr, '/');
829 }
830 snprintf(buf, sizeof(buf), "%.24s.PCI_ID", devbuf + 1);
831 if (sysctlbyname(buf, devbuf, &buflen, NULL, 0) == 0){
832 udev_list_insert(
833 udev_device_get_properties_list(parent), "PCI_ID", devbuf);}
834 #endif
835 }
836
837 #ifdef HAVE_DEV_HID_HIDRAW_H
838 static void
create_hidraw_handler(struct udev_device * ud)839 create_hidraw_handler(struct udev_device *ud)
840 {
841 char name[80], phys[80], uniq[32];
842 const char *sysname;
843 char *uevent;
844 struct hidraw_devinfo info;
845 struct udev_device *parent;
846 struct udev *udev;
847 struct udev_list *sysattrs;
848 int fd = -1;
849 bool opened = false;
850
851 fd = path_to_fd(udev_device_get_devnode(ud));
852 if (fd == -1) {
853 fd = open(udev_device_get_devnode(ud), O_RDONLY | O_CLOEXEC);
854 opened = true;
855 }
856 if (fd == -1)
857 return;
858
859 if (ioctl(fd, HIDIOCGRAWNAME(sizeof(name)), name) < 0 ||
860 ioctl(fd, HIDIOCGRAWPHYS(sizeof(phys)), phys) < 0 ||
861 ioctl(fd, HIDIOCGRAWUNIQ(sizeof(uniq)), uniq) < 0 ||
862 ioctl(fd, HIDIOCGRAWINFO, &info) < 0) {
863 ERR("could not query hidraw");
864 goto bail_out;
865 }
866
867 sysname = phys[0] == 0 ? virtual_sysname : phys;
868 udev = udev_device_get_udev(ud);
869 parent = udev_device_new_common(udev, sysname, UD_ACTION_NONE);
870 if (parent == NULL)
871 goto bail_out;
872
873 sysattrs = udev_device_get_sysattr_list(parent);
874 asprintf(&uevent,
875 "HID_ID=%04X:%08X:%08X\nHID_NAME=%s\nHID_PHYS=%s\nHID_UNIQ=%s",
876 info.bustype, info.vendor, info.product, name, phys, uniq);
877 udev_list_insert(sysattrs, "uevent", uevent);
878 free(uevent);
879
880 bail_out:
881 if (opened)
882 close(fd);
883 }
884 #endif
885
886 LIBUDEV_EXPORT int
udev_util_encode_string(const char * str,char * str_enc,size_t len)887 udev_util_encode_string(const char *str, char *str_enc, size_t len)
888 {
889 #ifdef ENABLE_GPL
890 return (encode_devnode_name(str, str_enc, len));
891 #else
892 return (strlcpy(str_enc, str, len) < len ? 0 : -EINVAL);
893 #endif
894 }
895