diff --git a/temp/usb-moded/0001-dyn-config-Add-option-for-running-a-command-on-mode-.patch b/temp/usb-moded/0001-dyn-config-Add-option-for-running-a-command-on-mode-.patch new file mode 100644 index 000000000..075cdf18c --- /dev/null +++ b/temp/usb-moded/0001-dyn-config-Add-option-for-running-a-command-on-mode-.patch @@ -0,0 +1,112 @@ +From 2782277f64a4d47dbdf5f5e4a78fcaa75fe711a8 Mon Sep 17 00:00:00 2001 +From: Dylan Van Assche +Date: Sat, 10 May 2025 14:37:52 +0200 +Subject: [PATCH 1/5] [dyn-config] Add option for running a command on mode + start/stop + +Allow specifying a command to execute on starting and stopping an USB mode +such as a DHCP server, MTP responder, or another daemon which is needed +for operating this USB mode. This feature complements DBus activation +and systemd service activation. + +Signed-off-by: Dylan Van Assche +--- + src/usb_moded-dyn-config.c | 11 +++++++++++ + src/usb_moded-dyn-config.h | 10 ++++++++++ + 2 files changed, 21 insertions(+) + +diff --git a/src/usb_moded-dyn-config.c b/src/usb_moded-dyn-config.c +index a6d9d7e..0623b57 100644 +--- a/src/usb_moded-dyn-config.c ++++ b/src/usb_moded-dyn-config.c +@@ -4,6 +4,7 @@ + * Copyright (c) 2011 Nokia Corporation. All rights reserved. + * Copyright (c) 2013 - 2021 Jolla Ltd. + * Copyright (c) 2020 Open Mobile Platform LLC. ++ * Copyright (c) 2025 Dylan Van Assche + * + * @author Philippe De Swert + * @author Philippe De Swert +@@ -11,6 +12,7 @@ + * @author Thomas Perl + * @author Slava Monich + * @author Simo Piiroinen ++ * @author Dylan Van Assche + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Lesser GNU General Public License +@@ -100,6 +102,9 @@ modedata_free(modedata_t *self) + #ifdef CONNMAN + g_free(self->connman_tethering); + #endif ++ g_free(self->command_up); ++ g_free(self->command_down); ++ g_free(self->ffs_daemon_mountpoint); + modedata_flush_settings(self); + free(self); + } +@@ -151,6 +156,9 @@ modedata_copy(const modedata_t *that) + self->cached_gateway = g_strdup(that->cached_gateway); + self->cached_nat_interface = g_strdup(that->cached_nat_interface); + self->cached_netmask = g_strdup(that->cached_netmask); ++ self->command_up = g_strdup(that->command_up); ++ self->command_down = g_strdup(that->command_down); ++ self->ffs_daemon_mountpoint = g_strdup(that->ffs_daemon_mountpoint); + + EXIT: + return self; +@@ -275,6 +283,9 @@ modedata_load(const gchar *filename) + #ifdef CONNMAN + self->connman_tethering = g_key_file_get_string(settingsfile, MODE_OPTIONS_ENTRY, MODE_CONNMAN_TETHERING, NULL); + #endif ++ self->command_up = g_key_file_get_string(settingsfile, MODE_OPTIONS_ENTRY, MODE_COMMAND_UP, NULL); ++ self->command_down = g_key_file_get_string(settingsfile, MODE_OPTIONS_ENTRY, MODE_COMMAND_DOWN, NULL); ++ self->ffs_daemon_mountpoint = g_key_file_get_string(settingsfile, MODE_OPTIONS_ENTRY, MODE_FFS_DAEMON_MOUNTPOINT, NULL); + + //log_debug("Dynamic mode sysfs path = %s\n", self->sysfs_path); + //log_debug("Dynamic mode sysfs value = %s\n", self->sysfs_value); +diff --git a/src/usb_moded-dyn-config.h b/src/usb_moded-dyn-config.h +index 79a143e..6e368a2 100644 +--- a/src/usb_moded-dyn-config.h ++++ b/src/usb_moded-dyn-config.h +@@ -4,6 +4,7 @@ + * Copyright (c) 2011 Nokia Corporation. All rights reserved. + * Copyright (c) 2013 - 2020 Jolla Ltd. + * Copyright (c) 2020 Open Mobile Platform LLC. ++ * Copyright (c) 2025 Dylan Van Assche + * + * @author Philippe De Swert + * @author Philippe De Swert +@@ -13,6 +14,7 @@ + * @author Slava Monich + * @author Simo Piiroinen + * @author Andrew den Exter ++ * @author Dylan Van Assche + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Lesser GNU General Public License +@@ -89,6 +91,10 @@ + # define MODE_CONNMAN_TETHERING "connman_tethering" + # endif + ++# define MODE_COMMAND_UP "command_up" ++# define MODE_COMMAND_DOWN "command_down" ++# define MODE_FFS_DAEMON_MOUNTPOINT "ffs_daemon_mountpoint" ++ + /* ========================================================================= * + * Types + * ========================================================================= */ +@@ -129,6 +135,10 @@ typedef struct modedata_t + gchar *cached_nat_interface; /**< Cached NETWORK_NAT_INTERFACE_KEY setting */ + gchar *cached_netmask; /**< Cached NETWORK_NETMASK_KEY setting */ + ++ gchar *command_up; /**< Command to execute when starting an USB mode */ ++ gchar *command_down; /**< Command to execute when stopping an USB mode */ ++ gchar *ffs_daemon_mountpoint; /**< Device mountpoint for userspace FunctionFS daemon */ ++ + } modedata_t; + + /* ========================================================================= * +-- +2.49.0 + diff --git a/temp/usb-moded/0002-worker-generalize-MTP-daemon-to-FunctionFS-daemon.patch b/temp/usb-moded/0002-worker-generalize-MTP-daemon-to-FunctionFS-daemon.patch new file mode 100644 index 000000000..c6042b9eb --- /dev/null +++ b/temp/usb-moded/0002-worker-generalize-MTP-daemon-to-FunctionFS-daemon.patch @@ -0,0 +1,496 @@ +From 651d1b5b3f5ec6419d2e25b0491afcc6f26959d5 Mon Sep 17 00:00:00 2001 +From: Dylan Van Assche +Date: Sat, 10 May 2025 15:47:28 +0200 +Subject: [PATCH 2/5] [worker] generalize MTP daemon to FunctionFS daemon + +MTP daemon handling is a hardcoded version of FunctionFS daemon +handling. Allow to specify for each dynamic FunctionFS mode which +daemon command must be executed to start/stop the FunctionFS userspace +daemon for the USB mode and where the FunctionFS device must be mounted +for the daemon. This prepares usb-moded to support more FunctionFS +userspace daemons such as supporting the Android Open Accesory mode. + +Signed-off-by: Dylan Van Assche +--- + config/dyn-modes/mtp_mode.ini | 2 +- + src/usb_moded-worker.c | 242 +++++++++++++++++++--------------- + 2 files changed, 139 insertions(+), 105 deletions(-) + +diff --git a/config/dyn-modes/mtp_mode.ini b/config/dyn-modes/mtp_mode.ini +index 10352f6..22b8a33 100644 +--- a/config/dyn-modes/mtp_mode.ini ++++ b/config/dyn-modes/mtp_mode.ini +@@ -1,4 +1,4 @@ + [mode] +-name = mtp_mode ++name = mtp_ffs_mode + module = g_ffs + appsync = 1 +diff --git a/src/usb_moded-worker.c b/src/usb_moded-worker.c +index 272698b..11662e9 100644 +--- a/src/usb_moded-worker.c ++++ b/src/usb_moded-worker.c +@@ -73,15 +73,15 @@ static const char * const devstate_name[] = { + + static bool worker_thread_p (void); + bool worker_bailing_out (void); +-static devstate_t worker_get_mtp_device_state (void); +-static void worker_unmount_mtp_device (void); +-static bool worker_mount_mtp_device (void); +-static bool worker_mode_is_mtp_mode (const char *mode); +-static bool worker_is_mtpd_running (void); +-static bool worker_mtpd_running_p (void *aptr); +-static bool worker_mtpd_stopped_p (void *aptr); +-static bool worker_stop_mtpd (void); +-static bool worker_start_mtpd (void); ++static devstate_t worker_get_ffs_device_state (void); ++static void worker_unmount_ffs_device (void); ++static bool worker_mount_ffs_device (void); ++static bool worker_mode_is_ffs_mode (const char *mode); ++static bool worker_is_ffs_daemon_running (void); ++static bool worker_ffs_daemon_running_p (void *aptr); ++static bool worker_ffs_daemon_stopped_p (void *aptr); ++static bool worker_run_command_down (void); ++static bool worker_run_command_up (void); + static bool worker_switch_to_charging (void); + const char *worker_get_kernel_module (void); + bool worker_set_kernel_module (const char *module); +@@ -169,16 +169,16 @@ worker_bailing_out(void) + } + + /* ------------------------------------------------------------------------- * +- * MTP_DEVICE ++ * FUNCTIONFS_DEVICE + * ------------------------------------------------------------------------- */ + +-/** Check if mtp device is mounted ++/** Check if FunctionFS device is mounted + * + * Returns DEVSTATE_MOUNTED / DEVSTATE_UNMOUNTED depending +- * on whether control endpoint file exists in the mtp device ++ * on whether control endpoint file exists in the FunctionFS device + * directory. + * +- * Note: If mtp device directory is for some reason not accessible by ++ * Note: If FunctionFS device directory is for some reason not accessible by + * uid=root processes and usb-moded does not have suitable DAC + * override permissions existance of the control endpoint file + * might not be determinable. In these cases DEVSTATE_UNKNOWN +@@ -190,59 +190,70 @@ worker_bailing_out(void) + * DEVSTATE_UNKNOWN + */ + static devstate_t +-worker_get_mtp_device_state(void) ++worker_get_ffs_device_state(void) + { + LOG_REGISTER_CONTEXT; + + devstate_t state = DEVSTATE_UNKNOWN; ++ const modedata_t *data = worker_get_usb_mode_data(); ++ gchar *path = g_strconcat("/dev/", data->ffs_daemon_mountpoint, "/ep0", NULL); + +- if( access("/dev/mtp/ep0", F_OK) == 0 ) ++ if( access(path, F_OK) == 0 ) + state = DEVSTATE_MOUNTED; + else if( errno == ENOENT ) + state = DEVSTATE_UNMOUNTED; + else +- log_warning("/dev/mtp/ep0: %m"); ++ log_warning("%s: %m", path); ++ ++ log_debug("FunctionFS device state = %s", devstate_name[state]); ++ ++ g_free(path); + +- log_debug("mtp device state = %s", devstate_name[state]); + return state; + } + +-/** Unmount mtp device ++/** Unmount ffs device + */ + static void +-worker_unmount_mtp_device(void) ++worker_unmount_ffs_device(void) + { + LOG_REGISTER_CONTEXT; ++ const modedata_t *data = worker_get_usb_mode_data(); ++ gchar *command = g_strconcat("/bin/umount ", "/dev/", data->ffs_daemon_mountpoint, NULL); + +- if( worker_get_mtp_device_state() != DEVSTATE_UNMOUNTED ) { +- log_debug("unmounting mtp device"); +- common_system("/bin/umount /dev/mtp"); ++ if( worker_get_ffs_device_state() != DEVSTATE_UNMOUNTED ) { ++ log_debug("unmounting FunctionFS device"); ++ common_system(command); + } ++ ++ g_free (command); + } + +-/** Mount mtp device ++/** Mount ffs device + * +- * Mount mtp device so that it is accessible by root and the ++ * Mount FunctionFS device so that it is accessible by root and the + * currently active user. + * +- * @return true if mtp device was mounted as result of call, false otherwise ++ * @return true if ffs device was mounted as result of call, false otherwise + */ + static bool +-worker_mount_mtp_device(void) ++worker_mount_ffs_device(void) + { + LOG_REGISTER_CONTEXT; + + bool mounted = false; ++ const modedata_t *data = worker_get_usb_mode_data(); ++ gchar *directory = g_strconcat("/dev/", data->ffs_daemon_mountpoint, NULL); + + /* Fail if control endpoint is already present */ +- if( worker_get_mtp_device_state() != DEVSTATE_UNMOUNTED ) { +- log_err("mtp device already mounted"); ++ if( worker_get_ffs_device_state() != DEVSTATE_UNMOUNTED ) { ++ log_err("FunctionFS device already mounted"); + goto EXIT; + } + + /* Ensure that device directory exists */ +- if( mkdir("/dev/mtp", 0755) == -1 && errno != EEXIST ) { +- log_err("failed to create /dev/mtp directory: %m"); ++ if( mkdir(directory, 0755) == -1 && errno != EEXIST ) { ++ log_err("failed to create %s directory: %m", data->ffs_daemon_mountpoint); + goto EXIT; + } + +@@ -257,143 +268,154 @@ worker_mount_mtp_device(void) + if( pw ) + gid = pw->pw_gid; + +- /* Attempt to mount mtp device using root uid and primary ++ /* Attempt to mount FunctionFS device using root uid and primary + * gid of the current user. + */ +- char cmd[256]; +- snprintf(cmd, sizeof cmd, +- "/bin/mount -o mode=0770,uid=0,gid=%u -t functionfs mtp /dev/mtp", +- (unsigned)gid); ++ char command[512]; ++ snprintf(command, sizeof command, ++ "/bin/mount -o mode=0770,uid=0,gid=%u -t functionfs %s /dev/%s", ++ (unsigned)gid, data->ffs_daemon_mountpoint, data->ffs_daemon_mountpoint); + +- log_debug("mounting mtp device"); +- if( common_system(cmd) != 0 ) ++ log_debug("mounting FunctionFS device"); ++ if( common_system(command) != 0 ) + goto EXIT; + + /* Check that control endpoint is present */ +- if( worker_get_mtp_device_state() != DEVSTATE_MOUNTED ) { +- log_err("mtp control not mounted"); ++ if( worker_get_ffs_device_state() != DEVSTATE_MOUNTED ) { ++ log_err("FunctionFS control not mounted"); + goto EXIT; + } + + mounted = true; + + EXIT: ++ g_free (directory); + return mounted; + } + + /* ------------------------------------------------------------------------- * +- * MTP_DAEMON ++ * FUNCTIONFS_DAEMON + * ------------------------------------------------------------------------- */ + +-/** Maximum time to wait for mtpd to start [ms] ++/** Maximum time to wait for FunctionFS daemon to start [ms] + * + * This needs to include time to start systemd unit +- * plus however long it might take for mtpd to scan +- * all files exposed over mtp. On a slow device with +- * lots of files it can easily take over 30 seconds, +- * especially during the 1st mtp connect after reboot. ++ * plus however long it might take for FunctionFS ++ * to start up, for example: scanning files over MTP. ++ * On a slow device with lots of files it can easily ++ * take over 30 seconds, especially during the 1st FunctionFS ++ * connect after reboot. + * + * Use two minutes as some kind of worst case estimate. + */ +-static unsigned worker_mtp_start_delay = 120 * 1000; ++static unsigned worker_ffs_daemon_start_delay = 120 * 1000; + +-/** Maximum time to wait for mtpd to stop [ms] ++/** Maximum time to wait for FunctionFS daemon to stop [ms] + * + * This is just regular service stop. Expected to + * take max couple of seconds, but use someting + * in the ballbark of systemd default i.e. 15 seconds + */ +-static unsigned worker_mtp_stop_delay = 15 * 1000; ++static unsigned worker_ffs_daemon_stop_delay = 15 * 1000; + +-/** Flag for: We have started mtp daemon ++/** Flag for: We have started FunctionFS daemon + * + * If we have issued systemd unit start, we should also +- * issue systemd unit stop even if probing for mtpd +- * presense gives negative result. ++ * issue systemd unit stop even if probing for FunctionFS ++ * daemon presense gives negative result. + */ +-static bool worker_mtp_service_started = false; ++static bool worker_ffs_daemon_service_started = false; + +-static bool worker_mode_is_mtp_mode(const char *mode) ++static bool worker_mode_is_ffs_mode(const char *mode) + { + LOG_REGISTER_CONTEXT; + +- return mode && !strcmp(mode, "mtp_mode"); ++ return mode && strstr(mode, "_ffs_mode") != NULL; + } + +-static bool worker_is_mtpd_running(void) ++static bool worker_is_ffs_daemon_running(void) + { + LOG_REGISTER_CONTEXT; + +- /* ep0 becomes available when /dev/mtp is mounted. ++ /* ep0 becomes available when ffs_daemon_mountpoint is mounted. + * +- * ep1, ep2, ep3 exist while mtp daemon is running, ++ * ep1, ep2, ep3 exist while FunctionFS daemon is running, + * has ep0 opened and has written config data to it. + */ + static const char * const lut[] = { +- "/dev/mtp/ep0", +- "/dev/mtp/ep1", +- "/dev/mtp/ep2", +- "/dev/mtp/ep3", ++ "ep0", ++ "ep1", ++ "ep2", ++ "ep3", + 0 + }; + + bool ack = true; ++ const modedata_t *data = worker_get_usb_mode_data(); + + for( size_t i = 0; lut[i]; ++i ) { +- if( access(lut[i], F_OK) == -1 ) { ++ gchar *path = g_strconcat("/dev/", data->ffs_daemon_mountpoint, "/", lut[i], NULL); ++ if( access(path, F_OK) == -1 ) { ++ log_debug("%s", path); + ack = false; ++ g_free (path); + break; +- } ++ } else ++ g_free (path); + } + + return ack; + } + + static bool +-worker_mtpd_running_p(void *aptr) ++worker_ffs_daemon_running_p(void *aptr) + { + LOG_REGISTER_CONTEXT; + + (void)aptr; +- return worker_is_mtpd_running(); ++ return worker_is_ffs_daemon_running(); + } + + static bool +-worker_mtpd_stopped_p(void *aptr) ++worker_ffs_daemon_stopped_p(void *aptr) + { + LOG_REGISTER_CONTEXT; + + (void)aptr; +- return !worker_is_mtpd_running(); ++ return !worker_is_ffs_daemon_running(); + } + + static bool +-worker_stop_mtpd(void) ++worker_run_command_down(void) + { + LOG_REGISTER_CONTEXT; + + bool ack = false; ++ const modedata_t *data = worker_get_usb_mode_data(); + +- if( !worker_mtp_service_started && worker_mtpd_stopped_p(0) ) { +- log_debug("mtp daemon is not running"); ++ if( !worker_ffs_daemon_service_started && worker_ffs_daemon_stopped_p(0) ) { ++ log_debug("FunctionFS daemon is not running"); + goto SUCCESS; + } + +- int rc = common_system("systemctl-user stop buteo-mtp.service"); ++ if( data->command_down == NULL) ++ goto SUCCESS; ++ ++ int rc = common_system(data->command_down); + if( rc != 0 ) { +- log_warning("failed to stop mtp daemon; exit code = %d", rc); ++ log_warning("failed to run bring-down command; exit code = %d", rc); + goto FAILURE; + } + +- /* Have succesfully stopped mtp service */ +- worker_mtp_service_started = false; ++ /* Have succesfully stopped FunctionFS daemon service */ ++ worker_ffs_daemon_service_started = false; + +- if( common_wait(worker_mtp_stop_delay, worker_mtpd_stopped_p, 0) != WAIT_READY ) { +- log_warning("failed to stop mtp daemon; giving up"); ++ if( common_wait(worker_ffs_daemon_stop_delay, worker_ffs_daemon_stopped_p, 0) != WAIT_READY ) { ++ log_warning("failed to stop FunctionFS daemon; giving up"); + goto FAILURE; + } + +- log_debug("mtp daemon has stopped"); ++ log_debug("Bring-down command executed"); + + SUCCESS: + ack = true; +@@ -403,32 +425,37 @@ FAILURE: + } + + static bool +-worker_start_mtpd(void) ++worker_run_command_up(void) + { + LOG_REGISTER_CONTEXT; + + bool ack = false; ++ const modedata_t *data = worker_get_usb_mode_data(); + +- if( worker_mtpd_running_p(0) ) { +- log_debug("mtp daemon is running"); ++ if( data->ffs_daemon_mountpoint != NULL && worker_ffs_daemon_running_p(0) ) { ++ log_debug("FunctionFS daemon is already running"); + goto SUCCESS; + } + +- /* Have attempted to start mtp service */ +- worker_mtp_service_started = true; ++ if (data->command_up == NULL) ++ goto SUCCESS; + +- int rc = common_system("systemctl-user start buteo-mtp.service"); ++ /* Have attempted to start FunctionFS daemon service */ ++ worker_ffs_daemon_service_started = true; ++ ++ int rc = common_system(data->command_up); + if( rc != 0 ) { +- log_warning("failed to start mtp daemon; exit code = %d", rc); ++ log_warning("failed to run bring-up command; exit code = %d", rc); + goto FAILURE; + } + +- if( common_wait(worker_mtp_start_delay, worker_mtpd_running_p, 0) != WAIT_READY ) { +- log_warning("failed to start mtp daemon; giving up"); ++ /* FunctionFS requires the daemon to fully run before enabling UDC */ ++ if( data->ffs_daemon_mountpoint != NULL && (common_wait(worker_ffs_daemon_start_delay, worker_ffs_daemon_running_p, 0) != WAIT_READY) ) { ++ log_warning("failed to start FunctionFS daemon; giving up"); + goto FAILURE; + } + +- log_debug("mtp daemon has started"); ++ log_debug("Bring-up command executed"); + + SUCCESS: + ack = true; +@@ -722,16 +749,15 @@ worker_switch_to_mode(const char *mode) + + log_debug("Cleaning up previous mode"); + +- /* Either mtp daemon is not needed, or it must be *started* in +- * correct phase of gadget configuration when entering mtp mode. ++ /* Either FunctionFS daemon is not needed, or it must be *started* in ++ * correct phase of gadget configuration when entering FunctionFS mode. + * +- * Similarly, unmount mtp device to make sure sure it gets mounted ++ * Similarly, unmount FunctionFS device to make sure sure it gets mounted + * with appropriate uid/gid values when it is actually needed. + */ +- worker_stop_mtpd(); +- worker_unmount_mtp_device(); +- + if( worker_get_usb_mode_data() ) { ++ worker_run_command_down(); ++ worker_unmount_ffs_device(); + modesetting_leave_dynamic_mode(); + worker_set_usb_mode_data(NULL); + } +@@ -767,14 +793,17 @@ worker_switch_to_mode(const char *mode) + worker_set_usb_mode_data(data); + + /* When dealing with configfs, we can't enable UDC without +- * already having mtpd running */ +- if( worker_mode_is_mtp_mode(mode) && configfs_in_use() ) { +- if( !worker_mount_mtp_device() ) +- goto FAILED; +- if( !worker_start_mtpd() ) ++ * already having FunctionFS daemon running */ ++ if( worker_mode_is_ffs_mode(mode) && configfs_in_use() ) { ++ if( !worker_mount_ffs_device() ) + goto FAILED; + } + ++ if (configfs_in_use()) { ++ if( !worker_run_command_up() ) ++ goto FAILED; ++ } ++ + if( !worker_set_kernel_module(data->mode_module) ) + goto FAILED; + +@@ -782,12 +811,15 @@ worker_switch_to_mode(const char *mode) + goto FAILED; + + /* When dealing with android usb, it must be enabled before +- * we can start mtpd. Assumption is that the same applies +- * when using kernel modules. */ +- if( worker_mode_is_mtp_mode(mode) && !configfs_in_use() ) { +- if( !worker_mount_mtp_device() ) ++ * we can start FunctionFS daemon. Assumption is that the ++ * same applies when using kernel modules. */ ++ if( worker_mode_is_ffs_mode(mode) && !configfs_in_use() ) { ++ if( !worker_mount_ffs_device() ) + goto FAILED; +- if( !worker_start_mtpd() ) ++ } ++ ++ if( !configfs_in_use() ) { ++ if( !worker_run_command_down() ) + goto FAILED; + } + +@@ -802,7 +834,9 @@ FAILED: + /* Undo any changes we might have might have already done */ + if( worker_get_usb_mode_data() ) { + log_debug("Cleaning up failed mode switch"); +- worker_stop_mtpd(); ++ worker_run_command_down(); ++ if( worker_mode_is_ffs_mode(mode)) ++ worker_unmount_ffs_device(); + modesetting_leave_dynamic_mode(); + worker_set_usb_mode_data(NULL); + } +-- +2.49.0 + diff --git a/temp/usb-moded/0003-worker-only-check-daemon-running-in-FunctionFS-mode.patch b/temp/usb-moded/0003-worker-only-check-daemon-running-in-FunctionFS-mode.patch new file mode 100644 index 000000000..d7bc60b33 --- /dev/null +++ b/temp/usb-moded/0003-worker-only-check-daemon-running-in-FunctionFS-mode.patch @@ -0,0 +1,52 @@ +From 43b7967f133dfd49777734949ff2b19c25beb84a Mon Sep 17 00:00:00 2001 +From: Dylan Van Assche +Date: Sat, 10 May 2025 20:29:41 +0200 +Subject: [PATCH 3/5] [worker] only check daemon running in FunctionFS mode + +Daemons for operating USB gadgets in FunctionFS must be fully ready +before enabling the gadget by the UDC. Daemons for other gadgets +such as USB Ethernet (NCM) do not require such functionality, thus +bypass this check to avoid timeouts waiting for the FunctionFS interface +to become fully ready as these gadgets do not have such interface. + +Signed-off-by: Dylan Van Assche +--- + src/usb_moded-worker.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/src/usb_moded-worker.c b/src/usb_moded-worker.c +index 11662e9..f70bdc8 100644 +--- a/src/usb_moded-worker.c ++++ b/src/usb_moded-worker.c +@@ -196,6 +196,10 @@ worker_get_ffs_device_state(void) + + devstate_t state = DEVSTATE_UNKNOWN; + const modedata_t *data = worker_get_usb_mode_data(); ++ ++ if( data->ffs_daemon_mountpoint == NULL ) ++ return DEVSTATE_UNMOUNTED; ++ + gchar *path = g_strconcat("/dev/", data->ffs_daemon_mountpoint, "/ep0", NULL); + + if( access(path, F_OK) == 0 ) +@@ -393,7 +397,7 @@ worker_run_command_down(void) + bool ack = false; + const modedata_t *data = worker_get_usb_mode_data(); + +- if( !worker_ffs_daemon_service_started && worker_ffs_daemon_stopped_p(0) ) { ++ if( data->ffs_daemon_mountpoint != NULL && !worker_ffs_daemon_service_started && worker_ffs_daemon_stopped_p(0) ) { + log_debug("FunctionFS daemon is not running"); + goto SUCCESS; + } +@@ -410,7 +414,7 @@ worker_run_command_down(void) + /* Have succesfully stopped FunctionFS daemon service */ + worker_ffs_daemon_service_started = false; + +- if( common_wait(worker_ffs_daemon_stop_delay, worker_ffs_daemon_stopped_p, 0) != WAIT_READY ) { ++ if( data->ffs_daemon_mountpoint != NULL && (common_wait(worker_ffs_daemon_stop_delay, worker_ffs_daemon_stopped_p, 0) != WAIT_READY) ) { + log_warning("failed to stop FunctionFS daemon; giving up"); + goto FAILURE; + } +-- +2.49.0 + diff --git a/temp/usb-moded/0004-configfs-Register-NCM-gadget-for-USB-networking.patch b/temp/usb-moded/0004-configfs-Register-NCM-gadget-for-USB-networking.patch new file mode 100644 index 000000000..700f01a3c --- /dev/null +++ b/temp/usb-moded/0004-configfs-Register-NCM-gadget-for-USB-networking.patch @@ -0,0 +1,73 @@ +From 045a0ead25e17b86ef97379534403da7d64ac1a1 Mon Sep 17 00:00:00 2001 +From: Dylan Van Assche +Date: Sat, 17 May 2025 13:50:52 +0200 +Subject: [PATCH 4/5] [configfs] Register NCM gadget for USB networking + +USB networking is also possible via the NCM gadget instead of +RNDIS which is considered insecure [1], but remains supported +in usb-moded. + +[1] https://lore.kernel.org/lkml/20221123124620.1387499-1-gregkh@linuxfoundation.org/t/ +--- + src/usb_moded-configfs.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/src/usb_moded-configfs.c b/src/usb_moded-configfs.c +index abfdd54..bcd1755 100644 +--- a/src/usb_moded-configfs.c ++++ b/src/usb_moded-configfs.c +@@ -54,6 +54,7 @@ + + #define DEFAULT_FUNCTION_MASS_STORAGE "mass_storage.usb0" + #define DEFAULT_FUNCTION_RNDIS "rndis_bam.rndis" ++#define DEFAULT_FUNCTION_NCM "ncm.usb0" + #define DEFAULT_FUNCTION_MTP "ffs.mtp" + + #define DEFAULT_RNDIS_CTRL_WCEIS "wceis" +@@ -126,6 +127,7 @@ static gchar *GADGET_CTRL_SERIAL = 0; + + static gchar *FUNCTION_MASS_STORAGE = 0; + static gchar *FUNCTION_RNDIS = 0; ++static gchar *FUNCTION_NCM = 0; + static gchar *FUNCTION_MTP = 0; + + static gchar *RNDIS_CTRL_WCEIS = 0; +@@ -236,6 +238,9 @@ static void configfs_read_configuration(void) + configfs_get_conf("function_rndis", + DEFAULT_FUNCTION_RNDIS); + ++ FUNCTION_NCM = ++ configfs_get_conf("function_ncm", ++ DEFAULT_FUNCTION_NCM); + FUNCTION_MTP = + configfs_get_conf("function_mtp", + DEFAULT_FUNCTION_MTP); +@@ -806,6 +811,7 @@ configfs_init(void) + configfs_register_function(FUNCTION_MTP); + + /* Prep: developer_mode */ ++ configfs_register_function(FUNCTION_NCM); + configfs_register_function(FUNCTION_RNDIS); + if( (text = mac_read_mac()) ) { + configfs_write_file(RNDIS_CTRL_ETHADDR, text); +@@ -848,6 +854,8 @@ configfs_quit(void) + FUNCTION_MASS_STORAGE = 0; + g_free(FUNCTION_RNDIS), + FUNCTION_RNDIS = 0; ++ g_free(FUNCTION_NCM), ++ FUNCTION_NCM = 0; + g_free(FUNCTION_MTP), + FUNCTION_MTP = 0; + +@@ -955,6 +963,8 @@ configfs_map_function(const char *func) + func = FUNCTION_MASS_STORAGE; + else if( !strcmp(func, "rndis") ) + func = FUNCTION_RNDIS; ++ else if( !strcmp(func, "ncm") ) ++ func = FUNCTION_NCM; + else if( !strcmp(func, "mtp") ) + func = FUNCTION_MTP; + else if( !strcmp(func, "ffs") ) // existing config files ... +-- +2.49.0 + diff --git a/temp/usb-moded/0005-usb-moded-Allow-disabling-rescue-mode.patch b/temp/usb-moded/0005-usb-moded-Allow-disabling-rescue-mode.patch new file mode 100644 index 000000000..7da17f9de --- /dev/null +++ b/temp/usb-moded/0005-usb-moded-Allow-disabling-rescue-mode.patch @@ -0,0 +1,56 @@ +From 1615aa38a63ead9dde88442f5f1b9ab1b615f76d Mon Sep 17 00:00:00 2001 +From: Dylan Van Assche +Date: Sun, 18 May 2025 10:54:02 +0200 +Subject: [PATCH 5/5] [usb-moded] Allow disabling rescue mode + +Some distros have their own rescue mode builtin and launch usb-moded +after initialization is complete. Therefore, no checks need to be +performed anymore. Furthermore, this allows non-systemd init systems +to launch usb-moded as well after initialization is complete. + +Signed-off-by: Dylan Van Assche +--- + configure.ac | 8 ++++++++ + src/usb_moded.c | 6 ++++++ + 2 files changed, 14 insertions(+) + +diff --git a/configure.ac b/configure.ac +index e8fdc69..2c56ae6 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -99,6 +99,14 @@ AC_ARG_ENABLE([ofono], AS_HELP_STRING([--enable-ofono], [Enable ofono DBUS inter + esac],[ofono=false]) + AM_CONDITIONAL([OFONO], [test x$ofono = xtrue]) + ++AC_ARG_ENABLE([rescue], AS_HELP_STRING([--enable-rescue], [Enable rescue mode @<:@default=true@:>@]), ++ [case "${enableval}" in ++ yes) rescue=true ; CFLAGS="-DRESCUE $CFLAGS" ;; ++ no) rescue=false ;; ++ *) AC_MSG_ERROR([bad value ${enableval} for --enable-rescue]) ;; ++ esac],[rescue=true]) ++AM_CONDITIONAL([RESCUE], [test x$rescue = xtrue]) ++ + PKG_CHECK_MODULES([DBUS], dbus-1 >= 1.8) + PKG_CHECK_MODULES([GLIB], glib-2.0 >= 2.24.0) + PKG_CHECK_MODULES([USB_MODED], [ +diff --git a/src/usb_moded.c b/src/usb_moded.c +index f7443d6..76625d9 100644 +--- a/src/usb_moded.c ++++ b/src/usb_moded.c +@@ -686,7 +686,13 @@ void usbmoded_probe_init_done(void) + { + LOG_REGISTER_CONTEXT; + ++#ifdef RESCUE + usbmoded_set_init_done(access(usbmoded_init_done_flagfile, F_OK) == 0); ++ return; ++#endif ++ ++ /* If rescue mode is not enabled, bypass init done check */ ++ usbmoded_set_init_done(true); + } + + /* ------------------------------------------------------------------------- * +-- +2.49.0 + diff --git a/temp/usb-moded/APKBUILD b/temp/usb-moded/APKBUILD new file mode 100644 index 000000000..afe29d38f --- /dev/null +++ b/temp/usb-moded/APKBUILD @@ -0,0 +1,101 @@ +# Forked from Alpine to adjust for mainline +pkgname=usb-moded +_pkgver=0.86.0 +pkgver="999$_pkgver" +_pkgver=$_pkgver+mer69 +pkgrel=0 +_commit_dbus_glib="d42176ae4763e5288ef37ea314fe58387faf2005" +pkgdesc="A daemon activating a certain USB profile based on the usb cable connection status" +url="https://github.com/sailfishos/usb-moded" +arch="all" +license="GPL-2.0-only" +depends_dev=" + eudev-dev + elogind-dev + glib-dev + gobject-introspection-dev + kmod-dev + libdsme-dev + sailfish-access-control + ssu-sysinfo-dev + " +makedepends="$depends_dev + autoconf + automake + dbus-dev + libtool + " +subpackages=" + $pkgname-dev + $pkgname-openrc + $pkgname-systemd + " +source="$pkgname-$pkgver.tar.gz::https://github.com/sailfishos/usb-moded/archive/refs/tags/mer/${_pkgver/\//-}.tar.gz + https://github.com/sailfishos-mirror/dbus-glib/archive/$_commit_dbus_glib/dbus-glib-$_commit_dbus_glib.tar.gz + usb-moded.confd + usb-moded.initd + umtprd.conf + basename.patch + 0001-dyn-config-Add-option-for-running-a-command-on-mode-.patch + 0002-worker-generalize-MTP-daemon-to-FunctionFS-daemon.patch + 0003-worker-only-check-daemon-running-in-FunctionFS-mode.patch + 0004-configfs-Register-NCM-gadget-for-USB-networking.patch + 0005-usb-moded-Allow-disabling-rescue-mode.patch + " +options="!check" # No test suite available +builddir="$srcdir/$pkgname-mer-${_pkgver/+/-}" + +prepare() { + default_prepare + + # Fix invalid pkgconf version + sed -i 's/+mer/./' configure.ac + + rmdir dbus-gmain + mv "$srcdir/dbus-glib-$_commit_dbus_glib" dbus-gmain +} + +build() { + ./autogen.sh + + # --enable-systemd is required to build, otherwise it can't find sd-login.h + ./configure \ + --prefix=/usr \ + --enable-connman \ + --enable-ofono \ + --enable-app-sync \ + --enable-systemd + make +} + +package() { + DESTDIR="$pkgdir" make install + + install -Dm755 "$srcdir"/usb-moded.initd "$pkgdir"/etc/init.d/usb-moded + install -Dm644 "$srcdir"/usb-moded.confd "$pkgdir"/etc/conf.d/usb-moded + + # The pkg-config & systemd-service file aren't installed automatically for some reason + install -Dm644 usb_moded.pc -t "$pkgdir"/usr/lib/pkgconfig/ + install -Dm644 systemd/usb-moded.service -t "$pkgdir"/usr/lib/systemd/system/ + + install -dm 755 "$pkgdir"/usr/include/$pkgname + cp src/*.h src/*.xml "$pkgdir"/usr/include/$pkgname + + # Install DBus policies + install -Dm644 debian/usb_moded.conf \ + "$pkgdir"/usr/share/dbus-1/system.d/usb_moded.conf +} + +sha512sums=" +55c8892c9f9c5a9cc6b526e8c1f9c55cd5f61922dbc52b1c85abb2850a00d1146c0d8e4f7a631bd0d7927e40908dae2541870bf1cc591b9d527ce29306051829 usb-moded-9990.86.0.tar.gz +665cd6395ee0ea14086ba30188c62a72697b3f63484681e18fc7f54109c9aca162f2e33aa2fa4d45287c6c0b590e81ca310c143dac0232cd5887692cdaf51256 dbus-glib-d42176ae4763e5288ef37ea314fe58387faf2005.tar.gz +b841282b96110ec59a7aa539db0737327b09549d55c78dc4b2c3b28b4a6ad1facf015b3175cb6d3a38f13e47aa6314ef3dc1514a4e60dd653a97409ec54ba706 usb-moded.confd +28c2d1e594d0be7d480885c1d3d38a2e33d310363a51093f19daf69221d173df5a03d04f1b7dfba3bcdb00697715123313441216a016efc8d11151daaa0ae4ea usb-moded.initd +912f0700c87883b55f631cfc3d76e172ff1c21aa57b0c18d1e7b9671ecd6254b1e7565816e3967c68caab196076bf7c8b848375c89185aa4466f4ca7f65231be umtprd.conf +8e15fcdcb5199c7c9deffc417035e2260aa7d4a437056f2ab9141c33220618da59324b87cbcebe9857d0269b170f98e2ea703c69b6543cbae237555cc6e297a4 basename.patch +23980ebf109c01ad9be366ac35cd101608ed14a826c20e73a33fbeed856feef435ba29b34033a054e282075bcac18108f2d6e0ec8e81f41d97c3639fdd5fe23f 0001-dyn-config-Add-option-for-running-a-command-on-mode-.patch +258a4004ebb85c01e7bb94f7b24a39d834b8699e6a035e04d3613800c8c2fdcc35290378866890ae1399919d6faddad8659c378c3022a5510375a4806b8911c5 0002-worker-generalize-MTP-daemon-to-FunctionFS-daemon.patch +fa62cce99e91437bbb9cd88cc193c66b7cf4f988708fad8647e91b031f9d0a844f11dd469f364b214b9ca65358f696d7e7b546d7887d0f99f2b5dee4328c20d3 0003-worker-only-check-daemon-running-in-FunctionFS-mode.patch +3a905d3038309e8a54e77ee601dc98f12c339fdd9c7ba5989d2edce5baf98fdb6d6cf092c3168da577b137a4b356edfb72bf2df7ef148fa778655934dcebe72c 0004-configfs-Register-NCM-gadget-for-USB-networking.patch +595d3541ee2aadbc3857cc81ef4c2e393351c4a9ba26c7e20b2b098c2cec32d8c6643d4f491e3c6e16be6d509486a8313f5b5627b354ee12e11f89cc62af6598 0005-usb-moded-Allow-disabling-rescue-mode.patch +" diff --git a/temp/usb-moded/basename.patch b/temp/usb-moded/basename.patch new file mode 100644 index 000000000..c5c76b272 --- /dev/null +++ b/temp/usb-moded/basename.patch @@ -0,0 +1,12 @@ +diff -upr usb-moded-mer-0.86.0-mer66.orig/src/usb_moded.c usb-moded-mer-0.86.0-mer66/src/usb_moded.c +--- usb-moded-mer-0.86.0-mer66.orig/src/usb_moded.c 2024-08-28 20:24:01.495130829 +0200 ++++ usb-moded-mer-0.86.0-mer66/src/usb_moded.c 2024-08-28 20:25:30.838474437 +0200 +@@ -175,6 +175,8 @@ static pthread_mutex_t usbmoded_mutex = + }\ + }while(0) + ++#define basename(name) (strrchr((name),'/') ? strrchr((name),'/')+1 : (name)) ++ + /* ========================================================================= * + * Functions + * ========================================================================= */ diff --git a/temp/usb-moded/configfs.ini b/temp/usb-moded/configfs.ini new file mode 100644 index 000000000..91c3b67a9 --- /dev/null +++ b/temp/usb-moded/configfs.ini @@ -0,0 +1,2 @@ +[configfs] +gadget_conf_directory=configs/c.1 diff --git a/temp/usb-moded/umtprd.conf b/temp/usb-moded/umtprd.conf new file mode 100644 index 000000000..58088ac3a --- /dev/null +++ b/temp/usb-moded/umtprd.conf @@ -0,0 +1,16 @@ +# FunctionFS configuration +usb_functionfs_mode 0x1 +usb_dev_path "/dev/mtp/ep0" +usb_epin_path "/dev/mtp/ep1" +usb_epout_path "/dev/mtp/ep2" +usb_epint_path "/dev/mtp/ep3" +usb_max_packet_size 0x200 + +# Prevent disconnection on cable status, managed by usb-moded +loop_on_disconnect 1 + +# Storage to expose over MTP +storage "/home" "Home" "rw" + +manufacturer "postmarketOS" +product "Device" diff --git a/temp/usb-moded/usb-moded.confd b/temp/usb-moded/usb-moded.confd new file mode 100644 index 000000000..9bd312c0c --- /dev/null +++ b/temp/usb-moded/usb-moded.confd @@ -0,0 +1 @@ +supervisor=supervise-daemon diff --git a/temp/usb-moded/usb-moded.initd b/temp/usb-moded/usb-moded.initd new file mode 100644 index 000000000..327025437 --- /dev/null +++ b/temp/usb-moded/usb-moded.initd @@ -0,0 +1,10 @@ +#!/sbin/openrc-run + +name=usb-moded +description="usb-moded USB gadget controller" +command="/usr/sbin/usb_moded" +command_background=yes + +depend() { + need dbus +}