hibyr1: route ADB through the usb-mode setting

rockbox-gerrit-noreply--- via rockbox-cvs <[email protected]> Sun, 12 Jul 2026 11:19:40 -0400
Newsgroups gmane.comp.systems.archos.rockbox.cvs
Message-ID <[email protected]>
commit 078a506dfd0deb18165a3ed80c7fcbdb3afb0d31
Author: Michael McAllister <[email protected]>
Date:   Mon Jul 6 22:47:01 2026 +0100

    hibyr1: route ADB through the usb-mode setting
    
    hibyr1 defines HAVE_USB_ADB so the USB mode setting offers an ADB
    entry, but hiby_set_usb_mode() never handled USB_MODE_ADB (it fell
    through to default), so selecting ADB did nothing.
    
    Wire USB_MODE_ADB up to enable_adb(). It builds the adb function on
    the gadget and hands the functionfs mount and adbd to the vendor
    respawner /sbin/adbserver.sh, rather than mounting functionfs inline
    (which the original code flagged as flaky); adbd binds the UDC itself,
    so usb_enable() leaves the UDC alone in ADB mode. disable_adb() unlinks
    the adb function and unmounts its functionfs but leaves the function in
    place to be reused, matching how adbserver.sh cycles it, so re-enabling
    adb never re-creates it.
    
    The mass-storage LUN is removable, so the host clears its backing file
    when it ejects the volume (Linux does this on unmount). Re-arm the LUN
    in usb_enable() on each connect, so the disk is exported on every
    insert and not only the first.
    
    Assisted-by: Claude Opus 4.8
    
    Change-Id: Ia8f119a1a599e6dd3c1219cb4e193c753725a06a

diff --git a/firmware/target/hosted/hiby/usb-hiby-gadget.c b/firmware/target/hosted/hiby/usb-hiby-gadget.c
index 651b25bb70..af04690248 100644
--- a/firmware/target/hosted/hiby/usb-hiby-gadget.c
+++ b/firmware/target/hosted/hiby/usb-hiby-gadget.c
@@ -65,6 +65,9 @@ void hiby_set_usb_mode(int mode) {
         usb_init_device();
     }
 
+    if (_usb_mode == mode)
+        return;
+
     switch(mode) {
     case USB_MODE_MASS_STORAGE:
         logf("Enabling Mass Storage\n");
@@ -74,6 +77,10 @@ void hiby_set_usb_mode(int mode) {
         logf("Enabling Charge\n");
         enable_charging();
         break;
+    case USB_MODE_ADB:
+        logf("Enabling ADB\n");
+        enable_adb();
+        break;
     default:
         break;
     }
@@ -90,11 +97,29 @@ int usb_detect(void)
     return power_input_status() == POWER_INPUT_USB_CHARGER ? USB_INSERTED : USB_EXTRACTED;
 }
 
+static void set_mass_storage_lun(void)
+{
+    const char *device = "/dev/mmcblk0p1";
+
+    // If partition 1 doesn't exist we'll try the main device
+    if (access(device, F_OK) != 0)
+        device = "/dev/mmcblk0";
+
+    sysfs_set_string("/sys/kernel/config/usb_gadget/adb_demo/functions/mass_storage.0/lun.0/file", device);
+}
+
 void usb_enable(bool on)
 {
     logf(">>>>>>>>>>>>>>>>> usb_enable(%d)\n", on);
     logf("usb enable %d %d\n", on, _usb_mode);
 
+    if (_usb_mode == USB_MODE_ADB)
+        return;
+
+    // Re-arm the LUN on each connect, otherwise the disk is only exported the first time.
+    if (on && _usb_mode == USB_MODE_MASS_STORAGE)
+        set_mass_storage_lun();
+
     sysfs_set_string("/sys/kernel/config/usb_gadget/adb_demo/UDC",
                      on ? "13500000.otg_new" : "\n");
 }
@@ -141,51 +166,49 @@ void enable_charging(void) {
     disable_adb();
 }
 
