gboolean usb_cleanup_timeout(gpointer data) { /* signal usb disconnected */ usb_moded_send_signal(USB_DISCONNECTED); usb_moded_mode_cleanup(get_usb_module()); usb_moded_module_cleanup(get_usb_module()); set_usb_mode(MODE_UNDEFINED); return FALSE; }
static int set_mass_storage_mode(struct mode_list_elem *data) { gchar *command; char command2[256], *real_path = NULL, *mountpath; const char *mount; gchar **mounts; int ret = 0, i = 0, mountpoints = 0, fua = 0, try = 0; /* send unmount signal so applications can release their grasp on the fs, do this here so they have time to act */ usb_moded_send_signal(USB_PRE_UNMOUNT); fua = find_sync(); mount = find_mounts(); if(mount) { mounts = g_strsplit(mount, ",", 0); /* check amount of mountpoints */ for(i=0 ; mounts[i] != NULL; i++) { mountpoints++; } if(strcmp(data->mode_module, MODULE_NONE)) { /* check if the file storage module has been loaded with sufficient luns in the parameter, if not, unload and reload or load it. Since mountpoints start at 0 the amount of them is one more than their id */ sprintf(command2, "/sys/devices/platform/musb_hdrc/gadget/gadget-lun%d/file", (mountpoints - 1) ); if(access(command2, R_OK) == -1) { log_debug("%s does not exist, unloading and reloading mass_storage\n", command2); usb_moded_unload_module(MODULE_MASS_STORAGE); sprintf(command2, "modprobe %s luns=%d \n", MODULE_MASS_STORAGE, mountpoints); log_debug("usb-load command = %s \n", command2); ret = system(command2); if(ret) return(ret); } } /* umount filesystems */ for(i=0 ; mounts[i] != NULL; i++) { /* check if filesystem is mounted or not, if ret = 1 it is already unmounted */ real_path = realpath(mounts[i], NULL); if(real_path) mountpath = real_path; else mountpath = mounts[i]; umount: command = g_strconcat("mount | grep ", mountpath, NULL); ret = system(command); g_free(command); if(!ret) { /* no check for / needed as that will fail to umount anyway */ command = g_strconcat("umount ", mountpath, NULL); log_debug("unmount command = %s\n", command); ret = system(command); g_free(command); if(ret != 0) { if(try != 3) { try++; sleep(1); log_err("Umount failed. Retrying\n"); report_mass_storage_blocker(mount, 1); goto umount; } else { log_err("Unmounting %s failed\n", mount); report_mass_storage_blocker(mount, 2); usb_moded_send_error_signal(UMOUNT_ERROR); return(ret); } } } else /* already unmounted. Set return value to 0 since there is no error */ ret = 0; } /* activate mounts after sleeping 1s to be sure enumeration happened and autoplay will work in windows*/ usleep(1800); for(i=0 ; mounts[i] != NULL; i++) { if(strcmp(data->mode_module, MODULE_NONE)) { sprintf(command2, "echo %i > /sys/devices/platform/musb_hdrc/gadget/gadget-lun%d/nofua", fua, i); log_debug("usb lun = %s active\n", command2); system(command2); sprintf(command2, "/sys/devices/platform/musb_hdrc/gadget/gadget-lun%d/file", i); log_debug("usb lun = %s active\n", command2); write_to_file(command2, mounts[i]); } else { write_to_file("/sys/class/android_usb/android0/enable", "0"); write_to_file("/sys/class/android_usb/android0/functions", "mass_storage"); //write_to_file("/sys/class/android_usb/f_mass_storage/lun/nofua", fua); write_to_file("/sys/class/android_usb/f_mass_storage/lun/file", mount); write_to_file("/sys/class/android_usb/android0/enable", "1"); } } g_strfreev(mounts); g_free((gpointer *)mount); if(real_path) free(real_path); }
/** clean up for modules when usb gets disconnected * * @param module The name of the module to unload * @return 0 on success, non-zero on failure * */ int usb_moded_module_cleanup(const char *module) { int retry = 0, failure; if(!strcmp(module, MODULE_NONE)) goto END; /* wait a bit for all components listening on dbus to clean up their act sleep(2); */ /* check if things were not reconnected in that timespan if(get_usb_connection_state()) return(0); */ failure = usb_moded_unload_module(module); /* if we have MODULE_MASS_STORAGE it might be MODULE_FILE_STORAGE might be loaded. So check and unload that one if unloading fails first time */ if(failure && !strcmp(MODULE_MASS_STORAGE, module)) failure = usb_moded_unload_module(MODULE_FILE_STORAGE); /* if it still failed it might be the mode has not been cleaned-up correctly, so we clean up the mode to be sure */ if(failure) { usb_moded_mode_cleanup(usb_moded_find_module()); } while(failure) { /* module did not get unloaded. We will wait a bit and try again */ sleep(1); /* send the REALLY disconnect message */ usb_moded_send_signal(USB_REALLY_DISCONNECT); failure = usb_moded_unload_module(module); log_debug("unloading failure = %d\n", failure); if(!failure) break; if(!usb_moded_find_module()) goto END; retry++; if(retry == 2) break; } if(!strcmp(module, MODULE_NETWORK)) { if(retry >= 2) { /* we exited the loop due to max retry's. Module is not unloaded yet lets go for more extreme measures lsof, then various options of kill */ log_info("Oh noes the platform is on fire!\n"); kill: /* DIRTY DESPERATE WORKAROUND */ /*system("for i in `lsof -t /dev/ttyGS*`; do cat /proc/$i/cmdline | sed 's/|//g' | sed "s/\x00/ /g" | awk '{ print $1 }' | xargs kill; done"); system("for i in `ps ax | grep phonet-at | grep -v grep | awk '{ print $1 }'`; do kill -9 $i ; done");*/ /* kill anything that still claims the usb tty's */ system("for i in `lsof -t /dev/ttyGS*`; do kill -s SIGTERM $i ; done"); system("for i in `lsof -t /dev/gc*`; do kill -s SIGTERM $i ; done"); system("for i in `lsof -t /dev/mtp*`; do kill -s SIGTERM $i ; done"); system("kill -s SIGTERM $(lsof -t /dev/usbacm"); // SP: three passes and for loops in sh? // SP: system("kill -s SIGTERM $(lsof -t /dev/ttyGS* /dev/gc* /dev/mtp*") ? // SP: or popen + kill loop? /* try to unload again and give up if it did not work yet */ failure = usb_moded_unload_module(module); if(failure && retry < 10) { retry++; // SP: NOTE: we have a root process in busyloop sending kill signals to // user processes? should we give them a chance to react? goto kill; // SP: IMHO backwards goto is bad - a loop perhaps? } if(failure && retry == 10) { system("for i in `lsof -t /dev/ttyGS*`; do kill -9 $i ; done"); system("for i in `lsof -t /dev/gc*`; do kill -9 $i ; done"); system("for i in `lsof -t /dev/mtp*`; do kill -9 $i ; done"); /* try again since there seem to be hard to kill processes there */ system("killall -9 obexd"); system("killall -9 msycnd"); failure = usb_moded_unload_module(module); } } } if(!failure) log_info("Module %s unloaded successfully\n", module); else { log_err("Module %s did not unload! Failing and going to undefined.\n", module); return(1); } END: return(0); }