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

Dan Williams dcbw at redhat.com
Thu May 31 14:12:42 UTC 2018


Support manual network selection by MCC/MNC via the 

---

diff --git a/src/qmicli/qmicli-helpers.c b/src/qmicli/qmicli-helpers.c
index 00f7122..ad68573 100644
--- a/src/qmicli/qmicli-helpers.c
+++ b/src/qmicli/qmicli-helpers.c
@@ -263,6 +263,77 @@ 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 *equals = NULL;
+    guint16 mcc = 0, mnc = 0;
+
+    equals = strchr (str, '=');
+    if (equals) {
+        /* Parse MCC/MNC */
+        *equals++ = '\0';
+        if (!parse_3gpp_mcc_mnc (equals, &mcc, &mnc)) {
+            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, str);
+    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", str);
+
+    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..d6cbe67 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


More information about the libqmi-devel mailing list