Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[usb_moded] Explicitly start/stop mtp daemon. Fixes JB#41748
The mtp functionality is started roughly as follows:

1. usb-moded completes whole gadget configuration, and then
2. signals mtp mode activation on D-Bus
3. msyncd sees the mode change and loads mtp plugin
4. mtp plugin writes endpoint configuration, and then
5. scans storage ares to enumerate files exposed via mtp, but
6. does not really respond to ptp/mtp requests until storages are ready

The problems are:

While the above sequence has worked with with android usb, it does cause
timing issues for usb enumeration and longer than expected response times
from pc side mtp initiator point of view.

Additionally when configfs is used, the gadget configuration can't even
be completed before mtp daemon gets a chance to write configuration data
to the control endpoint.

To remedy the situation the following changes are made:

1. buteo-mtp-qt5-sync-plugin package is removed from the system -> mtp
   functionality is no longer handled by msyncd process

2. mtp daemon is made to enumerate storage content before writing config
   data to control endpoint -> when usb enumeration is possible, mtp
   daemon is already ready to handle commands from initiator

3. usb-moded explicitly starts/stops mtp daemon when it is about to
   activate/deactivate mtp_mode -> usb stays configured in charging
   mode until it is ready to handle mtp

This patch handles step (3). Step (2) is in buteo-mtp-qt5 >= 0.5.0,
and (1) needs to be fixed in device specific package configuration.

Signed-off-by: Simo Piiroinen <simo.piiroinen@jollamobile.com>
  • Loading branch information
spiiroin committed Aug 24, 2018
1 parent 7896a72 commit 041d46d
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 18 deletions.
3 changes: 3 additions & 0 deletions rpm/usb-moded.spec
Expand Up @@ -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
Expand Down
18 changes: 0 additions & 18 deletions src/usb_moded-configfs.c
Expand Up @@ -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;

Expand All @@ -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 */

Expand Down
108 changes: 108 additions & 0 deletions src/usb_moded.c
Expand Up @@ -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] = {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;

Expand Down

0 comments on commit 041d46d

Please sign in to comment.