diff --git a/src/usb_moded-common.c b/src/usb_moded-common.c index d7a1bdc..f7e487f 100644 --- a/src/usb_moded-common.c +++ b/src/usb_moded-common.c @@ -59,6 +59,7 @@ FILE *common_popen_ (const char *file, int line, co waitres_t common_wait (unsigned tot_ms, bool (*ready_cb)(void *aptr), void *aptr); bool common_msleep_ (const char *file, int line, const char *func, unsigned msec); static bool common_mode_in_list (const char *mode, char *const *modes); +bool common_modename_is_internal (const char *modename); int common_valid_mode (const char *mode); gchar *common_get_mode_list (mode_list_type_t type); @@ -443,6 +444,25 @@ static bool common_mode_in_list(const char *mode, char * const *modes) return false; } +/** Check if given usb mode is internal + * + * @param modename name of a more + * + * @return true if mode is internal, false otherwise + */ +bool +common_modename_is_internal(const char *modename) +{ + LOG_REGISTER_CONTEXT; + + return (!g_strcmp0(modename, MODE_UNDEFINED) || + !g_strcmp0(modename, MODE_CHARGER) || + !g_strcmp0(modename, MODE_CHARGING_FALLBACK) || + !g_strcmp0(modename, MODE_ASK) || + !g_strcmp0(modename, MODE_CHARGING) || + !g_strcmp0(modename, MODE_BUSY)); +} + /** check if a given usb_mode exists * * @param mode The mode to look for diff --git a/src/usb_moded-common.h b/src/usb_moded-common.h index fb67358..74ea5f4 100644 --- a/src/usb_moded-common.h +++ b/src/usb_moded-common.h @@ -59,6 +59,7 @@ int common_system_ (const char *file, int line, con FILE *common_popen_ (const char *file, int line, const char *func, const char *command, const char *type); waitres_t common_wait (unsigned tot_ms, bool (*ready_cb)(void *aptr), void *aptr); bool common_msleep_ (const char *file, int line, const char *func, unsigned msec); +bool common_modename_is_internal (const char *modename); int common_valid_mode (const char *mode); gchar *common_get_mode_list (mode_list_type_t type); diff --git a/src/usb_moded-modes.h b/src/usb_moded-modes.h index 95517a7..0eba032 100644 --- a/src/usb_moded-modes.h +++ b/src/usb_moded-modes.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2010 Nokia Corporation. All rights reserved. - * Copyright (C) 2013-2018 Jolla Ltd. + * Copyright (C) 2013-2019 Jolla Ltd. * * Author: Philippe De Swert * Author: Philippe De Swert @@ -32,12 +32,57 @@ * Constants * ========================================================================= */ -/* possible values for the mode - * the first two are internal only. - */ +/* ------------------------------------------------------------------------- * + * Internal modes + * + * These modes are defined internally within usb-moded and are thus + * always available. + * + * Generally speaking these are also activated automatically and thus + * not really selectable - except: + * - MODE_ASK which can be set as default mode + * - MODE_CHARGING which can be acticated on request too + * ------------------------------------------------------------------------- */ +/** No cable connected */ # define MODE_UNDEFINED "undefined" + +/** Pending mode activation + * + * Used for signaling "in between modes" state. + */ +# define MODE_BUSY "busy" + +/** Connected to a dedicated charger */ +# define MODE_CHARGER "dedicated_charger" + +/** Blocked mode selection + * + * While prerequisites for dynamic mode activation are not met e.g. + * device is locked, pc connection is used for charging. + */ +# define MODE_CHARGING_FALLBACK "charging_only_fallback" + +/** Pending mode selection + * + * While mode selection dialog is shown to user, pc connection + * is used for charging. + */ # define MODE_ASK "ask" + +/** Charging only selected */ +# define MODE_CHARGING "charging_only" + +/* ------------------------------------------------------------------------- * + * Dynamic modes + * + * These modes are defined in usb-moded configuration files. + * + * From usb-moded point of view mode names have no special meaning, + * but a set of known values is still defined (and are likely to + * have localized name presentation in UI context). + * ------------------------------------------------------------------------- */ + # define MODE_MASS_STORAGE "mass_storage" # define MODE_DEVELOPER "developer_mode" # define MODE_MTP "mtp_mode" @@ -46,18 +91,5 @@ # define MODE_DIAG "diag_mode" # define MODE_ADB "adb_mode" # define MODE_PC_SUITE "pc_suite" -# define MODE_CHARGING "charging_only" -# define MODE_BUSY "busy" - -/** - * - * MODE_CHARGING : user manually selected charging mode - * MODE_CHARGING_FALLBACK : mode selection is not done by the user so we fallback to a charging mode to get some power - * MODE_CHARGER : there is a dedicated charger connected to the USB port - * - * the two last ones cannot be set and are not full modes - **/ -# define MODE_CHARGING_FALLBACK "charging_only_fallback" -# define MODE_CHARGER "dedicated_charger" #endif /* USB_MODED_MODES_H_ */ diff --git a/src/usb_moded.c b/src/usb_moded.c index 061ecff..5ac1fd4 100644 --- a/src/usb_moded.c +++ b/src/usb_moded.c @@ -53,6 +53,7 @@ #include "usb_moded-trigger.h" #include "usb_moded-udev.h" #include "usb_moded-worker.h" +#include "usb_moded-modes.h" #ifdef MEEGOLOCK # include "usb_moded-dsme.h" @@ -491,14 +492,57 @@ void usbmoded_handle_signal(int signum) } else if( signum == SIGHUP ) { - /* free and read in modelist again */ + /* Reload mode list */ + log_debug("reloading dynamic mode configuration"); usbmoded_free_modelist(); usbmoded_load_modelist(); + /* If default mode selection became invalid, + * revert setting to "ask" */ + gchar *config = config_get_mode_setting(); + if( g_strcmp0(config, MODE_ASK) && + common_valid_mode(config) ) { + log_warning("default mode '%s' is not valid, reset to '%s'", + config, MODE_ASK); + config_set_mode_setting(MODE_ASK); + } + else { + log_debug("default mode '%s' is still valid", config); + } + g_free(config); + + /* If current mode became invalid, select appropriate mode. + * + * Use target mode so that we catch also situations where + * we are making transition to invalid state. + */ + const char *current = control_get_target_mode(); + if( common_modename_is_internal(current) ) { + /* Internal modes are not affected by configuration + * file changes - no changes required. */ + log_debug("current mode '%s' is internal", current); + } + else if( common_valid_mode(current) ) { + /* Dynamic mode that is no longer valid - choose + * something else. */ + log_warning("current mode '%s' is not valid, re-evaluating", + current); + control_select_usb_mode(); + } + else { + /* Dynamic mode that is still valid - do nothing. + * + * Note: While the mode details /might/ have changed, + * skipping immediate usb reprogramming is assumed to + * be less harmful than potentially cutting developer + * mode connection during upgrade, etc. */ + log_debug("current mode '%s' is still valid", current); + } + + /* Signal availability */ + log_debug("broadcast mode availability lists"); common_send_supported_modes_signal(); common_send_available_modes_signal(); - - // FIXME invalidate current mode } else {