diff options
author | Ben Chan <benchan@chromium.org> | 2013-02-15 15:17:18 -0800 |
---|---|---|
committer | Aleksander Morgado <aleksander@lanedo.com> | 2013-02-25 09:10:56 +0100 |
commit | 8488782e1424db0ec42839b4713373b588224a3e (patch) | |
tree | a57e39580d4596fb4da47494e4bba2b6fd878a84 | |
parent | 980ad52a479a12e9777419d6e6f0a77005a36528 (diff) |
iface-modem-3gpp: defer registration state update when registration is lost
This patch defers the update of 3GPP registration state by 15 seconds
when the registration state changes from 'registered' (home / roaming)
to 'searching'. This allows a temporary loss of 3GPP registration to
recover itself when relying on ModemManager to explicitly disconnect and
reconnect to the network.
-rw-r--r-- | src/mm-iface-modem-3gpp.c | 122 |
1 files changed, 102 insertions, 20 deletions
diff --git a/src/mm-iface-modem-3gpp.c b/src/mm-iface-modem-3gpp.c index 7117e9c3..fa8da1a3 100644 --- a/src/mm-iface-modem-3gpp.c +++ b/src/mm-iface-modem-3gpp.c @@ -29,6 +29,7 @@ #include "mm-log.h" #define REGISTRATION_CHECK_TIMEOUT_SEC 30 +#define DEFERRED_REGISTRATION_STATE_UPDATE_TIMEOUT_SEC 15 #define SUBSYSTEM_3GPP "3gpp" @@ -73,6 +74,8 @@ typedef struct { MMModem3gppRegistrationState cs; MMModem3gppRegistrationState ps; MMModem3gppRegistrationState eps; + MMModem3gppRegistrationState deferred_new_state; + guint deferred_update_id; gboolean manual_registration; GCancellable *pending_registration_cancellable; gboolean reloading_operator; @@ -85,6 +88,9 @@ registration_state_context_free (RegistrationStateContext *ctx) g_cancellable_cancel (ctx->pending_registration_cancellable); g_object_unref (ctx->pending_registration_cancellable); } + if (ctx->deferred_update_id) { + g_source_remove (ctx->deferred_update_id); + } g_slice_free (RegistrationStateContext, ctx); } @@ -104,6 +110,7 @@ get_registration_state_context (MMIfaceModem3gpp *self) ctx->cs = MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN; ctx->ps = MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN; ctx->eps = MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN; + ctx->deferred_new_state = MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN; g_object_set_qdata_full ( G_OBJECT (self), @@ -1033,25 +1040,98 @@ update_registration_reload_current_operator_ready (MMIfaceModem3gpp *self, } static void +update_non_registered_state (MMIfaceModem3gpp *self, + MMModem3gppRegistrationState old_state, + MMModem3gppRegistrationState new_state) +{ + /* Not registered neither in home nor roaming network */ + mm_iface_modem_3gpp_clear_current_operator (self); + + /* The property in the interface is bound to the property + * in the skeleton, so just updating here is enough */ + g_object_set (self, + MM_IFACE_MODEM_3GPP_REGISTRATION_STATE, new_state, + NULL); + + mm_iface_modem_update_subsystem_state ( + MM_IFACE_MODEM (self), + SUBSYSTEM_3GPP, + (new_state == MM_MODEM_3GPP_REGISTRATION_STATE_SEARCHING ? + MM_MODEM_STATE_SEARCHING : + MM_MODEM_STATE_ENABLED), + MM_MODEM_STATE_CHANGE_REASON_UNKNOWN); +} + +static gboolean +run_deferred_registration_state_update (MMIfaceModem3gpp *self) +{ + MMModem3gppRegistrationState old_state = MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN; + MMModem3gppRegistrationState new_state; + RegistrationStateContext *ctx; + + ctx = get_registration_state_context (self); + ctx->deferred_update_id = 0; + + g_object_get (self, + MM_IFACE_MODEM_3GPP_REGISTRATION_STATE, &old_state, + NULL); + new_state = ctx->deferred_new_state; + + /* Only set new state if different */ + if (new_state == old_state) + return FALSE; + + mm_info ("Modem %s: (deferred) 3GPP Registration state changed (%s -> %s)", + g_dbus_object_get_object_path (G_DBUS_OBJECT (self)), + mm_modem_3gpp_registration_state_get_string (old_state), + mm_modem_3gpp_registration_state_get_string (new_state)); + + update_non_registered_state (self, old_state, new_state); + + return FALSE; +} + +static void update_registration_state (MMIfaceModem3gpp *self, MMModem3gppRegistrationState new_state) { MMModem3gppRegistrationState old_state = MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN; + RegistrationStateContext *ctx; g_object_get (self, MM_IFACE_MODEM_3GPP_REGISTRATION_STATE, &old_state, NULL); + ctx = get_registration_state_context (self); + g_assert (ctx); + + if (ctx->deferred_update_id != 0) { + /* If there is already a deferred 'registration loss' state update and the new update + * is not a registered state, update the deferred state update without extending the + * timeout. */ + if (new_state != MM_MODEM_3GPP_REGISTRATION_STATE_HOME && + new_state != MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING) { + mm_info ("Modem %s: 3GPP Registration state changed (%s -> %s), update deferred", + g_dbus_object_get_object_path (G_DBUS_OBJECT (self)), + mm_modem_3gpp_registration_state_get_string (old_state), + mm_modem_3gpp_registration_state_get_string (new_state)); + + ctx->deferred_new_state = new_state; + return; + } + + /* Otherwise, cancel any deferred registration state update */ + g_source_remove (ctx->deferred_update_id); + ctx->deferred_update_id = 0; + ctx->deferred_new_state = MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN; + } + /* Only set new state if different */ if (new_state == old_state) return; if (new_state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME || new_state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING) { - RegistrationStateContext *ctx; - - ctx = get_registration_state_context (self); - /* If already reloading operator, skip it */ if (ctx->reloading_operator) return; @@ -1070,27 +1150,29 @@ update_registration_state (MMIfaceModem3gpp *self, return; } + if ((old_state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME || + old_state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING) && + (new_state == MM_MODEM_3GPP_REGISTRATION_STATE_SEARCHING || + new_state == MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN)) { + mm_info ("Modem %s: 3GPP Registration state changed (%s -> %s), update deferred", + g_dbus_object_get_object_path (G_DBUS_OBJECT (self)), + mm_modem_3gpp_registration_state_get_string (old_state), + mm_modem_3gpp_registration_state_get_string (new_state)); + + ctx->deferred_new_state = new_state; + ctx->deferred_update_id = g_timeout_add_seconds ( + DEFERRED_REGISTRATION_STATE_UPDATE_TIMEOUT_SEC, + (GSourceFunc)run_deferred_registration_state_update, + self); + return; + } + mm_info ("Modem %s: 3GPP Registration state changed (%s -> %s)", g_dbus_object_get_object_path (G_DBUS_OBJECT (self)), mm_modem_3gpp_registration_state_get_string (old_state), mm_modem_3gpp_registration_state_get_string (new_state)); - /* Not registered neither in home nor roaming network */ - mm_iface_modem_3gpp_clear_current_operator (self); - - /* The property in the interface is bound to the property - * in the skeleton, so just updating here is enough */ - g_object_set (self, - MM_IFACE_MODEM_3GPP_REGISTRATION_STATE, new_state, - NULL); - - mm_iface_modem_update_subsystem_state ( - MM_IFACE_MODEM (self), - SUBSYSTEM_3GPP, - (new_state == MM_MODEM_3GPP_REGISTRATION_STATE_SEARCHING ? - MM_MODEM_STATE_SEARCHING : - MM_MODEM_STATE_ENABLED), - MM_MODEM_STATE_CHANGE_REASON_UNKNOWN); + update_non_registered_state (self, old_state, new_state); } void |