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
This commit is contained in:
Michael McAllister 2026-07-06 22:47:01 +01:00 • committed by Solomon Peachy
parent 37943178f0
commit 078a506dfd
3 changed files with 48 additions and 37 deletions

View file

@ -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) {

View file

@ -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)

View file

@ -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);