From 7f42931c13deb23fff8f57cfb44b77285c46a20b Mon Sep 17 00:00:00 2001 From: Simo Piiroinen Date: Mon, 1 Apr 2019 13:21:56 +0300 Subject: [PATCH] [usb-moded] Sanitize default and current mode after settings reload. JB#45312 Removing dynamic mode configuration files can invalidate default mode setting and/or currently active mode. If currently selected default mode is no longer available after configuration file refresh, select "ask" as default mode. If currently active mode is no longer available after configuration file refresh, re-evaluate appropriate mode similarly as what is done on cable connect. Also document mode names in a bit more detail. Signed-off-by: Simo Piiroinen --- src/usb_moded-common.c | 20 +++++++++++++ src/usb_moded-common.h | 1 + src/usb_moded-modes.h | 66 +++++++++++++++++++++++++++++++----------- src/usb_moded.c | 50 ++++++++++++++++++++++++++++++-- 4 files changed, 117 insertions(+), 20 deletions(-) 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 {