linput

Listen to input events
git clone git://git.akobets.xyz/linput
Log | Files | Refs | README | LICENSE

commit babe0967e0381a0db6f9e4c25d63ea818673b435
parent 6c65cf9172d32623bd22d7afb10b9c7ebb0bfd6b
Author: Artem Kobets <artem@akobets.xyz>
Date:   Mon, 20 Apr 2020 13:06:52 +0300

properly handle new input device files

Diffstat:
Mlinput.c | 51+++++++++++++++++++++++++++++----------------------
1 file changed, 29 insertions(+), 22 deletions(-)

diff --git a/linput.c b/linput.c @@ -20,6 +20,7 @@ typedef struct node { int fd; + char *path; struct node *next; } fd_node; @@ -31,7 +32,7 @@ static int is_match_hotkey_mod(const struct HotkeyRule *hotkey); static int is_hotkey_active(const struct HotkeyRule *hotkey, int last_key); static void run(char **cmd); -static void add_fd(int fd); +static void add_fd(int fd, const char *path); static void remove_fd(int fd); static void generate_poll_array(); static int open_input_file(const char *path); @@ -229,7 +230,7 @@ run(char **cmd) } void -add_fd(int fd) +add_fd(int fd, const char *path) { fd_node *new; @@ -237,6 +238,9 @@ add_fd(int fd) if (new == NULL) die("malloc: %s\n", strerror(errno)); new->fd = fd; + new->path = strdup(path); + if (new->path == NULL) + die("strdup: %s\n", strerror(errno)); new->next = NULL; if (fd_head == NULL) { @@ -276,6 +280,7 @@ remove_fd(int fd) fd_head = node->next; else if (prev != NULL) prev->next = node->next; + free(node->path); free(node); } } @@ -297,10 +302,12 @@ generate_poll_array() } } - nfds = n; - pfds = realloc(pfds, sizeof(struct pollfd) * n); - if (pfds == NULL) - die("malloc: %s\n", strerror(errno)); + if (n != nfds) { + nfds = n; + pfds = realloc(pfds, sizeof(struct pollfd) * n); + if (pfds == NULL) + die("malloc: %s\n", strerror(errno)); + } pfds[0].fd = inotify_fd; pfds[0].events = POLLIN; @@ -321,7 +328,7 @@ open_input_file(const char *path) { savedErrno = errno; if (fd != -1) { - add_fd(fd); + add_fd(fd, path); poll_change = 1; } @@ -369,7 +376,7 @@ init_inotify() return; } - if (inotify_add_watch(inotify_fd, "/dev/input", IN_CREATE) == -1) { + if (inotify_add_watch(inotify_fd, "/dev/input", IN_CREATE | IN_ATTRIB) == -1) { fprintf(stderr, "inotify init failed (inotify_add_watch): %s\n", strerror(errno)); return; } @@ -433,27 +440,27 @@ handle_inotify(int fd) { struct inotify_event* event = (struct inotify_event *) &buf[processed_bytes]; if ( - event->mask & IN_CREATE && + (event->mask & (IN_CREATE | IN_ATTRIB)) && + !(event->mask & IN_ISDIR) && strncmp(event->name, "event", 5) == 0 ) { - int fd, retries, max_retries; + fd_node *current; + int already_opened; snprintf(filename, sizeof(filename), "/dev/input/%s", event->name); - retries = 0; - max_retries = 1; - while (retries <= max_retries) { - fd = open_input_file(filename); - /* If program is executed as normal user, - * device files may not have required permissions - * to be opened right away (hotplug race condition) - * If that's the case, retry before giving up. */ - if (fd == -1 && errno == EACCES) { - sleep(1); - retries++; - } else + already_opened = 0; + current = fd_head; + while (current != NULL) { + if (strcmp(current->path, filename) == 0) { + already_opened = 1; break; + } + current = current->next; } + + if (!already_opened) + open_input_file(filename); } processed_bytes += sizeof(struct inotify_event) + event->len;