aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@lanedo.com>2012-08-08 13:19:49 +0200
committerAleksander Morgado <aleksander@lanedo.com>2012-08-29 17:26:44 +0200
commita6ff9b2a17d3f76026afcffc660d0842fb737b7b (patch)
tree0767e00e54f8e0c2b962826b837c2351110ec598 /src
parent7ce6b1296288271c02dbb7d2a85651f87bd244fb (diff)
iface-modem-3gpp: implement the network registration request logic
In the generic broadband modem implementation we'll just implement the specific command to request auto/manual network registration, and we leave all the other logic (waiting for the new registration status and all that) in the interface, as it is really common for every possible implementation.
Diffstat (limited to 'src')
-rw-r--r--src/mm-broadband-modem.c238
-rw-r--r--src/mm-iface-modem-3gpp.c386
-rw-r--r--src/mm-iface-modem-3gpp.h2
3 files changed, 310 insertions, 316 deletions
diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c
index d2cd9692..99229423 100644
--- a/src/mm-broadband-modem.c
+++ b/src/mm-broadband-modem.c
@@ -129,8 +129,6 @@ struct _MMBroadbandModemPrivate {
gboolean modem_3gpp_ps_network_supported;
/* Implementation helpers */
GPtrArray *modem_3gpp_registration_regex;
- gboolean modem_3gpp_manual_registration;
- GCancellable *modem_3gpp_pending_registration_cancellable;
/*<--- Modem 3GPP USSD interface --->*/
/* Properties */
@@ -2655,252 +2653,44 @@ modem_3gpp_scan_networks (MMIfaceModem3gpp *self,
/*****************************************************************************/
/* Register in network (3GPP interface) */
-typedef struct {
- MMBroadbandModem *self;
- GSimpleAsyncResult *result;
- GCancellable *cancellable;
- GTimer *timer;
- guint max_registration_time;
-} RegisterIn3gppNetworkContext;
-
-static void
-register_in_3gpp_network_context_complete_and_free (RegisterIn3gppNetworkContext *ctx)
-{
- /* If our cancellable reference is still around, clear it */
- if (ctx->self->priv->modem_3gpp_pending_registration_cancellable ==
- ctx->cancellable) {
- g_clear_object (&ctx->self->priv->modem_3gpp_pending_registration_cancellable);
- }
-
- if (ctx->timer)
- g_timer_destroy (ctx->timer);
-
- g_simple_async_result_complete (ctx->result);
- g_object_unref (ctx->result);
- g_object_unref (ctx->cancellable);
- g_object_unref (ctx->self);
- g_free (ctx);
-}
-
static gboolean
modem_3gpp_register_in_network_finish (MMIfaceModem3gpp *self,
GAsyncResult *res,
GError **error)
{
- return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error);
-}
-
-#undef REG_IS_IDLE
-#define REG_IS_IDLE(state) \
- (state != MM_MODEM_3GPP_REGISTRATION_STATE_HOME && \
- state != MM_MODEM_3GPP_REGISTRATION_STATE_SEARCHING && \
- state != MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING)
-
-#undef REG_IS_DONE
-#define REG_IS_DONE(state) \
- (state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME || \
- state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING || \
- state == MM_MODEM_3GPP_REGISTRATION_STATE_DENIED)
-
-static void run_3gpp_registration_checks_ready (MMBroadbandModem *self,
- GAsyncResult *res,
- RegisterIn3gppNetworkContext *ctx);
-
-static gboolean
-run_3gpp_registration_checks_again (RegisterIn3gppNetworkContext *ctx)
-{
- /* Get fresh registration state */
- mm_iface_modem_3gpp_run_registration_checks (
- MM_IFACE_MODEM_3GPP (ctx->self),
- (GAsyncReadyCallback)run_3gpp_registration_checks_ready,
- ctx);
- return FALSE;
-}
-
-static void
-run_3gpp_registration_checks_ready (MMBroadbandModem *self,
- GAsyncResult *res,
- RegisterIn3gppNetworkContext *ctx)
-{
- GError *error = NULL;
-
- mm_iface_modem_3gpp_run_registration_checks_finish (MM_IFACE_MODEM_3GPP (self),
- res,
- &error);
-
- if (error) {
- mm_dbg ("3GPP registration check failed: '%s'", error->message);
- mm_iface_modem_3gpp_update_ps_registration_state (MM_IFACE_MODEM_3GPP (self),
- MM_MODEM_3GPP_REGISTRATION_STATE_IDLE,
- MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN,
- 0, 0);
- mm_iface_modem_3gpp_update_cs_registration_state (MM_IFACE_MODEM_3GPP (self),
- MM_MODEM_3GPP_REGISTRATION_STATE_IDLE,
- MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN,
- 0, 0);
- g_simple_async_result_take_error (ctx->result, error);
- register_in_3gpp_network_context_complete_and_free (ctx);
- return;
- }
-
- /* If we got registered, end registration checks */
- if (REG_IS_DONE (self->priv->modem_3gpp_registration_state)) {
- mm_dbg ("Modem is currently registered in a 3GPP network");
- g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
- register_in_3gpp_network_context_complete_and_free (ctx);
- return;
- }
-
- /* Don't spend too much time waiting to get registered */
- if (g_timer_elapsed (ctx->timer, NULL) > ctx->max_registration_time) {
- mm_dbg ("3GPP registration check timed out");
- mm_iface_modem_3gpp_update_cs_registration_state (MM_IFACE_MODEM_3GPP (self),
- MM_MODEM_3GPP_REGISTRATION_STATE_IDLE,
- MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN,
- 0, 0);
- mm_iface_modem_3gpp_update_ps_registration_state (MM_IFACE_MODEM_3GPP (self),
- MM_MODEM_3GPP_REGISTRATION_STATE_IDLE,
- MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN,
- 0, 0);
- g_simple_async_result_take_error (
- ctx->result,
- mm_mobile_equipment_error_for_code (MM_MOBILE_EQUIPMENT_ERROR_NETWORK_TIMEOUT));
- register_in_3gpp_network_context_complete_and_free (ctx);
- return;
- }
-
- /* If we're still waiting for automatic registration to complete or
- * fail, check again in a few seconds.
- *
- * This 3s timeout will catch results from automatic registrations as
- * well.
- */
- mm_dbg ("Modem not yet registered in a 3GPP network... will recheck soon");
- g_timeout_add_seconds (3,
- (GSourceFunc)run_3gpp_registration_checks_again,
- ctx);
-}
-
-static void
-register_in_3gpp_network_ready (MMBroadbandModem *self,
- GAsyncResult *res,
- RegisterIn3gppNetworkContext *ctx)
-{
- GError *error = NULL;
-
- mm_base_modem_at_command_full_finish (MM_BASE_MODEM (self), res, &error);
-
- if (error) {
- /* Propagate error in COPS, if any */
- mm_iface_modem_3gpp_update_cs_registration_state (MM_IFACE_MODEM_3GPP (self),
- MM_MODEM_3GPP_REGISTRATION_STATE_IDLE,
- MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN,
- 0, 0);
- mm_iface_modem_3gpp_update_ps_registration_state (MM_IFACE_MODEM_3GPP (self),
- MM_MODEM_3GPP_REGISTRATION_STATE_IDLE,
- MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN,
- 0, 0);
- g_simple_async_result_take_error (ctx->result, error);
- register_in_3gpp_network_context_complete_and_free (ctx);
- return;
- }
-
- /* Get fresh registration state */
- ctx->timer = g_timer_new ();
- mm_iface_modem_3gpp_run_registration_checks (
- MM_IFACE_MODEM_3GPP (self),
- (GAsyncReadyCallback)run_3gpp_registration_checks_ready,
- ctx);
+ return !!mm_base_modem_at_command_full_finish (MM_BASE_MODEM (self), res, error);
}
static void
modem_3gpp_register_in_network (MMIfaceModem3gpp *self,
const gchar *operator_id,
- guint max_registration_time,
+ GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
- MMBroadbandModem *broadband = MM_BROADBAND_MODEM (self);
- RegisterIn3gppNetworkContext *ctx;
- gchar *command = NULL;
- GError *error = NULL;
-
- /* Validate input MCC/MNC */
- if (operator_id && !mm_3gpp_parse_operator_id (operator_id, NULL, NULL, &error)) {
- g_assert (error != NULL);
- g_simple_async_report_take_gerror_in_idle (G_OBJECT (self),
- callback,
- user_data,
- error);
- return;
- }
-
- /* (Try to) cancel previous registration request */
- if (broadband->priv->modem_3gpp_pending_registration_cancellable) {
- g_cancellable_cancel (broadband->priv->modem_3gpp_pending_registration_cancellable);
- g_clear_object (&broadband->priv->modem_3gpp_pending_registration_cancellable);
- }
-
- ctx = g_new0 (RegisterIn3gppNetworkContext, 1);
- ctx->self = g_object_ref (self);
- ctx->max_registration_time = max_registration_time;
- ctx->result = g_simple_async_result_new (G_OBJECT (self),
- callback,
- user_data,
- modem_3gpp_register_in_network);
- ctx->cancellable = g_cancellable_new ();
-
- /* Keep an accessible reference to the cancellable, so that we can cancel
- * previous request when needed */
- broadband->priv->modem_3gpp_pending_registration_cancellable =
- g_object_ref (ctx->cancellable);
+ gchar *command;
/* If the user sent a specific network to use, lock it in. */
- if (operator_id && operator_id[0]) {
+ if (operator_id)
command = g_strdup_printf ("+COPS=1,2,\"%s\"", operator_id);
- broadband->priv->modem_3gpp_manual_registration = TRUE;
- }
/* If no specific network was given, and the modem is not registered and not
* searching, kick it to search for a network. Also do auto registration if
* the modem had been set to manual registration last time but now is not.
*/
- else if (REG_IS_IDLE (broadband->priv->modem_3gpp_registration_state) ||
- broadband->priv->modem_3gpp_manual_registration) {
+ else
/* Note that '+COPS=0,,' (same but with commas) won't work in some Nokia
* phones */
command = g_strdup ("+COPS=0");
- broadband->priv->modem_3gpp_manual_registration = FALSE;
- }
-
- if (command) {
- /* Don't setup an additional timeout to handle registration timeouts. We
- * already do this with the 120s timeout in the AT command: if that times
- * out, we can consider the registration itself timed out.
- *
- * NOTE that we provide our own Cancellable here; we want to be able to
- * cancel the operation at any time. */
- mm_base_modem_at_command_full (MM_BASE_MODEM (self),
- mm_base_modem_peek_best_at_port (MM_BASE_MODEM (self), NULL),
- command,
- 120,
- FALSE,
- FALSE, /* raw */
- ctx->cancellable,
- (GAsyncReadyCallback)register_in_3gpp_network_ready,
- ctx);
- g_free (command);
- return;
- }
-
- /* Just rely on the unsolicited registration and periodic registration checks */
- mm_dbg ("Not launching any new network selection request");
- /* Get fresh registration state */
- ctx->timer = g_timer_new ();
- mm_iface_modem_3gpp_run_registration_checks (
- MM_IFACE_MODEM_3GPP (self),
- (GAsyncReadyCallback)run_3gpp_registration_checks_ready,
- ctx);
+ mm_base_modem_at_command_full (MM_BASE_MODEM (self),
+ mm_base_modem_peek_best_at_port (MM_BASE_MODEM (self), NULL),
+ command,
+ 120,
+ FALSE,
+ FALSE, /* raw */
+ cancellable,
+ callback,
+ user_data);
}
/*****************************************************************************/
diff --git a/src/mm-iface-modem-3gpp.c b/src/mm-iface-modem-3gpp.c
index 4056284f..f2cd62f4 100644
--- a/src/mm-iface-modem-3gpp.c
+++ b/src/mm-iface-modem-3gpp.c
@@ -24,6 +24,7 @@
#include "mm-iface-modem-3gpp.h"
#include "mm-base-modem.h"
#include "mm-modem-helpers.h"
+#include "mm-error-helpers.h"
#include "mm-log.h"
#define REGISTRATION_CHECK_TIMEOUT_SEC 30
@@ -65,6 +66,128 @@ mm_iface_modem_3gpp_bind_simple_status (MMIfaceModem3gpp *self,
/*****************************************************************************/
+typedef struct {
+ MMModem3gppRegistrationState cs;
+ MMModem3gppRegistrationState ps;
+ gboolean manual_registration;
+ GCancellable *pending_registration_cancellable;
+} RegistrationStateContext;
+
+static void
+registration_state_context_free (RegistrationStateContext *ctx)
+{
+ if (ctx->pending_registration_cancellable) {
+ g_cancellable_cancel (ctx->pending_registration_cancellable);
+ g_object_unref (ctx->pending_registration_cancellable);
+ }
+ g_slice_free (RegistrationStateContext, ctx);
+}
+
+static RegistrationStateContext *
+get_registration_state_context (MMIfaceModem3gpp *self)
+{
+ RegistrationStateContext *ctx;
+
+ if (G_UNLIKELY (!registration_state_context_quark))
+ registration_state_context_quark = (g_quark_from_static_string (
+ REGISTRATION_STATE_CONTEXT_TAG));
+
+ ctx = g_object_get_qdata (G_OBJECT (self), registration_state_context_quark);
+ if (!ctx) {
+ /* Create context and keep it as object data */
+ ctx = g_slice_new0 (RegistrationStateContext);
+ ctx->cs = MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN;
+ ctx->ps = MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN;
+
+ g_object_set_qdata_full (
+ G_OBJECT (self),
+ registration_state_context_quark,
+ ctx,
+ (GDestroyNotify)registration_state_context_free);
+ }
+
+ return ctx;
+}
+
+static MMModem3gppRegistrationState
+get_consolidated_reg_state (RegistrationStateContext *ctx)
+{
+ /* Some devices (Blackberries for example) will respond to +CGREG, but
+ * return ERROR for +CREG, probably because their firmware is just stupid.
+ * So here we prefer the +CREG response, but if we never got a successful
+ * +CREG response, we'll take +CGREG instead.
+ */
+ if (ctx->cs == MM_MODEM_3GPP_REGISTRATION_STATE_HOME ||
+ ctx->cs == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING)
+ return ctx->cs;
+
+ if (ctx->ps == MM_MODEM_3GPP_REGISTRATION_STATE_HOME ||
+ ctx->ps == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING)
+ return ctx->ps;
+
+ if (ctx->cs == MM_MODEM_3GPP_REGISTRATION_STATE_SEARCHING)
+ return ctx->cs;
+
+ if (ctx->ps == MM_MODEM_3GPP_REGISTRATION_STATE_SEARCHING)
+ return ctx->ps;
+
+ return ctx->cs;
+}
+
+/*****************************************************************************/
+
+typedef struct {
+ MMIfaceModem3gpp *self;
+ MmGdbusModem3gpp *skeleton;
+ GSimpleAsyncResult *result;
+ GCancellable *cancellable;
+ gchar *operator_id;
+ GTimer *timer;
+ guint max_registration_time;
+} RegisterInNetworkContext;
+
+static void
+register_in_network_context_complete_and_free (RegisterInNetworkContext *ctx)
+{
+ g_simple_async_result_complete_in_idle (ctx->result);
+ g_object_unref (ctx->result);
+
+ if (ctx->timer)
+ g_timer_destroy (ctx->timer);
+
+ if (ctx->cancellable) {
+ RegistrationStateContext *registration_state_context;
+
+ /* Clear our cancellable if still around */
+ registration_state_context = get_registration_state_context (ctx->self);
+ if (registration_state_context->pending_registration_cancellable == ctx->cancellable)
+ g_clear_object (&registration_state_context->pending_registration_cancellable);
+
+ g_object_unref (ctx->cancellable);
+ }
+
+ g_free (ctx->operator_id);
+ g_object_unref (ctx->skeleton);
+ g_object_unref (ctx->self);
+ g_slice_free (RegisterInNetworkContext, ctx);
+}
+
+static void
+register_in_network_context_failed (RegisterInNetworkContext *ctx,
+ GError *error)
+{
+ mm_iface_modem_3gpp_update_cs_registration_state (ctx->self,
+ MM_MODEM_3GPP_REGISTRATION_STATE_IDLE,
+ MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN,
+ 0, 0);
+ mm_iface_modem_3gpp_update_ps_registration_state (ctx->self,
+ MM_MODEM_3GPP_REGISTRATION_STATE_IDLE,
+ MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN,
+ 0, 0);
+
+ g_simple_async_result_take_error (ctx->result, error);
+}
+
gboolean
mm_iface_modem_3gpp_register_in_network_finish (MMIfaceModem3gpp *self,
GAsyncResult *res,
@@ -73,19 +196,101 @@ mm_iface_modem_3gpp_register_in_network_finish (MMIfaceModem3gpp *self,
return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error);
}
+static void run_registration_checks_ready (MMIfaceModem3gpp *self,
+ GAsyncResult *res,
+ RegisterInNetworkContext *ctx);
+
+static gboolean
+run_registration_checks_again (RegisterInNetworkContext *ctx)
+{
+ /* Get fresh registration state */
+ mm_iface_modem_3gpp_run_registration_checks (
+ ctx->self,
+ (GAsyncReadyCallback)run_registration_checks_ready,
+ ctx);
+ return FALSE;
+}
+
+static void
+run_registration_checks_ready (MMIfaceModem3gpp *self,
+ GAsyncResult *res,
+ RegisterInNetworkContext *ctx)
+{
+ GError *error = NULL;
+ RegistrationStateContext *registration_state_context;
+ MMModem3gppRegistrationState current_registration_state;
+
+ mm_iface_modem_3gpp_run_registration_checks_finish (MM_IFACE_MODEM_3GPP (self), res, &error);
+ if (error) {
+ mm_dbg ("3GPP registration check failed: '%s'", error->message);
+ register_in_network_context_failed (ctx, error);
+ register_in_network_context_complete_and_free (ctx);
+ return;
+ }
+
+ registration_state_context = get_registration_state_context (ctx->self);
+ current_registration_state = get_consolidated_reg_state (registration_state_context);
+
+ /* If we got a final state and it's denied, we can assume the registration is
+ * finished */
+ if (current_registration_state == MM_MODEM_3GPP_REGISTRATION_STATE_DENIED) {
+ mm_dbg ("Registration denied");
+ register_in_network_context_failed (
+ ctx,
+ mm_mobile_equipment_error_for_code (MM_MOBILE_EQUIPMENT_ERROR_NETWORK_NOT_ALLOWED));
+ register_in_network_context_complete_and_free (ctx);
+ return;
+ }
+
+ /* If we got registered, end registration checks */
+ if (current_registration_state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME ||
+ current_registration_state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING) {
+ mm_dbg ("Modem is currently registered in a 3GPP network");
+ g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
+ register_in_network_context_complete_and_free (ctx);
+ return;
+ }
+
+ /* Don't spend too much time waiting to get registered */
+ if (g_timer_elapsed (ctx->timer, NULL) > ctx->max_registration_time) {
+ mm_dbg ("3GPP registration check timed out");
+ register_in_network_context_failed (
+ ctx,
+ mm_mobile_equipment_error_for_code (MM_MOBILE_EQUIPMENT_ERROR_NETWORK_TIMEOUT));
+ register_in_network_context_complete_and_free (ctx);
+ return;
+ }
+
+ /* If we're still waiting for automatic registration to complete or
+ * fail, check again in a few seconds.
+ *
+ * This 3s timeout will catch results from automatic registrations as
+ * well.
+ */
+ mm_dbg ("Modem not yet registered in a 3GPP network... will recheck soon");
+ g_timeout_add_seconds (3, (GSourceFunc)run_registration_checks_again, ctx);
+}
+
static void
register_in_network_ready (MMIfaceModem3gpp *self,
GAsyncResult *res,
- GSimpleAsyncResult *simple)
+ RegisterInNetworkContext *ctx)
{
GError *error = NULL;
- if (!MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->register_in_network_finish (self, res, &error))
- g_simple_async_result_take_error (simple, error);
- else
- g_simple_async_result_set_op_res_gboolean (simple, TRUE);
- g_simple_async_result_complete (simple);
- g_object_unref (simple);
+ if (!MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->register_in_network_finish (self, res, &error)) {
+ /* Propagate error when trying to lock to network */
+ register_in_network_context_failed (ctx, error);
+ register_in_network_context_complete_and_free (ctx);
+ return;
+ }
+
+ /* Now try to gather current registration status until we're registered or
+ * the time goes off */
+ mm_iface_modem_3gpp_run_registration_checks (
+ self,
+ (GAsyncReadyCallback)run_registration_checks_ready,
+ ctx);
}
void
@@ -95,38 +300,93 @@ mm_iface_modem_3gpp_register_in_network (MMIfaceModem3gpp *self,
GAsyncReadyCallback callback,
gpointer user_data)
{
- GSimpleAsyncResult *result;
- MmGdbusModem3gpp *skeleton;
+ RegisterInNetworkContext *ctx;
const gchar *current_operator_code;
+ RegistrationStateContext *registration_state_context;
+ GError *error = NULL;
- result = g_simple_async_result_new (G_OBJECT (self),
- callback,
- user_data,
- mm_iface_modem_3gpp_register_in_network);
-
- /* If no operator ID given, or if we're already registered with the requested one,
- * then we're done */
+ ctx = g_slice_new0 (RegisterInNetworkContext);
+ ctx->self = g_object_ref (self);
+ ctx->result = g_simple_async_result_new (G_OBJECT (self),
+ callback,
+ user_data,
+ mm_iface_modem_3gpp_register_in_network);
+ ctx->operator_id = (operator_id && operator_id[0]) ? g_strdup (operator_id) : NULL;
+ ctx->max_registration_time = max_registration_time;
g_object_get (self,
- MM_IFACE_MODEM_3GPP_DBUS_SKELETON, &skeleton,
+ MM_IFACE_MODEM_3GPP_DBUS_SKELETON, &ctx->skeleton,
NULL);
- current_operator_code = mm_gdbus_modem3gpp_get_operator_code (skeleton);
- if (current_operator_code &&
- (!operator_id || g_str_equal (current_operator_code, operator_id))) {
- /* Already registered, no need to request it again */
- mm_dbg ("Already registered in network '%s'...", current_operator_code);
- g_simple_async_result_set_op_res_gboolean (result, TRUE);
- g_simple_async_result_complete_in_idle (result);
- g_object_unref (result);
- } else {
- MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->register_in_network (
- self,
- operator_id,
- max_registration_time,
- (GAsyncReadyCallback)register_in_network_ready,
- result);
+
+ /* Validate input MCC/MNC */
+ if (ctx->operator_id && !mm_3gpp_parse_operator_id (ctx->operator_id, NULL, NULL, &error)) {
+ g_assert (error != NULL);
+ g_simple_async_result_take_error (ctx->result, error);
+ register_in_network_context_complete_and_free (ctx);
+ return;
}
- g_object_unref (skeleton);
+ /* Get registration state context */
+ registration_state_context = get_registration_state_context (self);
+
+ /* (Try to) cancel previous registration request */
+ if (registration_state_context->pending_registration_cancellable) {
+ g_cancellable_cancel (registration_state_context->pending_registration_cancellable);
+ g_clear_object (&registration_state_context->pending_registration_cancellable);
+ }
+
+ current_operator_code = mm_gdbus_modem3gpp_get_operator_code (ctx->skeleton);
+
+ /* Manual registration requested? */
+ if (ctx->operator_id) {
+ /* If already registered with the requested operator, we're done */
+ if (current_operator_code &&
+ g_str_equal (current_operator_code, ctx->operator_id)) {
+ registration_state_context->manual_registration = TRUE;
+ mm_dbg ("Already registered in selected network '%s'...",
+ current_operator_code);
+ g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
+ register_in_network_context_complete_and_free (ctx);
+ return;
+ }
+
+ /* Manual registration to a new operator required */
+ mm_dbg ("Launching manual network registration (%s)...",
+ ctx->operator_id);
+ registration_state_context->manual_registration = TRUE;
+ }
+ /* Automatic registration requested? */
+ else {
+ /* If the modem is already registered and the last time it was asked
+ * automatic registration, we're done */
+ if (current_operator_code &&
+ !registration_state_context->manual_registration) {
+ mm_dbg ("Already registered in network '%s',"
+ " automatic registration not launched...",
+ current_operator_code);
+ g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
+ register_in_network_context_complete_and_free (ctx);
+ return;
+ }
+
+ /* Automatic registration to a new operator requested */
+ mm_dbg ("Launching automatic network registration...");
+ registration_state_context->manual_registration = FALSE;
+ }
+
+ ctx->cancellable = g_cancellable_new ();
+
+ /* Keep an accessible reference to the cancellable, so that we can cancel
+ * previous request when needed */
+ registration_state_context->pending_registration_cancellable =
+ g_object_ref (ctx->cancellable);
+
+ ctx->timer = g_timer_new ();
+ MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->register_in_network (
+ self,
+ ctx->operator_id,
+ ctx->cancellable,
+ (GAsyncReadyCallback)register_in_network_ready,
+ ctx);
}
typedef struct {
@@ -436,8 +696,8 @@ handle_scan (MmGdbusModem3gpp *skeleton,
gboolean
mm_iface_modem_3gpp_run_registration_checks_finish (MMIfaceModem3gpp *self,
- GAsyncResult *res,
- GError **error)
+ GAsyncResult *res,
+ GError **error)
{
g_assert (MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->run_registration_checks_finish != NULL);
return MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->run_registration_checks_finish (self, res, error);
@@ -665,62 +925,6 @@ update_registration_state (MMIfaceModem3gpp *self,
g_object_unref (skeleton);
}
-typedef struct {
- MMModem3gppRegistrationState cs;
- MMModem3gppRegistrationState ps;
-} RegistrationStateContext;
-
-static RegistrationStateContext *
-get_registration_state_context (MMIfaceModem3gpp *self)
-{
- RegistrationStateContext *ctx;
-
- if (G_UNLIKELY (!registration_state_context_quark))
- registration_state_context_quark = (g_quark_from_static_string (
- REGISTRATION_STATE_CONTEXT_TAG));
-
- ctx = g_object_get_qdata (G_OBJECT (self), registration_state_context_quark);
- if (!ctx) {
- /* Create context and keep it as object data */
- ctx = g_new0 (RegistrationStateContext, 1);
- ctx->cs = MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN;
- ctx->ps = MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN;
-
- g_object_set_qdata_full (
- G_OBJECT (self),
- registration_state_context_quark,
- ctx,
- (GDestroyNotify)g_free);
- }
-
- return ctx;
-}
-
-static MMModem3gppRegistrationState
-get_consolidated_reg_state (RegistrationStateContext *ctx)
-{
- /* Some devices (Blackberries for example) will respond to +CGREG, but
- * return ERROR for +CREG, probably because their firmware is just stupid.
- * So here we prefer the +CREG response, but if we never got a successful
- * +CREG response, we'll take +CGREG instead.
- */
- if (ctx->cs == MM_MODEM_3GPP_REGISTRATION_STATE_HOME ||
- ctx->cs == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING)
- return ctx->cs;
-
- if (ctx->ps == MM_MODEM_3GPP_REGISTRATION_STATE_HOME ||
- ctx->ps == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING)
- return ctx->ps;
-
- if (ctx->cs == MM_MODEM_3GPP_REGISTRATION_STATE_SEARCHING)
- return ctx->cs;
-
- if (ctx->ps == MM_MODEM_3GPP_REGISTRATION_STATE_SEARCHING)
- return ctx->ps;
-
- return ctx->cs;
-}
-
void
mm_iface_modem_3gpp_update_cs_registration_state (MMIfaceModem3gpp *self,
MMModem3gppRegistrationState state,
diff --git a/src/mm-iface-modem-3gpp.h b/src/mm-iface-modem-3gpp.h
index c0fe03d0..dc96ff1b 100644
--- a/src/mm-iface-modem-3gpp.h
+++ b/src/mm-iface-modem-3gpp.h
@@ -148,7 +148,7 @@ struct _MMIfaceModem3gpp {
/* Try to register in the network */
void (* register_in_network) (MMIfaceModem3gpp *self,
const gchar *operator_id,
- guint max_registration_time,
+ GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean (*register_in_network_finish) (MMIfaceModem3gpp *self,