aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/reference/libmm-glib/libmm-glib-docs.xml1
-rw-r--r--docs/reference/libmm-glib/libmm-glib-sections.txt23
-rw-r--r--introspection/org.freedesktop.ModemManager1.Sim.xml14
-rw-r--r--libmm-glib/Makefile.am3
-rw-r--r--libmm-glib/libmm-glib.h1
-rw-r--r--libmm-glib/mm-sim-preferred-network.c167
-rw-r--r--libmm-glib/mm-sim-preferred-network.h68
-rw-r--r--libmm-glib/mm-sim.c42
-rw-r--r--libmm-glib/mm-sim.h2
-rw-r--r--src/mm-base-sim.c135
-rw-r--r--src/mm-base-sim.h8
-rw-r--r--src/mm-modem-helpers.c84
-rw-r--r--src/mm-modem-helpers.h14
13 files changed, 562 insertions, 0 deletions
diff --git a/docs/reference/libmm-glib/libmm-glib-docs.xml b/docs/reference/libmm-glib/libmm-glib-docs.xml
index 71e74405..81c3cca3 100644
--- a/docs/reference/libmm-glib/libmm-glib-docs.xml
+++ b/docs/reference/libmm-glib/libmm-glib-docs.xml
@@ -153,6 +153,7 @@
<chapter>
<title>The SIM object</title>
<xi:include href="xml/mm-sim.xml"/>
+ <xi:include href="xml/mm-sim-preferred-network.xml"/>
</chapter>
<chapter>
diff --git a/docs/reference/libmm-glib/libmm-glib-sections.txt b/docs/reference/libmm-glib/libmm-glib-sections.txt
index 0a72befa..c1daf23a 100644
--- a/docs/reference/libmm-glib/libmm-glib-sections.txt
+++ b/docs/reference/libmm-glib/libmm-glib-sections.txt
@@ -1215,6 +1215,25 @@ mm_bearer_properties_get_type
</SECTION>
<SECTION>
+<FILE>mm-sim-preferred-network</FILE>
+<TITLE>MMSimPreferredNetwork</TITLE>
+MMSimPreferredNetwork
+mm_sim_preferred_network_get_operator_code
+mm_sim_preferred_network_get_access_technology
+mm_sim_preferred_network_free
+<SUBSECTION Private>
+mm_sim_preferred_network_new
+mm_sim_preferred_network_new_from_variant
+mm_sim_preferred_network_set_access_technology
+mm_sim_preferred_network_set_operator_code
+mm_sim_preferred_network_get_tuple
+mm_sim_preferred_network_list_get_variant
+<SUBSECTION Standard>
+MM_TYPE_SIM_PREFERRED_NETWORK
+mm_sim_preferred_network_get_type
+</SECTION>
+
+<SECTION>
<FILE>mm-sim</FILE>
<TITLE>MMSim</TITLE>
MMSim
@@ -1234,6 +1253,7 @@ mm_sim_get_operator_name
mm_sim_dup_operator_name
mm_sim_get_emergency_numbers
mm_sim_dup_emergency_numbers
+mm_sim_get_preferred_networks
<SUBSECTION Methods>
mm_sim_send_pin
mm_sim_send_pin_finish
@@ -3125,6 +3145,8 @@ mm_gdbus_sim_get_operator_name
mm_gdbus_sim_dup_operator_name
mm_gdbus_sim_get_emergency_numbers
mm_gdbus_sim_dup_emergency_numbers
+mm_gdbus_sim_dup_preferred_networks
+mm_gdbus_sim_get_preferred_networks
<SUBSECTION Methods>
mm_gdbus_sim_call_send_pin
mm_gdbus_sim_call_send_pin_finish
@@ -3146,6 +3168,7 @@ mm_gdbus_sim_set_operator_identifier
mm_gdbus_sim_set_operator_name
mm_gdbus_sim_set_sim_identifier
mm_gdbus_sim_set_emergency_numbers
+mm_gdbus_sim_set_preferred_networks
mm_gdbus_sim_complete_change_pin
mm_gdbus_sim_complete_enable_pin
mm_gdbus_sim_complete_send_pin
diff --git a/introspection/org.freedesktop.ModemManager1.Sim.xml b/introspection/org.freedesktop.ModemManager1.Sim.xml
index 87891e31..63d0e9b7 100644
--- a/introspection/org.freedesktop.ModemManager1.Sim.xml
+++ b/introspection/org.freedesktop.ModemManager1.Sim.xml
@@ -127,5 +127,19 @@
-->
<property name="EmergencyNumbers" type="as" access="read" />
+ <!--
+ PreferredNetworks:
+
+ List of preferred networks with access technologies configured in the SIM card.
+
+ Each entry contains an operator id string (<literal>"MCCMNC"</literal>)
+ consisting of 5 or 6 digits, and an
+ <link linkend="MMModemAccessTechnology">MMModemAccessTechnology</link> mask.
+ If the SIM card does not support access technology storage, the mask will be
+ set to <link linkend="MM-MODEM-ACCESS-TECHNOLOGY-UNKNOWN:CAPS">
+ MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN</link>.
+ -->
+ <property name="PreferredNetworks" type="a(su)" access="read" />
+
</interface>
</node>
diff --git a/libmm-glib/Makefile.am b/libmm-glib/Makefile.am
index 49f1e832..f33836f2 100644
--- a/libmm-glib/Makefile.am
+++ b/libmm-glib/Makefile.am
@@ -89,6 +89,8 @@ libmm_glib_la_SOURCES = \
mm-pco.c \
mm-call-audio-format.h \
mm-call-audio-format.c \
+ mm-sim-preferred-network.h \
+ mm-sim-preferred-network.c \
$(NULL)
libmm_glib_la_CPPFLAGS = \
@@ -160,6 +162,7 @@ include_HEADERS = \
mm-kernel-event-properties.h \
mm-pco.h \
mm-call-audio-format.h \
+ mm-sim-preferred-network.h \
$(NULL)
CLEANFILES =
diff --git a/libmm-glib/libmm-glib.h b/libmm-glib/libmm-glib.h
index e4504894..6572b2d3 100644
--- a/libmm-glib/libmm-glib.h
+++ b/libmm-glib/libmm-glib.h
@@ -80,6 +80,7 @@
#include <mm-signal.h>
#include <mm-kernel-event-properties.h>
#include <mm-pco.h>
+#include <mm-sim-preferred-network.h>
/* generated */
#include <mm-errors-types.h>
diff --git a/libmm-glib/mm-sim-preferred-network.c b/libmm-glib/mm-sim-preferred-network.c
new file mode 100644
index 00000000..c53239dd
--- /dev/null
+++ b/libmm-glib/mm-sim-preferred-network.c
@@ -0,0 +1,167 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2021 UROS Ltd
+ */
+
+#include "mm-sim-preferred-network.h"
+
+struct _MMSimPreferredNetwork {
+ gchar *operator_code;
+ MMModemAccessTechnology access_technology;
+};
+
+static MMSimPreferredNetwork *
+mm_sim_preferred_network_copy (MMSimPreferredNetwork *preferred_network)
+{
+ MMSimPreferredNetwork *preferred_network_copy;
+
+ preferred_network_copy = g_slice_new0 (MMSimPreferredNetwork);
+ preferred_network_copy->operator_code = g_strdup (preferred_network->operator_code);
+ preferred_network_copy->access_technology = preferred_network->access_technology;
+
+ return preferred_network_copy;
+}
+
+G_DEFINE_BOXED_TYPE (MMSimPreferredNetwork, mm_sim_preferred_network, (GBoxedCopyFunc) mm_sim_preferred_network_copy, (GBoxedFreeFunc) mm_sim_preferred_network_free)
+
+/**
+ * mm_sim_preferred_network_free:
+ * @self: A #MMSimPreferredNetwork.
+ *
+ * Frees a #MMSimPreferredNetwork.
+ *
+ * Since: 1.18
+ */
+void
+mm_sim_preferred_network_free (MMSimPreferredNetwork *self)
+{
+ if (!self)
+ return;
+
+ g_free (self->operator_code);
+ g_slice_free (MMSimPreferredNetwork, self);
+}
+
+/**
+ * mm_sim_preferred_network_get_operator_code:
+ * @self: A #MMSimPreferredNetwork.
+ *
+ * Get the operator code (MCCMNC) of the preferred network.
+ *
+ * Returns: (transfer none): The operator code, or %NULL if none available.
+ *
+ * Since: 1.18
+ */
+const gchar *
+mm_sim_preferred_network_get_operator_code (const MMSimPreferredNetwork *self)
+{
+ g_return_val_if_fail (self != NULL, NULL);
+
+ return self->operator_code;
+}
+
+/**
+ * mm_sim_preferred_network_get_access_technology:
+ * @self: A #MMSimPreferredNetwork.
+ *
+ * Get the access technology mask of the preferred network.
+ *
+ * Returns: A #MMModemAccessTechnology.
+ *
+ * Since: 1.18
+ */
+MMModemAccessTechnology
+mm_sim_preferred_network_get_access_technology (const MMSimPreferredNetwork *self)
+{
+ g_return_val_if_fail (self != NULL, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN);
+
+ return self->access_technology;
+}
+
+/**
+ * mm_sim_preferred_network_set_operator_code: (skip)
+ */
+void
+mm_sim_preferred_network_set_operator_code (MMSimPreferredNetwork *self,
+ const gchar *operator_code)
+{
+ g_return_if_fail (self != NULL);
+
+ g_free (self->operator_code);
+ self->operator_code = g_strdup (operator_code);
+}
+
+/**
+ * mm_sim_preferred_network_set_access_technology: (skip)
+ */
+void
+mm_sim_preferred_network_set_access_technology (MMSimPreferredNetwork *self,
+ MMModemAccessTechnology access_technology)
+{
+ g_return_if_fail (self != NULL);
+
+ self->access_technology = access_technology;
+}
+
+/**
+ * mm_sim_preferred_network_new: (skip)
+ */
+MMSimPreferredNetwork *
+mm_sim_preferred_network_new (void)
+{
+ return g_slice_new0 (MMSimPreferredNetwork);
+}
+
+/**
+ * mm_sim_preferred_network_new_from_variant: (skip)
+ */
+MMSimPreferredNetwork *
+mm_sim_preferred_network_new_from_variant (GVariant *variant)
+{
+ MMSimPreferredNetwork *preferred_net;
+
+ g_return_val_if_fail (g_variant_is_of_type (variant, G_VARIANT_TYPE ("(su)")),
+ NULL);
+
+ preferred_net = mm_sim_preferred_network_new ();
+ g_variant_get (variant, "(su)", &preferred_net->operator_code, &preferred_net->access_technology);
+ return preferred_net;
+}
+
+/**
+ * mm_sim_preferred_network_get_tuple: (skip)
+ */
+GVariant *
+mm_sim_preferred_network_get_tuple (const MMSimPreferredNetwork *self)
+{
+ return g_variant_new ("(su)",
+ self->operator_code,
+ self->access_technology);
+}
+
+/**
+ * mm_sim_preferred_network_list_get_variant: (skip)
+ */
+GVariant *
+mm_sim_preferred_network_list_get_variant (const GList *preferred_network_list)
+{
+ GVariantBuilder builder;
+ const GList *iter;
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(su)"));
+ for (iter = preferred_network_list; iter; iter = g_list_next (iter)) {
+ g_variant_builder_add_value (&builder,
+ mm_sim_preferred_network_get_tuple ((const MMSimPreferredNetwork *) iter->data));
+ }
+ return g_variant_builder_end (&builder);
+}
diff --git a/libmm-glib/mm-sim-preferred-network.h b/libmm-glib/mm-sim-preferred-network.h
new file mode 100644
index 00000000..e6042587
--- /dev/null
+++ b/libmm-glib/mm-sim-preferred-network.h
@@ -0,0 +1,68 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2021 UROS Ltd
+ */
+
+#ifndef MM_SIM_PREFERRED_NETWORK_H
+#define MM_SIM_PREFERRED_NETWORK_H
+
+#if !defined (__LIBMM_GLIB_H_INSIDE__) && !defined (LIBMM_GLIB_COMPILATION)
+#error "Only <libmm-glib.h> can be included directly."
+#endif
+
+#include <ModemManager.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+/**
+ * MMSimPreferredNetwork:
+ *
+ * The #MMSimPreferredNetwork structure contains private data and should only be accessed
+ * using the provided API.
+ */
+typedef struct _MMSimPreferredNetwork MMSimPreferredNetwork;
+
+#define MM_TYPE_SIM_PREFERRED_NETWORK (mm_sim_preferred_network_get_type ())
+GType mm_sim_preferred_network_get_type (void);
+
+const gchar *mm_sim_preferred_network_get_operator_code (const MMSimPreferredNetwork *self);
+MMModemAccessTechnology mm_sim_preferred_network_get_access_technology (const MMSimPreferredNetwork *self);
+
+void mm_sim_preferred_network_free (MMSimPreferredNetwork *self);
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMSimPreferredNetwork, mm_sim_preferred_network_free)
+
+/*****************************************************************************/
+/* ModemManager/libmm-glib/mmcli specific methods */
+
+#if defined (_LIBMM_INSIDE_MM) || \
+ defined (_LIBMM_INSIDE_MMCLI) || \
+ defined (LIBMM_GLIB_COMPILATION)
+
+MMSimPreferredNetwork * mm_sim_preferred_network_new (void);
+MMSimPreferredNetwork * mm_sim_preferred_network_new_from_variant (GVariant *variant);
+
+void mm_sim_preferred_network_set_operator_code (MMSimPreferredNetwork *self,
+ const gchar *operator_code);
+void mm_sim_preferred_network_set_access_technology (MMSimPreferredNetwork *self,
+ MMModemAccessTechnology access_technology);
+
+GVariant *mm_sim_preferred_network_get_tuple (const MMSimPreferredNetwork *self);
+GVariant *mm_sim_preferred_network_list_get_variant (const GList *preferred_network_list);
+
+#endif
+
+G_END_DECLS
+
+#endif /* MM_SIM_PREFERRED_NETWORK_H */
diff --git a/libmm-glib/mm-sim.c b/libmm-glib/mm-sim.c
index 0a3b6071..ac509d3e 100644
--- a/libmm-glib/mm-sim.c
+++ b/libmm-glib/mm-sim.c
@@ -23,6 +23,7 @@
#include "mm-helpers.h"
#include "mm-sim.h"
+#include "mm-sim-preferred-network.h"
/**
* SECTION: mm-sim
@@ -860,6 +861,47 @@ mm_sim_change_pin_sync (MMSim *self,
/*****************************************************************************/
+/**
+ * mm_sim_get_preferred_networks:
+ * @self: A #MMSim.
+ *
+ * Gets the list of #MMSimPreferredNetwork objects exposed by this
+ * #MMSim.
+ *
+ * Returns: (transfer full) (element-type ModemManager.SimPreferredNetwork): a list of
+ * #MMSimPreferredNetwork objects, or #NULL. The returned value should
+ * be freed with g_list_free_full() using mm_sim_preferred_network_free() as #GDestroyNotify
+ * function.
+ *
+ * Since: 1.18
+ */
+GList *
+mm_sim_get_preferred_networks (MMSim *self)
+{
+ GList *network_list = NULL;
+ GVariant *container, *child;
+ GVariantIter iter;
+
+ g_return_val_if_fail (MM_IS_SIM (self), NULL);
+
+ container = mm_gdbus_sim_get_preferred_networks (MM_GDBUS_SIM (self));
+ g_return_val_if_fail (g_variant_is_of_type (container, G_VARIANT_TYPE ("a(su)")), NULL);
+
+ g_variant_iter_init (&iter, container);
+ while ((child = g_variant_iter_next_value (&iter))) {
+ MMSimPreferredNetwork *preferred_net;
+
+ preferred_net = mm_sim_preferred_network_new_from_variant (child);
+ if (preferred_net)
+ network_list = g_list_append (network_list, preferred_net);
+ g_variant_unref (child);
+ }
+
+ return network_list;
+}
+
+/*****************************************************************************/
+
static void
mm_sim_init (MMSim *self)
{
diff --git a/libmm-glib/mm-sim.h b/libmm-glib/mm-sim.h
index 3449e289..8ebf069f 100644
--- a/libmm-glib/mm-sim.h
+++ b/libmm-glib/mm-sim.h
@@ -87,6 +87,8 @@ gchar *mm_sim_dup_operator_name (MMSim *self);
const gchar * const *mm_sim_get_emergency_numbers (MMSim *self);
gchar **mm_sim_dup_emergency_numbers (MMSim *self);
+GList* mm_sim_get_preferred_networks (MMSim *self);
+
void mm_sim_send_pin (MMSim *self,
const gchar *pin,
GCancellable *cancellable,
diff --git a/src/mm-base-sim.c b/src/mm-base-sim.c
index c8bd32d4..a3275fc1 100644
--- a/src/mm-base-sim.c
+++ b/src/mm-base-sim.c
@@ -1141,6 +1141,101 @@ load_emergency_numbers (MMBaseSim *self,
}
/*****************************************************************************/
+/* Preferred networks */
+
+static GList *
+parse_preferred_networks (const gchar *response,
+ GError **error)
+{
+ gchar **entries;
+ gchar **iter;
+ GList *result = NULL;
+
+ entries = g_strsplit_set (response, "\r\n", -1);
+ for (iter = entries; iter && *iter; iter++) {
+ gchar *operator_code = NULL;
+ gboolean gsm_act;
+ gboolean gsm_compact_act;
+ gboolean utran_act;
+ gboolean eutran_act;
+ gboolean ngran_act;
+ MMSimPreferredNetwork *preferred_network = NULL;
+ MMModemAccessTechnology act = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN;
+
+ g_strstrip (*iter);
+ if (strlen (*iter) == 0)
+ continue;
+
+ if (mm_sim_parse_cpol_query_response (*iter,
+ &operator_code,
+ &gsm_act,
+ &gsm_compact_act,
+ &utran_act,
+ &eutran_act,
+ &ngran_act,
+ error)) {
+ preferred_network = mm_sim_preferred_network_new ();
+ mm_sim_preferred_network_set_operator_code (preferred_network, operator_code);
+ if (gsm_act)
+ act |= MM_MODEM_ACCESS_TECHNOLOGY_GSM;
+ if (gsm_compact_act)
+ act |= MM_MODEM_ACCESS_TECHNOLOGY_GSM_COMPACT;
+ if (utran_act)
+ act |= MM_MODEM_ACCESS_TECHNOLOGY_UMTS;
+ if (eutran_act)
+ act |= MM_MODEM_ACCESS_TECHNOLOGY_LTE;
+ if (ngran_act)
+ act |= MM_MODEM_ACCESS_TECHNOLOGY_5GNR;
+ mm_sim_preferred_network_set_access_technology (preferred_network, act);
+ result = g_list_append (result, preferred_network);
+ } else
+ break;
+ g_free (operator_code);
+ }
+ g_strfreev (entries);
+
+ return result;
+}
+
+static GList *
+load_preferred_networks_finish (MMBaseSim *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ gchar *result;
+ GList *preferred_network_list;
+
+ result = g_task_propagate_pointer (G_TASK (res), error);
+ if (!result)
+ return NULL;
+
+ preferred_network_list = parse_preferred_networks (result, error);
+ mm_obj_dbg (self, "loaded %u preferred networks", g_list_length (preferred_network_list));
+
+ g_free (result);
+
+ return preferred_network_list;
+}
+
+STR_REPLY_READY_FN (load_preferred_networks)
+
+static void
+load_preferred_networks (MMBaseSim *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ mm_obj_dbg (self, "loading preferred networks...");
+
+ mm_base_modem_at_command (
+ self->priv->modem,
+ "+CPOL?",
+ 20,
+ FALSE,
+ (GAsyncReadyCallback)load_preferred_networks_command_ready,
+ g_task_new (self, NULL, callback, user_data));
+}
+
+/*****************************************************************************/
/* ICCID */
static gchar *
@@ -1525,6 +1620,7 @@ typedef enum {
INITIALIZATION_STEP_OPERATOR_ID,
INITIALIZATION_STEP_OPERATOR_NAME,
INITIALIZATION_STEP_EMERGENCY_NUMBERS,
+ INITIALIZATION_STEP_PREFERRED_NETWORKS,
INITIALIZATION_STEP_LAST
} InitializationStep;
@@ -1623,6 +1719,31 @@ init_load_emergency_numbers_ready (MMBaseSim *self,
interface_initialization_step (task);
}
+static void
+init_load_preferred_networks_ready (MMBaseSim *self,
+ GAsyncResult *res,
+ GTask *task)
+{
+ InitAsyncContext *ctx;
+ GError *error = NULL;
+ GList *preferred_nets_list;
+
+ preferred_nets_list = MM_BASE_SIM_GET_CLASS (self)->load_preferred_networks_finish (self, res, &error);
+ if (error) {
+ mm_obj_warn (self, "couldn't load list of preferred networks: %s", error->message);
+ g_error_free (error);
+ }
+
+ mm_gdbus_sim_set_preferred_networks (MM_GDBUS_SIM (self),
+ mm_sim_preferred_network_list_get_variant (preferred_nets_list));
+ g_list_free_full (preferred_nets_list, (GDestroyNotify) mm_sim_preferred_network_free);
+
+ /* Go on to next step */
+ ctx = g_task_get_task_data (task);
+ ctx->step++;
+ interface_initialization_step (task);
+}
+
#undef STR_REPLY_READY_FN
#define STR_REPLY_READY_FN(NAME,DISPLAY) \
static void \
@@ -1798,6 +1919,18 @@ interface_initialization_step (GTask *task)
ctx->step++;
/* Fall through */
+ case INITIALIZATION_STEP_PREFERRED_NETWORKS:
+ if (MM_BASE_SIM_GET_CLASS (self)->load_preferred_networks &&
+ MM_BASE_SIM_GET_CLASS (self)->load_preferred_networks_finish) {
+ MM_BASE_SIM_GET_CLASS (self)->load_preferred_networks (
+ self,
+ (GAsyncReadyCallback)init_load_preferred_networks_ready,
+ task);
+ return;
+ }
+ ctx->step++;
+ /* Fall through */
+
case INITIALIZATION_STEP_LAST:
/* We are done without errors! */
g_task_return_boolean (task, TRUE);
@@ -2051,6 +2184,8 @@ mm_base_sim_class_init (MMBaseSimClass *klass)
klass->load_operator_name_finish = load_operator_name_finish;
klass->load_emergency_numbers = load_emergency_numbers;
klass->load_emergency_numbers_finish = load_emergency_numbers_finish;
+ klass->load_preferred_networks = load_preferred_networks;
+ klass->load_preferred_networks_finish = load_preferred_networks_finish;
klass->send_pin = send_pin;
klass->send_pin_finish = common_send_pin_puk_finish;
klass->send_puk = send_puk;
diff --git a/src/mm-base-sim.h b/src/mm-base-sim.h
index ed582528..67f2690d 100644
--- a/src/mm-base-sim.h
+++ b/src/mm-base-sim.h
@@ -150,6 +150,14 @@ struct _MMBaseSimClass {
/* Signals */
void (* pin_lock_enabled) (MMBaseSim *self,
gboolean enabled);
+
+ /* Load preferred networks (async) */
+ void (* load_preferred_networks) (MMBaseSim *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+ GList * (* load_preferred_networks_finish) (MMBaseSim *self,
+ GAsyncResult *res,
+ GError **error);
};
GType mm_base_sim_get_type (void);
diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c
index 26b55f71..b6b7f113 100644
--- a/src/mm-modem-helpers.c
+++ b/src/mm-modem-helpers.c
@@ -5126,3 +5126,87 @@ out:
g_strfreev (split);
return valid;
}
+
+/*****************************************************************************/
+
+gboolean
+mm_sim_parse_cpol_query_response (const gchar *response,
+ gchar **out_operator_code,
+ gboolean *out_gsm_act,
+ gboolean *out_gsm_compact_act,
+ gboolean *out_utran_act,
+ gboolean *out_eutran_act,
+ gboolean *out_ngran_act,
+ GError **error)
+{
+ g_autoptr(GMatchInfo) match_info = NULL;
+ g_autoptr(GRegex) r = NULL;
+ g_autofree gchar *operator_code = NULL;
+ guint format = 0;
+ guint act = 0;
+ guint match_count;
+
+ r = g_regex_new ("\\+CPOL:\\s*\\d+,\\s*(\\d+),\\s*\"(\\d+)\""
+ "(?:,\\s*(\\d+))?" /* GSM_AcTn */
+ "(?:,\\s*(\\d+))?" /* GSM_Compact_AcTn */
+ "(?:,\\s*(\\d+))?" /* UTRAN_AcTn */
+ "(?:,\\s*(\\d+))?" /* E-UTRAN_AcTn */
+ "(?:,\\s*(\\d+))?", /* NG-RAN_AcTn */
+ G_REGEX_RAW, 0, NULL);
+ g_regex_match (r, response, 0, &match_info);
+
+ if (!g_match_info_matches (match_info)) {
+ g_set_error (error,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_FAILED,
+ "Couldn't parse +CPOL reply: %s", response);
+ return FALSE;
+ }
+
+ match_count = g_match_info_get_match_count (match_info);
+ /* Remember that g_match_info_get_match_count() includes match #0 */
+ g_assert (match_count >= 3);
+
+ if (!mm_get_uint_from_match_info (match_info, 1, &format) ||
+ !(operator_code = mm_get_string_unquoted_from_match_info (match_info, 2))) {
+ g_set_error (error,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_FAILED,
+ "Couldn't parse +CPOL reply parameters: %s", response);
+ return FALSE;
+ }
+
+ if (format != 2) {
+ g_set_error (error,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_FAILED,
+ "+CPOL reply not using numeric operator code: %s", response);
+ return FALSE;
+ }
+
+ if (out_operator_code) {
+ *out_operator_code = g_steal_pointer (&operator_code);
+ }
+ if (out_gsm_act)
+ *out_gsm_act = match_count >= 4 &&
+ mm_get_uint_from_match_info (match_info, 3, &act) &&
+ act != 0;
+ if (out_gsm_compact_act)
+ *out_gsm_compact_act = match_count >= 5 &&
+ mm_get_uint_from_match_info (match_info, 4, &act) &&
+ act != 0;
+ if (out_utran_act)
+ *out_utran_act = match_count >= 6 &&
+ mm_get_uint_from_match_info (match_info, 5, &act) &&
+ act != 0;
+ if (out_eutran_act)
+ *out_eutran_act = match_count >= 7 &&
+ mm_get_uint_from_match_info (match_info, 6, &act) &&
+ act != 0;
+ if (out_ngran_act)
+ *out_ngran_act = match_count >= 8 &&
+ mm_get_uint_from_match_info (match_info, 7, &act) &&
+ act != 0;
+
+ return TRUE;
+}
diff --git a/src/mm-modem-helpers.h b/src/mm-modem-helpers.h
index 0f314959..806a8e79 100644
--- a/src/mm-modem-helpers.h
+++ b/src/mm-modem-helpers.h
@@ -521,6 +521,20 @@ gboolean mm_parse_supl_address (const gchar *supl,
GError **error);
/*****************************************************************************/
+/* SIM specific helpers and utilities */
+/*****************************************************************************/
+
+/* +CPOL? response parser (for a single entry) - accepts only numeric operator format*/
+gboolean mm_sim_parse_cpol_query_response (const gchar *response,
+ gchar **out_operator_code,
+ gboolean *out_gsm_act,
+ gboolean *out_gsm_compact_act,
+ gboolean *out_utran_act,
+ gboolean *out_eutran_act,
+ gboolean *out_ngran_act,
+ GError **error);
+
+/*****************************************************************************/
/* Useful when clamp-ing an unsigned integer with implicit low limit set to 0,
* and in order to avoid -Wtype-limits warnings. */