blob: 39915040e62af112379a1a7cfbb8f287f13f9d87 [file] [log] [blame]
Dominik Behr5239cca2016-01-21 18:22:04 -08001/*
2 * Copyright 2016 The Chromium OS Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
5 */
6
Dominik Behr5239cca2016-01-21 18:22:04 -08007#include <errno.h>
8#include <libudev.h>
Mike Frysinger006bdb22016-09-14 13:43:48 -04009#include <string.h>
Dominik Behr5239cca2016-01-21 18:22:04 -080010
11#include "dev.h"
12#include "input.h"
Dominik Behr01a7a582016-01-28 17:02:21 -080013#include "term.h"
Dominik Behr5239cca2016-01-21 18:22:04 -080014#include "util.h"
15
16static struct udev* udev = NULL;
17static struct udev_monitor* udev_monitor = NULL;
18static int udev_fd = -1;
19
20int dev_init(void)
21{
22 udev = udev_new();
23 if (!udev)
24 return -ENOENT;
25
26 udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
27 if (!udev_monitor) {
28 udev_unref(udev);
29 udev = NULL;
30 return -ENOENT;
31 }
32 udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "input",
33 NULL);
Dominik Behr01a7a582016-01-28 17:02:21 -080034 udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "drm",
35 "drm_minor");
Dominik Behr5239cca2016-01-21 18:22:04 -080036 udev_monitor_enable_receiving(udev_monitor);
37 udev_fd = udev_monitor_get_fd(udev_monitor);
38
39 dev_add_existing_input_devs();
40
41 return 0;
42}
43
44void dev_close(void)
45{
46 if (!udev_monitor) {
47 return;
48 }
49 udev_monitor_unref(udev_monitor);
50 udev_monitor = NULL;
51 udev_unref(udev);
52 udev = NULL;
53 udev_fd = -1;
54}
55
Daniel Kurtzf0e61aa2018-08-03 17:16:53 -060056static bool dev_is_pointer_device(struct udev_device* dev)
57{
58 static const char * const pointer_device_ids[] = {
59 "ID_INPUT_JOYSTICK",
60 "ID_INPUT_MOUSE",
61 "ID_INPUT_TOUCHPAD",
62 "ID_INPUT_TOUCHSCREEN",
63 };
64 unsigned long i;
65
66 for (i = 0; i < ARRAY_SIZE(pointer_device_ids); i++) {
67 const char *value;
68 value = udev_device_get_property_value(dev,
69 pointer_device_ids[i]);
70 if (value && !strcmp(value, "1"))
71 return true;
72 }
73
74 return false;
75}
76
Dominik Behr5239cca2016-01-21 18:22:04 -080077void dev_add_existing_input_devs(void)
78{
79 struct udev_enumerate* udev_enum;
80 struct udev_list_entry* devices, *deventry;
81 udev_enum = udev_enumerate_new(udev);
82 udev_enumerate_add_match_subsystem(udev_enum, "input");
83 udev_enumerate_scan_devices(udev_enum);
84 devices = udev_enumerate_get_list_entry(udev_enum);
85 udev_list_entry_foreach(deventry, devices) {
86 const char* syspath;
87 struct udev_device* dev;
88 syspath = udev_list_entry_get_name(deventry);
89 dev = udev_device_new_from_syspath(udev, syspath);
Daniel Kurtzf0e61aa2018-08-03 17:16:53 -060090 if (!dev_is_pointer_device(dev))
91 input_add(udev_device_get_devnode(dev));
Dominik Behr5239cca2016-01-21 18:22:04 -080092 udev_device_unref(dev);
93 }
94 udev_enumerate_unref(udev_enum);
95}
96
97void dev_add_fds(fd_set* read_set, fd_set* exception_set, int *maxfd)
98{
99 FD_SET(udev_fd, read_set);
100 FD_SET(udev_fd, exception_set);
101 if (udev_fd > *maxfd)
102 *maxfd = udev_fd;
103}
104
105void dev_dispatch_io(fd_set* read_set, fd_set* exception_set)
106{
107 if (FD_ISSET(udev_fd, exception_set)) {
108 /* udev died on us? */
109 LOG(ERROR, "Exception on udev fd");
110 return;
111 }
112
113 if (FD_ISSET(udev_fd, read_set)
114 && !FD_ISSET(udev_fd, exception_set)) {
115 /* we got an udev notification */
116 struct udev_device* dev =
117 udev_monitor_receive_device(udev_monitor);
118 if (dev) {
Dominik Behr01a7a582016-01-28 17:02:21 -0800119 if (!strcmp("input", udev_device_get_subsystem(dev))) {
120 if (!strcmp("add", udev_device_get_action(dev))) {
Daniel Kurtzf0e61aa2018-08-03 17:16:53 -0600121 if (!dev_is_pointer_device(dev))
122 input_add(udev_device_get_devnode(dev));
Dominik Behr01a7a582016-01-28 17:02:21 -0800123 } else if (!strcmp("remove", udev_device_get_action(dev))) {
124 input_remove(udev_device_get_devnode(dev));
125 }
126 } else if (!strcmp("drm", udev_device_get_subsystem(dev))
127 && !strcmp("drm_minor", udev_device_get_devtype(dev))
128 && !strcmp("change", udev_device_get_action(dev))) {
129 const char *hotplug = udev_device_get_property_value(dev, "HOTPLUG");
130 if (hotplug && atoi(hotplug) == 1)
131 term_monitor_hotplug();
Dominik Behr5239cca2016-01-21 18:22:04 -0800132 }
133 udev_device_unref(dev);
134 }
135 }
136}