From 4b740d5c8cff9591c666476cc0d3aef0cb637e62 Mon Sep 17 00:00:00 2001 From: papush! Date: Fri, 4 Jul 2025 23:58:36 +0200 Subject: support hotplugging when udev rules are used to change device perms --- src/main.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/src/main.c b/src/main.c index 00c6eb2..63b6c3d 100644 --- a/src/main.c +++ b/src/main.c @@ -20,13 +20,39 @@ struct pollfd pfds[NPFDS] = {0}; +int open_devices[NPFDS] = {0}; int test_mode = 0; uint64_t keys[KEYS_SIZE] = {0}; -void add_device(const char name[static 1]) +int parse_device_name(const char name[static 1], unsigned long *device_id) { if (strncmp(name, "event", strlen("event")) != 0) + { + return -1; + } + char *endptr; + *device_id = strtoul(name + strlen("event"), &endptr, 10); + if (*endptr != '\0') + { + return -1; + } + return 0; +} + +void add_device(const char name[static 1]) +{ + unsigned long device_id; + if (parse_device_name(name, &device_id) == -1) + { + return; + } + if (device_id >= NPFDS) + { + fprintf(stderr, "exceeded device limit\n"); + return; + } + if (open_devices[device_id]) { return; } @@ -38,6 +64,7 @@ void add_device(const char name[static 1]) fprintf(stderr, "failed to open device: %s: %s\n", path, strerror(errno)); return; } + open_devices[device_id] = 1; for (size_t i = 1; i < NPFDS; i++) { if (pfds[i].fd < 0) @@ -48,6 +75,20 @@ void add_device(const char name[static 1]) } } +void del_device(const char name[static 1]) +{ + unsigned long device_id; + if (parse_device_name(name, &device_id) == -1) + { + return; + } + if (device_id >= NPFDS) + { + return; + } + open_devices[device_id] = 0; +} + void process_inotify_watch(int inotify_fd) { char buf[sizeof (struct inotify_event) + NAME_MAX + 1] = {0}; @@ -67,7 +108,14 @@ void process_inotify_watch(int inotify_fd) fputs("inotify error (filesystem unmounted?)", stderr); exit(EXIT_FAILURE); } - add_device(event->name); + else if (event->mask & IN_DELETE) + { + del_device(event->name); + } + else + { + add_device(event->name); + } } } @@ -165,7 +213,8 @@ int run(const char *bindings_file_path) fprintf(stderr, "inotify_init1 failed: %s\n", strerror(errno)); return EXIT_FAILURE; } - int watch_fd = inotify_add_watch(inotify_fd, "/dev/input/", IN_CREATE); + int watch_fd = inotify_add_watch(inotify_fd, "/dev/input/", + IN_CREATE | IN_ATTRIB | IN_DELETE); if (watch_fd < 0) { fprintf(stderr, "inotify_add_watch failed: %s\n", strerror(errno)); -- cgit v1.2.3-70-g09d2