Commit 041d46de authored by spiiroin's avatar spiiroin

[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: spiiroin's avatarSimo Piiroinen <simo.piiroinen@jollamobile.com>
parent 7896a728
......@@ -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
......
......@@ -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 */
......
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment