[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