blob: ffba67ec8b85d663c145c87d4bd0d407dc0b5ee5 [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
7
8#include <errno.h>
9#include <libudev.h>
10
11#include "dev.h"
12#include "input.h"
13#include "util.h"
14
15static struct udev* udev = NULL;
16static struct udev_monitor* udev_monitor = NULL;
17static int udev_fd = -1;
18
19int dev_init(void)
20{
21 udev = udev_new();
22 if (!udev)
23 return -ENOENT;
24
25 udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
26 if (!udev_monitor) {
27 udev_unref(udev);
28 udev = NULL;
29 return -ENOENT;
30 }
31 udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "input",
32 NULL);
33 udev_monitor_enable_receiving(udev_monitor);
34 udev_fd = udev_monitor_get_fd(udev_monitor);
35
36 dev_add_existing_input_devs();
37
38 return 0;
39}
40
41void dev_close(void)
42{
43 if (!udev_monitor) {
44 return;
45 }
46 udev_monitor_unref(udev_monitor);
47 udev_monitor = NULL;
48 udev_unref(udev);
49 udev = NULL;
50 udev_fd = -1;
51}
52
53void dev_add_existing_input_devs(void)
54{
55 struct udev_enumerate* udev_enum;
56 struct udev_list_entry* devices, *deventry;
57 udev_enum = udev_enumerate_new(udev);
58 udev_enumerate_add_match_subsystem(udev_enum, "input");
59 udev_enumerate_scan_devices(udev_enum);
60 devices = udev_enumerate_get_list_entry(udev_enum);
61 udev_list_entry_foreach(deventry, devices) {
62 const char* syspath;
63 struct udev_device* dev;
64 syspath = udev_list_entry_get_name(deventry);
65 dev = udev_device_new_from_syspath(udev, syspath);
66 input_add(udev_device_get_devnode(dev));
67 udev_device_unref(dev);
68 }
69 udev_enumerate_unref(udev_enum);
70}
71
72void dev_add_fds(fd_set* read_set, fd_set* exception_set, int *maxfd)
73{
74 FD_SET(udev_fd, read_set);
75 FD_SET(udev_fd, exception_set);
76 if (udev_fd > *maxfd)
77 *maxfd = udev_fd;
78}
79
80void dev_dispatch_io(fd_set* read_set, fd_set* exception_set)
81{
82 if (FD_ISSET(udev_fd, exception_set)) {
83 /* udev died on us? */
84 LOG(ERROR, "Exception on udev fd");
85 return;
86 }
87
88 if (FD_ISSET(udev_fd, read_set)
89 && !FD_ISSET(udev_fd, exception_set)) {
90 /* we got an udev notification */
91 struct udev_device* dev =
92 udev_monitor_receive_device(udev_monitor);
93 if (dev) {
94 if (!strcmp("add", udev_device_get_action(dev))) {
95 input_add(udev_device_get_devnode(dev));
96 } else if (!strcmp("remove",
97 udev_device_get_action(dev))) {
98 input_remove(udev_device_get_devnode(dev));
99 }
100 udev_device_unref(dev);
101 }
102 }
103}