<div dir="ltr">Argh.<div><br></div><div>Stupid mistake. My local branch was tracking the outdated chromium tree, and I never noticed.</div><div><br></div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Wed, Oct 9, 2013 at 1:03 AM, Aleksander Morgado <span dir="ltr"><<a href="mailto:aleksander@lanedo.com" target="_blank">aleksander@lanedo.com</a>></span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="im">On 08/10/13 22:31, Prathmesh Prabhu wrote:<br>
> This patch uses the extended error code after a registration failure to<br>
> determine if the SIM in the relevant modem is associated with a non-provisioned<br>
> account. It uses the standard AT+CEER command, but the implementation is<br>
> restricted to the altair plugin.<br>
<br>
</div>Now I got lost. Your V2 patch contains several of the fixes I suggested<br>
in the code review; but this V3 patch doesn't have them...<br>
<div class="HOEnZb"><div class="h5"><br>
<br>
> ---<br>
>  plugins/Makefile.am                                |  13 ++<br>
>  plugins/altair/mm-broadband-modem-altair-lte.c     | 138 ++++++++++++++++++++-<br>
>  plugins/altair/mm-modem-helpers-altair-lte.c       |  68 ++++++++++<br>
>  plugins/altair/mm-modem-helpers-altair-lte.h       |  26 ++++<br>
>  .../altair/tests/test-modem-helpers-altair-lte.c   |  75 +++++++++++<br>
>  5 files changed, 317 insertions(+), 3 deletions(-)<br>
>  create mode 100644 plugins/altair/mm-modem-helpers-altair-lte.c<br>
>  create mode 100644 plugins/altair/mm-modem-helpers-altair-lte.h<br>
>  create mode 100644 plugins/altair/tests/test-modem-helpers-altair-lte.c<br>
><br>
> diff --git a/plugins/Makefile.am b/plugins/Makefile.am<br>
> index d10c929..d775d5a 100644<br>
> --- a/plugins/Makefile.am<br>
> +++ b/plugins/Makefile.am<br>
> @@ -348,6 +348,8 @@ libmm_plugin_novatel_la_LDFLAGS = $(PLUGIN_COMMON_LINKER_FLAGS)<br>
><br>
>  # Altair LTE modem<br>
>  libmm_plugin_altair_lte_la_SOURCES = \<br>
> +     altair/mm-modem-helpers-altair-lte.c \<br>
> +     altair/mm-modem-helpers-altair-lte.h \<br>
>       altair/mm-plugin-altair-lte.c \<br>
>       altair/mm-plugin-altair-lte.h \<br>
>       altair/mm-broadband-modem-altair-lte.c \<br>
> @@ -357,6 +359,17 @@ libmm_plugin_altair_lte_la_SOURCES = \<br>
>  libmm_plugin_altair_lte_la_CPPFLAGS = $(PLUGIN_COMMON_COMPILER_FLAGS)<br>
>  libmm_plugin_altair_lte_la_LDFLAGS = $(PLUGIN_COMMON_LINKER_FLAGS)<br>
><br>
> +noinst_PROGRAMS += test-modem-helpers-altair-lte<br>
> +test_modem_helpers_altair_lte_SOURCES = \<br>
> +     altair/mm-modem-helpers-altair-lte.c \<br>
> +     altair/mm-modem-helpers-altair-lte.h \<br>
> +     altair/tests/test-modem-helpers-altair-lte.c<br>
> +test_modem_helpers_altair_lte_CPPFLAGS = \<br>
> +     -I$(top_srcdir)/plugins/altair \<br>
> +     $(PLUGIN_COMMON_COMPILER_FLAGS)<br>
> +test_modem_helpers_altair_lte_LDFLAGS = $(top_builddir)/libmm-glib/<a href="http://libmm-glib.la" target="_blank">libmm-glib.la</a><br>
> +<br>
> +<br>
>  # VIA modem<br>
>  libmm_plugin_via_la_SOURCES = \<br>
>       via/mm-plugin-via.c \<br>
> diff --git a/plugins/altair/mm-broadband-modem-altair-lte.c b/plugins/altair/mm-broadband-modem-altair-lte.c<br>
> index 3303cbb..da9510b 100644<br>
> --- a/plugins/altair/mm-broadband-modem-altair-lte.c<br>
> +++ b/plugins/altair/mm-broadband-modem-altair-lte.c<br>
> @@ -24,6 +24,9 @@<br>
>  #include <ctype.h><br>
><br>
>  #include "ModemManager.h"<br>
> +#define _LIBMM_INSIDE_MM<br>
> +#include <libmm-glib.h><br>
> +<br>
>  #include "mm-base-modem-at.h"<br>
>  #include "mm-broadband-bearer-altair-lte.h"<br>
>  #include "mm-broadband-modem-altair-lte.h"<br>
> @@ -34,6 +37,7 @@<br>
>  #include "mm-iface-modem-messaging.h"<br>
>  #include "mm-log.h"<br>
>  #include "mm-modem-helpers.h"<br>
> +#include "mm-modem-helpers-altair-lte.h"<br>
>  #include "mm-serial-parsers.h"<br>
>  #include "mm-bearer-list.h"<br>
><br>
> @@ -465,6 +469,135 @@ reset (MMIfaceModem *self,<br>
>  }<br>
><br>
>  /*****************************************************************************/<br>
> +/* Run registration checks (3GPP interface) */<br>
> +<br>
> +typedef struct {<br>
> +    MMBroadbandModemAltairLte *self;<br>
> +    GSimpleAsyncResult *result;<br>
> +} RunRegistrationChecksContext;<br>
> +<br>
> +static void<br>
> +run_registration_checks_context_complete_and_free (RunRegistrationChecksContext *ctx)<br>
> +{<br>
> +    g_simple_async_result_complete_in_idle (ctx->result);<br>
> +    g_object_unref (ctx->result);<br>
> +    g_object_unref (ctx->self);<br>
> +    g_free (ctx);<br>
> +}<br>
> +<br>
> +static void<br>
> +run_registration_checks_subscription_state_ready (MMIfaceModem3gpp *self,<br>
> +                                                  GAsyncResult *res,<br>
> +                                                  RunRegistrationChecksContext *ctx)<br>
> +{<br>
> +    GError *error = NULL;<br>
> +    const gchar *at_response;<br>
> +    gchar *ceer_response;<br>
> +<br>
> +    at_response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error);<br>
> +    if (!at_response) {<br>
> +        g_assert (error);<br>
> +        g_simple_async_result_take_error (ctx->result, error);<br>
> +        run_registration_checks_context_complete_and_free (ctx);<br>
> +        return;<br>
> +    }<br>
> +<br>
> +    ceer_response = mm_altair_parse_ceer_response (at_response, &error);<br>
> +    if (!ceer_response) {<br>
> +        g_assert (error);<br>
> +        g_simple_async_result_take_error (ctx->result, error);<br>
> +        run_registration_checks_context_complete_and_free (ctx);<br>
> +        return;<br>
> +    }<br>
> +<br>
> +    g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);<br>
> +<br>
> +    if (g_strcmp0 ("EPS_AND_NON_EPS_SERVICES_NOT_ALLOWED", ceer_response) == 0) {<br>
> +        mm_dbg ("Registration failed due to unprovisioned SIM.");<br>
> +        mm_iface_modem_3gpp_update_subscription_state (self, MM_MODEM_3GPP_SUBSCRIPTION_STATE_UNPROVISIONED);<br>
> +    } else {<br>
> +        mm_dbg ("Failed to find a better reason for registration failure.");<br>
> +    }<br>
> +<br>
> +    run_registration_checks_context_complete_and_free (ctx);<br>
> +    g_free (ceer_response);<br>
> +}<br>
> +<br>
> +static void<br>
> +run_registration_checks_ready (MMIfaceModem3gpp *self,<br>
> +                               GAsyncResult *res,<br>
> +                               RunRegistrationChecksContext *ctx)<br>
> +{<br>
> +    GError *error = NULL;<br>
> +    gboolean success;<br>
> +    MMModem3gppRegistrationState registration_state;<br>
> +<br>
> +    g_assert (iface_modem_3gpp_parent->run_registration_checks_finish);<br>
> +    success = iface_modem_3gpp_parent->run_registration_checks_finish (self, res, &error);<br>
> +    if (!success) {<br>
> +        g_assert (error);<br>
> +        g_simple_async_result_take_error (ctx->result, error);<br>
> +        run_registration_checks_context_complete_and_free (ctx);<br>
> +        return;<br>
> +    }<br>
> +<br>
> +    g_object_get (self,<br>
> +                  MM_IFACE_MODEM_3GPP_REGISTRATION_STATE, &registration_state,<br>
> +                  NULL);<br>
> +<br>
> +    if (registration_state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME ||<br>
> +        registration_state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING) {<br>
> +        mm_dbg ("Registration succeeded: Marking the SIM as provisioned.");<br>
> +        mm_iface_modem_3gpp_update_subscription_state (self, MM_MODEM_3GPP_SUBSCRIPTION_STATE_PROVISIONED);<br>
> +        g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);<br>
> +        run_registration_checks_context_complete_and_free (ctx);<br>
> +        return;<br>
> +    }<br>
> +<br>
> +    mm_dbg ("Registration not successful yet. Checking if SIM is unprovisioned.");<br>
> +    mm_base_modem_at_command (MM_BASE_MODEM (self),<br>
> +                              "+CEER",<br>
> +                              6,<br>
> +                              FALSE,<br>
> +                              (GAsyncReadyCallback) run_registration_checks_subscription_state_ready,<br>
> +                              ctx);<br>
> +}<br>
> +<br>
> +static void<br>
> +modem_3gpp_run_registration_checks (MMIfaceModem3gpp *self,<br>
> +                                    gboolean cs_supported,<br>
> +                                    gboolean ps_supported,<br>
> +                                    gboolean eps_supported,<br>
> +                                    GAsyncReadyCallback callback,<br>
> +                                    gpointer user_data)<br>
> +{<br>
> +    RunRegistrationChecksContext *ctx;<br>
> +<br>
> +    ctx = g_new0 (RunRegistrationChecksContext, 1);<br>
> +    ctx->self = g_object_ref (MM_BROADBAND_MODEM_ALTAIR_LTE (self));<br>
> +    ctx->result = g_simple_async_result_new (G_OBJECT (self),<br>
> +                                             callback,<br>
> +                                             user_data,<br>
> +                                             modem_3gpp_run_registration_checks);<br>
> +<br>
> +    g_assert (iface_modem_3gpp_parent->run_registration_checks);<br>
> +    iface_modem_3gpp_parent->run_registration_checks (self,<br>
> +                                                      cs_supported,<br>
> +                                                      ps_supported,<br>
> +                                                      eps_supported,<br>
> +                                                      (GAsyncReadyCallback) run_registration_checks_ready,<br>
> +                                                      ctx);<br>
> +}<br>
> +<br>
> +static gboolean<br>
> +modem_3gpp_run_registration_checks_finish (MMIfaceModem3gpp *self,<br>
> +                                           GAsyncResult *res,<br>
> +                                           GError **error)<br>
> +{<br>
> +    return !!mm_base_modem_at_command_full_finish (MM_BASE_MODEM (self), res, error);<br>
> +}<br>
> +<br>
> +/*****************************************************************************/<br>
>  /* Register in network (3GPP interface) */<br>
><br>
>  static void<br>
> @@ -989,7 +1122,6 @@ iface_modem_init (MMIfaceModem *iface)<br>
>      iface->setup_charset_finish = NULL;<br>
>      iface->setup_flow_control = NULL;<br>
>      iface->setup_flow_control_finish = NULL;<br>
> -<br>
>  }<br>
><br>
>  static void<br>
> @@ -1003,7 +1135,6 @@ iface_modem_3gpp_ussd_init (MMIfaceModem3gppUssd *iface)<br>
>  static void<br>
>  iface_modem_3gpp_init (MMIfaceModem3gpp *iface)<br>
>  {<br>
> -<br>
>      iface_modem_3gpp_parent = g_type_interface_peek_parent (iface);<br>
><br>
>      iface->setup_unsolicited_events = modem_3gpp_setup_unsolicited_events;<br>
> @@ -1017,6 +1148,8 @@ iface_modem_3gpp_init (MMIfaceModem3gpp *iface)<br>
><br>
>      iface->register_in_network = modem_3gpp_register_in_network;<br>
>      iface->register_in_network_finish = modem_3gpp_register_in_network_finish;<br>
> +    iface->run_registration_checks = modem_3gpp_run_registration_checks;<br>
> +    iface->run_registration_checks_finish = modem_3gpp_run_registration_checks_finish;<br>
><br>
>      /* Scanning is not currently supported */<br>
>      iface->scan_networks = NULL;<br>
> @@ -1027,7 +1160,6 @@ iface_modem_3gpp_init (MMIfaceModem3gpp *iface)<br>
>      iface->load_operator_code_finish = modem_3gpp_load_operator_code_finish;<br>
>      iface->load_operator_name = modem_3gpp_load_operator_name;<br>
>      iface->load_operator_name_finish = modem_3gpp_load_operator_name_finish;<br>
> -<br>
>  }<br>
><br>
>  static void<br>
> diff --git a/plugins/altair/mm-modem-helpers-altair-lte.c b/plugins/altair/mm-modem-helpers-altair-lte.c<br>
> new file mode 100644<br>
> index 0000000..9e5b421<br>
> --- /dev/null<br>
> +++ b/plugins/altair/mm-modem-helpers-altair-lte.c<br>
> @@ -0,0 +1,68 @@<br>
> +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */<br>
> +/*<br>
> + * This program is free software; you can redistribute it and/or modify<br>
> + * it under the terms of the GNU General Public License as published by<br>
> + * the Free Software Foundation; either version 2 of the License, or<br>
> + * (at your option) any later version.<br>
> + *<br>
> + * This program is distributed in the hope that it will be useful,<br>
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of<br>
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the<br>
> + * GNU General Public License for more details:<br>
> + *<br>
> + * Copyright (C) 2013 Google Inc.<br>
> + *<br>
> + */<br>
> +<br>
> +#include <string.h><br>
> +<br>
> +#include <ModemManager.h><br>
> +#define _LIBMM_INSIDE_MM<br>
> +#include <libmm-glib.h><br>
> +<br>
> +#include "mm-modem-helpers-altair-lte.h"<br>
> +<br>
> +/*****************************************************************************/<br>
> +/* +CEER response parser */<br>
> +<br>
> +gchar *<br>
> +mm_altair_parse_ceer_response (const gchar *response,<br>
> +                               GError **error)<br>
> +{<br>
> +    GRegex *r;<br>
> +    GMatchInfo *match_info = NULL;<br>
> +    gchar *ceer_response = NULL;<br>
> +<br>
> +<br>
> +    /* First accept an empty response as the no error case. Sometimes, the only<br>
> +     * respone to the AT+CEER query is an OK.<br>
> +     */<br>
> +    if (g_strcmp0 ("", response) == 0) {<br>
> +        return g_strdup ("");<br>
> +    }<br>
> +<br>
> +    /* The response we are interested in looks so:<br>
> +     * +CEER: EPS_AND_NON_EPS_SERVICES_NOT_ALLOWED<br>
> +     */<br>
> +    r = g_regex_new ("\\+CEER:\\s*(\\w*)?",<br>
> +                     G_REGEX_RAW,<br>
> +                     0, NULL);<br>
> +    g_assert (r != NULL);<br>
> +<br>
> +    if (!g_regex_match (r, response, 0, &match_info)) {<br>
> +        g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Could not parse +CEER response");<br>
> +        g_match_info_free (match_info);<br>
> +        g_regex_unref (r);<br>
> +        return NULL;<br>
> +    }<br>
> +<br>
> +    if (g_match_info_matches (match_info)) {<br>
> +        ceer_response = mm_get_string_unquoted_from_match_info (match_info, 1);<br>
> +        if (!ceer_response)<br>
> +            ceer_response = g_strdup ("");<br>
> +    }<br>
> +<br>
> +    g_match_info_free (match_info);<br>
> +    g_regex_unref (r);<br>
> +    return ceer_response;<br>
> +}<br>
> diff --git a/plugins/altair/mm-modem-helpers-altair-lte.h b/plugins/altair/mm-modem-helpers-altair-lte.h<br>
> new file mode 100644<br>
> index 0000000..dbd641c<br>
> --- /dev/null<br>
> +++ b/plugins/altair/mm-modem-helpers-altair-lte.h<br>
> @@ -0,0 +1,26 @@<br>
> +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */<br>
> +/*<br>
> + * This program is free software; you can redistribute it and/or modify<br>
> + * it under the terms of the GNU General Public License as published by<br>
> + * the Free Software Foundation; either version 2 of the License, or<br>
> + * (at your option) any later version.<br>
> + *<br>
> + * This program is distributed in the hope that it will be useful,<br>
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of<br>
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the<br>
> + * GNU General Public License for more details:<br>
> + *<br>
> + * Copyright (C) 2013 Google Inc.<br>
> + *<br>
> + */<br>
> +<br>
> +#ifndef MM_MODEM_HELPERS_ALTAIR_H<br>
> +#define MM_MODEM_HELPERS_ALTAIR_H<br>
> +<br>
> +#include <glib.h><br>
> +<br>
> +/* +CEER response parser */<br>
> +gchar *mm_altair_parse_ceer_response (const gchar *response,<br>
> +                                      GError **error);<br>
> +<br>
> +#endif  /* MM_MODEM_HELPERS_ALTAIR_H */<br>
> diff --git a/plugins/altair/tests/test-modem-helpers-altair-lte.c b/plugins/altair/tests/test-modem-helpers-altair-lte.c<br>
> new file mode 100644<br>
> index 0000000..1b3eaa1<br>
> --- /dev/null<br>
> +++ b/plugins/altair/tests/test-modem-helpers-altair-lte.c<br>
> @@ -0,0 +1,75 @@<br>
> +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */<br>
> +/*<br>
> + * This program is free software; you can redistribute it and/or modify<br>
> + * it under the terms of the GNU General Public License as published by<br>
> + * the Free Software Foundation; either version 2 of the License, or<br>
> + * (at your option) any later version.<br>
> + *<br>
> + * This program is distributed in the hope that it will be useful,<br>
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of<br>
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the<br>
> + * GNU General Public License for more details:<br>
> + *<br>
> + * Copyright (C) 2013 Google Inc.<br>
> + *<br>
> + */<br>
> +<br>
> +#include <stdarg.h><br>
> +#include <stdio.h><br>
> +#include <glib.h><br>
> +#include <glib-object.h><br>
> +#include <locale.h><br>
> +<br>
> +#include "mm-modem-helpers-altair-lte.h"<br>
> +<br>
> +/*****************************************************************************/<br>
> +/* Test +CEER responses */<br>
> +<br>
> +typedef struct {<br>
> +    const gchar *str;<br>
> +    const gchar *result;<br>
> +} CeerTest;<br>
> +<br>
> +static const CeerTest ceer_tests[] = {<br>
> +    { "", "" }, /* Special case, sometimes the response is empty, treat it as a valid response. */<br>
> +    { "+CEER:", "" },<br>
> +    { "+CEER: EPS_AND_NON_EPS_SERVICES_NOT_ALLOWED", "EPS_AND_NON_EPS_SERVICES_NOT_ALLOWED" },<br>
> +    { "+CEER: NO_SUITABLE_CELLS_IN_TRACKING_AREA", "NO_SUITABLE_CELLS_IN_TRACKING_AREA" },<br>
> +    { "WRONG RESPONSE", NULL },<br>
> +    { NULL, NULL }<br>
> +};<br>
> +<br>
> +static void<br>
> +test_ceer (void)<br>
> +{<br>
> +    guint i;<br>
> +<br>
> +    for (i = 0; ceer_tests[i].str; ++i) {<br>
> +        GError *error = NULL;<br>
> +        gchar *result;<br>
> +<br>
> +        result = mm_altair_parse_ceer_response (ceer_tests[i].str, &error);<br>
> +        if (ceer_tests[i].result) {<br>
> +            g_assert (g_strcmp0 (ceer_tests[i].result, result) == 0);<br>
> +            g_assert (error == NULL);<br>
> +            g_free (result);<br>
> +        }<br>
> +        else {<br>
> +            g_assert (result == NULL);<br>
> +            g_assert (error != NULL);<br>
> +            g_error_free (error);<br>
> +        }<br>
> +    }<br>
> +}<br>
> +<br>
> +int main (int argc, char **argv)<br>
> +{<br>
> +    setlocale (LC_ALL, "");<br>
> +<br>
> +    g_type_init ();<br>
> +    g_test_init (&argc, &argv, NULL);<br>
> +<br>
> +    g_test_add_func ("/MM/altair/ceer", test_ceer);<br>
> +<br>
> +    return g_test_run ();<br>
> +}<br>
><br>
<br>
<br>
--<br>
</div></div><span class="HOEnZb"><font color="#888888">Aleksander<br>
</font></span></blockquote></div><br></div>