[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