-#if 1
 void enable_adb(void) {
     logf(">>>>>>>>>>>>>>>>> set_adb()\n");
 
     // Disable mass storage if it was running
     disable_mass_storage();
 
-    // Remove any lingering adb daemon
-    system("killall -9 adbd");
+    // Remove any lingering adb daemon and its respawner
+    system("killall adbserver.sh adbd 2>/dev/null");
 
     system("mkdir -p /sys/kernel/config/usb_gadget/adb_demo/configs/c.1/strings/0x409");
     system("mkdir -p /sys/kernel/config/usb_gadget/adb_demo/functions/ffs.adb");
 
+    // Use the adb VID/PID so the host recognises the device
+    sysfs_set_string("/sys/kernel/config/usb_gadget/adb_demo/idVendor", "0x18d1");
+    sysfs_set_string("/sys/kernel/config/usb_gadget/adb_demo/idProduct", "0xd002");
+
     // Now we'll override configuration and MaxPower
     sysfs_set_string("/sys/kernel/config/usb_gadget/adb_demo/configs/c.1/strings/0x409/configuration", "adb");
     sysfs_set_int("/sys/kernel/config/usb_gadget/adb_demo/configs/c.1/MaxPower", 120);
 
     // And link up the adb function to the usb gadget config
-    system("ln -s /sys/kernel/config/usb_gadget/adb_demo/functions/ffs.adb /sys/kernel/config/usb_gadget/adb_demo/configs/c.1/");
+    system("ln -sf /sys/kernel/config/usb_gadget/adb_demo/functions/ffs.adb /sys/kernel/config/usb_gadget/adb_demo/configs/c.1/");
 
-    int is_mounted = !system("mountpoint -q /dev/usb-ffs/adb");
+    system("mkdir -p /dev/usb-ffs/adb");
 
-    if (!is_mounted) {
-        system("mkdir -p /dev/usb-ffs/adb");
-        /* This seems to fail, but adb will still work and then it will be mounted. Not sure what's up here... */
-        system("mount -t functionfs adb /dev/usb-ffs/adb");
-    }
-
-    // Boot adb daemon
-    system("/usr/bin/adbd &");
+    // Let the vendor respawner mount functionfs and run adbd, which binds the UDC.
+    system("/sbin/adbserver.sh 440 &");
 }
 
 
 void disable_adb(void) {
-    // Remove any lingering adb daemon
-    system("killall -9 adbd");
+    // Remove any lingering adb daemon and its respawner
+    system("killall adbserver.sh adbd 2>/dev/null");
 
-    // Remove the adb link to config
-    if (access("/sys/kernel/config/usb_gadget/adb_demo/configs/c.1/ffs.adb", F_OK) == 0) {
-        system("rm /sys/kernel/config/usb_gadget/adb_demo/configs/c.1/ffs.adb");
+    // Unbind the UDC so the gadget can be reconfigured
+    if (access("/sys/kernel/config/usb_gadget/adb_demo/UDC", F_OK) == 0) {
+        sysfs_set_string("/sys/kernel/config/usb_gadget/adb_demo/UDC", "\n");
     }
 
-    // Remove the adb function
-    if (access("/sys/kernel/config/usb_gadget/adb_demo/functions/ffs.adb", F_OK) == 0) {
-        system("rm -rf /sys/kernel/config/usb_gadget/adb_demo/functions/ffs.adb");
+    // Unlink the adb function from config (the function is left in place and
+    // reused, so re-creating it in enable_adb can't block)
+    if (access("/sys/kernel/config/usb_gadget/adb_demo/configs/c.1/ffs.adb", F_OK) == 0) {
+        system("rm /sys/kernel/config/usb_gadget/adb_demo/configs/c.1/ffs.adb");
     }
 
     // Reset the MaxPower to its default value
@@ -200,13 +223,9 @@ void disable_adb(void) {
 
     // Unmount adb
     if (!system("mountpoint -q /dev/usb-ffs/adb")) {
-        system("unmount /dev/usb-ffs/adb");
+        system("umount -l /dev/usb-ffs/adb");
     }
 }
-#else
-void enable_adb(void) {}
-void disable_adb(void) {}
-#endif
 
 void enable_mass_storage(void) {
     logf(">>>>>>>>>>>>>>>>> set_mass_storage()\n");
@@ -226,15 +245,7 @@ void enable_mass_storage(void) {
 
     system("ln -s /sys/kernel/config/usb_gadget/adb_demo/functions/mass_storage.0 /sys/kernel/config/usb_gadget/adb_demo/configs/c.1/");
 
-    char mount_device[32] = "/dev/mmcblk0p1";
-
-    // If partition 1 doesn't exist we'll try the main device
-    if (access(mount_device, F_OK) != 0) {
-        memset(mount_device, 0, sizeof(mount_device));
-        strcpy(mount_device, "/dev/mmcblk0");
-    }
-
-    sysfs_set_string("/sys/kernel/config/usb_gadget/adb_demo/functions/mass_storage.0/lun.0/file", mount_device);
+    set_mass_storage_lun();
 }
 
 void disable_mass_storage(void) {
diff --git a/firmware/target/hosted/sysfs.c b/firmware/target/hosted/sysfs.c
index 1c3fe8c396..7bacb3de54 100644
--- a/firmware/target/hosted/sysfs.c
+++ b/firmware/target/hosted/sysfs.c
@@ -178,7 +178,7 @@ bool sysfs_get_string(const char *path, char *value, int size)
 }
 
 
-bool sysfs_set_string(const char *path, char *value)
+bool sysfs_set_string(const char *path, const char *value)
 {
     FILE *f = open_write(path);
     if(f == NULL)
diff --git a/firmware/target/hosted/sysfs.h b/firmware/target/hosted/sysfs.h
index 639cc1c409..de2b8db31e 100644
--- a/firmware/target/hosted/sysfs.h
+++ b/firmware/target/hosted/sysfs.h
@@ -28,4 +28,4 @@ bool sysfs_set_int(const char *path, int value);
 bool sysfs_get_char(const char *path, char *value);
 bool sysfs_set_char(const char *path, char value);
 bool sysfs_get_string(const char *path, char *value, int size);
-bool sysfs_set_string(const char *path, char *value);
+bool sysfs_set_string(const char *path, const char *value);
-- 
rockbox-cvs mailing list
[email protected]
https://lists.haxx.se/mailman/listinfo/rockbox-cvs