From cf9afc32208ca4068fc2e0a2daa088c15160e9cb Mon Sep 17 00:00:00 2001 From: Aleksander Morgado Date: Wed, 18 Dec 2019 12:11:22 +0100 Subject: [PATCH] broadband-modem: retry +COPS=1,2, with current charset If the modem (e.g. u-blox LARA) returns a "Not supported" error when attempting to run +COPS=1,2, with the MCCMNC encoded in ASCII (and current charset is different, e.g. UCS2), then attempt to re-run the same command with the MCCMNC encoded in the explicit current charset. (ttyACM0): --> 'AT+COPS=1,2,"21404"' (ttyACM0): <-- '+CME ERROR: 4' Got failure code 4: Operation not supported (ttyACM0): --> 'AT+COPS=1,2,"00320031003400300034"' (ttyACM0): <-- '+CME ERROR: 111 --- src/mm-broadband-modem.c | 111 ++++++++++++++++++++++++++++++++------- 1 file changed, 91 insertions(+), 20 deletions(-) diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c index 6d2443f1..be52a498 100644 --- a/src/mm-broadband-modem.c +++ b/src/mm-broadband-modem.c @@ -4666,34 +4666,105 @@ modem_3gpp_scan_networks (MMIfaceModem3gpp *self, /* Register in network (3GPP interface) */ static gboolean -modem_3gpp_register_in_network_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) +modem_3gpp_register_in_network_finish (MMIfaceModem3gpp *self, + GAsyncResult *res, + GError **error) { - return !!mm_base_modem_at_command_full_finish (MM_BASE_MODEM (self), res, error); + return g_task_propagate_boolean (G_TASK (res), error); } static void -modem_3gpp_register_in_network (MMIfaceModem3gpp *self, - const gchar *operator_id, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) +cops_set_ready (MMBaseModem *self, + GAsyncResult *res, + GTask *task) { + GError *error = NULL; + + if (!mm_base_modem_at_command_full_finish (MM_BASE_MODEM (self), res, &error)) + g_task_return_error (task, error); + else + g_task_return_boolean (task, TRUE); + g_object_unref (task); +} + +static void +cops_ascii_set_ready (MMBaseModem *self, + GAsyncResult *res, + GTask *task) +{ + GError *error = NULL; + + if (!mm_base_modem_at_command_full_finish (MM_BASE_MODEM (self), res, &error)) { + /* If it failed with an unsupported error, retry with current modem charset */ + if (g_error_matches (error, MM_MOBILE_EQUIPMENT_ERROR, MM_MOBILE_EQUIPMENT_ERROR_NOT_SUPPORTED)) { + gchar *operator_id; + gchar *operator_id_current_charset; + + operator_id = g_task_get_task_data (task); + operator_id_current_charset = mm_broadband_modem_take_and_convert_to_current_charset (MM_BROADBAND_MODEM (self), g_strdup (operator_id)); + + if (g_strcmp0 (operator_id, operator_id_current_charset) != 0) { + gchar *command; + + command = g_strdup_printf ("+COPS=1,2,\"%s\"", operator_id_current_charset); + 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 */ + g_task_get_cancellable (task), + (GAsyncReadyCallback)cops_set_ready, + task); + g_error_free (error); + g_free (operator_id_current_charset); + g_free (command); + return; + } + /* operator id string would be the same on the current charset, + * so fallback and return the not supported error */ + g_free (operator_id_current_charset); + } + g_task_return_error (task, error); + } else + g_task_return_boolean (task, TRUE); + g_object_unref (task); +} + +static void +modem_3gpp_register_in_network (MMIfaceModem3gpp *self, + const gchar *operator_id, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask *task; gchar *command; - /* If the user sent a specific network to use, lock it in. */ - if (operator_id) - command = g_strdup_printf ("+COPS=1,2,\"%s\"", operator_id); - /* 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 + task = g_task_new (self, cancellable, callback, user_data); + + /* Trigger automatic network registration if no explicit operator id given */ + if (!operator_id) { /* Note that '+COPS=0,,' (same but with commas) won't work in some Nokia * phones */ - command = g_strdup ("+COPS=0"); + mm_base_modem_at_command_full (MM_BASE_MODEM (self), + mm_base_modem_peek_best_at_port (MM_BASE_MODEM (self), NULL), + "+COPS=0", + 120, + FALSE, + FALSE, /* raw */ + cancellable, + (GAsyncReadyCallback)cops_set_ready, + task); + return; + } + /* Store operator id in context, in case we need to retry with the current + * modem charset */ + g_task_set_task_data (task, g_strdup (operator_id), g_free); + + /* Use the operator id given in ASCII initially */ + command = g_strdup_printf ("+COPS=1,2,\"%s\"", operator_id); mm_base_modem_at_command_full (MM_BASE_MODEM (self), mm_base_modem_peek_best_at_port (MM_BASE_MODEM (self), NULL), command, @@ -4701,8 +4772,8 @@ modem_3gpp_register_in_network (MMIfaceModem3gpp *self, FALSE, FALSE, /* raw */ cancellable, - callback, - user_data); + (GAsyncReadyCallback)cops_ascii_set_ready, + task); g_free (command); }