hiby: ability to add/remove input device

rockbox-gerrit-noreply--- via rockbox-cvs <[email protected]> Thu, 16 Apr 2026 08:03:06 -0400
Newsgroups gmane.comp.systems.archos.rockbox.cvs
Message-ID <[email protected]>
commit a496e011734aa28b7b991c4cb39f3445fcc7e561
Author: Roman Artiukhin <[email protected]>
Date:   Sat Apr 11 18:30:34 2026 +0300

    hiby: ability to add/remove input device
    
    Required for dynamic inputs (like bluetooth).
    Files are now opened with O_NONBLOCK, and inputs are automatically removed on poll errors.
    Also added call to close all devices on power off.
    
    Change-Id: I8991bdb881fdc00135d1fd5b01ac900c0b007aeb

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 <poll.h>
 #include <errno.h>
+#include <stdio.h>
 #include <unistd.h>
 #include <sys/types.h>
 #include <linux/input.h>
@@ -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_init_device(void)
+void button_add_input_device(int i)
 {
-    const char * const input_devs[NR_POLL_DESC] = {
-        "/dev/input/event0",
-        "/dev/input/event1",
-        "/dev/input/event2",
-        "/dev/input/event3",
-    };
+    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)
+{
     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)
 {
+    num_devices = 0;
     /* close descriptors */
-    for(int i = 0; i < num_devices; i++)
+    for(int i = 0; i < NR_POLL_DESC; i++)
     {
-        close(poll_fds[i].fd);
+        button_remove_input_device(i);
     }
-    num_devices = 0;
 }
 
 #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) {
-- 
rockbox-cvs mailing list
[email protected]
https://lists.haxx.se/mailman/listinfo/rockbox-cvs