blob: 0bd5ac392f423fdfaf7107d6c5032ed7eb8cea94 [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
Dominik Behr20cc8e52018-11-02 16:53:07 -070056static bool dev_is_keyboard_device(struct udev_device* dev)
Daniel Kurtzf0e61aa2018-08-03 17:16:53 -060057{
Dominik Behr20cc8e52018-11-02 16:53:07 -070058 const char *keyboard = udev_device_get_property_value(dev, "ID_INPUT_KEYBOARD");
Daniel Kurtzf0e61aa2018-08-03 17:16:53 -060059
Dominik Behr20cc8e52018-11-02 16:53:07 -070060 if (keyboard && !strcmp(keyboard, "1"))
61 return true;
Daniel Kurtzf0e61aa2018-08-03 17:16:53 -060062
63 return false;
64}
65
Dominik Behr5239cca2016-01-21 18:22:04 -080066void dev_add_existing_input_devs(void)
67{
68 struct udev_enumerate* udev_enum;
69 struct udev_list_entry* devices, *deventry;
70 udev_enum = udev_enumerate_new(udev);
71 udev_enumerate_add_match_subsystem(udev_enum, "input");
72 udev_enumerate_scan_devices(udev_enum);
73 devices = udev_enumerate_get_list_entry(udev_enum);
74 udev_list_entry_foreach(deventry, devices) {
75 const char* syspath;
76 struct udev_device* dev;
77 syspath = udev_list_entry_get_name(deventry);
78 dev = udev_device_new_from_syspath(udev, syspath);
Dominik Behr20cc8e52018-11-02 16:53:07 -070079 if (dev_is_keyboard_device(dev))
Daniel Kurtzf0e61aa2018-08-03 17:16:53 -060080 input_add(udev_device_get_devnode(dev));
Dominik Behr5239cca2016-01-21 18:22:04 -080081 udev_device_unref(dev);
82 }
83 udev_enumerate_unref(udev_enum);
84}
85
86void 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}