diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mm-broadband-modem.c | 3 | ||||
-rw-r--r-- | src/mm-iface-modem-3gpp.c | 254 | ||||
-rw-r--r-- | src/mm-iface-modem-3gpp.h | 8 |
3 files changed, 189 insertions, 76 deletions
diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c index 14c0d40c..3863c71c 100644 --- a/src/mm-broadband-modem.c +++ b/src/mm-broadband-modem.c @@ -6107,7 +6107,8 @@ enable_location_gathering (MMIfaceModemLocation *self, /* Reload registration to get LAC/CI */ mm_iface_modem_3gpp_run_registration_checks (MM_IFACE_MODEM_3GPP (self), NULL, NULL); /* Reload operator to get MCC/MNC */ - mm_iface_modem_3gpp_reload_current_operator (MM_IFACE_MODEM_3GPP (self)); + if (MM_BROADBAND_MODEM (self)->priv->modem_state >= MM_MODEM_STATE_REGISTERED) + mm_iface_modem_3gpp_reload_current_operator (MM_IFACE_MODEM_3GPP (self), NULL, NULL); } /* Done we are */ diff --git a/src/mm-iface-modem-3gpp.c b/src/mm-iface-modem-3gpp.c index 0000aee7..a3dcb86f 100644 --- a/src/mm-iface-modem-3gpp.c +++ b/src/mm-iface-modem-3gpp.c @@ -71,6 +71,7 @@ typedef struct { MMModem3gppRegistrationState ps; gboolean manual_registration; GCancellable *pending_registration_cancellable; + gboolean reloading_operator; } RegistrationStateContext; static void @@ -727,12 +728,41 @@ mm_iface_modem_3gpp_run_registration_checks (MMIfaceModem3gpp *self, /*****************************************************************************/ +typedef struct { + MMIfaceModem3gpp *self; + MmGdbusModem3gpp *skeleton; + GSimpleAsyncResult *result; + gboolean operator_code_loaded; + gboolean operator_name_loaded; +} ReloadCurrentOperatorContext; + +static void +reload_current_operator_context_complete_and_free (ReloadCurrentOperatorContext *ctx) +{ + g_simple_async_result_complete_in_idle (ctx->result); + g_object_unref (ctx->result); + if (ctx->skeleton) + g_object_unref (ctx->skeleton); + g_object_unref (ctx->self); + g_slice_free (ReloadCurrentOperatorContext, ctx); +} + +gboolean +mm_iface_modem_3gpp_reload_current_operator_finish (MMIfaceModem3gpp *self, + GAsyncResult *res, + GError **error) +{ + return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error); +} + +static void reload_current_operator_context_step (ReloadCurrentOperatorContext *ctx); + static void load_operator_name_ready (MMIfaceModem3gpp *self, - GAsyncResult *res) + GAsyncResult *res, + ReloadCurrentOperatorContext *ctx) { GError *error = NULL; - MmGdbusModem3gpp *skeleton = NULL; gchar *str; str = MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->load_operator_name_finish (self, res, &error); @@ -741,12 +771,12 @@ load_operator_name_ready (MMIfaceModem3gpp *self, g_error_free (error); } - g_object_get (self, - MM_IFACE_MODEM_3GPP_DBUS_SKELETON, &skeleton, - NULL); - mm_gdbus_modem3gpp_set_operator_name (skeleton, str); + if (ctx->skeleton) + mm_gdbus_modem3gpp_set_operator_name (ctx->skeleton, str); g_free (str); - g_object_unref (skeleton); + + ctx->operator_name_loaded = TRUE; + reload_current_operator_context_step (ctx); } static gboolean @@ -779,10 +809,10 @@ parse_mcc_mnc (const gchar *mccmnc, static void load_operator_code_ready (MMIfaceModem3gpp *self, - GAsyncResult *res) + GAsyncResult *res, + ReloadCurrentOperatorContext *ctx) { GError *error = NULL; - MmGdbusModem3gpp *skeleton = NULL; gchar *str; str = MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->load_operator_code_finish (self, res, &error); @@ -791,10 +821,8 @@ load_operator_code_ready (MMIfaceModem3gpp *self, g_error_free (error); } - g_object_get (self, - MM_IFACE_MODEM_3GPP_DBUS_SKELETON, &skeleton, - NULL); - mm_gdbus_modem3gpp_set_operator_code (skeleton, str); + if (ctx->skeleton) + mm_gdbus_modem3gpp_set_operator_code (ctx->skeleton, str); /* If we also implement the location interface, update the 3GPP location */ if (str && MM_IS_IFACE_MODEM_LOCATION (self)) { @@ -804,46 +832,87 @@ load_operator_code_ready (MMIfaceModem3gpp *self, if (parse_mcc_mnc (str, &mcc, &mnc)) mm_iface_modem_location_3gpp_update_mcc_mnc (MM_IFACE_MODEM_LOCATION (self), mcc, mnc); } - g_free (str); - g_object_unref (skeleton); + + ctx->operator_code_loaded = TRUE; + reload_current_operator_context_step (ctx); +} + +static void +reload_current_operator_context_step (ReloadCurrentOperatorContext *ctx) +{ + if (!ctx->operator_code_loaded) { + /* Launch operator code update */ + MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->load_operator_code ( + ctx->self, + (GAsyncReadyCallback)load_operator_code_ready, + ctx); + return; + } + + if (!ctx->operator_name_loaded) { + /* Launch operator name update */ + MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->load_operator_name ( + ctx->self, + (GAsyncReadyCallback)load_operator_name_ready, + ctx); + return; + } + + /* If both loaded, all done */ + g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); + reload_current_operator_context_complete_and_free (ctx); } void -mm_iface_modem_3gpp_reload_current_operator (MMIfaceModem3gpp *self) +mm_iface_modem_3gpp_reload_current_operator (MMIfaceModem3gpp *self, + GAsyncReadyCallback callback, + gpointer user_data) { - MMModem3gppRegistrationState state = MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN; - MmGdbusModem3gpp *skeleton = NULL; + ReloadCurrentOperatorContext *ctx; + + ctx = g_slice_new0 (ReloadCurrentOperatorContext); + ctx->self = g_object_ref (self); + ctx->result = g_simple_async_result_new (G_OBJECT (self), + callback, + user_data, + mm_iface_modem_3gpp_reload_current_operator); g_object_get (self, - MM_IFACE_MODEM_3GPP_REGISTRATION_STATE, &state, - MM_IFACE_MODEM_3GPP_DBUS_SKELETON, &skeleton, + MM_IFACE_MODEM_3GPP_DBUS_SKELETON, &ctx->skeleton, NULL); - if (state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME || - state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING) { - /* Launch operator code update */ - if (MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->load_operator_code && - MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->load_operator_code_finish) - MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->load_operator_code ( - self, - (GAsyncReadyCallback)load_operator_code_ready, - NULL); - /* Launch operator name update */ - if (MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->load_operator_name && - MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->load_operator_name_finish) - MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->load_operator_name ( - self, - (GAsyncReadyCallback)load_operator_name_ready, - NULL); - } else { - mm_gdbus_modem3gpp_set_operator_code (skeleton, NULL); - mm_gdbus_modem3gpp_set_operator_name (skeleton, NULL); + ctx->operator_code_loaded = !(MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->load_operator_code && + MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->load_operator_code_finish); + if (ctx->operator_code_loaded) { + mm_gdbus_modem3gpp_set_operator_code (ctx->skeleton, NULL); if (MM_IS_IFACE_MODEM_LOCATION (self)) mm_iface_modem_location_3gpp_update_mcc_mnc (MM_IFACE_MODEM_LOCATION (self), 0, 0); } - g_object_unref (skeleton); + ctx->operator_name_loaded = !(MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->load_operator_name && + MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->load_operator_name_finish); + if (ctx->operator_name_loaded) + mm_gdbus_modem3gpp_set_operator_name (ctx->skeleton, NULL); + + reload_current_operator_context_step (ctx); +} + +void +mm_iface_modem_3gpp_clear_current_operator (MMIfaceModem3gpp *self) +{ + MmGdbusModem3gpp *skeleton = NULL; + + g_object_get (self, + MM_IFACE_MODEM_3GPP_DBUS_SKELETON, &skeleton, + NULL); + if (!skeleton) + return; + + mm_gdbus_modem3gpp_set_operator_code (skeleton, NULL); + mm_gdbus_modem3gpp_set_operator_name (skeleton, NULL); + if (MM_IS_IFACE_MODEM_LOCATION (self)) + mm_iface_modem_location_3gpp_update_mcc_mnc (MM_IFACE_MODEM_LOCATION (self), 0, 0); } /*****************************************************************************/ @@ -901,56 +970,93 @@ mm_iface_modem_3gpp_update_location (MMIfaceModem3gpp *self, /*****************************************************************************/ static void +update_registration_reload_current_operator_ready (MMIfaceModem3gpp *self, + GAsyncResult *res, + gpointer user_data) +{ + MMModem3gppRegistrationState new_state; + RegistrationStateContext *ctx; + + new_state = GPOINTER_TO_UINT (user_data); + + mm_info ("Modem %s: 3GPP Registration state changed (registering -> %s)", + g_dbus_object_get_object_path (G_DBUS_OBJECT (self)), + mm_modem_3gpp_registration_state_get_string (new_state)); + + /* 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, + MM_MODEM_STATE_REGISTERED, + MM_MODEM_STATE_CHANGE_REASON_UNKNOWN); + + ctx = get_registration_state_context (self); + ctx->reloading_operator = FALSE; +} + +static void update_registration_state (MMIfaceModem3gpp *self, MMModem3gppRegistrationState new_state) { MMModem3gppRegistrationState old_state = MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN; - MmGdbusModem3gpp *skeleton = NULL; g_object_get (self, MM_IFACE_MODEM_3GPP_REGISTRATION_STATE, &old_state, - MM_IFACE_MODEM_3GPP_DBUS_SKELETON, &skeleton, NULL); - if (!skeleton) + /* Only set new state if different */ + if (new_state == old_state) return; - /* Only set new state if different */ - if (new_state != old_state) { - 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)); + if (new_state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME || + new_state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING) { + RegistrationStateContext *ctx; - /* 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); + ctx = get_registration_state_context (self); - /* Reload current operator */ - mm_iface_modem_3gpp_reload_current_operator (self); + /* If already reloading operator, skip it */ + if (ctx->reloading_operator) + return; - if (new_state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME || - new_state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING) { - mm_iface_modem_update_subsystem_state (MM_IFACE_MODEM (self), - SUBSYSTEM_3GPP, - MM_MODEM_STATE_REGISTERED, - MM_MODEM_STATE_CHANGE_REASON_UNKNOWN); - } - /* Not registered neither in home nor roaming network */ - else { - 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); - } + mm_info ("Modem %s: 3GPP Registration state changed (%s -> registering)", + g_dbus_object_get_object_path (G_DBUS_OBJECT (self)), + mm_modem_3gpp_registration_state_get_string (old_state)); + + /* Reload current operator. ONLY update the state to REGISTERED after + * having loaded operator code/name */ + ctx->reloading_operator = TRUE; + mm_iface_modem_3gpp_reload_current_operator ( + self, + (GAsyncReadyCallback)update_registration_reload_current_operator_ready, + GUINT_TO_POINTER (new_state)); + return; } - g_object_unref (skeleton); + 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); } void diff --git a/src/mm-iface-modem-3gpp.h b/src/mm-iface-modem-3gpp.h index 2bc25613..aaf727cd 100644 --- a/src/mm-iface-modem-3gpp.h +++ b/src/mm-iface-modem-3gpp.h @@ -234,7 +234,13 @@ gboolean mm_iface_modem_3gpp_run_registration_checks_finish (MMIfaceModem3gpp *s GError **error); /* Request to reload current operator */ -void mm_iface_modem_3gpp_reload_current_operator (MMIfaceModem3gpp *self); +void mm_iface_modem_3gpp_reload_current_operator (MMIfaceModem3gpp *self, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean mm_iface_modem_3gpp_reload_current_operator_finish (MMIfaceModem3gpp *self, + GAsyncResult *res, + GError **error); +void mm_iface_modem_3gpp_clear_current_operator (MMIfaceModem3gpp *self); /* Allow registering in the network */ gboolean mm_iface_modem_3gpp_register_in_network_finish (MMIfaceModem3gpp *self, |