blob: f8e71a96a50933b0f8eac37dd5a08f9b9759d856 [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
Julius Werneraa279292019-07-18 19:33:16 -070020static bool dev_is_keyboard_device(struct udev_device* dev)
21{
22 const char *keyboard = udev_device_get_property_value(dev, "ID_INPUT_KEYBOARD");
23
24 if (keyboard && !strcmp(keyboard, "1"))
25 return true;
26
27 return false;
28}
29
30static void dev_add_existing_input_devs(void)
31{
32 struct udev_enumerate* udev_enum;
33 struct udev_list_entry* devices, *deventry;
34 udev_enum = udev_enumerate_new(udev);
35 udev_enumerate_add_match_subsystem(udev_enum, "input");
36 udev_enumerate_scan_devices(udev_enum);
37 devices = udev_enumerate_get_list_entry(udev_enum);
38 udev_list_entry_foreach(deventry, devices) {
39 const char* syspath;
40 struct udev_device* dev;
41 syspath = udev_list_entry_get_name(deventry);
42 dev = udev_device_new_from_syspath(udev, syspath);
43 if (dev_is_keyboard_device(dev))
44 input_add(udev_device_get_devnode(dev));
45 udev_device_unref(dev);
46 }
47 udev_enumerate_unref(udev_enum);
48}
49
Dominik Behr5239cca2016-01-21 18:22:04 -080050int dev_init(void)
51{
52 udev = udev_new();
53 if (!udev)
54 return -ENOENT;
55
56 udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
57 if (!udev_monitor) {
58 udev_unref(udev);
59 udev = NULL;
60 return -ENOENT;
61 }
62 udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "input",
63 NULL);
Dominik Behr01a7a582016-01-28 17:02:21 -080064 udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "drm",
65 "drm_minor");
Dominik Behr5239cca2016-01-21 18:22:04 -080066 udev_monitor_enable_receiving(udev_monitor);
67 udev_fd = udev_monitor_get_fd(udev_monitor);
68
69 dev_add_existing_input_devs();
70
71 return 0;
72}
73
74void dev_close(void)
75{
76 if (!udev_monitor) {
77 return;
78 }
79 udev_monitor_unref(udev_monitor);
80 udev_monitor = NULL;
81 udev_unref(udev);
82 udev = NULL;
83 udev_fd = -1;
84}
85
Dominik Behr5239cca2016-01-21 18:22:04 -080086void dev_add_fds(fd_set* read_set, fd_set* exception_set, int *maxfd)
87{
88 FD_SET(udev_fd, read_set);
89 FD_SET(udev_fd, exception_set);
90 if (udev_fd > *maxfd)
91 *maxfd = udev_fd;
92}
93
94void dev_dispatch_io(fd_set* read_set, fd_set* exception_set)
95{
96 if (FD_ISSET(udev_fd, exception_set)) {
97 /* udev died on us? */
98 LOG(ERROR, "Exception on udev fd");
99 return;
100 }
101
102 if (FD_ISSET(udev_fd, read_set)
103 && !FD_ISSET(udev_fd, exception_set)) {
104 /* we got an udev notification */
105 struct udev_device* dev =
106 udev_monitor_receive_device(udev_monitor);
107 if (dev) {
Dominik Behr01a7a582016-01-28 17:02:21 -0800108 if (!strcmp("input", udev_device_get_subsystem(dev))) {
109 if (!strcmp("add", udev_device_get_action(dev))) {
Dominik Behr20cc8e52018-11-02 16:53:07 -0700110 if (dev_is_keyboard_device(dev))
Daniel Kurtzf0e61aa2018-08-03 17:16:53 -0600111 input_add(udev_device_get_devnode(dev));
Dominik Behr01a7a582016-01-28 17:02:21 -0800112 } else if (!strcmp("remove", udev_device_get_action(dev))) {
113 input_remove(udev_device_get_devnode(dev));
114 }
115 } else if (!strcmp("drm", udev_device_get_subsystem(dev))
116 && !strcmp("drm_minor", udev_device_get_devtype(dev))
117 && !strcmp("change", udev_device_get_action(dev))) {
118 const char *hotplug = udev_device_get_property_value(dev, "HOTPLUG");
119 if (hotplug && atoi(hotplug) == 1)
120 term_monitor_hotplug();
Dominik Behr5239cca2016-01-21 18:22:04 -0800121 }
122 udev_device_unref(dev);
123 }
124 }
125}