aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/mmcli-sim.c110
-rw-r--r--libmm-glib/mm-common-helpers.c70
-rw-r--r--libmm-glib/mm-common-helpers.h5
3 files changed, 183 insertions, 2 deletions
diff --git a/cli/mmcli-sim.c b/cli/mmcli-sim.c
index 68ae7f5d..3056783b 100644
--- a/cli/mmcli-sim.c
+++ b/cli/mmcli-sim.c
@@ -51,6 +51,7 @@ static gchar *puk_str;
static gboolean enable_pin_flag;
static gboolean disable_pin_flag;
static gchar *change_pin_str;
+static gchar *set_preferred_networks_str;
static GOptionEntry entries[] = {
{ "pin", 0, 0, G_OPTION_ARG_STRING, &pin_str,
@@ -73,6 +74,10 @@ static GOptionEntry entries[] = {
"Change the PIN in a given SIM (must send the current PIN with --pin).",
"[New PIN]"
},
+ { "sim-set-preferred-networks", 0, 0, G_OPTION_ARG_STRING, &set_preferred_networks_str,
+ "Set preferred network list stored in a given SIM.",
+ "[[MCCMNC[,access_tech]],...]"
+ },
{ NULL }
};
@@ -104,10 +109,11 @@ mmcli_sim_options_enabled (void)
n_actions = (!!puk_str +
enable_pin_flag +
disable_pin_flag +
- !!change_pin_str);
+ !!change_pin_str +
+ !!set_preferred_networks_str);
if (n_actions == 1) {
- if (!pin_str) {
+ if (!pin_str && !set_preferred_networks_str) {
g_printerr ("error: action requires also the PIN code\n");
exit (EXIT_FAILURE);
}
@@ -310,6 +316,77 @@ change_pin_ready (MMSim *sim,
}
static void
+parse_preferred_networks (GList **preferred_networks)
+{
+ gchar **parts;
+ GList *preferred_nets_list = NULL;
+ GError *error = NULL;
+
+ parts = g_strsplit (set_preferred_networks_str, ",", -1);
+ if (parts) {
+ guint i;
+
+ for (i = 0; parts[i]; i++) {
+ MMModemAccessTechnology access_tech = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN;
+ MMSimPreferredNetwork *preferred_net;
+ const gchar *mccmnc;
+
+ mccmnc = parts[i];
+ if (!mm_is_string_mccmnc (mccmnc)) {
+ g_printerr ("error: couldn't parse MCCMNC for preferred network: '%s'\n",
+ mccmnc);
+ exit (EXIT_FAILURE);
+ }
+ /* if the next item is MCCMNC or is missing, omit the access technology */
+ if (parts[i + 1] && !mm_is_string_mccmnc (parts[i + 1])) {
+ i++;
+ access_tech = mm_common_get_access_technology_from_string (parts[i], &error);
+ if (error) {
+ g_printerr ("error: %s\n", error->message);
+ g_error_free (error);
+ exit (EXIT_FAILURE);
+ }
+ }
+
+ preferred_net = mm_sim_preferred_network_new ();
+ mm_sim_preferred_network_set_operator_code (preferred_net, mccmnc);
+ mm_sim_preferred_network_set_access_technology (preferred_net, access_tech);
+ preferred_nets_list = g_list_append (preferred_nets_list, preferred_net);
+ }
+ }
+ g_strfreev (parts);
+
+ *preferred_networks = preferred_nets_list;
+}
+
+static void
+set_preferred_networks_process_reply (gboolean result,
+ const GError *error)
+{
+ if (!result) {
+ g_printerr ("error: couldn't set preferred networks: '%s'\n",
+ error ? error->message : "unknown error");
+ exit (EXIT_FAILURE);
+ }
+
+ g_print ("successfully set preferred networks\n");
+}
+
+static void
+set_preferred_networks_ready (MMSim *sim,
+ GAsyncResult *result,
+ gpointer nothing)
+{
+ gboolean operation_result;
+ GError *error = NULL;
+
+ operation_result = mm_sim_set_preferred_networks_finish (sim, result, &error);
+ set_preferred_networks_process_reply (operation_result, error);
+
+ mmcli_async_operation_done ();
+}
+
+static void
get_sim_ready (GObject *source,
GAsyncResult *result,
gpointer none)
@@ -366,6 +443,20 @@ get_sim_ready (GObject *source,
return;
}
+ /* Requesting to set preferred networks? */
+ if (set_preferred_networks_str) {
+ GList *preferred_networks = NULL;
+
+ parse_preferred_networks (&preferred_networks);
+ mm_sim_set_preferred_networks (ctx->sim,
+ preferred_networks,
+ ctx->cancellable,
+ (GAsyncReadyCallback)set_preferred_networks_ready,
+ NULL);
+ g_list_free_full (preferred_networks, (GDestroyNotify) mm_sim_preferred_network_free);
+ return;
+ }
+
/* Requesting to send PIN? (always LAST check!) */
if (pin_str) {
mm_sim_send_pin (ctx->sim,
@@ -468,6 +559,21 @@ mmcli_sim_run_synchronous (GDBusConnection *connection)
return;
}
+ /* Requesting to set preferred networks? */
+ if (set_preferred_networks_str) {
+ gboolean operation_result;
+ GList *preferred_networks = NULL;
+
+ parse_preferred_networks (&preferred_networks);
+ operation_result = mm_sim_set_preferred_networks_sync (ctx->sim,
+ preferred_networks,
+ NULL,
+ &error);
+ g_list_free_full (preferred_networks, (GDestroyNotify) mm_sim_preferred_network_free);
+ set_preferred_networks_process_reply (operation_result, error);
+ return;
+ }
+
/* Requesting to send PIN? (always LAST check!) */
if (pin_str) {
gboolean operation_result;
diff --git a/libmm-glib/mm-common-helpers.c b/libmm-glib/mm-common-helpers.c
index 43fff922..f2faf71c 100644
--- a/libmm-glib/mm-common-helpers.c
+++ b/libmm-glib/mm-common-helpers.c
@@ -1313,6 +1313,56 @@ mm_common_parse_key_value_string (const gchar *str,
return TRUE;
}
+MMModemAccessTechnology
+mm_common_get_access_technology_from_string (const gchar *str,
+ GError **error)
+{
+ GError *inner_error = NULL;
+ MMModemAccessTechnology technologies;
+ gchar **technology_strings;
+ GFlagsClass *flags_class;
+
+ technologies = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN;
+
+ flags_class = G_FLAGS_CLASS (g_type_class_ref (MM_TYPE_MODEM_ACCESS_TECHNOLOGY));
+ technology_strings = g_strsplit (str, "|", -1);
+
+ if (technology_strings) {
+ guint i;
+
+ for (i = 0; technology_strings[i]; i++) {
+ guint j;
+ gboolean found = FALSE;
+
+ for (j = 0; flags_class->values[j].value_nick; j++) {
+ if (!g_ascii_strcasecmp (technology_strings[i], flags_class->values[j].value_nick)) {
+ technologies |= flags_class->values[j].value;
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (!found) {
+ inner_error = g_error_new (
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_INVALID_ARGS,
+ "Couldn't match '%s' with a valid MMModemAccessTechnology value",
+ technology_strings[i]);
+ break;
+ }
+ }
+ }
+
+ if (inner_error) {
+ g_propagate_error (error, inner_error);
+ technologies = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN;
+ }
+
+ g_type_class_unref (flags_class);
+ g_strfreev (technology_strings);
+ return technologies;
+}
+
/*****************************************************************************/
gboolean
@@ -1612,6 +1662,26 @@ mm_get_string_unquoted_from_match_info (GMatchInfo *match_info,
return str;
}
+gboolean
+mm_is_string_mccmnc (const gchar *str)
+{
+ gsize len;
+ guint i;
+
+ if (!str)
+ return FALSE;
+
+ len = strlen (str);
+ if (len < 5 || len > 6)
+ return FALSE;
+
+ for (i = 0; i < len; i++)
+ if (str[i] < '0' || str[i] > '9')
+ return FALSE;
+
+ return TRUE;
+}
+
/*****************************************************************************/
const gchar *
diff --git a/libmm-glib/mm-common-helpers.h b/libmm-glib/mm-common-helpers.h
index 4e6d9784..960a1f52 100644
--- a/libmm-glib/mm-common-helpers.h
+++ b/libmm-glib/mm-common-helpers.h
@@ -79,6 +79,9 @@ MMOmaSessionType mm_common_get_oma_session_type_from_string (const gchar *s
MMModem3gppEpsUeModeOperation mm_common_get_eps_ue_mode_operation_from_string (const gchar *str,
GError **error);
+MMModemAccessTechnology mm_common_get_access_technology_from_string (const gchar *str,
+ GError **error);
+
GArray *mm_common_ports_variant_to_garray (GVariant *variant);
MMModemPortInfo *mm_common_ports_variant_to_array (GVariant *variant,
guint *n_ports);
@@ -178,6 +181,8 @@ gboolean mm_get_double_from_match_info (GMatchInfo *match_info,
gchar *mm_get_string_unquoted_from_match_info (GMatchInfo *match_info,
guint32 match_index);
+gboolean mm_is_string_mccmnc (const gchar *str);
+
const gchar *mm_sms_delivery_state_get_string_extended (guint delivery_state);
gint mm_utils_hex2byte (const gchar *hex);