blob: 6ff23e1bece54bd8a93eb5485d0398b200159bf6 [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
56void dev_add_existing_input_devs(void)
57{
58 struct udev_enumerate* udev_enum;
59 struct udev_list_entry* devices, *deventry;
60 udev_enum = udev_enumerate_new(udev);
61 udev_enumerate_add_match_subsystem(udev_enum, "input");
62 udev_enumerate_scan_devices(udev_enum);
63 devices = udev_enumerate_get_list_entry(udev_enum);
64 udev_list_entry_foreach(deventry, devices) {
65 const char* syspath;
66 struct udev_device* dev;
67 syspath = udev_list_entry_get_name(deventry);
68 dev = udev_device_new_from_syspath(udev, syspath);
69 input_add(udev_device_get_devnode(dev));
70 udev_device_unref(dev);
71 }
72 udev_enumerate_unref(udev_enum);
73}
74
75void dev_add_fds(fd_set* read_set, fd_set* exception_set, int *maxfd)
76{
77 FD_SET(udev_fd, read_set);
78 FD_SET(udev_fd, exception_set);
79 if (udev_fd > *maxfd)
80 *maxfd = udev_fd;
81}
82
83void dev_dispatch_io(fd_set* read_set, fd_set* exception_set)
84{
85 if (FD_ISSET(udev_fd, exception_set)) {
86 /* udev died on us? */
87 LOG(ERROR, "Exception on udev fd");
88 return;
89 }
90
91 if (FD_ISSET(udev_fd, read_set)
92 && !FD_ISSET(udev_fd, exception_set)) {
93 /* we got an udev notification */
94 struct udev_device* dev =
95 udev_monitor_receive_device(udev_monitor);
96 if (dev) {
Dominik Behr01a7a582016-01-28 17:02:21 -080097 if (!strcmp("input", udev_device_get_subsystem(dev))) {
98 if (!strcmp("add", udev_device_get_action(dev))) {
99 input_add(udev_device_get_devnode(dev));
100 } else if (!strcmp("remove", udev_device_get_action(dev))) {
101 input_remove(udev_device_get_devnode(dev));
102 }
103 } else if (!strcmp("drm", udev_device_get_subsystem(dev))
104 && !strcmp("drm_minor", udev_device_get_devtype(dev))
105 && !strcmp("change", udev_device_get_action(dev))) {
106 const char *hotplug = udev_device_get_property_value(dev, "HOTPLUG");
107 if (hotplug && atoi(hotplug) == 1)
108 term_monitor_hotplug();
Dominik Behr5239cca2016-01-21 18:22:04 -0800109 }
110 udev_device_unref(dev);
111 }
112 }
113}