[PATCH v2] qmicli: support auto/manual network with --nas-set-system-selection-preference

Aleksander Morgado aleksander at aleksander.es
Tue Jun 5 07:30:54 UTC 2018


On Mon, Jun 4, 2018 at 6:13 PM, Dan Williams <dcbw at redhat.com> wrote:
> Support auto/manual network selection by extending the existing
> NAS Set System Selection Preference command with some new options.
>
> --nas-set-system-selection-preference=auto
> --nas-set-system-selection-preference=manual=310260
> --nas-set-system-selection-preference=gsm|umts|lte,manual=310260

LGTM!

> ---
>  src/qmicli/qmicli-helpers.c |  74 ++++++++++++++++++++++++++++
>  src/qmicli/qmicli-helpers.h |   4 ++
>  src/qmicli/qmicli-nas.c     | 114 +++++++++++++++++++++++++++++++-------------
>  3 files changed, 160 insertions(+), 32 deletions(-)
>
> diff --git a/src/qmicli/qmicli-helpers.c b/src/qmicli/qmicli-helpers.c
> index 00f7122..84aef4a 100644
> --- a/src/qmicli/qmicli-helpers.c
> +++ b/src/qmicli/qmicli-helpers.c
> @@ -263,6 +263,80 @@ qmicli_read_rat_mode_pref_from_string (const gchar *str,
>      return success && set;
>  }
>
> +static gboolean
> +parse_3gpp_mcc_mnc (const gchar *str,
> +                    guint16 *out_mcc,
> +                    guint16 *out_mnc)
> +{
> +    guint len;
> +    guint i;
> +    gchar aux[4];
> +    guint16 tmp;
> +
> +    len = strlen (str);
> +    if (len != 5 && len != 6)
> +        return FALSE;
> +    for (i = 0; i < len; i++) {
> +        if (!g_ascii_isdigit (str[i]))
> +            return FALSE;
> +    }
> +
> +    memcpy (&aux[0], str, 3);
> +    aux[3] = '\0';
> +    tmp = atoi (aux);
> +    if (tmp == 0)
> +        return FALSE;
> +    *out_mcc = tmp;
> +
> +    if (len == 5) {
> +        memcpy (&aux[0], &str[3], 2);
> +        aux[2] = '\0';
> +    } else
> +        memcpy (&aux[0], &str[3], 3);
> +    *out_mnc = atoi (aux);
> +
> +    return TRUE;
> +}
> +
> +gboolean
> +qmicli_read_net_selection_pref_from_string (const gchar *str,
> +                                            QmiNasNetworkSelectionPreference *out,
> +                                            guint16 *out_mcc,
> +                                            guint16 *out_mnc)
> +{
> +    GType type;
> +    GEnumClass *enum_class;
> +    GEnumValue *enum_value;
> +    gchar *copy, *equals;
> +    guint16 mcc = 0, mnc = 0;
> +
> +    copy = g_strdup (str);
> +    equals = strchr (copy, '=');
> +    if (equals) {
> +        /* Parse MCC/MNC */
> +        *equals++ = '\0';
> +        if (!parse_3gpp_mcc_mnc (equals, &mcc, &mnc)) {
> +            g_free (copy);
> +            g_printerr ("error: invalid net selection MCC/MNC: '%s'\n", equals);
> +            return FALSE;
> +        }
> +    }
> +
> +    type = qmi_nas_network_selection_preference_get_type ();
> +    enum_class = G_ENUM_CLASS (g_type_class_ref (type));
> +    enum_value = g_enum_get_value_by_nick (enum_class, copy);
> +    if (enum_value) {
> +        *out = (QmiNasNetworkSelectionPreference)enum_value->value;
> +        *out_mcc = mcc;
> +        *out_mnc = mnc;
> +    } else
> +        g_printerr ("error: invalid net selection preference value given: '%s'\n", copy);
> +
> +    g_free (copy);
> +    g_type_class_unref (enum_class);
> +    return !!enum_value;
> +}
> +
>  gboolean
>  qmicli_read_facility_from_string (const gchar *str,
>                                    QmiDmsUimFacility *out)
> diff --git a/src/qmicli/qmicli-helpers.h b/src/qmicli/qmicli-helpers.h
> index e8fac1d..6fd45d7 100644
> --- a/src/qmicli/qmicli-helpers.h
> +++ b/src/qmicli/qmicli-helpers.h
> @@ -40,6 +40,10 @@ gboolean qmicli_read_operating_mode_from_string              (const gchar *str,
>                                                                QmiDmsOperatingMode *out);
>  gboolean qmicli_read_rat_mode_pref_from_string               (const gchar *str,
>                                                                QmiNasRatModePreference *out);
> +gboolean qmicli_read_net_selection_pref_from_string          (const gchar *str,
> +                                                              QmiNasNetworkSelectionPreference *out,
> +                                                              guint16 *out_mcc,
> +                                                              guint16 *out_mnc);
>  gboolean qmicli_read_facility_from_string                    (const gchar *str,
>                                                                QmiDmsUimFacility *out);
>  gboolean qmicli_read_enable_disable_from_string              (const gchar *str,
> diff --git a/src/qmicli/qmicli-nas.c b/src/qmicli/qmicli-nas.c
> index 2ea5a6b..203aa1e 100644
> --- a/src/qmicli/qmicli-nas.c
> +++ b/src/qmicli/qmicli-nas.c
> @@ -97,7 +97,7 @@ static GOptionEntry entries[] = {
>      },
>      { "nas-set-system-selection-preference", 0, 0, G_OPTION_ARG_STRING, &set_system_selection_preference_str,
>        "Set system selection preference",
> -      "[cdma-1x|cdma-1xevdo|gsm|umts|lte|td-scdma]"
> +      "[cdma-1x|cdma-1xevdo|gsm|umts|lte|td-scdma][,[auto|manual=MCCMNC]]"
>      },
>      { "nas-network-scan", 0, 0, G_OPTION_ARG_NONE, &network_scan_flag,
>        "Scan networks",
> @@ -2137,24 +2137,81 @@ static QmiMessageNasSetSystemSelectionPreferenceInput *
>  set_system_selection_preference_input_create (const gchar *str)
>  {
>      QmiMessageNasSetSystemSelectionPreferenceInput *input = NULL;
> -    QmiNasRatModePreference pref;
> +    QmiNasRatModePreference pref = 0;
> +    QmiNasNetworkSelectionPreference net_pref = 0;
> +    gchar *rat_pref_str = NULL;
> +    gchar *net_pref_str = NULL;
>      GError *error = NULL;
> +    guint16 mcc = 0, mnc = 0;
>
> -    if (!qmicli_read_rat_mode_pref_from_string (str, &pref)) {
> -        g_printerr ("error: failed to parse mode pref\n");
> -        return NULL;
> +    if (strchr (str, ',')) {
> +        gchar **parts;
> +
> +        /* Both RAT mode preference and network selection preference were given */
> +        parts = g_strsplit_set (str, ",", -1);
> +        if (g_strv_length (parts) != 2) {
> +            g_printerr ("error: failed to parse selection pref: '%s'\n", str);
> +            g_strfreev (parts);
> +            return NULL;
> +        }
> +        rat_pref_str = g_strdup (parts[0]);
> +        net_pref_str = g_strdup (parts[1]);
> +        g_strfreev (parts);
> +    } else if (g_str_has_prefix (str, "auto") || g_str_has_prefix (str, "manual")) {
> +        /* Only network selection preference was given */
> +        net_pref_str = g_strdup (str);
> +    } else {
> +        /* Only RAT mode preference was given */
> +        rat_pref_str = g_strdup (str);
> +    }
> +
> +    if (net_pref_str && !qmicli_read_net_selection_pref_from_string (net_pref_str, &net_pref, &mcc, &mnc)) {
> +        g_printerr ("error: failed to parse net pref: '%s'\n", net_pref_str);
> +        goto error;
> +    }
> +
> +    if (rat_pref_str && !qmicli_read_rat_mode_pref_from_string (rat_pref_str, &pref)) {
> +        g_printerr ("error: failed to parse mode pref: '%s'\n", rat_pref_str);
> +        goto error;
>      }
>
>      input = qmi_message_nas_set_system_selection_preference_input_new ();
> -    if (!qmi_message_nas_set_system_selection_preference_input_set_mode_preference (
> -            input,
> -            pref,
> -            &error)) {
> -        g_printerr ("error: couldn't create input data bundle: '%s'\n",
> -                    error->message);
> -        g_error_free (error);
> -        qmi_message_nas_set_system_selection_preference_input_unref (input);
> -        return NULL;
> +
> +    if (rat_pref_str) {
> +        if (!qmi_message_nas_set_system_selection_preference_input_set_mode_preference (
> +                input,
> +                pref,
> +                &error)) {
> +            g_printerr ("error: couldn't create input data bundle: '%s'\n",
> +                        error->message);
> +            goto error;
> +        }
> +
> +        if (pref & (QMI_NAS_RAT_MODE_PREFERENCE_GSM |
> +                    QMI_NAS_RAT_MODE_PREFERENCE_UMTS |
> +                    QMI_NAS_RAT_MODE_PREFERENCE_LTE)) {
> +            if (!qmi_message_nas_set_system_selection_preference_input_set_gsm_wcdma_acquisition_order_preference (
> +                    input,
> +                    QMI_NAS_GSM_WCDMA_ACQUISITION_ORDER_PREFERENCE_AUTOMATIC,
> +                    &error)) {
> +                g_printerr ("error: couldn't create input data bundle: '%s'\n",
> +                            error->message);
> +                goto error;
> +            }
> +        }
> +    }
> +
> +    if (net_pref_str) {
> +        if (!qmi_message_nas_set_system_selection_preference_input_set_network_selection_preference (
> +                input,
> +                net_pref,
> +                mcc,
> +                mnc,
> +                &error)) {
> +            g_printerr ("error: couldn't create input data bundle: '%s'\n",
> +                        error->message);
> +            goto error;
> +        }
>      }
>
>      if (!qmi_message_nas_set_system_selection_preference_input_set_change_duration (
> @@ -2163,27 +2220,20 @@ set_system_selection_preference_input_create (const gchar *str)
>              &error)) {
>          g_printerr ("error: couldn't create input data bundle: '%s'\n",
>                      error->message);
> -        g_error_free (error);
> -        qmi_message_nas_set_system_selection_preference_input_unref (input);
> -        return NULL;
> -    }
> -
> -    if (pref & (QMI_NAS_RAT_MODE_PREFERENCE_GSM |
> -                QMI_NAS_RAT_MODE_PREFERENCE_UMTS |
> -                QMI_NAS_RAT_MODE_PREFERENCE_LTE)) {
> -        if (!qmi_message_nas_set_system_selection_preference_input_set_gsm_wcdma_acquisition_order_preference (
> -                input,
> -                QMI_NAS_GSM_WCDMA_ACQUISITION_ORDER_PREFERENCE_AUTOMATIC,
> -                &error)) {
> -            g_printerr ("error: couldn't create input data bundle: '%s'\n",
> -                        error->message);
> -            g_error_free (error);
> -            qmi_message_nas_set_system_selection_preference_input_unref (input);
> -            return NULL;
> -        }
> +        goto error;
>      }
>
> +    g_free (rat_pref_str);
> +    g_free (net_pref_str);
>      return input;
> +
> +error:
> +    g_clear_error (&error);
> +    if (input)
> +        qmi_message_nas_set_system_selection_preference_input_unref (input);
> +    g_free (rat_pref_str);
> +    g_free (net_pref_str);
> +    return NULL;
>  }
>
>  static void
> --
> 2.14.3



-- 
Aleksander
https://aleksander.es


More information about the libqmi-devel mailing list