From 278842108c2cc1cb887f1afedfbf6cfd4a91d26a Mon Sep 17 00:00:00 2001 From: Aleksander Morgado Date: Mon, 6 Aug 2012 11:58:42 +0200 Subject: iface-modem-3gpp: refactor registration sequences Once upon a time it was a good idea to have separate steps for CS and PS related actions, so that plugins could override specific steps with a great detail. That idea turned out to be not very useful, as the only case which requires custom CS/PS registration actions is the QMI-enabled modem, and that one has commands to act on both registration actions at the same time. So, we now consolidate all steps, so that the implementation of the interface needs to provide all the logic to setup/enable/disable/cleanup/check registrations in each mode. Also, we consolidate how the unsolicited registration messages are handled, so that it's equivalent to other unsolicited messages: * 'Setup' will configure ports to process the unsolicited messages. * 'Enable' will tell the modem to send unsolicited messages. * 'Disable' will tell the modem not to send unsolicited messages. * 'Cleanup will configure ports to ignore the unsolicited messages. --- src/mm-broadband-modem.c | 789 +++++++++++++++++++++++++--------------------- src/mm-iface-modem-3gpp.c | 334 ++++++-------------- src/mm-iface-modem-3gpp.h | 113 +++---- 3 files changed, 559 insertions(+), 677 deletions(-) (limited to 'src') diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c index 3c9cfcb2..04b505df 100644 --- a/src/mm-broadband-modem.c +++ b/src/mm-broadband-modem.c @@ -2486,9 +2486,9 @@ modem_3gpp_load_operator_name (MMIfaceModem3gpp *self, /* Unsolicited registration messages handling (3GPP interface) */ static gboolean -modem_3gpp_setup_unsolicited_registration_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) +modem_3gpp_setup_unsolicited_registration_events_finish (MMIfaceModem3gpp *self, + GAsyncResult *res, + GError **error) { return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error); } @@ -2533,9 +2533,9 @@ registration_state_changed (MMAtSerialPort *port, } static void -modem_3gpp_setup_unsolicited_registration (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) +modem_3gpp_setup_unsolicited_registration_events (MMIfaceModem3gpp *self, + GAsyncReadyCallback callback, + gpointer user_data) { GSimpleAsyncResult *result; MMAtSerialPort *ports[2]; @@ -2546,7 +2546,7 @@ modem_3gpp_setup_unsolicited_registration (MMIfaceModem3gpp *self, result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, - modem_3gpp_setup_unsolicited_registration); + modem_3gpp_setup_unsolicited_registration_events); ports[0] = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)); ports[1] = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self)); @@ -2579,17 +2579,17 @@ modem_3gpp_setup_unsolicited_registration (MMIfaceModem3gpp *self, /* Unsolicited registration messages cleaning up (3GPP interface) */ static gboolean -modem_3gpp_cleanup_unsolicited_registration_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) +modem_3gpp_cleanup_unsolicited_registration_events_finish (MMIfaceModem3gpp *self, + GAsyncResult *res, + GError **error) { return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error); } static void -modem_3gpp_cleanup_unsolicited_registration (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) +modem_3gpp_cleanup_unsolicited_registration_events (MMIfaceModem3gpp *self, + GAsyncReadyCallback callback, + gpointer user_data) { GSimpleAsyncResult *result; MMAtSerialPort *ports[2]; @@ -2600,7 +2600,7 @@ modem_3gpp_cleanup_unsolicited_registration (MMIfaceModem3gpp *self, result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, - modem_3gpp_cleanup_unsolicited_registration); + modem_3gpp_cleanup_unsolicited_registration_events); ports[0] = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)); ports[1] = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self)); @@ -2710,31 +2710,31 @@ modem_3gpp_register_in_network_finish (MMIfaceModem3gpp *self, state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING || \ state == MM_MODEM_3GPP_REGISTRATION_STATE_DENIED) -static void run_all_3gpp_registration_checks_ready (MMBroadbandModem *self, - GAsyncResult *res, - RegisterIn3gppNetworkContext *ctx); +static void run_3gpp_registration_checks_ready (MMBroadbandModem *self, + GAsyncResult *res, + RegisterIn3gppNetworkContext *ctx); static gboolean -run_all_3gpp_registration_checks_again (RegisterIn3gppNetworkContext *ctx) +run_3gpp_registration_checks_again (RegisterIn3gppNetworkContext *ctx) { /* Get fresh registration state */ - mm_iface_modem_3gpp_run_all_registration_checks ( + mm_iface_modem_3gpp_run_registration_checks ( MM_IFACE_MODEM_3GPP (ctx->self), - (GAsyncReadyCallback)run_all_3gpp_registration_checks_ready, + (GAsyncReadyCallback)run_3gpp_registration_checks_ready, ctx); return FALSE; } static void -run_all_3gpp_registration_checks_ready (MMBroadbandModem *self, - GAsyncResult *res, - RegisterIn3gppNetworkContext *ctx) +run_3gpp_registration_checks_ready (MMBroadbandModem *self, + GAsyncResult *res, + RegisterIn3gppNetworkContext *ctx) { GError *error = NULL; - mm_iface_modem_3gpp_run_all_registration_checks_finish (MM_IFACE_MODEM_3GPP (self), - res, - &error); + 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); @@ -2785,7 +2785,7 @@ run_all_3gpp_registration_checks_ready (MMBroadbandModem *self, */ mm_dbg ("Modem not yet registered in a 3GPP network... will recheck soon"); g_timeout_add_seconds (3, - (GSourceFunc)run_all_3gpp_registration_checks_again, + (GSourceFunc)run_3gpp_registration_checks_again, ctx); } @@ -2815,9 +2815,9 @@ register_in_3gpp_network_ready (MMBroadbandModem *self, /* Get fresh registration state */ ctx->timer = g_timer_new (); - mm_iface_modem_3gpp_run_all_registration_checks ( + mm_iface_modem_3gpp_run_registration_checks ( MM_IFACE_MODEM_3GPP (self), - (GAsyncReadyCallback)run_all_3gpp_registration_checks_ready, + (GAsyncReadyCallback)run_3gpp_registration_checks_ready, ctx); } @@ -2893,334 +2893,303 @@ modem_3gpp_register_in_network (MMIfaceModem3gpp *self, /* Get fresh registration state */ ctx->timer = g_timer_new (); - mm_iface_modem_3gpp_run_all_registration_checks ( + mm_iface_modem_3gpp_run_registration_checks ( MM_IFACE_MODEM_3GPP (self), - (GAsyncReadyCallback)run_all_3gpp_registration_checks_ready, + (GAsyncReadyCallback)run_3gpp_registration_checks_ready, ctx); } /*****************************************************************************/ -/* CS and PS Registration checks (3GPP interface) */ +/* Registration checks (3GPP interface) */ -static gboolean -modem_3gpp_run_cs_registration_check_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) +typedef struct { + MMBroadbandModem *self; + GSimpleAsyncResult *result; + gboolean cs_supported; + gboolean ps_supported; + gboolean run_cs; + gboolean run_ps; + gboolean running_cs; + gboolean running_ps; + GError *cs_error; + GError *ps_error; +} RunRegistrationChecksContext; + +static void +run_registration_checks_context_complete_and_free (RunRegistrationChecksContext *ctx) { - return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error); + g_simple_async_result_complete_in_idle (ctx->result); + if (ctx->cs_error) + g_error_free (ctx->cs_error); + if (ctx->ps_error) + g_error_free (ctx->ps_error); + g_object_unref (ctx->result); + g_object_unref (ctx->self); + g_free (ctx); } static gboolean -modem_3gpp_run_ps_registration_check_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) +modem_3gpp_run_registration_checks_finish (MMIfaceModem3gpp *self, + GAsyncResult *res, + GError **error) { return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error); } +static void run_registration_checks_context_step (RunRegistrationChecksContext *ctx); + static void registration_status_check_ready (MMBroadbandModem *self, GAsyncResult *res, - GSimpleAsyncResult *operation_result) + RunRegistrationChecksContext *ctx) { const gchar *response; GError *error = NULL; + GMatchInfo *match_info; + guint i; + gboolean parsed; + gboolean cgreg; + MMModem3gppRegistrationState state; + MMModemAccessTechnology act; + gulong lac; + gulong cid; + + /* Only one must be running */ + g_assert (!(ctx->running_ps && ctx->running_cs) && + (ctx->running_cs || ctx->running_ps)); response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); if (!response) { g_assert (error != NULL); - g_simple_async_result_take_error (operation_result, error); + if (ctx->running_cs) + ctx->cs_error = error; + else + ctx->ps_error = error; + + run_registration_checks_context_step (ctx); + return; } + /* Unsolicited registration status handlers will usually process the * response for us, but just in case they don't, do that here. */ - else if (!response[0]) + if (!response[0]) { /* Done */ - g_simple_async_result_set_op_res_gboolean (operation_result, TRUE); - else { - GMatchInfo *match_info; - guint i; - - /* Try to match the response */ - for (i = 0; - i < self->priv->modem_3gpp_registration_regex->len; - i++) { - if (g_regex_match ((GRegex *)g_ptr_array_index ( - self->priv->modem_3gpp_registration_regex, i), - response, - 0, - &match_info)) - break; - g_match_info_free (match_info); - match_info = NULL; - } - - if (!match_info) { - g_simple_async_result_set_error (operation_result, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Unknown registration status response: '%s'", - response); - } else { - GError *inner_error = NULL; - gboolean parsed; - gboolean cgreg = FALSE; - MMModem3gppRegistrationState state = MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN; - MMModemAccessTechnology act = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; - gulong lac = 0; - gulong cid = 0; - - parsed = mm_3gpp_parse_creg_response (match_info, - &state, - &lac, - &cid, - &act, - &cgreg, - &inner_error); - g_match_info_free (match_info); - - if (!parsed) { - if (inner_error) - g_simple_async_result_take_error (operation_result, inner_error); - else - g_simple_async_result_set_error (operation_result, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Error parsing registration response: '%s'", - response); - } else { - /* Report new registration state */ - if (cgreg) - mm_iface_modem_3gpp_update_ps_registration_state ( - MM_IFACE_MODEM_3GPP (self), - state, - act, - lac, - cid); - else - mm_iface_modem_3gpp_update_cs_registration_state ( - MM_IFACE_MODEM_3GPP (self), - state, - act, - lac, - cid); - - g_simple_async_result_set_op_res_gboolean (operation_result, TRUE); - } - } + run_registration_checks_context_step (ctx); + return; } - g_simple_async_result_complete (operation_result); - g_object_unref (operation_result); -} - -static void -modem_3gpp_run_cs_registration_check (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GSimpleAsyncResult *result; - - result = g_simple_async_result_new (G_OBJECT (self), - callback, - user_data, - modem_3gpp_run_cs_registration_check); - - /* Check current CS-registration state. */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CREG?", - 10, - FALSE, - (GAsyncReadyCallback)registration_status_check_ready, - result); -} - -static void -modem_3gpp_run_ps_registration_check (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GSimpleAsyncResult *result; - - result = g_simple_async_result_new (G_OBJECT (self), - callback, - user_data, - modem_3gpp_run_ps_registration_check); - - /* Check current PS-registration state. */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CGREG?", - 10, - FALSE, - (GAsyncReadyCallback)registration_status_check_ready, - result); -} - -/*****************************************************************************/ -/* CS and PS Registrations cleanup (3GPP interface) */ - -typedef struct { - GSimpleAsyncResult *result; - gchar *command; - gboolean secondary_done; -} CleanupRegistrationContext; - -static void -cleanup_registration_context_free (CleanupRegistrationContext *ctx) -{ - g_object_unref (ctx->result); - g_free (ctx->command); - g_free (ctx); -} - -static gboolean -modem_3gpp_cleanup_cs_registration_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error); -} - -static gboolean -modem_3gpp_cleanup_ps_registration_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error); -} + /* Try to match the response */ + for (i = 0; + i < self->priv->modem_3gpp_registration_regex->len; + i++) { + if (g_regex_match ((GRegex *)g_ptr_array_index ( + self->priv->modem_3gpp_registration_regex, i), + response, + 0, + &match_info)) + break; + g_match_info_free (match_info); + match_info = NULL; + } -static void -cleanup_registration_sequence_ready (MMBroadbandModem *self, - GAsyncResult *res, - CleanupRegistrationContext *ctx) -{ - GError *error = NULL; + if (!match_info) { + error = g_error_new (MM_CORE_ERROR, + MM_CORE_ERROR_FAILED, + "Unknown registration status response: '%s'", + response); + if (ctx->running_cs) + ctx->cs_error = error; + else + ctx->ps_error = error; - mm_base_modem_at_command_full_finish (MM_BASE_MODEM (self), res, &error); - if (error) { - g_simple_async_result_take_error (ctx->result, error); - g_simple_async_result_complete (ctx->result); - cleanup_registration_context_free (ctx); + run_registration_checks_context_step (ctx); return; } - if (!ctx->secondary_done) { - MMAtSerialPort *secondary; + cgreg = FALSE; + state = MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN; + act = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; + lac = 0; + cid = 0; + parsed = mm_3gpp_parse_creg_response (match_info, + &state, + &lac, + &cid, + &act, + &cgreg, + &error); + g_match_info_free (match_info); - secondary = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self)); - if (secondary) { - /* Now use the same registration setup in secondary port, if any */ - ctx->secondary_done = TRUE; - mm_base_modem_at_command_full ( - MM_BASE_MODEM (self), - secondary, - ctx->command, - 10, - FALSE, - NULL, /* cancellable */ - (GAsyncReadyCallback)cleanup_registration_sequence_ready, - ctx); - return; - } + if (!parsed) { + if (!error) + error = g_error_new (MM_CORE_ERROR, + MM_CORE_ERROR_FAILED, + "Error parsing registration response: '%s'", + response); + if (ctx->running_cs) + ctx->cs_error = error; + else + ctx->ps_error = error; + run_registration_checks_context_step (ctx); + return; } - /* Update registration state(s) */ - if (g_str_has_prefix (ctx->command, "+CREG")) - 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); - else + /* Report new registration state */ + if (cgreg) { + if (ctx->running_cs) + mm_dbg ("Got PS registration state when checking CS registration state"); 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); + state, + act, + lac, + cid); + } else { + if (ctx->running_ps) + mm_dbg ("Got CS registration state when checking PS registration state"); + mm_iface_modem_3gpp_update_cs_registration_state ( + MM_IFACE_MODEM_3GPP (self), + state, + act, + lac, + cid); + } - /* We're done */ - g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); - g_simple_async_result_complete (ctx->result); - cleanup_registration_context_free (ctx); + run_registration_checks_context_step (ctx); } static void -modem_3gpp_cleanup_cs_registration (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) +run_registration_checks_context_step (RunRegistrationChecksContext *ctx) { - CleanupRegistrationContext *ctx; + ctx->running_cs = FALSE; + ctx->running_ps = FALSE; - ctx = g_new0 (CleanupRegistrationContext, 1); - ctx->result = g_simple_async_result_new (G_OBJECT (self), - callback, - user_data, - modem_3gpp_cleanup_cs_registration); - ctx->command = g_strdup ("+CREG=0"); + if (ctx->run_cs) { + ctx->running_cs = TRUE; + ctx->run_cs = FALSE; + /* Check current CS-registration state. */ + mm_base_modem_at_command (MM_BASE_MODEM (ctx->self), + "+CREG?", + 10, + FALSE, + (GAsyncReadyCallback)registration_status_check_ready, + ctx); + return; + } - mm_base_modem_at_command_full ( - MM_BASE_MODEM (self), - mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)), - ctx->command, - 10, - FALSE, - NULL, /* cancellable */ - (GAsyncReadyCallback)cleanup_registration_sequence_ready, - ctx); + if (ctx->run_ps) { + ctx->running_ps = TRUE; + ctx->run_ps = FALSE; + /* Check current PS-registration state. */ + mm_base_modem_at_command (MM_BASE_MODEM (ctx->self), + "+CGREG?", + 10, + FALSE, + (GAsyncReadyCallback)registration_status_check_ready, + ctx); + return; + } + + /* If all run checks returned errors we fail */ + if ((ctx->ps_supported && ctx->ps_error && ctx->cs_supported && ctx->cs_error) || + (ctx->ps_supported && ctx->ps_error && !ctx->cs_supported) || + (ctx->cs_supported && ctx->cs_error && !ctx->ps_supported)) { + /* Prefer the PS error if any */ + if (ctx->ps_error) { + g_simple_async_result_set_from_error (ctx->result, ctx->ps_error); + ctx->ps_error = NULL; + } else if (ctx->cs_error) { + g_simple_async_result_set_from_error (ctx->result, ctx->cs_error); + ctx->cs_error = NULL; + } else + g_assert_not_reached (); + } else + g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); + + run_registration_checks_context_complete_and_free (ctx); } static void -modem_3gpp_cleanup_ps_registration (MMIfaceModem3gpp *self, +modem_3gpp_run_registration_checks (MMIfaceModem3gpp *self, + gboolean cs_supported, + gboolean ps_supported, GAsyncReadyCallback callback, gpointer user_data) { - CleanupRegistrationContext *ctx; + RunRegistrationChecksContext *ctx; - ctx = g_new0 (CleanupRegistrationContext, 1); + ctx = g_new0 (RunRegistrationChecksContext, 1); + ctx->self = g_object_ref (self); ctx->result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, - modem_3gpp_cleanup_cs_registration); - ctx->command = g_strdup ("+CGREG=0"); + modem_3gpp_run_registration_checks); + ctx->cs_supported = cs_supported; + ctx->ps_supported = ps_supported; + ctx->run_cs = cs_supported; + ctx->run_ps = ps_supported; - mm_base_modem_at_command_full ( - MM_BASE_MODEM (self), - mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)), - ctx->command, - 10, - FALSE, - NULL, /* cancellable */ - (GAsyncReadyCallback)cleanup_registration_sequence_ready, - ctx); + run_registration_checks_context_step (ctx); } /*****************************************************************************/ -/* CS and PS Registrations setup (3GPP interface) */ +/* Enable/Disable unsolicited registration events (3GPP interface) */ typedef struct { + MMBroadbandModem *self; GSimpleAsyncResult *result; + gboolean enable; /* TRUE for enabling, FALSE for disabling */ + gboolean run_cs; + gboolean run_ps; + gboolean running_cs; + gboolean running_ps; + GError *cs_error; + GError *ps_error; + gboolean secondary_sequence; gboolean secondary_done; -} SetupRegistrationContext; +} UnsolicitedRegistrationEventsContext; static void -setup_registration_context_free (SetupRegistrationContext *ctx) +unsolicited_registration_events_context_complete_and_free (UnsolicitedRegistrationEventsContext *ctx) { + g_simple_async_result_complete_in_idle (ctx->result); + if (ctx->cs_error) + g_error_free (ctx->cs_error); + if (ctx->ps_error) + g_error_free (ctx->ps_error); g_object_unref (ctx->result); + g_object_unref (ctx->self); g_free (ctx); } -static gboolean -modem_3gpp_setup_cs_registration_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) +static UnsolicitedRegistrationEventsContext * +unsolicited_registration_events_context_new (MMBroadbandModem *self, + gboolean enable, + gboolean cs_supported, + gboolean ps_supported, + GAsyncReadyCallback callback, + gpointer user_data) { - return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error); + UnsolicitedRegistrationEventsContext *ctx; + + ctx = g_new0 (UnsolicitedRegistrationEventsContext, 1); + ctx->self = g_object_ref (self); + ctx->result = g_simple_async_result_new (G_OBJECT (self), + callback, + user_data, + unsolicited_registration_events_context_new); + ctx->enable = FALSE; + ctx->run_cs = cs_supported; + ctx->run_ps = ps_supported; + + return ctx; } static gboolean -modem_3gpp_setup_ps_registration_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) +modem_3gpp_enable_disable_unsolicited_registration_events_finish (MMIfaceModem3gpp *self, + GAsyncResult *res, + GError **error) { return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error); } @@ -3252,6 +3221,12 @@ static const MMBaseModemAtCommand cs_registration_sequence[] = { { NULL } }; +static const MMBaseModemAtCommand cs_unregistration_sequence[] = { + /* Disable unsolicited registration notifications in CS network */ + { "+CREG=0", 3, FALSE, parse_registration_setup_reply }, + { NULL } +}; + static const MMBaseModemAtCommand ps_registration_sequence[] = { /* Enable unsolicited registration notifications in PS network, with location */ { "+CGREG=2", 3, FALSE, parse_registration_setup_reply }, @@ -3260,103 +3235,195 @@ static const MMBaseModemAtCommand ps_registration_sequence[] = { { NULL } }; +static const MMBaseModemAtCommand ps_unregistration_sequence[] = { + /* Disable unsolicited registration notifications in PS network */ + { "+CGREG=0", 3, FALSE, parse_registration_setup_reply }, + { NULL } +}; + +static void unsolicited_registration_events_context_step (UnsolicitedRegistrationEventsContext *ctx); + static void -setup_registration_sequence_ready (MMBroadbandModem *self, - GAsyncResult *res, - SetupRegistrationContext *ctx) +unsolicited_registration_events_sequence_ready (MMBroadbandModem *self, + GAsyncResult *res, + UnsolicitedRegistrationEventsContext *ctx) { GError *error = NULL; + GVariant *command; + MMAtSerialPort *secondary; + + /* Only one must be running */ + g_assert (!(ctx->running_ps && ctx->running_cs) && + (ctx->running_cs || ctx->running_ps)); if (ctx->secondary_done) { - mm_base_modem_at_command_full_finish (MM_BASE_MODEM (self), res, &error); + if (ctx->secondary_sequence) + mm_base_modem_at_sequence_finish (MM_BASE_MODEM (self), res, NULL, &error); + else + mm_base_modem_at_command_full_finish (MM_BASE_MODEM (self), res, &error); + if (error) { - g_simple_async_result_take_error (ctx->result, error); - g_simple_async_result_complete (ctx->result); - setup_registration_context_free (ctx); - return; - } - /* success */ - } else { - GVariant *command; - MMAtSerialPort *secondary; - - command = mm_base_modem_at_sequence_finish (MM_BASE_MODEM (self), res, NULL, &error); - if (!command) { - g_assert (error != NULL); - g_simple_async_result_take_error (ctx->result, error); - g_simple_async_result_complete (ctx->result); - setup_registration_context_free (ctx); - return; + mm_dbg ("%s unsolicited registration events in secondary port failed: '%s'", + ctx->enable ? "Enabling" : "Disabling", + error->message); + /* Keep errors reported */ + if (ctx->running_cs && !ctx->cs_error) + ctx->cs_error = error; + else if (ctx->running_ps && !ctx->ps_error) + ctx->ps_error = error; + else + g_error_free (error); + } else { + /* If successful in secondary port, cleanup primary error if any */ + if (ctx->running_cs && ctx->cs_error) { + g_error_free (ctx->cs_error); + ctx->cs_error = NULL; + } + else if (ctx->running_ps && ctx->ps_error) { + g_error_free (ctx->ps_error); + ctx->ps_error = NULL; + } } - secondary = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self)); - if (secondary) { - /* Now use the same registration setup in secondary port, if any */ - ctx->secondary_done = TRUE; + /* Done with primary and secondary, keep on */ + unsolicited_registration_events_context_step (ctx); + return; + } + + /* We just run the sequence in the primary port */ + command = mm_base_modem_at_sequence_finish (MM_BASE_MODEM (self), res, NULL, &error); + if (!command) { + g_assert (error != NULL); + mm_dbg ("%s unsolicited registration events in primary port failed: '%s'", + ctx->enable ? "Enabling" : "Disabling", + error->message); + /* Keep errors reported */ + if (ctx->running_cs) + ctx->cs_error = error; + else + ctx->ps_error = error; + /* Even if primary failed, go on and try to enable in secondary port */ + } + + secondary = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self)); + if (secondary) { + ctx->secondary_done = TRUE; + + /* Now use the same registration setup in secondary port, if any */ + if (command) { mm_base_modem_at_command_full ( MM_BASE_MODEM (self), - mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)), + secondary, g_variant_get_string (command, NULL), 3, FALSE, NULL, /* cancellable */ - (GAsyncReadyCallback)setup_registration_sequence_ready, + (GAsyncReadyCallback)unsolicited_registration_events_sequence_ready, ctx); return; } - /* success */ + + /* If primary failed, run the whole sequence in secondary */ + ctx->secondary_sequence = TRUE; + mm_base_modem_at_sequence_full ( + MM_BASE_MODEM (self), + secondary, + (ctx->running_cs ? + (ctx->enable ? cs_registration_sequence : cs_unregistration_sequence) : + (ctx->enable ? ps_registration_sequence : ps_unregistration_sequence)), + NULL, /* response processor context */ + NULL, /* response processor context free */ + NULL, /* cancellable */ + (GAsyncReadyCallback)unsolicited_registration_events_sequence_ready, + ctx); + return; } /* We're done */ - g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); - g_simple_async_result_complete (ctx->result); - setup_registration_context_free (ctx); + unsolicited_registration_events_context_step (ctx); } static void -modem_3gpp_setup_cs_registration (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) +unsolicited_registration_events_context_step (UnsolicitedRegistrationEventsContext *ctx) { - SetupRegistrationContext *ctx; + ctx->running_cs = FALSE; + ctx->running_ps = FALSE; + ctx->secondary_done = FALSE; - ctx = g_new0 (SetupRegistrationContext, 1); - ctx->result = g_simple_async_result_new (G_OBJECT (self), - callback, - user_data, - modem_3gpp_setup_cs_registration); - mm_base_modem_at_sequence_full ( - MM_BASE_MODEM (self), - mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)), - cs_registration_sequence, - NULL, /* response processor context */ - NULL, /* response processor context free */ - NULL, /* cancellable */ - (GAsyncReadyCallback)setup_registration_sequence_ready, - ctx); + if (ctx->run_cs) { + ctx->running_cs = TRUE; + ctx->run_cs = FALSE; + mm_base_modem_at_sequence_full ( + MM_BASE_MODEM (ctx->self), + mm_base_modem_peek_port_primary (MM_BASE_MODEM (ctx->self)), + cs_registration_sequence, + NULL, /* response processor context */ + NULL, /* response processor context free */ + NULL, /* cancellable */ + (GAsyncReadyCallback)unsolicited_registration_events_sequence_ready, + ctx); + return; + } + + if (ctx->run_ps) { + ctx->running_ps = TRUE; + ctx->run_ps = FALSE; + mm_base_modem_at_sequence_full ( + MM_BASE_MODEM (ctx->self), + mm_base_modem_peek_port_primary (MM_BASE_MODEM (ctx->self)), + ps_registration_sequence, + NULL, /* response processor context */ + NULL, /* response processor context free */ + NULL, /* cancellable */ + (GAsyncReadyCallback)unsolicited_registration_events_sequence_ready, + ctx); + return; + } + + /* All done! + * If we have any error reported, we'll propagate it. PS errors take + * precendence over CS errors. */ + if (ctx->ps_error) { + g_simple_async_result_take_error (ctx->result, ctx->ps_error); + ctx->ps_error = NULL; + } else if (ctx->cs_error) { + g_simple_async_result_take_error (ctx->result, ctx->cs_error); + ctx->cs_error = NULL; + } else + g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); + unsolicited_registration_events_context_complete_and_free (ctx); } static void -modem_3gpp_setup_ps_registration (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) +modem_3gpp_disable_unsolicited_registration_events (MMIfaceModem3gpp *self, + gboolean cs_supported, + gboolean ps_supported, + GAsyncReadyCallback callback, + gpointer user_data) { - SetupRegistrationContext *ctx; + unsolicited_registration_events_context_step ( + unsolicited_registration_events_context_new (MM_BROADBAND_MODEM (self), + FALSE, + cs_supported, + ps_supported, + callback, + user_data)); +} - ctx = g_new0 (SetupRegistrationContext, 1); - ctx->result = g_simple_async_result_new (G_OBJECT (self), - callback, - user_data, - modem_3gpp_setup_ps_registration); - mm_base_modem_at_sequence_full ( - MM_BASE_MODEM (self), - mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)), - ps_registration_sequence, - NULL, /* response processor context */ - NULL, /* response processor context free */ - NULL, /* cancellable */ - (GAsyncReadyCallback)setup_registration_sequence_ready, - ctx); +static void +modem_3gpp_enable_unsolicited_registration_events (MMIfaceModem3gpp *self, + gboolean cs_supported, + gboolean ps_supported, + GAsyncReadyCallback callback, + gpointer user_data) +{ + unsolicited_registration_events_context_step ( + unsolicited_registration_events_context_new (MM_BROADBAND_MODEM (self), + TRUE, + cs_supported, + ps_supported, + callback, + user_data)); } /*****************************************************************************/ @@ -6098,7 +6165,7 @@ enable_location_gathering (MMIfaceModemLocation *self, if (source == MM_MODEM_LOCATION_SOURCE_3GPP_LAC_CI && mm_iface_modem_is_3gpp (MM_IFACE_MODEM (self))) { /* Reload registration to get LAC/CI */ - mm_iface_modem_3gpp_run_all_registration_checks (MM_IFACE_MODEM_3GPP (self), NULL, NULL); + 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)); } @@ -7912,34 +7979,28 @@ iface_modem_3gpp_init (MMIfaceModem3gpp *iface) iface->setup_unsolicited_events_finish = modem_3gpp_setup_cleanup_unsolicited_events_finish; iface->enable_unsolicited_events = modem_3gpp_enable_unsolicited_events; iface->enable_unsolicited_events_finish = modem_3gpp_enable_disable_unsolicited_events_finish; - iface->setup_unsolicited_registration = modem_3gpp_setup_unsolicited_registration; - iface->setup_unsolicited_registration_finish = modem_3gpp_setup_unsolicited_registration_finish; - iface->setup_cs_registration = modem_3gpp_setup_cs_registration; - iface->setup_cs_registration_finish = modem_3gpp_setup_cs_registration_finish; - iface->setup_ps_registration = modem_3gpp_setup_ps_registration; - iface->setup_ps_registration_finish = modem_3gpp_setup_ps_registration_finish; + iface->setup_unsolicited_registration_events = modem_3gpp_setup_unsolicited_registration_events; + iface->setup_unsolicited_registration_events_finish = modem_3gpp_setup_unsolicited_registration_events_finish; + iface->enable_unsolicited_registration_events = modem_3gpp_enable_unsolicited_registration_events; + iface->enable_unsolicited_registration_events_finish = modem_3gpp_enable_disable_unsolicited_registration_events_finish; /* Disabling steps */ iface->disable_unsolicited_events = modem_3gpp_disable_unsolicited_events; iface->disable_unsolicited_events_finish = modem_3gpp_enable_disable_unsolicited_events_finish; iface->cleanup_unsolicited_events = modem_3gpp_cleanup_unsolicited_events; iface->cleanup_unsolicited_events_finish = modem_3gpp_setup_cleanup_unsolicited_events_finish; - iface->cleanup_unsolicited_registration = modem_3gpp_cleanup_unsolicited_registration; - iface->cleanup_unsolicited_registration_finish = modem_3gpp_cleanup_unsolicited_registration_finish; - iface->cleanup_cs_registration = modem_3gpp_cleanup_cs_registration; - iface->cleanup_cs_registration_finish = modem_3gpp_cleanup_cs_registration_finish; - iface->cleanup_ps_registration = modem_3gpp_cleanup_ps_registration; - iface->cleanup_ps_registration_finish = modem_3gpp_cleanup_ps_registration_finish; + iface->disable_unsolicited_registration_events = modem_3gpp_disable_unsolicited_registration_events; + iface->disable_unsolicited_registration_events_finish = modem_3gpp_enable_disable_unsolicited_registration_events_finish; + iface->cleanup_unsolicited_registration_events = modem_3gpp_cleanup_unsolicited_registration_events; + iface->cleanup_unsolicited_registration_events_finish = modem_3gpp_cleanup_unsolicited_registration_events_finish; /* Additional actions */ iface->load_operator_code = modem_3gpp_load_operator_code; iface->load_operator_code_finish = modem_3gpp_load_operator_code_finish; iface->load_operator_name = modem_3gpp_load_operator_name; iface->load_operator_name_finish = modem_3gpp_load_operator_name_finish; - iface->run_cs_registration_check = modem_3gpp_run_cs_registration_check; - iface->run_cs_registration_check_finish = modem_3gpp_run_cs_registration_check_finish; - iface->run_ps_registration_check = modem_3gpp_run_ps_registration_check; - iface->run_ps_registration_check_finish = modem_3gpp_run_ps_registration_check_finish; + iface->run_registration_checks = modem_3gpp_run_registration_checks; + iface->run_registration_checks_finish = modem_3gpp_run_registration_checks_finish; iface->register_in_network = modem_3gpp_register_in_network; iface->register_in_network_finish = modem_3gpp_register_in_network_finish; iface->scan_networks = modem_3gpp_scan_networks; diff --git a/src/mm-iface-modem-3gpp.c b/src/mm-iface-modem-3gpp.c index 8d6c6ce0..50d1f8b5 100644 --- a/src/mm-iface-modem-3gpp.c +++ b/src/mm-iface-modem-3gpp.c @@ -434,121 +434,34 @@ handle_scan (MmGdbusModem3gpp *skeleton, /*****************************************************************************/ -typedef struct { - GSimpleAsyncResult *result; - gboolean cs_supported; - gboolean ps_supported; - gboolean cs_done; - GError *cs_reg_error; - GError *ps_reg_error; -} RunAllRegistrationChecksContext; - -static void -run_all_registration_checks_context_complete_and_free (RunAllRegistrationChecksContext *ctx) -{ - g_simple_async_result_complete_in_idle (ctx->result); - g_clear_error (&ctx->cs_reg_error); - g_clear_error (&ctx->ps_reg_error); - g_object_unref (ctx->result); - g_free (ctx); -} - gboolean -mm_iface_modem_3gpp_run_all_registration_checks_finish (MMIfaceModem3gpp *self, +mm_iface_modem_3gpp_run_registration_checks_finish (MMIfaceModem3gpp *self, GAsyncResult *res, GError **error) { - return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error); -} - -static void -run_ps_registration_check_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - RunAllRegistrationChecksContext *ctx) -{ - MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->run_ps_registration_check_finish (self, res, &ctx->ps_reg_error); - - /* If both CS and PS registration checks returned errors we fail */ - if (ctx->ps_reg_error && - (ctx->cs_reg_error || !ctx->cs_done)) - /* Prefer the PS error */ - g_simple_async_result_set_from_error (ctx->result, ctx->ps_reg_error); - else - g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); - run_all_registration_checks_context_complete_and_free (ctx); -} - -static void -run_cs_registration_check_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - RunAllRegistrationChecksContext *ctx) -{ - MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->run_cs_registration_check_finish (self, res, &ctx->cs_reg_error); - - if (ctx->ps_supported && - MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->run_ps_registration_check && - MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->run_ps_registration_check_finish) { - ctx->cs_done = TRUE; - MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->run_ps_registration_check ( - self, - (GAsyncReadyCallback)run_ps_registration_check_ready, - ctx); - return; - } - - /* All done */ - if (ctx->cs_reg_error) - g_simple_async_result_set_from_error (ctx->result, ctx->cs_reg_error); - else - g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); - run_all_registration_checks_context_complete_and_free (ctx); + 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); } void -mm_iface_modem_3gpp_run_all_registration_checks (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) +mm_iface_modem_3gpp_run_registration_checks (MMIfaceModem3gpp *self, + GAsyncReadyCallback callback, + gpointer user_data) { - RunAllRegistrationChecksContext *ctx; + gboolean cs_supported = FALSE; + gboolean ps_supported = FALSE; - ctx = g_new0 (RunAllRegistrationChecksContext, 1); - ctx->result = g_simple_async_result_new (G_OBJECT (self), - callback, - user_data, - mm_iface_modem_3gpp_run_all_registration_checks); + g_assert (MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->run_registration_checks != NULL); g_object_get (self, - MM_IFACE_MODEM_3GPP_PS_NETWORK_SUPPORTED, &ctx->ps_supported, - MM_IFACE_MODEM_3GPP_CS_NETWORK_SUPPORTED, &ctx->cs_supported, + MM_IFACE_MODEM_3GPP_CS_NETWORK_SUPPORTED, &cs_supported, + MM_IFACE_MODEM_3GPP_PS_NETWORK_SUPPORTED, &ps_supported, NULL); - mm_dbg ("Running registration checks (CS: '%s', PS: '%s')", - ctx->cs_supported ? "yes" : "no", - ctx->ps_supported ? "yes" : "no"); - - if (ctx->cs_supported && - MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->run_cs_registration_check && - MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->run_cs_registration_check_finish) { - MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->run_cs_registration_check ( - self, - (GAsyncReadyCallback)run_cs_registration_check_ready, - ctx); - return; - } - - if (ctx->ps_supported && - MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->run_ps_registration_check && - MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->run_ps_registration_check_finish) { - MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->run_ps_registration_check ( - self, - (GAsyncReadyCallback)run_ps_registration_check_ready, - ctx); - return; - } - - /* Nothing to do :-/ all done */ - g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); - run_all_registration_checks_context_complete_and_free (ctx); + MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->run_registration_checks (self, + cs_supported, + ps_supported, + callback, user_data); } /*****************************************************************************/ @@ -879,7 +792,7 @@ periodic_registration_checks_ready (MMIfaceModem3gpp *self, RegistrationCheckContext *ctx; GError *error = NULL; - mm_iface_modem_3gpp_run_all_registration_checks_finish (self, res, &error); + mm_iface_modem_3gpp_run_registration_checks_finish (self, res, &error); if (error) { mm_dbg ("Couldn't refresh 3GPP registration status: '%s'", error->message); g_error_free (error); @@ -899,7 +812,7 @@ periodic_registration_check (MMIfaceModem3gpp *self) ctx = g_object_get_qdata (G_OBJECT (self), registration_check_context_quark); if (!ctx->running) { ctx->running = TRUE; - mm_iface_modem_3gpp_run_all_registration_checks ( + mm_iface_modem_3gpp_run_registration_checks ( self, (GAsyncReadyCallback)periodic_registration_checks_ready, NULL); @@ -957,9 +870,8 @@ static void interface_disabling_step (DisablingContext *ctx); typedef enum { DISABLING_STEP_FIRST, DISABLING_STEP_PERIODIC_REGISTRATION_CHECKS, - DISABLING_STEP_CLEANUP_PS_REGISTRATION, - DISABLING_STEP_CLEANUP_CS_REGISTRATION, - DISABLING_STEP_CLEANUP_UNSOLICITED_REGISTRATION, + DISABLING_STEP_DISABLE_UNSOLICITED_REGISTRATION_EVENTS, + DISABLING_STEP_CLEANUP_UNSOLICITED_REGISTRATION_EVENTS, DISABLING_STEP_CLEANUP_UNSOLICITED_EVENTS, DISABLING_STEP_DISABLE_UNSOLICITED_EVENTS, DISABLING_STEP_LAST @@ -1032,16 +944,14 @@ mm_iface_modem_3gpp_disable_finish (MMIfaceModem3gpp *self, interface_disabling_step (ctx); \ } -VOID_REPLY_READY_FN (cleanup_unsolicited_registration, - "cleanup unsolicited registration") -VOID_REPLY_READY_FN (cleanup_ps_registration, - "cleanup PS registration") -VOID_REPLY_READY_FN (cleanup_cs_registration, - "cleanup CS registration") VOID_REPLY_READY_FN (cleanup_unsolicited_events, "cleanup unsolicited events") VOID_REPLY_READY_FN (disable_unsolicited_events, "disable unsolicited events") +VOID_REPLY_READY_FN (cleanup_unsolicited_registration_events, + "cleanup unsolicited registration events") +VOID_REPLY_READY_FN (disable_unsolicited_registration_events, + "disable unsolicited registration events") static void interface_disabling_step (DisablingContext *ctx) @@ -1056,39 +966,22 @@ interface_disabling_step (DisablingContext *ctx) /* Fall down to next step */ ctx->step++; - case DISABLING_STEP_CLEANUP_PS_REGISTRATION: { - gboolean ps_supported = FALSE; - - g_object_get (ctx->self, - MM_IFACE_MODEM_3GPP_PS_NETWORK_SUPPORTED, &ps_supported, - NULL); - - if (ps_supported && - MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->cleanup_ps_registration && - MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->cleanup_ps_registration_finish) { - MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->cleanup_ps_registration ( - ctx->self, - (GAsyncReadyCallback)cleanup_ps_registration_ready, - ctx); - return; - } - /* Fall down to next step */ - ctx->step++; - } - - case DISABLING_STEP_CLEANUP_CS_REGISTRATION: { + case DISABLING_STEP_DISABLE_UNSOLICITED_REGISTRATION_EVENTS: { gboolean cs_supported = FALSE; + gboolean ps_supported = FALSE; g_object_get (ctx->self, MM_IFACE_MODEM_3GPP_CS_NETWORK_SUPPORTED, &cs_supported, + MM_IFACE_MODEM_3GPP_PS_NETWORK_SUPPORTED, &ps_supported, NULL); - if (cs_supported && - MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->cleanup_cs_registration && - MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->cleanup_cs_registration_finish) { - MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->cleanup_cs_registration ( + if (MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->disable_unsolicited_registration_events && + MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->disable_unsolicited_registration_events_finish) { + MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->disable_unsolicited_registration_events ( ctx->self, - (GAsyncReadyCallback)cleanup_cs_registration_ready, + cs_supported, + ps_supported, + (GAsyncReadyCallback)disable_unsolicited_registration_events_ready, ctx); return; } @@ -1096,12 +989,12 @@ interface_disabling_step (DisablingContext *ctx) ctx->step++; } - case DISABLING_STEP_CLEANUP_UNSOLICITED_REGISTRATION: - if (MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->cleanup_unsolicited_registration && - MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->cleanup_unsolicited_registration_finish) { - MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->cleanup_unsolicited_registration ( + case DISABLING_STEP_CLEANUP_UNSOLICITED_REGISTRATION_EVENTS: + if (MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->cleanup_unsolicited_registration_events && + MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->cleanup_unsolicited_registration_events_finish) { + MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->cleanup_unsolicited_registration_events ( ctx->self, - (GAsyncReadyCallback)cleanup_unsolicited_registration_ready, + (GAsyncReadyCallback)cleanup_unsolicited_registration_events_ready, ctx); return; } @@ -1161,10 +1054,9 @@ typedef enum { ENABLING_STEP_FIRST, ENABLING_STEP_SETUP_UNSOLICITED_EVENTS, ENABLING_STEP_ENABLE_UNSOLICITED_EVENTS, - ENABLING_STEP_SETUP_UNSOLICITED_REGISTRATION, - ENABLING_STEP_SETUP_CS_REGISTRATION, - ENABLING_STEP_SETUP_PS_REGISTRATION, - ENABLING_STEP_RUN_ALL_REGISTRATION_CHECKS, + ENABLING_STEP_SETUP_UNSOLICITED_REGISTRATION_EVENTS, + ENABLING_STEP_ENABLE_UNSOLICITED_REGISTRATION_EVENTS, + ENABLING_STEP_RUN_REGISTRATION_CHECKS, ENABLING_STEP_LAST } EnablingStep; @@ -1233,46 +1125,6 @@ mm_iface_modem_3gpp_enable_finish (MMIfaceModem3gpp *self, return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error); } -#undef VOID_REPLY_READY_FN -#define VOID_REPLY_READY_FN(NAME) \ - static void \ - NAME##_ready (MMIfaceModem3gpp *self, \ - GAsyncResult *res, \ - EnablingContext *ctx) \ - { \ - GError *error = NULL; \ - \ - MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->NAME##_finish (self, res, &error); \ - if (error) { \ - g_simple_async_result_take_error (ctx->result, error); \ - enabling_context_complete_and_free (ctx); \ - return; \ - } \ - \ - /* Go on to next step */ \ - ctx->step++; \ - interface_enabling_step (ctx); \ - } - -static void -enable_unsolicited_events_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - EnablingContext *ctx) -{ - GError *error = NULL; - - MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->enable_unsolicited_events_finish (self, res, &error); - if (error) { - /* This error shouldn't be treated as critical */ - mm_dbg ("Enabling unsolicited events failed: '%s'", error->message); - g_error_free (error); - } - - /* Go on to next step */ - ctx->step++; - interface_enabling_step (ctx); -} - static void setup_unsolicited_events_ready (MMIfaceModem3gpp *self, GAsyncResult *res, @@ -1299,18 +1151,16 @@ setup_unsolicited_events_ready (MMIfaceModem3gpp *self, } static void -setup_cs_registration_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - EnablingContext *ctx) +enable_unsolicited_events_ready (MMIfaceModem3gpp *self, + GAsyncResult *res, + EnablingContext *ctx) { GError *error = NULL; - MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->setup_cs_registration_finish (self, res, &error); + MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->enable_unsolicited_events_finish (self, res, &error); if (error) { - /* If error, setup periodic registration checks */ - periodic_registration_check_enable (ctx->self); - mm_dbg ("Couldn't setup CS registration: '%s'", - error->message); + /* This error shouldn't be treated as critical */ + mm_dbg ("Enabling unsolicited events failed: '%s'", error->message); g_error_free (error); } @@ -1320,19 +1170,25 @@ setup_cs_registration_ready (MMIfaceModem3gpp *self, } static void -setup_ps_registration_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - EnablingContext *ctx) +setup_unsolicited_registration_events_ready (MMIfaceModem3gpp *self, + GAsyncResult *res, + EnablingContext *ctx) { GError *error = NULL; - MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->setup_ps_registration_finish (self, res, &error); + MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->setup_unsolicited_registration_events_finish (self, res, &error); if (error) { + /* This error shouldn't be treated as critical */ + mm_dbg ("Setting up unsolicited registration events failed: '%s'", error->message); + g_error_free (error); + + /* If we get an error setting up unsolicited events, don't even bother trying to + * enable them. */ + ctx->step = ENABLING_STEP_ENABLE_UNSOLICITED_REGISTRATION_EVENTS + 1; + interface_enabling_step (ctx); /* If error, setup periodic registration checks */ periodic_registration_check_enable (ctx->self); - mm_dbg ("Couldn't setup PS registration: '%s'", - error->message); - g_error_free (error); + return; } /* Go on to next step */ @@ -1341,17 +1197,19 @@ setup_ps_registration_ready (MMIfaceModem3gpp *self, } static void -run_all_registration_checks_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - EnablingContext *ctx) +enable_unsolicited_registration_events_ready (MMIfaceModem3gpp *self, + GAsyncResult *res, + EnablingContext *ctx) { GError *error = NULL; - mm_iface_modem_3gpp_run_all_registration_checks_finish (self, res, &error); + MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->enable_unsolicited_registration_events_finish (self, res, &error); if (error) { - g_simple_async_result_take_error (ctx->result, error); - enabling_context_complete_and_free (ctx); - return; + /* This error shouldn't be treated as critical */ + mm_dbg ("Enabling unsolicited registration events failed: '%s'", error->message); + g_error_free (error); + /* If error, setup periodic registration checks */ + periodic_registration_check_enable (ctx->self); } /* Go on to next step */ @@ -1360,13 +1218,13 @@ run_all_registration_checks_ready (MMIfaceModem3gpp *self, } static void -setup_unsolicited_registration_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - EnablingContext *ctx) +run_all_registration_checks_ready (MMIfaceModem3gpp *self, + GAsyncResult *res, + EnablingContext *ctx) { GError *error = NULL; - MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->setup_unsolicited_registration_finish (self, res, &error); + mm_iface_modem_3gpp_run_registration_checks_finish (self, res, &error); if (error) { g_simple_async_result_take_error (ctx->result, error); enabling_context_complete_and_free (ctx); @@ -1414,59 +1272,43 @@ interface_enabling_step (EnablingContext *ctx) /* Fall down to next step */ ctx->step++; - case ENABLING_STEP_SETUP_UNSOLICITED_REGISTRATION: - if (MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->setup_unsolicited_registration && - MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->setup_unsolicited_registration_finish) { - MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->setup_unsolicited_registration ( + case ENABLING_STEP_SETUP_UNSOLICITED_REGISTRATION_EVENTS: + if (MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->setup_unsolicited_registration_events && + MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->setup_unsolicited_registration_events_finish) { + MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->setup_unsolicited_registration_events ( ctx->self, - (GAsyncReadyCallback)setup_unsolicited_registration_ready, + (GAsyncReadyCallback)setup_unsolicited_registration_events_ready, ctx); return; } /* Fall down to next step */ ctx->step++; - case ENABLING_STEP_SETUP_CS_REGISTRATION: { + case ENABLING_STEP_ENABLE_UNSOLICITED_REGISTRATION_EVENTS: { gboolean cs_supported = FALSE; - - g_object_get (ctx->self, - MM_IFACE_MODEM_3GPP_CS_NETWORK_SUPPORTED, &cs_supported, - NULL); - - if (cs_supported && - MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->setup_cs_registration && - MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->setup_cs_registration_finish) { - MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->setup_cs_registration ( - ctx->self, - (GAsyncReadyCallback)setup_cs_registration_ready, - ctx); - return; - } - /* Fall down to next step */ - ctx->step++; - } - - case ENABLING_STEP_SETUP_PS_REGISTRATION: { gboolean ps_supported = FALSE; g_object_get (ctx->self, + MM_IFACE_MODEM_3GPP_CS_NETWORK_SUPPORTED, &cs_supported, MM_IFACE_MODEM_3GPP_PS_NETWORK_SUPPORTED, &ps_supported, NULL); - if (ps_supported && - MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->setup_ps_registration && - MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->setup_ps_registration_finish) { - MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->setup_ps_registration ( + if (MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->enable_unsolicited_registration_events && + MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->enable_unsolicited_registration_events_finish) { + MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->enable_unsolicited_registration_events ( ctx->self, - (GAsyncReadyCallback)setup_ps_registration_ready, + cs_supported, + ps_supported, + (GAsyncReadyCallback)enable_unsolicited_registration_events_ready, ctx); return; } /* Fall down to next step */ ctx->step++; } - case ENABLING_STEP_RUN_ALL_REGISTRATION_CHECKS: - mm_iface_modem_3gpp_run_all_registration_checks ( + + case ENABLING_STEP_RUN_REGISTRATION_CHECKS: + mm_iface_modem_3gpp_run_registration_checks ( ctx->self, (GAsyncReadyCallback)run_all_registration_checks_ready, ctx); diff --git a/src/mm-iface-modem-3gpp.h b/src/mm-iface-modem-3gpp.h index 12dc8bda..c0fe03d0 100644 --- a/src/mm-iface-modem-3gpp.h +++ b/src/mm-iface-modem-3gpp.h @@ -10,7 +10,7 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details: * - * Copyright (C) 2011 Google, Inc. + * Copyright (C) 2011-2012 Google, Inc. */ #ifndef MM_IFACE_MODEM_3GPP_H @@ -99,73 +99,52 @@ struct _MMIfaceModem3gpp { GError **error); /* Setup unsolicited registration messages */ - void (* setup_unsolicited_registration) (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data); - gboolean (*setup_unsolicited_registration_finish) (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error); + void (* setup_unsolicited_registration_events) (MMIfaceModem3gpp *self, + GAsyncReadyCallback callback, + gpointer user_data); + gboolean (*setup_unsolicited_registration_events_finish) (MMIfaceModem3gpp *self, + GAsyncResult *res, + GError **error); + + /* Asynchronous enabling of unsolicited registration events */ + void (*enable_unsolicited_registration_events) (MMIfaceModem3gpp *self, + gboolean cs_supported, + gboolean ps_supported, + GAsyncReadyCallback callback, + gpointer user_data); + gboolean (*enable_unsolicited_registration_events_finish) (MMIfaceModem3gpp *self, + GAsyncResult *res, + GError **error); /* Cleanup unsolicited registration messages */ - void (* cleanup_unsolicited_registration) (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data); - gboolean (*cleanup_unsolicited_registration_finish) (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error); - - /* Setup CS Registration */ - void (* setup_cs_registration) (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data); - gboolean (*setup_cs_registration_finish) (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error); - - /* Cleanup CS Registration */ - void (* cleanup_cs_registration) (MMIfaceModem3gpp *self, + void (* cleanup_unsolicited_registration_events) (MMIfaceModem3gpp *self, + GAsyncReadyCallback callback, + gpointer user_data); + gboolean (*cleanup_unsolicited_registration_events_finish) (MMIfaceModem3gpp *self, + GAsyncResult *res, + GError **error); + /* Asynchronous disabling of unsolicited registration events */ + void (*disable_unsolicited_registration_events) (MMIfaceModem3gpp *self, + gboolean cs_supported, + gboolean ps_supported, + GAsyncReadyCallback callback, + gpointer user_data); + gboolean (*disable_unsolicited_registration_events_finish) (MMIfaceModem3gpp *self, + GAsyncResult *res, + GError **error); + + /* Run CS/PS registration state checks.. + * Note that no registration state is returned, implementations should call + * mm_iface_modem_3gpp_update_registration_state(). */ + void (* run_registration_checks) (MMIfaceModem3gpp *self, + gboolean cs_supported, + gboolean ps_supported, GAsyncReadyCallback callback, gpointer user_data); - gboolean (*cleanup_cs_registration_finish) (MMIfaceModem3gpp *self, + gboolean (*run_registration_checks_finish) (MMIfaceModem3gpp *self, GAsyncResult *res, GError **error); - /* Setup PS Registration */ - void (* setup_ps_registration) (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data); - gboolean (*setup_ps_registration_finish) (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error); - - /* Cleanup PS Registration */ - void (* cleanup_ps_registration) (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data); - gboolean (*cleanup_ps_registration_finish) (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error); - - /* Run CS registration state check. - * Note that no registration state is returned, implementations should call - * mm_iface_modem_3gpp_update_registration_state(). */ - void (* run_cs_registration_check) (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data); - gboolean (*run_cs_registration_check_finish) (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error); - - /* Run PS registration state check. - * Note that no registration state is returned, implementations should call - * mm_iface_modem_3gpp_update_registration_state(). */ - void (* run_ps_registration_check) (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data); - gboolean (*run_ps_registration_check_finish) (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error); - /* Try to register in the network */ void (* register_in_network) (MMIfaceModem3gpp *self, const gchar *operator_id, @@ -247,12 +226,12 @@ void mm_iface_modem_3gpp_update_ps_registration_state (MMIfaceModem3gpp *self, gulong cell_id); /* Run all registration checks */ -void mm_iface_modem_3gpp_run_all_registration_checks (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_iface_modem_3gpp_run_all_registration_checks_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error); +void mm_iface_modem_3gpp_run_registration_checks (MMIfaceModem3gpp *self, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean mm_iface_modem_3gpp_run_registration_checks_finish (MMIfaceModem3gpp *self, + GAsyncResult *res, + GError **error); /* Request to reload current operator */ void mm_iface_modem_3gpp_reload_current_operator (MMIfaceModem3gpp *self); -- cgit v1.2.3-70-g09d2