<div dir="ltr">Thank you!<div><br></div><div>Carlo</div></div><br><div class="gmail_quote"><div dir="ltr">On Mon, 25 Jan 2016 at 14:02 Aleksander Morgado <<a href="mailto:aleksander@aleksander.es">aleksander@aleksander.es</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On 25/01/16 11:02, <a href="mailto:c.lobrano@gmail.com" target="_blank">c.lobrano@gmail.com</a> wrote:<br>
> From: Carlo Lobrano <<a href="mailto:c.lobrano@gmail.com" target="_blank">c.lobrano@gmail.com</a>><br>
><br>
> ---<br>
>  plugins/telit/mm-broadband-modem-telit.c          |  86 +++++<br>
>  plugins/telit/mm-modem-helpers-telit.c            | 372 +++++++++++++++++++++-<br>
>  plugins/telit/mm-modem-helpers-telit.h            |  67 ++++<br>
>  plugins/telit/tests/test-mm-modem-helpers-telit.c | 150 ++++++++-<br>
>  4 files changed, 671 insertions(+), 4 deletions(-)<br>
><br>
<br>
Pushed to git master and mm-1-4. I also pushed a follow-up commit fixing<br>
some minor coding style things.<br>
<br>
Thanks!<br>
<br>
> diff --git a/plugins/telit/mm-broadband-modem-telit.c b/plugins/telit/mm-broadband-modem-telit.c<br>
> index b4f481b..2e09ac7 100644<br>
> --- a/plugins/telit/mm-broadband-modem-telit.c<br>
> +++ b/plugins/telit/mm-broadband-modem-telit.c<br>
> @@ -41,6 +41,90 @@ G_DEFINE_TYPE_EXTENDED (MMBroadbandModemTelit, mm_broadband_modem_telit, MM_TYPE<br>
>                          G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_3GPP, iface_modem_3gpp_init));<br>
><br>
>  /*****************************************************************************/<br>
> +/* Load supported bands (Modem interface) */<br>
> +typedef struct {<br>
> +    MMIfaceModem *self;<br>
> +    GSimpleAsyncResult *result;<br>
> +    gboolean mm_modem_is_2g;<br>
> +    gboolean mm_modem_is_3g;<br>
> +    gboolean mm_modem_is_4g;<br>
> +} LoadSupportedBandsContext;<br>
> +<br>
> +static void<br>
> +load_supported_bands_context_complete_and_free (LoadSupportedBandsContext *ctx)<br>
> +{<br>
> +    g_simple_async_result_complete (ctx->result);<br>
> +    g_object_unref (ctx->result);<br>
> +    g_object_unref (ctx->self);<br>
> +    g_slice_free (LoadSupportedBandsContext, ctx);<br>
> +}<br>
> +<br>
> +static GArray *<br>
> +modem_load_supported_bands_finish (MMIfaceModem *self,<br>
> +                                   GAsyncResult *res,<br>
> +                                   GError **error)<br>
> +{<br>
> +    if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))<br>
> +        return NULL;<br>
> +<br>
> +    return (GArray *) g_array_ref (g_simple_async_result_get_op_res_gpointer (<br>
> +                                       G_SIMPLE_ASYNC_RESULT (res)));<br>
> +}<br>
> +<br>
> +static void<br>
> +load_supported_bands_ready (MMBaseModem *self,<br>
> +                            GAsyncResult *res,<br>
> +                            LoadSupportedBandsContext *ctx)<br>
> +{<br>
> +    const gchar *response;<br>
> +    GError *error = NULL;<br>
> +    GArray *bands = NULL;<br>
> +<br>
> +    response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error);<br>
> +<br>
> +    if (!response)<br>
> +        g_simple_async_result_take_error (ctx->result, error);<br>
> +    else if (!mm_telit_parse_supported_bands_response (response,<br>
> +                                                       ctx->mm_modem_is_2g,<br>
> +                                                       ctx->mm_modem_is_3g,<br>
> +                                                       ctx->mm_modem_is_4g,<br>
> +                                                       &bands,<br>
> +                                                       &error))<br>
> +        g_simple_async_result_take_error (ctx->result, error);<br>
> +    else<br>
> +        g_simple_async_result_set_op_res_gpointer (ctx->result, bands, (GDestroyNotify)g_array_unref);<br>
> +<br>
> +    load_supported_bands_context_complete_and_free(ctx);<br>
> +}<br>
> +<br>
> +static void<br>
> +modem_load_supported_bands (MMIfaceModem *self,<br>
> +                            GAsyncReadyCallback callback,<br>
> +                            gpointer user_data)<br>
> +{<br>
> +    LoadSupportedBandsContext *ctx;<br>
> +<br>
> +    ctx = g_slice_new0(LoadSupportedBandsContext);<br>
> +<br>
> +    ctx->self = g_object_ref (self);<br>
> +    ctx->mm_modem_is_2g = mm_iface_modem_is_2g (ctx->self);<br>
> +    ctx->mm_modem_is_3g = mm_iface_modem_is_3g (ctx->self);<br>
> +    ctx->mm_modem_is_4g = mm_iface_modem_is_4g (ctx->self);<br>
> +<br>
> +    ctx->result = g_simple_async_result_new (G_OBJECT (self),<br>
> +                                             callback,<br>
> +                                             user_data,<br>
> +                                             modem_load_supported_bands);<br>
> +<br>
> +    mm_base_modem_at_command (MM_BASE_MODEM (self),<br>
> +                              "#BND=?",<br>
> +                              3,<br>
> +                              FALSE,<br>
> +                              (GAsyncReadyCallback) load_supported_bands_ready,<br>
> +                              ctx);<br>
> +}<br>
> +<br>
> +/*****************************************************************************/<br>
>  /* Load unlock retries (Modem interface) */<br>
><br>
>  #define CSIM_QUERY_PIN_RETRIES_STR  "+CSIM=10,0020000100"<br>
> @@ -517,6 +601,8 @@ mm_broadband_modem_telit_init (MMBroadbandModemTelit *self)<br>
>  static void<br>
>  iface_modem_init (MMIfaceModem *iface)<br>
>  {<br>
> +    iface->load_supported_bands = modem_load_supported_bands;<br>
> +    iface->load_supported_bands_finish = modem_load_supported_bands_finish;<br>
>      iface->load_unlock_retries_finish = modem_load_unlock_retries_finish;<br>
>      iface->load_unlock_retries = modem_load_unlock_retries;<br>
>      iface->reset = modem_reset;<br>
> diff --git a/plugins/telit/mm-modem-helpers-telit.c b/plugins/telit/mm-modem-helpers-telit.c<br>
> index 5344600..f287887 100644<br>
> --- a/plugins/telit/mm-modem-helpers-telit.c<br>
> +++ b/plugins/telit/mm-modem-helpers-telit.c<br>
> @@ -26,6 +26,9 @@<br>
>  #include "mm-modem-helpers.h"<br>
>  #include "mm-modem-helpers-telit.h"<br>
><br>
> +#define EMPTY_STRING ""<br>
> +<br>
> +<br>
>  /*****************************************************************************/<br>
>  /* +CSIM response parser */<br>
><br>
> @@ -36,7 +39,7 @@ mm_telit_parse_csim_response (const guint step,<br>
>  {<br>
>      GRegex *r = NULL;<br>
>      GMatchInfo *match_info = NULL;<br>
> -    gchar* retries_hex_str;<br>
> +    gchar *retries_hex_str;<br>
>      guint retries;<br>
><br>
>      r = g_regex_new ("\\+CSIM:\\s*[0-9]+,\\s*.*63C(.*)\"", G_REGEX_RAW, 0, NULL);<br>
> @@ -76,3 +79,370 @@ mm_telit_parse_csim_response (const guint step,<br>
><br>
>      return retries;<br>
>  }<br>
> +<br>
> +/*****************************************************************************/<br>
> +/* #BND=? response parser<br>
> + *<br>
> + * Example:<br>
> + *  AT#BND=?<br>
> + *      #BND: <2G band flags>,<3G band flags>[, <4G band flags>]<br>
> + *<br>
> + *  where "band flags" is a list of numbers definining the supported bands.<br>
> + *  Note that the one Telit band flag may represent more than one MM band.<br>
> + *<br>
> + *  e.g.<br>
> + *<br>
> + *  #BND: (0-2),(3,4)<br>
> + *<br>
> + *  (0,2) = 2G band flag 0 is EGSM + DCS<br>
> + *        = 2G band flag 1 is EGSM + PCS<br>
> + *        = 2G band flag 2 is DCS + G850<br>
> + *  (3,4) = 3G band flag 3 is U2100 + U1900 + U850<br>
> + *        = 3G band flag 4 is U1900 + U850<br>
> + *<br>
> + * Modems that supports 4G bands, return a range value(X-Y) where<br>
> + * X: represent the lower supported band, such as X = 2^(B-1), being B = B1, B2,..., B32<br>
> + * Y: is a 32 bit number resulting from a mask of all the supported bands:<br>
> + *      1 - B1<br>
> + *      2 - B2<br>
> + *      4 - B3<br>
> + *      8 - B4<br>
> + *      ...<br>
> + *      i - B(2exp(i-1))<br>
> + *      ...<br>
> + *      2147483648 - B32<br>
> + *<br>
> + *   e.g.<br>
> + *      (2-4106)<br>
> + *       2 = 2^1 --> lower supported band B2<br>
> + *       4106 = 2^1 + 2^3 + 2^12 --> the supported bands are B2, B4, B13<br>
> + */<br>
> +<br>
> +#define SUPP_BAND_RESPONSE_REGEX          "#BND:\\s*\\((?P<Bands2G>.*)\\),\\s*\\((?P<Bands3G>.*)\\)"<br>
> +#define SUPP_BAND_4G_MODEM_RESPONSE_REGEX "#BND:\\s*\\((?P<Bands2G>.*)\\),\\s*\\((?P<Bands3G>.*)\\),\\s*\\((?P<Bands4G>\\d+-\\d+)\\)"<br>
> +<br>
> +gboolean<br>
> +mm_telit_parse_supported_bands_response (const gchar *response,<br>
> +                                         const gboolean modem_is_2g,<br>
> +                                         const gboolean modem_is_3g,<br>
> +                                         const gboolean modem_is_4g,<br>
> +                                         GArray **supported_bands,<br>
> +                                         GError **error)<br>
> +{<br>
> +    GArray *bands = NULL;<br>
> +    GMatchInfo *match_info = NULL;<br>
> +    GRegex *r = NULL;<br>
> +    gboolean ret = FALSE;<br>
> +<br>
> +    /* Parse #BND=? response */<br>
> +    if (modem_is_4g)<br>
> +        r = g_regex_new (SUPP_BAND_4G_MODEM_RESPONSE_REGEX, G_REGEX_RAW, 0, NULL);<br>
> +    else<br>
> +        r = g_regex_new (SUPP_BAND_RESPONSE_REGEX, G_REGEX_RAW, 0, NULL);<br>
> +<br>
> +    if (!g_regex_match (r, response, 0, &match_info)) {<br>
> +        g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,<br>
> +                     "Could not parse reponse '%s'", response);<br>
> +        goto end;<br>
> +    }<br>
> +<br>
> +    if (!g_match_info_matches(match_info)) {<br>
> +        g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,<br>
> +                     "Could not find matches in response '%s'", response);<br>
> +        goto end;<br>
> +    }<br>
> +<br>
> +    bands = g_array_new (TRUE, TRUE, sizeof (MMModemBand));<br>
> +<br>
> +    if (modem_is_2g && !mm_telit_get_2g_mm_bands (match_info, &bands, error))<br>
> +        goto end;<br>
> +<br>
> +    if (modem_is_3g && !mm_telit_get_3g_mm_bands (match_info, &bands, error))<br>
> +        goto end;<br>
> +<br>
> +    if(modem_is_4g && !mm_telit_get_4g_mm_bands (match_info, &bands, error))<br>
> +        goto end;<br>
> +<br>
> +    *supported_bands = bands;<br>
> +    ret = TRUE;<br>
> +<br>
> +end:<br>
> +    if (!ret && bands != NULL)<br>
> +        g_array_free(bands, TRUE);<br>
> +<br>
> +    if(match_info)<br>
> +        g_match_info_free (match_info);<br>
> +<br>
> +    g_regex_unref (r);<br>
> +<br>
> +    return ret;<br>
> +}<br>
> +<br>
> +gboolean<br>
> +mm_telit_get_2g_mm_bands (GMatchInfo *match_info,<br>
> +                          GArray **bands,<br>
> +                          GError **error)<br>
> +{<br>
> +    GArray *flags = NULL;<br>
> +    gchar *match_str = NULL;<br>
> +    guint i;<br>
> +    gboolean ret = TRUE;<br>
> +<br>
> +    TelitToMMBandMap map [5] = {<br>
> +        { BND_FLAG_GSM900_DCS1800, {MM_MODEM_BAND_EGSM, MM_MODEM_BAND_DCS, MM_MODEM_BAND_UNKNOWN} }, /* 0 */<br>
> +        { BND_FLAG_GSM900_PCS1900, {MM_MODEM_BAND_EGSM, MM_MODEM_BAND_PCS, MM_MODEM_BAND_UNKNOWN} }, /* 1 */<br>
> +        { BND_FLAG_GSM850_DCS1800, {MM_MODEM_BAND_DCS, MM_MODEM_BAND_G850, MM_MODEM_BAND_UNKNOWN} }, /* 2 */<br>
> +        { BND_FLAG_GSM850_PCS1900, {MM_MODEM_BAND_PCS, MM_MODEM_BAND_G850, MM_MODEM_BAND_UNKNOWN} }, /* 3 */<br>
> +        { BND_FLAG_UNKNOWN, {}},<br>
> +    };<br>
> +<br>
> +    match_str = g_match_info_fetch_named (match_info, "Bands2G");<br>
> +<br>
> +    if (match_str == NULL || g_strcmp0(match_str, EMPTY_STRING) == 0) {<br>
> +        g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,<br>
> +                     "Could not find 2G band flags from response");<br>
> +        ret = FALSE;<br>
> +        goto end;<br>
> +    }<br>
> +<br>
> +    flags = g_array_new (FALSE, FALSE, sizeof(guint));<br>
> +<br>
> +    if (!mm_telit_get_band_flags_from_string (match_str, &flags, error)) {<br>
> +        ret = FALSE;<br>
> +        goto end;<br>
> +    }<br>
> +<br>
> +    for (i = 0; i < flags->len; i++) {<br>
> +        guint flag = g_array_index (flags, guint, i);<br>
> +        if (!mm_telit_update_band_array (flag, map, bands, error)) {<br>
> +            ret = FALSE;<br>
> +            goto end;<br>
> +        }<br>
> +    }<br>
> +<br>
> +end:<br>
> +    if (match_str != NULL)<br>
> +        g_free (match_str);<br>
> +<br>
> +    if (flags != NULL)<br>
> +        g_array_free (flags, TRUE);<br>
> +<br>
> +    return ret;<br>
> +}<br>
> +<br>
> +gboolean<br>
> +mm_telit_get_3g_mm_bands (GMatchInfo *match_info,<br>
> +                          GArray **bands,<br>
> +                          GError **error)<br>
> +{<br>
> +    GArray *flags = NULL;<br>
> +    gchar *match_str = NULL;<br>
> +    guint i;<br>
> +    gboolean ret = TRUE;<br>
> +<br>
> +    TelitToMMBandMap map [] = {<br>
> +        { BND_FLAG_0, { MM_MODEM_BAND_U2100, MM_MODEM_BAND_UNKNOWN} },<br>
> +        { BND_FLAG_1, { MM_MODEM_BAND_U1900, MM_MODEM_BAND_UNKNOWN} },<br>
> +        { BND_FLAG_2, { MM_MODEM_BAND_U850, MM_MODEM_BAND_UNKNOWN} },<br>
> +        { BND_FLAG_3, { MM_MODEM_BAND_U2100, MM_MODEM_BAND_U1900, MM_MODEM_BAND_U850, MM_MODEM_BAND_UNKNOWN} },<br>
> +        { BND_FLAG_4, { MM_MODEM_BAND_U1900, MM_MODEM_BAND_U850, MM_MODEM_BAND_UNKNOWN} },<br>
> +        { BND_FLAG_5, { MM_MODEM_BAND_U900, MM_MODEM_BAND_UNKNOWN} },<br>
> +        { BND_FLAG_6, { MM_MODEM_BAND_U2100, MM_MODEM_BAND_U900, MM_MODEM_BAND_UNKNOWN} },<br>
> +        { BND_FLAG_7, { MM_MODEM_BAND_U17IV, MM_MODEM_BAND_UNKNOWN} },<br>
> +        { BND_FLAG_8, { MM_MODEM_BAND_U2100, MM_MODEM_BAND_U850, MM_MODEM_BAND_UNKNOWN }},<br>
> +        { BND_FLAG_9, { MM_MODEM_BAND_U2100, MM_MODEM_BAND_U900, MM_MODEM_BAND_U850, MM_MODEM_BAND_UNKNOWN }},<br>
> +        { BND_FLAG_10, { MM_MODEM_BAND_U1900, MM_MODEM_BAND_U17IV, MM_MODEM_BAND_U850, MM_MODEM_BAND_UNKNOWN }},<br>
> +        { BND_FLAG_12, { MM_MODEM_BAND_U800, MM_MODEM_BAND_UNKNOWN}},<br>
> +        { BND_FLAG_13, { MM_MODEM_BAND_U1800, MM_MODEM_BAND_UNKNOWN }},<br>
> +        { BND_FLAG_14, { MM_MODEM_BAND_U2100, MM_MODEM_BAND_U900, MM_MODEM_BAND_U17IV, MM_MODEM_BAND_U850, MM_MODEM_BAND_U800, MM_MODEM_BAND_UNKNOWN }},<br>
> +        { BND_FLAG_15, { MM_MODEM_BAND_U2100, MM_MODEM_BAND_U900, MM_MODEM_BAND_U1800, MM_MODEM_BAND_UNKNOWN }},<br>
> +        { BND_FLAG_16, { MM_MODEM_BAND_U900, MM_MODEM_BAND_U850, MM_MODEM_BAND_UNKNOWN }},<br>
> +        { BND_FLAG_17, { MM_MODEM_BAND_U1900, MM_MODEM_BAND_U17IV, MM_MODEM_BAND_U850, MM_MODEM_BAND_U800, MM_MODEM_BAND_UNKNOWN }},<br>
> +        { BND_FLAG_18, { MM_MODEM_BAND_U2100, MM_MODEM_BAND_U1900, MM_MODEM_BAND_U850, MM_MODEM_BAND_U800, MM_MODEM_BAND_UNKNOWN}},<br>
> +        { BND_FLAG_19, { MM_MODEM_BAND_U1900, MM_MODEM_BAND_U800, MM_MODEM_BAND_UNKNOWN }},<br>
> +        { BND_FLAG_20, { MM_MODEM_BAND_U850, MM_MODEM_BAND_U800, MM_MODEM_BAND_UNKNOWN}},<br>
> +        { BND_FLAG_21, { MM_MODEM_BAND_U1900, MM_MODEM_BAND_U850, MM_MODEM_BAND_U800, MM_MODEM_BAND_UNKNOWN}},<br>
> +        { BND_FLAG_UNKNOWN, {}},<br>
> +    };<br>
> +<br>
> +<br>
> +    match_str = g_match_info_fetch_named (match_info, "Bands3G");<br>
> +<br>
> +    if (match_str == NULL || g_strcmp0(match_str, EMPTY_STRING) == 0) {<br>
> +        g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,<br>
> +                     "Could not find 3G band flags from response");<br>
> +        ret = FALSE;<br>
> +        goto end;<br>
> +    }<br>
> +<br>
> +    flags = g_array_new (FALSE, FALSE, sizeof(guint));<br>
> +<br>
> +    if (!mm_telit_get_band_flags_from_string (match_str, &flags, error)) {<br>
> +        ret = FALSE;<br>
> +        goto end;<br>
> +    }<br>
> +<br>
> +    for (i = 0; i < flags->len; i++) {<br>
> +        guint flag = g_array_index (flags, guint, i);<br>
> +        if (!mm_telit_update_band_array (flag, map, bands, error)) {<br>
> +            ret = FALSE;<br>
> +            goto end;<br>
> +        }<br>
> +    }<br>
> +<br>
> +end:<br>
> +    if (match_str != NULL)<br>
> +        g_free (match_str);<br>
> +<br>
> +    if (flags != NULL)<br>
> +        g_array_free (flags, TRUE);<br>
> +<br>
> +    return ret;<br>
> +}<br>
> +<br>
> +gboolean<br>
> +mm_telit_get_4g_mm_bands(GMatchInfo *match_info,<br>
> +                         GArray **bands,<br>
> +                         GError **error)<br>
> +{<br>
> +    GArray *flags = NULL;<br>
> +    MMModemBand band;<br>
> +    gboolean ret = TRUE;<br>
> +    gchar *match_str = NULL;<br>
> +    guint i;<br>
> +    guint max_value;<br>
> +<br>
> +    gchar **tokens;<br>
> +<br>
> +    match_str = g_match_info_fetch_named (match_info, "Bands4G");<br>
> +<br>
> +    if (match_str == NULL || g_strcmp0(match_str, EMPTY_STRING) == 0) {<br>
> +        g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,<br>
> +                     "Could not find 4G band flags from response");<br>
> +        ret = FALSE;<br>
> +        goto end;<br>
> +    }<br>
> +<br>
> +    tokens = g_strsplit (match_str, "-", -1);<br>
> +    if (tokens == NULL) {<br>
> +        g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,<br>
> +                     "Could not get 4G band ranges from string '%s'",<br>
> +                     match_str);<br>
> +        ret = FALSE;<br>
> +        goto end;<br>
> +    }<br>
> +<br>
> +    sscanf(tokens[1], "%d", &max_value);<br>
> +<br>
> +    for(i = 0; max_value > 0; i++) {<br>
> +        if (max_value % 2 != 0) {<br>
> +            band = MM_MODEM_BAND_EUTRAN_I + i;<br>
> +            g_array_append_val(*bands, band);<br>
> +        }<br>
> +        max_value = max_value >> 1;<br>
> +    }<br>
> +<br>
> +end:<br>
> +    if (match_str != NULL)<br>
> +        g_free (match_str);<br>
> +<br>
> +    if (flags != NULL)<br>
> +        g_array_free (flags, TRUE);<br>
> +<br>
> +    return ret;<br>
> +}<br>
> +gboolean<br>
> +mm_telit_bands_contains (GArray *mm_bands, const MMModemBand mm_band)<br>
> +{<br>
> +    guint i;<br>
> +<br>
> +    for (i = 0; i < mm_bands->len; i++) {<br>
> +        if (mm_band == g_array_index (mm_bands, MMModemBand, i))<br>
> +            return TRUE;<br>
> +    }<br>
> +<br>
> +    return FALSE;<br>
> +}<br>
> +<br>
> +gboolean<br>
> +mm_telit_update_band_array (const gint bands_flag,<br>
> +                            const TelitToMMBandMap *map,<br>
> +                            GArray **bands,<br>
> +                            GError **error)<br>
> +{<br>
> +    guint i;<br>
> +    guint j;<br>
> +<br>
> +    for (i = 0; map[i].flag != BND_FLAG_UNKNOWN; i++) {<br>
> +        if (bands_flag == map[i].flag) {<br>
> +            for (j = 0; map[i].mm_bands[j] != MM_MODEM_BAND_UNKNOWN; j++) {<br>
> +                if (!mm_telit_bands_contains (*bands, map[i].mm_bands[j])) {<br>
> +                    g_array_append_val (*bands, map[i].mm_bands[j]);<br>
> +                }<br>
> +            }<br>
> +<br>
> +            return TRUE;<br>
> +        }<br>
> +    }<br>
> +<br>
> +    g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,<br>
> +                 "No MM band found for Telit #BND flag '%d'",<br>
> +                 bands_flag);<br>
> +<br>
> +    return FALSE;<br>
> +}<br>
> +<br>
> +<br>
> +gboolean<br>
> +mm_telit_get_band_flags_from_string (const gchar *flag_str,<br>
> +                                     GArray **band_flags,<br>
> +                                     GError **error)<br>
> +{<br>
> +    gchar **range;<br>
> +    gchar **tokens;<br>
> +    guint flag;<br>
> +    guint i;<br>
> +<br>
> +    if (g_strcmp0(flag_str, "") == 0) {<br>
> +        g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,<br>
> +                     "String is empty, no band flags to parse");<br>
> +        return FALSE;<br>
> +    }<br>
> +<br>
> +    tokens = g_strsplit (flag_str, ",", -1);<br>
> +    if (!tokens) {<br>
> +        g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,<br>
> +                     "Could not get the list of flags");<br>
> +        return FALSE;<br>
> +    }<br>
> +<br>
> +    for (i = 0; tokens[i]; i++) {<br>
> +        /* check whether tokens[i] defines a<br>
> +         * single band value or a range of bands */<br>
> +        if (!strstr(tokens[i], "-")) {<br>
> +            sscanf(tokens[i], "%d", &flag);<br>
> +            g_array_append_val (*band_flags, flag);<br>
> +        } else {<br>
> +            gint range_start;<br>
> +            gint range_end;<br>
> +<br>
> +            range = g_strsplit(tokens[i], "-", 2);<br>
> +<br>
> +            sscanf(range[0], "%d", &range_start);<br>
> +            sscanf(range[1], "%d", &range_end);<br>
> +<br>
> +            for (flag=range_start; flag <= range_end; flag++) {<br>
> +                g_array_append_val (*band_flags, flag);<br>
> +            }<br>
> +<br>
> +            g_strfreev (range);<br>
> +        }<br>
> +    }<br>
> +<br>
> +    g_strfreev (tokens);<br>
> +<br>
> +    return TRUE;<br>
> +}<br>
> +<br>
> +<br>
> +<br>
> diff --git a/plugins/telit/mm-modem-helpers-telit.h b/plugins/telit/mm-modem-helpers-telit.h<br>
> index 112e04b..d0d74b5 100644<br>
> --- a/plugins/telit/mm-modem-helpers-telit.h<br>
> +++ b/plugins/telit/mm-modem-helpers-telit.h<br>
> @@ -18,9 +18,76 @@<br>
><br>
>  #include <glib.h><br>
><br>
> +#define MAX_BANDS_LIST_LEN 20<br>
> +<br>
> +#define BND_FLAG_UNKNOWN -1<br>
> +<br>
> +/* AT#BND 2G flags */<br>
> +typedef enum {<br>
> +    BND_FLAG_GSM900_DCS1800,<br>
> +    BND_FLAG_GSM900_PCS1900,<br>
> +    BND_FLAG_GSM850_DCS1800,<br>
> +    BND_FLAG_GSM850_PCS1900,<br>
> +} BndFlag2G;<br>
> +<br>
> +/* AT#BND 3G flags */<br>
> +typedef enum {<br>
> +    BND_FLAG_0,    /* B1 (2100 MHz) */<br>
> +    BND_FLAG_1,    /* B2 (1900 MHz) */<br>
> +    BND_FLAG_2,    /* B5 (850 MHz) */<br>
> +    BND_FLAG_3,    /* B1 (2100 MHz) + B2 (1900 MHz) + B5 (850 MHz) */<br>
> +    BND_FLAG_4,    /* B2 (1900 MHz) + B5 (850 MHz) */<br>
> +    BND_FLAG_5,    /* B8 (900 MHz) */<br>
> +    BND_FLAG_6,    /* B1 (2100 MHz) + B8 (900 MHz) */<br>
> +    BND_FLAG_7,    /* B4 (1700 MHz) */<br>
> +    BND_FLAG_8,    /* B1 (2100 MHz) + B5 (850 MHz) */<br>
> +    BND_FLAG_9,    /* B1 (2100 MHz) + B8 (900 MHz) + B5 (850 MHz) */<br>
> +    BND_FLAG_10,   /* B2 (1900 MHz) + B4 (1700 MHz) + B5 (850 MHz) */<br>
> +    BND_FLAG_12,   /* B6 (800 MHz) */<br>
> +    BND_FLAG_13,   /* B3 (1800 MHz) */<br>
> +    BND_FLAG_14,   /* B1 (2100 MHz) + B2 (1900 MHz) + B4 (1700 MHz) + B5 (850 MHz) + B6 (800MHz) */<br>
> +    BND_FLAG_15,   /* B1 (2100 MHz) + B8 (900 MHz) + B3 (1800 MHz) */<br>
> +    BND_FLAG_16,   /* B8 (900 MHz) + B5 (850 MHz) */<br>
> +    BND_FLAG_17,   /* B2 (1900 MHz) + B4 (1700 MHz) + B5 (850 MHz) + B6 (800 MHz) */<br>
> +    BND_FLAG_18,   /* B1 (2100 MHz) + B2 (1900 MHz) + B5 (850 MHz) + B6 (800 MHz) */<br>
> +    BND_FLAG_19,   /* B2 (1900 MHz) + B6 (800 MHz) */<br>
> +    BND_FLAG_20,   /* B5 (850 MHz) + B6 (800 MHz) */<br>
> +    BND_FLAG_21,   /* B2 (1900 MHz) + B5 (850 MHz) + B6 (800 MHz) */<br>
> +} BndFlag3G;<br>
> +<br>
> +typedef struct {<br>
> +    gint flag;<br>
> +    MMModemBand mm_bands[MAX_BANDS_LIST_LEN];<br>
> +} TelitToMMBandMap;<br>
> +<br>
>  /* +CSIM response parser */<br>
>  gint mm_telit_parse_csim_response (const guint step,<br>
>                                     const gchar *response,<br>
>                                     GError **error);<br>
><br>
> +/* #BND=? response parser */<br>
> +gboolean<br>
> +mm_telit_parse_supported_bands_response (const gchar *response,<br>
> +                                         const gboolean modem_is_2g,<br>
> +                                         const gboolean modem_is_3g,<br>
> +                                         const gboolean modem_is_4g,<br>
> +                                         GArray **supported_bands,<br>
> +                                         GError **error);<br>
> +<br>
> +gboolean mm_telit_bands_contains (GArray *mm_bands, const MMModemBand mm_band);<br>
> +<br>
> +gboolean mm_telit_update_band_array (const gint bands_flag,<br>
> +                                     const TelitToMMBandMap *map,<br>
> +                                     GArray **bands,<br>
> +                                     GError **error);<br>
> +<br>
> +gboolean mm_telit_get_band_flags_from_string (const gchar *flag_str, GArray **band_flags, GError **error);<br>
> +gboolean mm_telit_get_2g_mm_bands(GMatchInfo *match_info, GArray **bands, GError **error);<br>
> +gboolean mm_telit_get_3g_mm_bands(GMatchInfo *match_info, GArray **bands, GError **error);<br>
> +gboolean mm_telit_get_4g_mm_bands(GMatchInfo *match_info, GArray **bands, GError **error);<br>
> +<br>
> +gboolean mm_telit_update_2g_bands(gchar *band_list, GMatchInfo **match_info, GArray **bands, GError **error);<br>
> +gboolean mm_telit_update_3g_bands(gchar *band_list, GMatchInfo **match_info, GArray **bands, GError **error);<br>
> +gboolean mm_telit_update_4g_bands(GArray** bands, GMatchInfo *match_info, GError **error);<br>
> +<br>
>  #endif  /* MM_MODEM_HELPERS_TELIT_H */<br>
> diff --git a/plugins/telit/tests/test-mm-modem-helpers-telit.c b/plugins/telit/tests/test-mm-modem-helpers-telit.c<br>
> index afe9f82..7084779 100644<br>
> --- a/plugins/telit/tests/test-mm-modem-helpers-telit.c<br>
> +++ b/plugins/telit/tests/test-mm-modem-helpers-telit.c<br>
> @@ -22,7 +22,6 @@<br>
>  #define _LIBMM_INSIDE_MM<br>
>  #include <libmm-glib.h><br>
><br>
> -#include "mm-log.h"<br>
>  #include "mm-modem-helpers.h"<br>
>  #include "mm-modem-helpers-telit.h"<br>
><br>
> @@ -63,7 +62,7 @@ static CSIMResponseTest invalid_csim_response_test_list [] = {<br>
>  };<br>
><br>
>  static void<br>
> -test_parse_csim_response (void)<br>
> +test_mm_telit_parse_csim_response (void)<br>
>  {<br>
>      const gint step = 1;<br>
>      guint i;<br>
> @@ -92,6 +91,148 @@ test_parse_csim_response (void)<br>
>      }<br>
>  }<br>
><br>
> +static void<br>
> +test_mm_bands_contains (void) {<br>
> +    GArray* mm_bands;<br>
> +    guint i = 1;<br>
> +<br>
> +    mm_bands = g_array_sized_new (FALSE, TRUE, sizeof (MMModemBand), 3);<br>
> +<br>
> +    for (i = 0; i < 3; i++)<br>
> +        g_array_append_val (mm_bands, i);<br>
> +<br>
> +    g_assert_true (mm_telit_bands_contains (mm_bands, 2));<br>
> +    g_assert_true (mm_telit_bands_contains (mm_bands, 2));<br>
> +    g_assert_false (mm_telit_bands_contains (mm_bands, 3));<br>
> +<br>
> +    g_array_free (mm_bands, TRUE);<br>
> +}<br>
> +<br>
> +typedef struct {<br>
> +    gchar* band_flag_str;<br>
> +    guint band_flags_len;<br>
> +    guint band_flags [MAX_BANDS_LIST_LEN];<br>
> +} BNDFlagsTest;<br>
> +<br>
> +static BNDFlagsTest band_flag_test[] = {<br>
> +    {"0-3", 4, {0, 1, 2, 3} },<br>
> +    {"0,3", 2, {0, 3} },<br>
> +    {"0,2-3,5-7,9", 2, {0, 2, 3, 5, 6, 7, 9} },<br>
> +    { NULL, 0, {}},<br>
> +};<br>
> +<br>
> +static void<br>
> +test_parse_band_flag_str (void) {<br>
> +    GError *error = NULL;<br>
> +    gboolean res = FALSE;<br>
> +    GArray *band_flags = NULL;<br>
> +    guint i, j;<br>
> +<br>
> +    for (i = 0; band_flag_test[i].band_flag_str != NULL; i++) {<br>
> +        band_flags = g_array_new (FALSE, FALSE, sizeof (guint));<br>
> +        res = mm_telit_get_band_flags_from_string (band_flag_test[i].band_flag_str,<br>
> +                                                   &band_flags,<br>
> +                                                   &error);<br>
> +        g_assert_no_error (error);<br>
> +        g_assert_true (res);<br>
> +<br>
> +        for (j = 0; j < band_flag_test[i].band_flags_len; j++) {<br>
> +            guint ref = band_flag_test[i].band_flags[j];<br>
> +            guint cur = g_array_index (band_flags, guint, j);<br>
> +<br>
> +            g_assert_true (ref == cur);<br>
> +        }<br>
> +<br>
> +        g_array_free (band_flags, TRUE);<br>
> +    }<br>
> +}<br>
> +<br>
> +typedef struct {<br>
> +    gchar* response;<br>
> +    gboolean modem_is_2g;<br>
> +    gboolean modem_is_3g;<br>
> +    gboolean modem_is_4g;<br>
> +    guint mm_bands_len;<br>
> +    MMModemBand mm_bands [MAX_BANDS_LIST_LEN];<br>
> +} BNDResponseTest;<br>
> +<br>
> +static BNDResponseTest supported_band_mapping_tests [] = {<br>
> +    { "#BND: (0-3),(0,2,5,6)", TRUE, TRUE, FALSE, 7, { MM_MODEM_BAND_EGSM,<br>
> +                                                      MM_MODEM_BAND_DCS,<br>
> +                                                      MM_MODEM_BAND_PCS,<br>
> +                                                      MM_MODEM_BAND_G850,<br>
> +                                                      MM_MODEM_BAND_U2100,<br>
> +                                                      MM_MODEM_BAND_U850,<br>
> +                                                      MM_MODEM_BAND_U900} },<br>
> +    { "#BND: (0,3),(0,2,5,6)", TRUE, TRUE, FALSE, 7, { MM_MODEM_BAND_EGSM,<br>
> +                                                       MM_MODEM_BAND_DCS,<br>
> +                                                       MM_MODEM_BAND_PCS,<br>
> +                                                       MM_MODEM_BAND_G850,<br>
> +                                                       MM_MODEM_BAND_U2100,<br>
> +                                                       MM_MODEM_BAND_U850,<br>
> +                                                       MM_MODEM_BAND_U900} },<br>
> +    { "#BND: (0,2),(0,2,5,6)", TRUE, TRUE, FALSE, 6, { MM_MODEM_BAND_EGSM,<br>
> +                                                       MM_MODEM_BAND_DCS,<br>
> +                                                       MM_MODEM_BAND_G850,<br>
> +                                                       MM_MODEM_BAND_U2100,<br>
> +                                                       MM_MODEM_BAND_U850,<br>
> +                                                       MM_MODEM_BAND_U900} },<br>
> +    { "#BND: (0,2),(0-4,5,6)", TRUE, TRUE, FALSE, 7, { MM_MODEM_BAND_EGSM,<br>
> +                                                       MM_MODEM_BAND_DCS,<br>
> +                                                       MM_MODEM_BAND_G850,<br>
> +                                                       MM_MODEM_BAND_U2100,<br>
> +                                                       MM_MODEM_BAND_U1900,<br>
> +                                                       MM_MODEM_BAND_U850,<br>
> +                                                       MM_MODEM_BAND_U900} },<br>
> +    { "#BND: (0-3),(0,2,5,6),(1-1)", TRUE, TRUE, TRUE, 8, { MM_MODEM_BAND_EGSM,<br>
> +                                                         MM_MODEM_BAND_DCS,<br>
> +                                                         MM_MODEM_BAND_PCS,<br>
> +                                                         MM_MODEM_BAND_G850,<br>
> +                                                         MM_MODEM_BAND_U2100,<br>
> +                                                         MM_MODEM_BAND_U850,<br>
> +                                                         MM_MODEM_BAND_U900,<br>
> +                                                         MM_MODEM_BAND_EUTRAN_I} },<br>
> +    { "#BND: (0),(0),(1-3)", TRUE, TRUE, TRUE, 5, { MM_MODEM_BAND_EGSM,<br>
> +                                                    MM_MODEM_BAND_DCS,<br>
> +                                                    MM_MODEM_BAND_U2100,<br>
> +                                                    MM_MODEM_BAND_EUTRAN_I,<br>
> +                                                    MM_MODEM_BAND_EUTRAN_II} },<br>
> +    { "#BND: (0),(0),(1-3)", FALSE, FALSE, TRUE, 2, { MM_MODEM_BAND_EUTRAN_I,<br>
> +                                                      MM_MODEM_BAND_EUTRAN_II} },<br>
> +    { NULL, FALSE, FALSE, FALSE, 0, {}},<br>
> +};<br>
> +<br>
> +static void<br>
> +test_parse_supported_bands_response (void) {<br>
> +    GError* error = NULL;<br>
> +    gboolean res = FALSE;<br>
> +    guint i, j;<br>
> +    GArray* bands = NULL;<br>
> +<br>
> +    for (i = 0; supported_band_mapping_tests[i].response != NULL; i++) {<br>
> +        res = mm_telit_parse_supported_bands_response (supported_band_mapping_tests[i].response,<br>
> +                                                       supported_band_mapping_tests[i].modem_is_2g,<br>
> +                                                       supported_band_mapping_tests[i].modem_is_3g,<br>
> +                                                       supported_band_mapping_tests[i].modem_is_4g,<br>
> +                                                       &bands,<br>
> +                                                       &error);<br>
> +        g_assert_no_error (error);<br>
> +        g_assert_true (res);<br>
> +<br>
> +<br>
> +        for (j = 0; j < supported_band_mapping_tests[i].mm_bands_len; j++) {<br>
> +            MMModemBand ref = supported_band_mapping_tests[i].mm_bands[j];<br>
> +            MMModemBand cur = g_array_index (bands, MMModemBand, j);<br>
> +            g_assert_cmpint (cur, ==, ref);<br>
> +        }<br>
> +<br>
> +        g_assert_cmpint(bands->len, ==, supported_band_mapping_tests[i].mm_bands_len);<br>
> +<br>
> +        g_array_free (bands, FALSE);<br>
> +        bands = NULL;<br>
> +    }<br>
> +}<br>
> +<br>
>  int main (int argc, char **argv)<br>
>  {<br>
>      setlocale (LC_ALL, "");<br>
> @@ -99,6 +240,9 @@ int main (int argc, char **argv)<br>
>      g_type_init ();<br>
>      g_test_init (&argc, &argv, NULL);<br>
><br>
> -    g_test_add_func ("/MM/telit/csim", test_parse_csim_response);<br>
> +    g_test_add_func ("/MM/telit/csim", test_mm_telit_parse_csim_response);<br>
> +    g_test_add_func ("/MM/telit/bands/supported/bands_contains", test_mm_bands_contains);<br>
> +    g_test_add_func ("/MM/telit/bands/supported/parse_band_flag", test_parse_band_flag_str);<br>
> +    g_test_add_func ("/MM/telit/bands/supported/parse_bands_response", test_parse_supported_bands_response);<br>
>      return g_test_run ();<br>
>  }<br>
><br>
<br>
<br>
--<br>
Aleksander<br>
<a href="https://aleksander.es" rel="noreferrer" target="_blank">https://aleksander.es</a><br>
</blockquote></div>