Commit 64350689 authored by spiiroin's avatar spiiroin

[usb_moded] Refactor entering/leaving usb mode. JB#41748

Split mode switching to three layers: Tracking cable connection state,
choosing target mode, and performing required actions to activate
the chosen mode.

Try to minimize places where layer borders are crossed - which should
work also as an enabler for moving blocking actions to separate thread
later on.

Arrange logic in such manner that usb gadget is always configured as
being able to serve some function - fallback being the dummy mass_storage
function used for charging.

Deprecate command line options that serve no useful purpose after the
changes.
Signed-off-by: spiiroin's avatarSimo Piiroinen <simo.piiroinen@jollamobile.com>
parent 18efbfcc
......@@ -62,7 +62,7 @@ static gboolean appsync_enumerate_usb_cb (gpointer data);
static void appsync_start_enumerate_usb_timer (void);
static void appsync_cancel_enumerate_usb_timer(void);
static void appsync_enumerate_usb (void);
static void appsync_stop_apps (int post);
void appsync_stop_apps (int post);
int appsync_stop (gboolean force);
/* ========================================================================= *
......@@ -456,7 +456,7 @@ static void appsync_enumerate_usb(void)
#endif /* APP_SYNC_DBUS */
}
static void appsync_stop_apps(int post)
void appsync_stop_apps(int post)
{
GList *iter = 0;
......
......@@ -80,5 +80,6 @@ int appsync_activate_sync (const char *mode);
int appsync_activate_sync_post(const char *mode);
int appsync_mark_active (const gchar *name, int post);
int appsync_stop (gboolean force);
void appsync_stop_apps (int post);
#endif /* USB_MODED_APPSYNC_H_ */
......@@ -591,7 +591,6 @@ set_config_result_t config_set_mode_whitelist(const char *whitelist)
else if (strcmp(current_mode, MODE_CHARGING_FALLBACK) && strcmp(current_mode, MODE_ASK) && usbmoded_valid_mode(current_mode)) {
/* Invalid mode that is not MODE_ASK or MODE_CHARGING_FALLBACK
* -> switch to MODE_CHARGING_FALLBACK */
modesetting_cleanup(usbmoded_get_usb_module());
usbmoded_set_usb_mode(MODE_CHARGING_FALLBACK);
}
......
......@@ -283,7 +283,6 @@ static DBusHandlerResult umdbus_msg_handler(DBusConnection *const connection, DB
/* do not change mode if the mode requested is the one already set */
if(strcmp(use, usbmoded_get_usb_mode()) != 0)
{
modesetting_cleanup(usbmoded_get_usb_module());
usbmoded_set_usb_mode(use);
}
if((reply = dbus_message_new_method_return(msg)))
......
This diff is collapsed.
......@@ -31,6 +31,8 @@
# include "usb_moded-dyn-config.h"
# include <stdbool.h>
/* ========================================================================= *
* Prototypes
* ========================================================================= */
......@@ -39,8 +41,8 @@
void modesetting_verify_values (void);
int modesetting_write_to_file_real(const char *file, int line, const char *func, const char *path, const char *text);
int modesetting_set_dynamic_mode (void);
int modesetting_cleanup (const char *module);
bool modesetting_set_dynamic_mode (void);
void modesetting_unset_dynamic_mode(void);
void modesetting_init (void);
void modesetting_quit (void);
......
......@@ -56,19 +56,22 @@ bool modules_in_use (void);
void modules_quit (void);
int modules_load_module (const char *module);
int modules_unload_module (const char *module);
static int modules_module_is_loaded (const char *module);
const char *modules_get_loaded_module (void);
int modules_cleanup_module (const char *module);
static int modules_prepare_for_module_switch(int force);
void modules_check_module_state (const char *module_name);
/* ========================================================================= *
* Data
* ========================================================================= */
/** Availability of kernel module based gadget configuration functionality
*
* -1 = not checked yet
* 0 = not available
* 1 = chosen as means of gadget configuration for usb-moded
*/
static int modules_probed = -1;
/* kmod context - initialized at start in usbmoded_init by ctx_init()
* and cleaned up by ctx_cleanup() functions */
static struct kmod_ctx *ctx = 0;
static struct kmod_ctx *modules_ctx = 0;
/* ========================================================================= *
* Functions
......@@ -81,7 +84,7 @@ static bool modules_have_module(const char *module)
bool ack = false;
struct kmod_list *list = 0;
if( kmod_module_new_from_lookup(ctx, module, &list) < 0 )
if( kmod_module_new_from_lookup(modules_ctx, module, &list) < 0 )
goto EXIT;
if( list == 0 )
......@@ -98,8 +101,6 @@ EXIT:
}
static int modules_probed = -1;
bool modules_in_use(void)
{
if( modules_probed < 0 )
......@@ -140,12 +141,12 @@ bool modules_init(void)
{
bool ack = false;
if( !ctx ) {
if( !(ctx = kmod_new(NULL, NULL)) )
if( !modules_ctx ) {
if( !(modules_ctx = kmod_new(NULL, NULL)) )
goto EXIT;
}
if( kmod_load_resources(ctx) < 0 )
if( kmod_load_resources(modules_ctx) < 0 )
goto EXIT;
if( !modules_probe() )
......@@ -159,8 +160,8 @@ EXIT:
/* kmod module cleanup */
void modules_quit(void)
{
if( ctx )
kmod_unref(ctx), ctx = 0;
if( modules_ctx )
kmod_unref(modules_ctx), modules_ctx = 0;
}
/** load module
......@@ -206,14 +207,14 @@ int modules_load_module(const char *module)
g_strfreev(strings);
}
ret = kmod_module_new_from_name(ctx, load, &mod);
ret = kmod_module_new_from_name(modules_ctx, load, &mod);
/* since kmod_module_new_from_name does not check if the module
* exists we test it's path in case we deal with the mass-storage one */
if(!strcmp(module, MODULE_MASS_STORAGE) &&
(kmod_module_get_path(mod) == NULL))
{
log_debug("Fallback on older g_file_storage\n");
ret = kmod_module_new_from_name(ctx, MODULE_FILE_STORAGE, &mod);
ret = kmod_module_new_from_name(modules_ctx, MODULE_FILE_STORAGE, &mod);
}
if(!charging_args)
......@@ -253,182 +254,9 @@ int modules_unload_module(const char *module)
return -1;
}
kmod_module_new_from_name(ctx, module, &mod);
kmod_module_new_from_name(modules_ctx, module, &mod);
ret = kmod_module_remove_module(mod, KMOD_REMOVE_NOWAIT);
kmod_module_unref(mod);
return(ret);
}
/** Check which state a module is in
*
* @return 1 if loaded, 0 when not loaded
*/
static int modules_module_is_loaded(const char *module)
{
int ret = 0;
struct kmod_module *mod;
kmod_module_new_from_name(ctx, module, &mod);
ret = kmod_module_get_initstate(mod);
kmod_module_unref(mod);
if( ret == KMOD_MODULE_LIVE)
return 1;
return 0;
}
/** find which module is loaded
*
* @return The name of the loaded module, or NULL if no modules are loaded.
*/
const char * modules_get_loaded_module(void)
{
if( !modules_in_use() ) {
log_warning("get loaded module - without module support");
return 0;
}
if(modules_module_is_loaded("g_ether"))
return(MODULE_DEVELOPER);
if(modules_module_is_loaded("g_ncm"))
return("g_ncm");
if(modules_module_is_loaded("g_ffs"))
return(MODULE_MTP);
if(modules_module_is_loaded("g_mass_storage"))
return(MODULE_MASS_STORAGE);
if(modules_module_is_loaded("g_file_storage"))
return(MODULE_FILE_STORAGE);
if(modules_module_is_loaded(usbmoded_get_usb_module()))
return(usbmoded_get_usb_module());
/* no module loaded */
return(0);
}
/** 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 modules_cleanup_module(const char *module)
{
int retry = 0, failure;
if(!strcmp(module, MODULE_NONE))
goto END;
if( !modules_in_use() ) {
log_warning("cleanup module %s - without module support", module);
goto END;
}
/* wait a bit for all components listening on dbus to clean up their act
* usbmoded_sleep(2); */
/* check if things were not reconnected in that timespan
* if(usbmoded_get_connection_state())
* return(0);
*/
failure = modules_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 = modules_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)
{
modesetting_cleanup(modules_get_loaded_module());
}
while(failure)
{
/* module did not get unloaded. We will wait a bit and try again */
usbmoded_sleep(1);
/* send the REALLY disconnect message */
umdbus_send_state_signal(USB_REALLY_DISCONNECT);
failure = modules_unload_module(module);
log_debug("unloading failure = %d\n", failure);
if(!failure)
break;
if(!modules_get_loaded_module())
goto END;
retry++;
if(retry == 2)
break;
}
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);
}
/** try to unload modules to support switching
*
*
* @param force force unloading with a nasty clean-up on TRUE, or just try unloading when FALSE
* @return 0 on success, 1 on failure, 2 if hard clean-up failed
*/
static int modules_prepare_for_module_switch (int force)
{
if( !modules_in_use() ) {
log_warning("prep for module switch force=%d - without module support", force);
return 0;
}
const char *unload;
int ret = 1;
unload = modules_get_loaded_module();
if(unload)
{
if(force)
ret = modules_cleanup_module(unload);
else
ret = modules_unload_module(unload);
}
if(ret && force)
return(2);
return ret;
}
/** check for loaded modules and clean-up if they are not for the chosen mode
*
* @param module_name module name to check for
*
*/
void modules_check_module_state(const char *module_name)
{
if( !modules_in_use() ) {
log_warning("check module %s state - without module support", module_name);
return;
}
const char *module;
module = modules_get_loaded_module();
if(module != NULL)
{
/* do nothing if the right module is already loaded */
if(strcmp(module, module_name) != 0)
{
log_debug("%s not loaded, cleaning up\n", module_name);
modules_prepare_for_module_switch(TRUE);
}
}
}
......@@ -53,8 +53,5 @@ bool modules_init (void);
void modules_quit (void);
int modules_load_module (const char *module);
int modules_unload_module (const char *module);
const char *modules_get_loaded_module (void);
int modules_cleanup_module (const char *module);
void modules_check_module_state(const char *module_name);
#endif /* USB_MODED_MODULES_H_ */
......@@ -235,7 +235,6 @@ static void trigger_parse_udev_properties(struct udev_device *dev)
#endif /* MEEGOLOCK */
if(strcmp(config_get_trigger_mode(), usbmoded_get_usb_mode()) != 0)
{
modesetting_cleanup(usbmoded_get_usb_module());
usbmoded_set_usb_mode(config_get_trigger_mode());
}
free(trigger);
......@@ -254,7 +253,6 @@ static void trigger_parse_udev_properties(struct udev_device *dev)
#endif /* MEEGOLOCK */
if(strcmp(config_get_trigger_mode(), usbmoded_get_usb_mode()) != 0)
{
modesetting_cleanup(usbmoded_get_usb_module());
usbmoded_set_usb_mode(config_get_trigger_mode());
}
}
......
This diff is collapsed.
......@@ -118,7 +118,7 @@ void usbmoded_set_charger_connected (bool state);
int usbmoded_valid_mode (const char *mode);
gchar *usbmoded_get_mode_list (mode_list_type_t type);
const char *usbmoded_get_usb_module (void);
void usbmoded_set_usb_module (const char *module);
bool usbmoded_set_usb_module (const char *module);
struct mode_list_elem *usbmoded_get_usb_mode_data (void);
void usbmoded_set_usb_mode_data (struct mode_list_elem *data);
void usbmoded_send_supported_modes_signal (void);
......
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