aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTeijo Kinnunen <teijo.kinnunen@uros.com>2021-02-26 13:26:53 +0200
committerAleksander Morgado <aleksander@aleksander.es>2021-03-01 13:37:03 +0000
commit7b8427c8fdd4cd879c97aa680fd95908fab3e2c7 (patch)
treef72baeac423cdd0d7716a98bc4808eb3de7bbbe4
parente0900654d60dedab83a9dc1a2f4a74aa73b6e4b2 (diff)
qmicli,nas: add --nas-get-preferred-networks/--nas-set-preferred-networks
-rw-r--r--src/qmicli/qmicli-helpers.h5
-rw-r--r--src/qmicli/qmicli-nas.c248
2 files changed, 251 insertions, 2 deletions
diff --git a/src/qmicli/qmicli-helpers.h b/src/qmicli/qmicli-helpers.h
index 077047e..446e4ec 100644
--- a/src/qmicli/qmicli-helpers.h
+++ b/src/qmicli/qmicli-helpers.h
@@ -58,8 +58,9 @@ QMICLI_ENUM_LIST
/* Common helpers to read flags from strings */
#define QMICLI_FLAGS_LIST \
- QMICLI_FLAGS_LIST_ITEM (QmiDeviceOpenFlags, device_open_flags, "device open flags") \
- QMICLI_FLAGS_LIST_ITEM (QmiLocNmeaType, loc_nmea_type, "NMEA type")
+ QMICLI_FLAGS_LIST_ITEM (QmiDeviceOpenFlags, device_open_flags, "device open flags") \
+ QMICLI_FLAGS_LIST_ITEM (QmiLocNmeaType, loc_nmea_type, "NMEA type") \
+ QMICLI_FLAGS_LIST_ITEM (QmiNasPlmnAccessTechnologyIdentifier, nas_plmn_access_technology_identifier, "PLMN access technology")
#define QMICLI_FLAGS_LIST_ITEM(TYPE,TYPE_UNDERSCORE,DESCR) \
gboolean qmicli_read_## TYPE_UNDERSCORE ##_from_string (const gchar *str, TYPE *out);
diff --git a/src/qmicli/qmicli-nas.c b/src/qmicli/qmicli-nas.c
index 70371e6..b78a5b4 100644
--- a/src/qmicli/qmicli-nas.c
+++ b/src/qmicli/qmicli-nas.c
@@ -51,6 +51,8 @@ static gboolean get_home_network_flag;
static gboolean get_serving_system_flag;
static gboolean get_system_info_flag;
static gboolean get_technology_preference_flag;
+static gboolean get_preferred_networks_flag;
+static gchar *set_preferred_networks_str;
static gboolean get_system_selection_preference_flag;
static gchar *set_system_selection_preference_str;
static gchar *get_plmn_name_str;
@@ -109,6 +111,18 @@ static GOptionEntry entries[] = {
NULL
},
#endif
+#if defined HAVE_QMI_MESSAGE_NAS_GET_PREFERRED_NETWORKS
+ { "nas-get-preferred-networks", 0, 0, G_OPTION_ARG_NONE, &get_preferred_networks_flag,
+ "Get preferred networks",
+ NULL
+ },
+#endif
+#if defined HAVE_QMI_MESSAGE_NAS_SET_PREFERRED_NETWORKS
+ { "nas-set-preferred-networks", 0, 0, G_OPTION_ARG_STRING, &set_preferred_networks_str,
+ "Set preferred networks list",
+ "[[MCCMNC,access_tech],...]"
+ },
+#endif
#if defined HAVE_QMI_MESSAGE_NAS_GET_SYSTEM_SELECTION_PREFERENCE
{ "nas-get-system-selection-preference", 0, 0, G_OPTION_ARG_NONE, &get_system_selection_preference_flag,
"Get system selection preference",
@@ -225,6 +239,8 @@ qmicli_nas_options_enabled (void)
get_serving_system_flag +
get_system_info_flag +
get_technology_preference_flag +
+ get_preferred_networks_flag +
+ !!set_preferred_networks_str +
get_system_selection_preference_flag +
!!set_system_selection_preference_str +
!!get_plmn_name_str +
@@ -1004,6 +1020,203 @@ get_home_network_ready (QmiClientNas *client,
#endif /* HAVE_QMI_MESSAGE_NAS_GET_HOME_NETWORK */
+#if defined HAVE_QMI_MESSAGE_NAS_GET_PREFERRED_NETWORKS
+
+static void
+get_preferred_networks_ready (QmiClientNas *client,
+ GAsyncResult *res)
+{
+ QmiMessageNasGetPreferredNetworksOutput *output;
+ GError *error = NULL;
+ GArray *preferred_networks_array;
+ GArray *pcs_digit_array;
+
+ output = qmi_client_nas_get_preferred_networks_finish (client, res, &error);
+ if (!output) {
+ g_printerr ("error: operation failed: %s\n", error->message);
+ g_error_free (error);
+ operation_shutdown (FALSE);
+ return;
+ }
+
+ if (!qmi_message_nas_get_preferred_networks_output_get_result (output, &error)) {
+ g_printerr ("error: couldn't get preferred networks: %s\n", error->message);
+ g_error_free (error);
+ qmi_message_nas_get_preferred_networks_output_unref (output);
+ operation_shutdown (FALSE);
+ return;
+ }
+
+ g_print ("[%s] Successfully got preferred networks:\n",
+ qmi_device_get_path_display (ctx->device));
+
+ if (qmi_message_nas_get_preferred_networks_output_get_preferred_networks (output, &preferred_networks_array, NULL)) {
+ guint i;
+ gchar *access_tech_string;
+
+ g_print ("Preferred PLMN list:\n");
+ if (preferred_networks_array->len == 0)
+ g_print ("\t<empty>\n");
+ for (i = 0; i < preferred_networks_array->len; i++) {
+ QmiMessageNasGetPreferredNetworksOutputPreferredNetworksElement *element;
+
+ element = &g_array_index (preferred_networks_array, QmiMessageNasGetPreferredNetworksOutputPreferredNetworksElement, i);
+ access_tech_string = qmi_nas_plmn_access_technology_identifier_build_string_from_mask (element->radio_access_technology);
+ g_print ("[%u]:\n"
+ "\tMCC: '%" G_GUINT16_FORMAT "'\n"
+ "\tMNC: '%" G_GUINT16_FORMAT "'\n"
+ "\tAccess Technology: '%s'\n",
+ i,
+ element->mcc,
+ element->mnc,
+ access_tech_string);
+ g_free (access_tech_string);
+ }
+ }
+
+ if (qmi_message_nas_get_preferred_networks_output_get_mnc_pcs_digit_include_status (output, &pcs_digit_array, NULL)) {
+ guint i;
+
+ g_print ("PCS digit status:\n");
+ if (pcs_digit_array->len == 0)
+ g_print ("\t<empty>\n");
+ for (i = 0; i < pcs_digit_array->len; i++) {
+ QmiMessageNasGetPreferredNetworksOutputMncPcsDigitIncludeStatusElement *element;
+
+ element = &g_array_index (pcs_digit_array, QmiMessageNasGetPreferredNetworksOutputMncPcsDigitIncludeStatusElement, i);
+ g_print ("[%u]:\n"
+ "\tMCC: '%" G_GUINT16_FORMAT "'\n"
+ "\tMNC: '%" G_GUINT16_FORMAT "'\n"
+ "\tMCC with PCS digit: '%s'\n",
+ i,
+ element->mcc,
+ element->mnc,
+ element->includes_pcs_digit ? "yes" : "no");
+ }
+ }
+
+ qmi_message_nas_get_preferred_networks_output_unref (output);
+ operation_shutdown (TRUE);
+}
+
+#endif /* HAVE_QMI_MESSAGE_NAS_GET_PREFERRED_NETWORKS */
+
+#if defined HAVE_QMI_MESSAGE_NAS_SET_PREFERRED_NETWORKS
+
+static QmiMessageNasSetPreferredNetworksInput *
+set_preferred_networks_input_create (const gchar *str)
+{
+ QmiMessageNasSetPreferredNetworksInput *input = NULL;
+ GError *error = NULL;
+ gchar **parts = NULL;
+ gint i;
+ gint num_parts;
+ const gchar *part;
+ guint16 mcc = 0;
+ guint16 mnc = 0;
+ gboolean pcs_digit = FALSE;
+ QmiNasPlmnAccessTechnologyIdentifier access_tech = QMI_NAS_PLMN_ACCESS_TECHNOLOGY_IDENTIFIER_UNSPECIFIED;
+ GArray *preferred_nets_array;
+ GArray *pcs_digit_array;
+ QmiMessageNasSetPreferredNetworksInputPreferredNetworksElement preferred_nets_element;
+ QmiMessageNasSetPreferredNetworksInputMncPcsDigitIncludeStatusElement pcs_digit_element;
+
+ preferred_nets_array = g_array_new (FALSE, FALSE, sizeof (QmiMessageNasSetPreferredNetworksInputPreferredNetworksElement));
+ pcs_digit_array = g_array_new (FALSE, FALSE, sizeof (QmiMessageNasSetPreferredNetworksInputMncPcsDigitIncludeStatusElement));
+
+ parts = g_strsplit (str, ",", -1);
+ num_parts = g_strv_length (parts);
+ for (i = 0; i < num_parts; i += 2) {
+ part = parts[i];
+ /* Parse MCCMNC, if it's found, also read the access technology in numeric format */
+ if (qmicli_read_parse_3gpp_mcc_mnc (part, &mcc, &mnc, &pcs_digit)) {
+ access_tech = QMI_NAS_PLMN_ACCESS_TECHNOLOGY_IDENTIFIER_UNSPECIFIED;
+ if (i + 1 < num_parts) {
+ const gchar *access_tech_str = parts[i + 1];
+
+ if (!qmicli_read_nas_plmn_access_technology_identifier_from_string (access_tech_str, &access_tech))
+ goto out;
+
+ memset (&preferred_nets_element, 0, sizeof (preferred_nets_element));
+ preferred_nets_element.mcc = mcc;
+ preferred_nets_element.mnc = mnc;
+ preferred_nets_element.radio_access_technology = access_tech;
+ g_array_append_val (preferred_nets_array, preferred_nets_element);
+ memset (&pcs_digit_element, 0, sizeof (pcs_digit_element));
+ pcs_digit_element.mcc = mcc;
+ pcs_digit_element.mnc = mnc;
+ pcs_digit_element.includes_pcs_digit = pcs_digit;
+ g_array_append_val (pcs_digit_array, pcs_digit_element);
+ } else {
+ g_printerr ("error: access technology missing for MCCMNC: '%s'\n", part);
+ goto out;
+ }
+ } else
+ goto out;
+ }
+
+ input = qmi_message_nas_set_preferred_networks_input_new ();
+
+ if (!qmi_message_nas_set_preferred_networks_input_set_preferred_networks (input, preferred_nets_array, &error))
+ goto out;
+
+ if (!qmi_message_nas_set_preferred_networks_input_set_mnc_pcs_digit_include_status (input, pcs_digit_array, &error))
+ goto out;
+
+ /* Always set the clear previous flag, leaving any previously configured networks is not desired */
+ if (!qmi_message_nas_set_preferred_networks_input_set_clear_previous_preferred_networks (input, TRUE, &error))
+ goto out;
+
+out:
+ g_strfreev (parts);
+
+ if (preferred_nets_array)
+ g_array_unref (preferred_nets_array);
+ if (pcs_digit_array)
+ g_array_unref (pcs_digit_array);
+
+ if (error) {
+ g_printerr ("error: couldn't create preferred networks input data bundle: '%s'\n", error->message);
+ g_error_free (error);
+ qmi_message_nas_set_preferred_networks_input_unref (input);
+ return NULL;
+ }
+
+ return input;
+}
+
+static void
+set_preferred_networks_ready (QmiClientNas *client,
+ GAsyncResult *res)
+{
+ QmiMessageNasSetPreferredNetworksOutput *output = NULL;
+ GError *error = NULL;
+
+ output = qmi_client_nas_set_preferred_networks_finish (client, res, &error);
+ if (!output) {
+ g_printerr ("error: operation failed: %s\n", error->message);
+ g_error_free (error);
+ operation_shutdown (FALSE);
+ return;
+ }
+
+ if (!qmi_message_nas_set_preferred_networks_output_get_result (output, &error)) {
+ g_printerr ("error: couldn't set preferred networks: %s\n", error->message);
+ g_error_free (error);
+ qmi_message_nas_set_preferred_networks_output_unref (output);
+ operation_shutdown (FALSE);
+ return;
+ }
+
+ g_print ("[%s] Preferred networks set successfully.\n",
+ qmi_device_get_path_display (ctx->device));
+
+ qmi_message_nas_set_preferred_networks_output_unref (output);
+ operation_shutdown (TRUE);
+}
+
+#endif /* HAVE_QMI_MESSAGE_NAS_SET_PREFERRED_NETWORKS */
+
#if defined HAVE_QMI_MESSAGE_NAS_GET_SERVING_SYSTEM
static void
@@ -4057,6 +4270,41 @@ qmicli_nas_run (QmiDevice *device,
}
#endif
+#if defined HAVE_QMI_MESSAGE_NAS_GET_PREFERRED_NETWORKS
+ if (get_preferred_networks_flag) {
+ g_debug ("Asynchronously getting preferred networks...");
+ qmi_client_nas_get_preferred_networks (ctx->client,
+ NULL,
+ 10,
+ ctx->cancellable,
+ (GAsyncReadyCallback)get_preferred_networks_ready,
+ NULL);
+ return;
+ }
+#endif
+
+#if defined HAVE_QMI_MESSAGE_NAS_SET_PREFERRED_NETWORKS
+ if (set_preferred_networks_str) {
+ QmiMessageNasSetPreferredNetworksInput *input;
+ g_debug ("Asynchronously setting preferred networks...");
+
+ input = set_preferred_networks_input_create (set_preferred_networks_str);
+ if (!input) {
+ operation_shutdown (FALSE);
+ return;
+ }
+
+ qmi_client_nas_set_preferred_networks (ctx->client,
+ input,
+ 10,
+ ctx->cancellable,
+ (GAsyncReadyCallback)set_preferred_networks_ready,
+ NULL);
+ qmi_message_nas_set_preferred_networks_input_ref (input);
+ return;
+ }
+#endif
+
#if defined HAVE_QMI_MESSAGE_NAS_GET_SERVING_SYSTEM
if (get_serving_system_flag) {
g_debug ("Asynchronously getting serving system...");