diff --git a/rpm/usb-moded.spec b/rpm/usb-moded.spec index ff7dbbc..799e307 100644 --- a/rpm/usb-moded.spec +++ b/rpm/usb-moded.spec @@ -24,6 +24,9 @@ Requires: busybox-symlinks-dhcp Requires(post): systemd Requires(postun): systemd Conflicts: dsme < 0.79.0 +Conflicts: buteo-mtp-qt5-sync-plugin +Conflicts: buteo-mtp-qt5 < 0.5.0 +Recommends: buteo-mtp-qt5 %description Usb_moded is a daemon to control the USB states. For this diff --git a/src/usb_moded-configfs.c b/src/usb_moded-configfs.c index 6de953a..a7931d2 100644 --- a/src/usb_moded-configfs.c +++ b/src/usb_moded-configfs.c @@ -635,14 +635,6 @@ configfs_set_function(const char *func) */ func = configfs_map_function(func); - /* HACK: Stop mtp daemon when enabling any other function - * after bootup is finished (assumption being it - * can't be started before init done and we do not - * want to spam bootup journal with warnings. - */ - if( strcmp(func, FUNCTION_MTP) && usbmoded_init_done_p() ) - usbmoded_system("systemctl-user stop buteo-mtp.service"); - if( !configfs_set_udc(false) ) goto EXIT; @@ -652,16 +644,6 @@ configfs_set_function(const char *func) if( !configfs_enable_function(func) ) goto EXIT; - /* HACK: Start mtp daemon when enabling mtp function. - * Then wait "a bit" since udc can't be enabled - * before mtpd has written suitable configuration - * to control endpoint. - */ - if( !strcmp(func, FUNCTION_MTP) ) { - usbmoded_system("systemctl-user start buteo-mtp.service"); - usbmoded_msleep(1500); - } - /* Leave disabled, so that caller can adjust attributes * etc before enabling */ diff --git a/src/usb_moded.c b/src/usb_moded.c index 12b44d0..ad91c3a 100644 --- a/src/usb_moded.c +++ b/src/usb_moded.c @@ -369,6 +369,108 @@ static const modemapping_t modemapping[] = * Functions * ========================================================================= */ +static bool usbmoded_mode_is_mtp_mode(const char *mode) +{ + return mode && !strcmp(mode, "mtp_mode"); +} + +static bool usbmoded_is_mtpd_running(void) +{ + /* ep0 becomes available when /dev/mtp is mounted. + * + * ep1, ep2, ep3 exist while mtp 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", + 0 + }; + + bool ack = true; + + for( size_t i = 0; lut[i]; ++i ) { + if( access(lut[i], F_OK) == -1 ) { + ack = false; + break; + } + } + + return ack; +} + +static bool +usbmoded_stop_mtpd(void) +{ + bool ack = !usbmoded_is_mtpd_running(); + + if( ack ) { + log_debug("mtp daemon is not running"); + goto EXIT; + } + + int rc = usbmoded_system("systemctl-user stop buteo-mtp.service"); + if( rc != 0 ) { + log_warning("failed to stop mtp daemon; exit code = %d", rc); + goto EXIT; + } + + for( int attempts = 3; ; ) { + if( (ack = !usbmoded_is_mtpd_running()) ) { + log_debug("mtp daemon has stopped"); + break; + } + + if( --attempts <= 0) { + log_warning("failed to stop mtp daemon; giving up"); + break; + } + + log_debug("waiting for mtp daemon to stop"); + usbmoded_msleep(2000); + } +EXIT: + + return ack; +} + +static bool +usbmoded_start_mtpd(void) +{ + bool ack = usbmoded_is_mtpd_running(); + + if( ack ) { + log_debug("mtp daemon is not running"); + goto EXIT; + } + + int rc = usbmoded_system("systemctl-user start buteo-mtp.service"); + if( rc != 0 ) { + log_warning("failed to start mtp daemon; exit code = %d", rc); + goto EXIT; + } + + for( int attempts = 15; ; ) { + if( (ack = usbmoded_is_mtpd_running()) ) { + log_debug("mtp daemon has started"); + break; + } + + if( --attempts <= 0) { + log_warning("failed to start mtp daemon; giving up"); + break; + } + + log_debug("waiting for mtp daemon to start"); + usbmoded_msleep(2000); + } +EXIT: + + return ack; +} + const char *cable_state_repr(cable_state_t state) { static const char * const lut[CABLE_STATE_NUMOF] = { @@ -471,6 +573,9 @@ static void usbmoded_switch_to_mode(const char *mode) log_debug("Cleaning up previous mode"); + if( !usbmoded_mode_is_mtp_mode(mode) ) + usbmoded_stop_mtpd(); + if( usbmoded_get_usb_mode_data() ) { modesetting_leave_dynamic_mode(); usbmoded_set_usb_mode_data(NULL); @@ -507,6 +612,9 @@ static void usbmoded_switch_to_mode(const char *mode) * as they will use the usbmoded_get_usb_mode_data function */ usbmoded_set_usb_mode_data(data); + if( usbmoded_mode_is_mtp_mode(mode) ) + usbmoded_start_mtpd(); + if( !usbmoded_set_usb_module(data->mode_module) ) break;