diff --git a/firmware/target/hosted/button-devinput.c b/firmware/target/hosted/button-devinput.c index a9129f3ea6..1c5e2abea2 100644 --- a/firmware/target/hosted/button-devinput.c +++ b/firmware/target/hosted/button-devinput.c @@ -21,6 +21,7 @@ ****************************************************************************/ #include #include +#include #include #include #include @@ -49,42 +50,60 @@ * Compute to angular velocity (degrees per second) */ -#define NR_POLL_DESC 4 +#define NR_POLL_DESC 5 static int num_devices = 0; static struct pollfd poll_fds[NR_POLL_DESC]; +void button_add_input_device(int i) +{ + int fd = poll_fds[i].fd; + if (fd >= 0) + close(fd); + + char path[32]; + snprintf(path, sizeof(path), "/dev/input/event%d", i); + fd = open(path, O_RDONLY | O_CLOEXEC | O_NONBLOCK); + poll_fds[i].fd = fd >= 0 ? fd : -1; + if(fd >= 0) + { + poll_fds[i].events = POLLIN; + poll_fds[i].revents = 0; + if (num_devices <= i) + num_devices = i + 1; + } +} + void button_init_device(void) { - const char * const input_devs[NR_POLL_DESC] = { - "/dev/input/event0", - "/dev/input/event1", - "/dev/input/event2", - "/dev/input/event3", - }; - for(int i = 0; i < NR_POLL_DESC; i++) { - int fd = open(input_devs[i], O_RDONLY | O_CLOEXEC); - - if(fd >= 0) - { - poll_fds[num_devices].fd = fd; - poll_fds[num_devices].events = POLLIN; - poll_fds[num_devices].revents = 0; - num_devices++; - } + poll_fds[i].fd = -1; + button_add_input_device(i); } } +void button_remove_input_device(int i) +{ + int fd = poll_fds[i].fd; + if (fd < 0) + return; + + if (i == num_devices - 1) + num_devices = i; + + close(fd); + poll_fds[i].fd = -1; +} + void button_close_device(void) { - /* close descriptors */ - for(int i = 0; i < num_devices; i++) - { - close(poll_fds[i].fd); - } num_devices = 0; + /* close descriptors */ + for(int i = 0; i < NR_POLL_DESC; i++) + { + button_remove_input_device(i); + } } #ifdef BUTTON_DELAY_RELEASE @@ -261,6 +280,10 @@ int button_read_device(BDATA) } } } + /* device was removed/disconnected — close it to stop poll returning POLLHUP forever */ + else if (poll_fds[i].revents & (POLLERR | POLLHUP)) { + button_remove_input_device(i); + } } } diff --git a/firmware/target/hosted/button-devinput.h b/firmware/target/hosted/button-devinput.h new file mode 100644 index 0000000000..20c76cab4b --- /dev/null +++ b/firmware/target/hosted/button-devinput.h @@ -0,0 +1,28 @@ +/*************************************************************************** + * __________ __ ___ + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2026 by Roman Artiukhin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + ****************************************************************************/ + + +#ifndef __BUTTON_DEVINPUT_H__ +#define __BUTTON_DEVINPUT_H__ + +void button_close_device(void); +void button_add_input_device(int i); +void button_remove_input_device(int i); + +#endif diff --git a/firmware/target/hosted/system-hosted.c b/firmware/target/hosted/system-hosted.c index bb20842d79..65b035c640 100644 --- a/firmware/target/hosted/system-hosted.c +++ b/firmware/target/hosted/system-hosted.c @@ -29,6 +29,7 @@ #include "font.h" #include "power.h" #include "button.h" +#include "button-devinput.h" #include "backlight-target.h" #include "lcd.h" #include "filesystem-hosted.h" @@ -92,6 +93,7 @@ static void sig_handler(int sig, siginfo_t *siginfo, void *context) void power_off(void) { backlight_hw_off(); + button_close_device(); sync(); system("/sbin/poweroff"); while (1) {