From 8e4690914e264ba0507de9347a40eed60755e4ec Mon Sep 17 00:00:00 2001 From: Simo Piiroinen Date: Mon, 16 Jul 2018 14:08:17 +0300 Subject: [PATCH] [usb_moded] Do not track pc / charger connect separately. JB#41748 Handling "connected to pc" and "connected to charger" as separate boolean states just complicates things. Move cable_state_t enumeration values from udev module to usb_moded.h to make them generally available. Utilize cable_state_t also within usb_moded.c module. Signed-off-by: Simo Piiroinen --- src/usb_moded-dbus.c | 3 +- src/usb_moded-network.c | 23 ++---- src/usb_moded-udev.c | 151 +++++++++++++++++----------------------- src/usb_moded.c | 139 ++++++++++++++++++------------------ src/usb_moded.h | 18 ++++- 5 files changed, 155 insertions(+), 179 deletions(-) diff --git a/src/usb_moded-dbus.c b/src/usb_moded-dbus.c index 0088abc..6a06107 100644 --- a/src/usb_moded-dbus.c +++ b/src/usb_moded-dbus.c @@ -272,8 +272,7 @@ static DBusHandlerResult umdbus_msg_handler(DBusConnection *const connection, DB else { /* check if usb is connected, since it makes no sense to change mode if it isn't */ - if(!usbmoded_get_connection_state()) - { + if( usbmoded_get_cable_state() != CABLE_STATE_PC_CONNECTED ) { log_warning("USB not connected, not changing mode!\n"); goto error_reply; } diff --git a/src/usb_moded-network.c b/src/usb_moded-network.c index 539efb2..14d7a4b 100644 --- a/src/usb_moded-network.c +++ b/src/usb_moded-network.c @@ -1240,21 +1240,12 @@ int network_down(struct mode_list_elem *data) */ int network_update(void) { - struct mode_list_elem * data; - - if(!usbmoded_get_connection_state()) - return(0); - - data = usbmoded_get_usb_mode_data(); - if(data == NULL) - return(0); - if(data->network) - { - network_down(data); - network_up(data); - return(0); + if( usbmoded_get_cable_state() == CABLE_STATE_PC_CONNECTED ) { + struct mode_list_elem *data = usbmoded_get_usb_mode_data(); + if( data && data->network ) { + network_down(data); + network_up(data); + } } - else - return(0); - + return 0; } diff --git a/src/usb_moded-udev.c b/src/usb_moded-udev.c index c842668..0cfc3eb 100644 --- a/src/usb_moded-udev.c +++ b/src/usb_moded-udev.c @@ -46,35 +46,21 @@ #include "usb_moded-modes.h" #include "usb_moded-dbus-private.h" -/* ========================================================================= * - * Types - * ========================================================================= */ - -typedef enum { - CABLE_STATE_UNKNOWN, - CABLE_STATE_DISCONNECTED, - CABLE_STATE_CHARGER_CONNECTED, - CABLE_STATE_PC_CONNECTED, - CABLE_STATE_NUMOF -} cable_state_t; - /* ========================================================================= * * Prototypes * ========================================================================= */ -/* -- cable -- */ - -static gboolean cable_state_timer_cb (gpointer aptr); -static void cable_state_stop_timer (void); -static void cable_state_start_timer(void); -static bool cable_state_connected (void); -static cable_state_t cable_state_get (void); -static void cable_state_set (cable_state_t state); -static void cable_state_changed (void); -static void cable_state_from_udev (cable_state_t state); - /* -- umudev -- */ +static gboolean umudev_cable_state_timer_cb (gpointer aptr); +static void umudev_cable_state_stop_timer (void); +static void umudev_cable_state_start_timer(void); +static bool umudev_cable_state_connected (void); +static cable_state_t umudev_cable_state_get (void); +static void umudev_cable_state_set (cable_state_t state); +static void umudev_cable_state_changed (void); +static void umudev_cable_state_from_udev (cable_state_t state); + static void umudev_io_error_cb (gpointer data); static gboolean umudev_io_input_cb (GIOChannel *iochannel, GIOCondition cond, gpointer data); static void umudev_parse_properties (struct udev_device *dev, bool initial); @@ -86,13 +72,6 @@ void umudev_quit (void); * Data * ========================================================================= */ -static const char * const cable_state_name[CABLE_STATE_NUMOF] = { - [CABLE_STATE_UNKNOWN] = "unknown", - [CABLE_STATE_DISCONNECTED] = "disconnected", - [CABLE_STATE_CHARGER_CONNECTED] = "charger_connected", - [CABLE_STATE_PC_CONNECTED] = "pc_connected", -}; - /* global variables */ static struct udev *umudev_object = 0; static struct udev_monitor *umudev_monitor = 0; @@ -101,57 +80,58 @@ static guint umudev_watch_id = 0; static bool umudev_in_cleanup = false; /** Cable state as evaluated from udev events */ -static cable_state_t cable_state_current = CABLE_STATE_UNKNOWN; +static cable_state_t umudev_cable_state_current = CABLE_STATE_UNKNOWN; /** Cable state considered active by usb-moded */ -static cable_state_t cable_state_active = CABLE_STATE_UNKNOWN; +static cable_state_t umudev_cable_state_active = CABLE_STATE_UNKNOWN; /** Previously active cable state */ -static cable_state_t cable_state_previous = CABLE_STATE_UNKNOWN; +static cable_state_t umudev_cable_state_previous = CABLE_STATE_UNKNOWN; /** Timer id for delaying: reported by udev -> active in usb-moded */ -static guint cable_state_timer_id = 0; +static guint umudev_cable_state_timer_id = 0; /* ========================================================================= * * cable state * ========================================================================= */ -static gboolean cable_state_timer_cb(gpointer aptr) +static gboolean umudev_cable_state_timer_cb(gpointer aptr) { (void)aptr; - cable_state_timer_id = 0; + umudev_cable_state_timer_id = 0; log_debug("trigger delayed transfer to: %s", - cable_state_name[cable_state_current]); - cable_state_set(cable_state_current); + cable_state_repr(umudev_cable_state_current)); + umudev_cable_state_set(umudev_cable_state_current); return FALSE; } -static void cable_state_stop_timer(void) +static void umudev_cable_state_stop_timer(void) { - if( cable_state_timer_id ) { + if( umudev_cable_state_timer_id ) { log_debug("cancel delayed transfer to: %s", - cable_state_name[cable_state_current]); - g_source_remove(cable_state_timer_id), - cable_state_timer_id = 0; + cable_state_repr(umudev_cable_state_current)); + g_source_remove(umudev_cable_state_timer_id), + umudev_cable_state_timer_id = 0; } } -static void cable_state_start_timer(void) +static void umudev_cable_state_start_timer(void) { - if( !cable_state_timer_id ) { + if( !umudev_cable_state_timer_id ) { log_debug("schedule delayed transfer to: %s", - cable_state_name[cable_state_current]); - cable_state_timer_id = g_timeout_add(usbmoded_cable_connection_delay, - cable_state_timer_cb, 0); + cable_state_repr(umudev_cable_state_current)); + umudev_cable_state_timer_id = + g_timeout_add(usbmoded_cable_connection_delay, + umudev_cable_state_timer_cb, 0); } } static bool -cable_state_connected(void) +umudev_cable_state_connected(void) { bool connected = false; - switch( cable_state_get() ) { + switch( umudev_cable_state_get() ) { default: break; case CABLE_STATE_CHARGER_CONNECTED: @@ -162,32 +142,32 @@ cable_state_connected(void) return connected; } -static cable_state_t cable_state_get(void) +static cable_state_t umudev_cable_state_get(void) { - return cable_state_active; + return umudev_cable_state_active; } -static void cable_state_set(cable_state_t state) +static void umudev_cable_state_set(cable_state_t state) { - cable_state_stop_timer(); + umudev_cable_state_stop_timer(); - if( cable_state_active == state ) + if( umudev_cable_state_active == state ) goto EXIT; - cable_state_previous = cable_state_active; - cable_state_active = state; + umudev_cable_state_previous = umudev_cable_state_active; + umudev_cable_state_active = state; log_debug("cable_state: %s -> %s", - cable_state_name[cable_state_previous], - cable_state_name[cable_state_active]); + cable_state_repr(umudev_cable_state_previous), + cable_state_repr(umudev_cable_state_active)); - cable_state_changed(); + umudev_cable_state_changed(); EXIT: return; } -static void cable_state_changed(void) +static void umudev_cable_state_changed(void) { /* The rest of usb-moded separates charger * and pc connection states... make single @@ -196,61 +176,56 @@ static void cable_state_changed(void) /* First handle pc/charger disconnect based * on previous state. */ - switch( cable_state_previous ) { + switch( umudev_cable_state_previous ) { default: case CABLE_STATE_DISCONNECTED: /* dontcare */ break; case CABLE_STATE_CHARGER_CONNECTED: - log_debug("*** HANDLE CHARGER DISCONNECT"); umdbus_send_state_signal(CHARGER_DISCONNECTED); - usbmoded_set_charger_connected(false); break; case CABLE_STATE_PC_CONNECTED: - log_debug("*** HANDLE PC DISCONNECT"); umdbus_send_state_signal(USB_DISCONNECTED); - usbmoded_set_usb_connected(false); break; } - /* Then handle pc/charger sconnect based + /* Then handle pc/charger connect based * on current state. */ - switch( cable_state_active ) { + switch( umudev_cable_state_active ) { default: case CABLE_STATE_DISCONNECTED: /* dontcare */ break; case CABLE_STATE_CHARGER_CONNECTED: - log_debug("*** HANDLE CHARGER CONNECT"); umdbus_send_state_signal(CHARGER_CONNECTED); - usbmoded_set_charger_connected(true); break; case CABLE_STATE_PC_CONNECTED: - log_debug("*** HANDLE PC CONNECT"); umdbus_send_state_signal(USB_CONNECTED); - usbmoded_set_usb_connected(true); break; } + + /* Then act on usb mode */ + usbmoded_set_cable_state(umudev_cable_state_active); } -static void cable_state_from_udev(cable_state_t curr) +static void umudev_cable_state_from_udev(cable_state_t curr) { - cable_state_t prev = cable_state_current; - cable_state_current = curr; + cable_state_t prev = umudev_cable_state_current; + umudev_cable_state_current = curr; if( prev == curr ) goto EXIT; log_debug("reported cable state: %s -> %s", - cable_state_name[prev], - cable_state_name[curr]); + cable_state_repr(prev), + cable_state_repr(curr)); if( curr == CABLE_STATE_PC_CONNECTED && prev != CABLE_STATE_UNKNOWN ) - cable_state_start_timer(); + umudev_cable_state_start_timer(); else - cable_state_set(curr); + umudev_cable_state_set(curr); EXIT: return; @@ -371,7 +346,7 @@ static void umudev_parse_properties(struct udev_device *dev, bool initial) if( warnings && !power_supply_present ) log_err("No usable power supply indicator\n"); - cable_state_from_udev(CABLE_STATE_DISCONNECTED); + umudev_cable_state_from_udev(CABLE_STATE_DISCONNECTED); } else { if( warnings && power_supply_online ) @@ -393,7 +368,7 @@ static void umudev_parse_properties(struct udev_device *dev, bool initial) if( warnings ) log_warning("Fallback since cable detection might not be accurate. " "Will connect on any voltage on charger.\n"); - cable_state_from_udev(CABLE_STATE_PC_CONNECTED); + umudev_cable_state_from_udev(CABLE_STATE_PC_CONNECTED); goto cleanup; } @@ -401,27 +376,27 @@ static void umudev_parse_properties(struct udev_device *dev, bool initial) if( !strcmp(power_supply_type, "USB") || !strcmp(power_supply_type, "USB_CDP") ) { - cable_state_from_udev(CABLE_STATE_PC_CONNECTED); + umudev_cable_state_from_udev(CABLE_STATE_PC_CONNECTED); } else if( !strcmp(power_supply_type, "USB_DCP") || !strcmp(power_supply_type, "USB_HVDCP") || !strcmp(power_supply_type, "USB_HVDCP_3") ) { - cable_state_from_udev(CABLE_STATE_CHARGER_CONNECTED); + umudev_cable_state_from_udev(CABLE_STATE_CHARGER_CONNECTED); } else if( !strcmp(power_supply_type, "USB_FLOAT")) { - if( !cable_state_connected() ) + if( !umudev_cable_state_connected() ) log_warning("connection type detection failed, assuming charger"); - cable_state_from_udev(CABLE_STATE_CHARGER_CONNECTED); + umudev_cable_state_from_udev(CABLE_STATE_CHARGER_CONNECTED); } else if( !strcmp(power_supply_type, "Unknown")) { // nop log_warning("unknown connection type reported, assuming disconnected"); - cable_state_from_udev(CABLE_STATE_DISCONNECTED); + umudev_cable_state_from_udev(CABLE_STATE_DISCONNECTED); } else { if( warnings ) log_warning("unhandled power supply type: %s", power_supply_type); - cable_state_from_udev(CABLE_STATE_DISCONNECTED); + umudev_cable_state_from_udev(CABLE_STATE_DISCONNECTED); } } @@ -631,5 +606,5 @@ void umudev_quit(void) g_free(umudev_sysname), umudev_sysname = 0; - cable_state_stop_timer(); + umudev_cable_state_stop_timer(); } diff --git a/src/usb_moded.c b/src/usb_moded.c index dfacc78..ca9b350 100644 --- a/src/usb_moded.c +++ b/src/usb_moded.c @@ -111,10 +111,10 @@ typedef struct usb_mode /** Connection status * * Access only via: + * - usbmoded_set_cable_state() * - usbmoded_get_connection_state() - * - usbmoded_set_connection_state() */ - bool connected; + cable_state_t cable_state; /** Mount status, true for mounted -UNUSED atm- */ bool mounted; @@ -163,6 +163,9 @@ typedef struct modemapping_t * Prototypes * ========================================================================= */ +/* -- cable -- */ +const char *cable_state_repr(cable_state_t state); + /* -- usbmoded -- */ static const char *usbmoded_map_mode_to_hardware(const char *internal_mode); @@ -181,21 +184,13 @@ static void usbmoded_update_hardware_mode (void); const char *usbmoded_get_external_mode (void); static void usbmoded_update_external_mode (void); -// from here and there const char *usbmoded_get_usb_mode (void); void usbmoded_set_usb_mode (const char *internal_mode); +void usbmoded_select_usb_mode (void); -// from usbmoded_set_usb_connected() -// usbmoded_set_charger_connected() +void usbmoded_set_cable_state (cable_state_t cable_state); +cable_state_t usbmoded_get_cable_state (void); bool usbmoded_get_connection_state (void); -static bool usbmoded_set_connection_state (bool state); - -// from usbmoded_set_usb_connected() -void usbmoded_set_usb_connected_state (void); - -// from udev cable_state_changed() -void usbmoded_set_usb_connected (bool connected); -void usbmoded_set_charger_connected (bool state); // ---------------------------------------------------------------- // internal movements @@ -269,7 +264,7 @@ static bool systemd_notify = false; int usbmoded_cable_connection_delay = CABLE_CONNECTION_DELAY_DEFAULT; static struct usb_mode current_mode = { - .connected = false, + .cable_state = CABLE_STATE_UNKNOWN, .mounted = false, .internal_mode = NULL, .hardware_mode = NULL, @@ -374,6 +369,17 @@ static const modemapping_t modemapping[] = * Functions * ========================================================================= */ +const char *cable_state_repr(cable_state_t state) +{ + static const char * const lut[CABLE_STATE_NUMOF] = { + [CABLE_STATE_UNKNOWN] = "unknown", + [CABLE_STATE_DISCONNECTED] = "disconnected", + [CABLE_STATE_CHARGER_CONNECTED] = "charger_connected", + [CABLE_STATE_PC_CONNECTED] = "pc_connected", + }; + return lut[state]; +} + static const char * usbmoded_map_mode_to_hardware(const char *internal_mode) { @@ -410,11 +416,12 @@ usbmoded_map_mode_to_external(const char *internal_mode) void usbmoded_rethink_usb_charging_fallback(void) { - /* Cable must be connected */ - if( !usbmoded_get_connection_state() ) + /* Cable must be connected to a pc */ + if( usbmoded_get_cable_state() != CABLE_STATE_PC_CONNECTED ) goto EXIT; - /* Suitable usb-mode mode selected */ + /* Switching can happen only from MODE_UNDEFINED + * or MODE_CHARGING_FALLBACK */ const char *usb_mode = usbmoded_get_usb_mode(); if( strcmp(usb_mode, MODE_UNDEFINED) && @@ -427,7 +434,7 @@ usbmoded_rethink_usb_charging_fallback(void) } log_debug("attempt to leave %s", usb_mode); - usbmoded_set_usb_connected_state(); + usbmoded_select_usb_mode(); EXIT: return; @@ -658,39 +665,12 @@ static void usbmoded_mode_switched(const char *override) return; } -/** Get if the cable (pc or charger) is connected or not - * - * @ return true if connected, false if disconnected - */ -bool usbmoded_get_connection_state(void) -{ - return current_mode.connected; -} - -/** Set if the cable (pc or charger) is connected or not - * - * @param state true for connected, false for disconnected - * - * @return true if value changed, false otherwise - */ -static bool usbmoded_set_connection_state(bool state) -{ - bool changed = false; - if( current_mode.connected != state ) { - log_debug("current_mode.connected: %d -> %d", - current_mode.connected, state); - current_mode.connected = state; - changed = true; - } - return changed; -} - /** set the chosen usb state * * gauge what mode to enter and then call usbmoded_set_usb_mode() * */ -void usbmoded_set_usb_connected_state(void) +void usbmoded_select_usb_mode(void) { char *mode_to_set = 0; @@ -740,43 +720,62 @@ void usbmoded_set_usb_connected_state(void) /** set the usb connection status * - * @param connected The connection status, true for connected - * + * @param cable_state CABLE_STATE_DISCONNECTED, ... */ -void usbmoded_set_usb_connected(bool connected) +void usbmoded_set_cable_state(cable_state_t cable_state) { - if( !usbmoded_set_connection_state(connected) ) + cable_state_t prev = current_mode.cable_state; + current_mode.cable_state = cable_state; + + if( current_mode.cable_state == prev ) goto EXIT; - if( usbmoded_get_connection_state() ) { - /* choose mode + call usbmoded_set_usb_mode() */ - usbmoded_set_usb_connected_state(); - } - else { + log_debug("current_mode.cable_state: %s -> %s", + cable_state_repr(prev), + cable_state_repr(current_mode.cable_state)); + + switch( current_mode.cable_state ) { + default: + case CABLE_STATE_DISCONNECTED: usbmoded_set_usb_mode(MODE_UNDEFINED); + break; + case CABLE_STATE_CHARGER_CONNECTED: + usbmoded_set_usb_mode(MODE_CHARGER); + break; + case CABLE_STATE_PC_CONNECTED: + usbmoded_select_usb_mode(); + break; } + EXIT: return; } -/** set and track charger state +/** get the usb connection status * + * @return CABLE_STATE_DISCONNECTED, ... */ -void usbmoded_set_charger_connected(bool state) +cable_state_t usbmoded_get_cable_state(void) { - /* check if charger is already connected - * to avoid spamming dbus */ - if( !usbmoded_set_connection_state(state) ) - goto EXIT; + return current_mode.cable_state; +} - if( usbmoded_get_connection_state() ) { - usbmoded_set_usb_mode(MODE_CHARGER); - } - else { - usbmoded_set_usb_mode(MODE_UNDEFINED); +/** Get if the cable (pc or charger) is connected or not + * + * @ return true if connected, false if disconnected + */ +bool usbmoded_get_connection_state(void) +{ + bool connected = false; + switch( usbmoded_get_cable_state() ) { + case CABLE_STATE_CHARGER_CONNECTED: + case CABLE_STATE_PC_CONNECTED: + connected = true; + break; + default: + break; } -EXIT: - return; + return connected; } /** Helper for setting allowed cable detection delay @@ -1261,7 +1260,7 @@ static void usbmoded_handle_signal(int signum) /* set default values for usb_moded */ static void usbmoded_init(void) { - current_mode.connected = false; + current_mode.cable_state = CABLE_STATE_UNKNOWN; current_mode.mounted = false; current_mode.internal_mode = strdup(MODE_UNDEFINED); current_mode.hardware_mode = NULL; @@ -1835,7 +1834,7 @@ int main(int argc, char* argv[]) { log_warning("Forcing USB state to connected always. ASK mode non functional!\n"); /* Since there will be no disconnect signals coming from hw the state should not change */ - usbmoded_set_usb_connected(true); + usbmoded_set_cable_state(CABLE_STATE_PC_CONNECTED); } /* - - - - - - - - - - - - - - - - - - - * diff --git a/src/usb_moded.h b/src/usb_moded.h index 50ea957..dcb9e28 100644 --- a/src/usb_moded.h +++ b/src/usb_moded.h @@ -71,6 +71,14 @@ * Types * ========================================================================= */ +typedef enum { + CABLE_STATE_UNKNOWN, + CABLE_STATE_DISCONNECTED, + CABLE_STATE_CHARGER_CONNECTED, + CABLE_STATE_PC_CONNECTED, + CABLE_STATE_NUMOF +} cable_state_t; + /** Mode list types */ typedef enum mode_list_type_t { @@ -105,16 +113,20 @@ extern bool usbmoded_rescue_mode; * Functions * ========================================================================= */ +/* -- cable -- */ + +const char *cable_state_repr(cable_state_t state); + /* -- usbmoded -- */ void usbmoded_rethink_usb_charging_fallback(void); const char *usbmoded_get_external_mode (void); const char *usbmoded_get_usb_mode (void); void usbmoded_set_usb_mode (const char *internal_mode); +void usbmoded_select_usb_mode (void); +void usbmoded_set_cable_state (cable_state_t cable_state); +cable_state_t usbmoded_get_cable_state (void); bool usbmoded_get_connection_state (void); -void usbmoded_set_usb_connected_state (void); -void usbmoded_set_usb_connected (bool connected); -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);