diff --git a/src/usb_moded-android.c b/src/usb_moded-android.c index b568c22..e69b866 100644 --- a/src/usb_moded-android.c +++ b/src/usb_moded-android.c @@ -23,6 +23,7 @@ #include #include +#include "usb_moded.h" #include "usb_moded-android.h" #include "usb_moded-log.h" #include "usb_moded-modesetting.h" @@ -84,11 +85,17 @@ void android_init_values(void) { gchar *text; + /* If the directory is not there, no point emitting warnings + * about every file that is not going to be there either. */ if( access("/sys/class/android_usb/android0", F_OK) != 0 ) { goto EXIT; } + /* Disable */ + write_to_file("/sys/class/android_usb/android0/enable", "0"); + + /* Configure */ if( (text = get_android_serial()) ) { write_to_file("/sys/class/android_usb/android0/iSerial", text); @@ -128,8 +135,22 @@ void android_init_values(void) /* For rndis to be discovered correctly in M$ Windows (vista and later) */ write_to_file("/sys/class/android_usb/f_rndis/wceis", "1"); - /* Make sure android_usb does not stay disabled in case usb moded - * has crashed / been killed in inconvenient time. */ + + /* Some devices can have enumeration issues due to incomplete + * configuration on the 1st connect after bootup. Briefly setting + * up for example mass_storage function can be utilized as a + * workaround in such cases. */ + if(!init_done_p()) { + const char *function = get_android_bootup_function(); + if(function) { + write_to_file("/sys/class/android_usb/android0/functions", function); + write_to_file("/sys/class/android_usb/android0/enable", "1"); + write_to_file("/sys/class/android_usb/android0/enable", "0"); + } + } + + /* Clear functions and enable */ + write_to_file("/sys/class/android_usb/android0/functions", "none"); write_to_file("/sys/class/android_usb/android0/enable", "1"); EXIT: diff --git a/src/usb_moded.c b/src/usb_moded.c index 80b2a79..455123b 100644 --- a/src/usb_moded.c +++ b/src/usb_moded.c @@ -92,6 +92,30 @@ static gboolean android_ignore_next_udev_disconnect_event = FALSE; static gboolean systemd_notify = FALSE; #endif +/** Optional android usb function to setup during bootup */ +static gchar *android_bootup_function = 0; + + +/** Get android usb function to setup during bootup + * + * @returns function name, or NULL if no function was requested + */ +const char *get_android_bootup_function(void) +{ + return android_bootup_function; +} + +/** Set android usb function to setup during bootup + * + * @param function usb function name, or NULL + */ +void set_android_bootup_function(const char *function) +{ + char *value = function ? g_strdup(function) : 0; + g_free(android_bootup_function); + android_bootup_function = value; +} + /** Default allowed cable detection delay * * To comply with USB standards, the delay should be @@ -879,6 +903,10 @@ static void usage(void) " output version information and exit\n" " -m, --max-cable-delay=\n" " maximum delay before accepting cable connection\n" + " -b, --android-bootup-function=\n" + " Setup given function during bootup. Might be required\n" + " on some devices to make enumeration work on the 1st\n" + " cable connect.\n" "\n"); } @@ -1332,6 +1360,7 @@ int main(int argc, char* argv[]) { "systemd", no_argument, 0, 'n' }, { "version", no_argument, 0, 'v' }, { "max-cable-delay", required_argument, 0, 'm' }, + { "android-bootup-function", required_argument, 0, 'b' }, { 0, 0, 0, 0 } }; @@ -1343,7 +1372,7 @@ int main(int argc, char* argv[]) * - - - - - - - - - - - - - - - - - - - */ /* Parse the command-line options */ - while ((opt = getopt_long(argc, argv, "aifsTlDdhrnvm:", options, &opt_idx)) != -1) + while ((opt = getopt_long(argc, argv, "aifsTlDdhrnvm:b:", options, &opt_idx)) != -1) { switch (opt) { @@ -1397,6 +1426,10 @@ int main(int argc, char* argv[]) set_cable_connection_delay(strtol(optarg, 0, 0)); break; + case 'b': + set_android_bootup_function(optarg); + break; + default: usage(); exit(0); @@ -1602,6 +1635,8 @@ int main(int argc, char* argv[]) # endif #endif + set_android_bootup_function(0); + /* Must be done just before exit to make sure no more wakelocks * are taken and left behind on exit path */ allow_suspend(); diff --git a/src/usb_moded.h b/src/usb_moded.h index b425f53..9e71e8b 100644 --- a/src/usb_moded.h +++ b/src/usb_moded.h @@ -108,4 +108,7 @@ bool init_done_p(void); void set_init_done(bool reached); void probe_init_done(void); +const char *get_android_bootup_function(void); +void set_android_bootup_function(const char *function); + #endif /* USB_MODED_H */