aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2020-08-01 09:59:27 +0200
committerAleksander Morgado <aleksander@aleksander.es>2020-08-28 14:59:06 +0000
commite7409b689876488594409e945687486adb1d9514 (patch)
tree0b10be5c3d08fa5e21b22565e51b4fdfc071dcc2 /src
parentb2979c63eb2d724512c7a96c071f3d4b422e79cb (diff)
api,modem: new 'SimSlots' and 'PrimarySimSlot' properties
The 'SimSlots' property exposes an array of SIM object paths, with one array item for each available SIM slot in the system. If a valid SIM card is found in a given slot, the path of the SIM object will be exposed in the array item; if no valid SIM card is found, the empty object path ("/") will be exposed instead. The 'PrimarySimSlot' property exposes which of the SIM slots available in the system is the one configured as being primary. In a Multi-SIM Single-Standby setup, the primary slot will be the one corresponding to the single active SIM in the system. In a Multi-SIM Multi-Standby setup, the primary slot will be the one configured to act as primary (e.g. the one that will be used for the data connection) among all the active SIM cards found.
Diffstat (limited to 'src')
-rw-r--r--src/mm-broadband-modem.c14
-rw-r--r--src/mm-iface-modem.c94
-rw-r--r--src/mm-iface-modem.h11
-rw-r--r--src/mm-private-boxed-types.c29
-rw-r--r--src/mm-private-boxed-types.h3
5 files changed, 150 insertions, 1 deletions
diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c
index aeb660c6..9b10f83e 100644
--- a/src/mm-broadband-modem.c
+++ b/src/mm-broadband-modem.c
@@ -100,6 +100,7 @@ enum {
PROP_MODEM_OMA_DBUS_SKELETON,
PROP_MODEM_FIRMWARE_DBUS_SKELETON,
PROP_MODEM_SIM,
+ PROP_MODEM_SIM_SLOTS,
PROP_MODEM_BEARER_LIST,
PROP_MODEM_STATE,
PROP_MODEM_3GPP_REGISTRATION_STATE,
@@ -153,6 +154,7 @@ struct _MMBroadbandModemPrivate {
/* Properties */
GObject *modem_dbus_skeleton;
MMBaseSim *modem_sim;
+ GPtrArray *modem_sim_slots;
MMBearerList *modem_bearer_list;
MMModemState modem_state;
gchar *carrier_config_mapping;
@@ -12007,6 +12009,10 @@ set_property (GObject *object,
g_clear_object (&self->priv->modem_sim);
self->priv->modem_sim = g_value_dup_object (value);
break;
+ case PROP_MODEM_SIM_SLOTS:
+ g_clear_pointer (&self->priv->modem_sim_slots, g_ptr_array_unref);
+ self->priv->modem_sim_slots = g_value_dup_boxed (value);
+ break;
case PROP_MODEM_BEARER_LIST:
g_clear_object (&self->priv->modem_bearer_list);
self->priv->modem_bearer_list = g_value_dup_object (value);
@@ -12147,6 +12153,9 @@ get_property (GObject *object,
case PROP_MODEM_SIM:
g_value_set_object (value, self->priv->modem_sim);
break;
+ case PROP_MODEM_SIM_SLOTS:
+ g_value_set_boxed (value, self->priv->modem_sim_slots);
+ break;
case PROP_MODEM_BEARER_LIST:
g_value_set_object (value, self->priv->modem_bearer_list);
break;
@@ -12351,6 +12360,7 @@ dispose (GObject *object)
g_clear_object (&self->priv->modem_3gpp_initial_eps_bearer);
g_clear_object (&self->priv->modem_sim);
+ g_clear_pointer (&self->priv->modem_sim_slots, g_ptr_array_unref);
g_clear_object (&self->priv->modem_bearer_list);
g_clear_object (&self->priv->modem_messaging_sms_list);
g_clear_object (&self->priv->modem_voice_call_list);
@@ -12713,6 +12723,10 @@ mm_broadband_modem_class_init (MMBroadbandModemClass *klass)
MM_IFACE_MODEM_SIM);
g_object_class_override_property (object_class,
+ PROP_MODEM_SIM_SLOTS,
+ MM_IFACE_MODEM_SIM_SLOTS);
+
+ g_object_class_override_property (object_class,
PROP_MODEM_BEARER_LIST,
MM_IFACE_MODEM_BEARER_LIST);
diff --git a/src/mm-iface-modem.c b/src/mm-iface-modem.c
index 8a4a00af..9045d290 100644
--- a/src/mm-iface-modem.c
+++ b/src/mm-iface-modem.c
@@ -13,7 +13,6 @@
* Copyright (C) 2011 Google, Inc.
*/
-
#include <ModemManager.h>
#define _LIBMM_INSIDE_MM
#include <libmm-glib.h>
@@ -26,6 +25,7 @@
#include "mm-base-modem-at.h"
#include "mm-base-sim.h"
#include "mm-bearer-list.h"
+#include "mm-private-boxed-types.h"
#include "mm-log-object.h"
#include "mm-context.h"
@@ -4016,6 +4016,7 @@ typedef enum {
INITIALIZATION_STEP_SUPPORTED_IP_FAMILIES,
INITIALIZATION_STEP_POWER_STATE,
INITIALIZATION_STEP_SIM_HOT_SWAP,
+ INITIALIZATION_STEP_SIM_SLOTS,
INITIALIZATION_STEP_UNLOCK_REQUIRED,
INITIALIZATION_STEP_SIM,
INITIALIZATION_STEP_SETUP_CARRIER_CONFIG,
@@ -4401,6 +4402,73 @@ setup_sim_hot_swap_ready (MMIfaceModem *self,
}
static void
+load_sim_slots_ready (MMIfaceModem *self,
+ GAsyncResult *res,
+ GTask *task)
+{
+ InitializationContext *ctx;
+ g_autoptr(GPtrArray) sim_slots = NULL;
+ g_autoptr(GError) error = NULL;
+ guint primary_sim_slot = 0;
+
+ ctx = g_task_get_task_data (task);
+
+ if (!MM_IFACE_MODEM_GET_INTERFACE (self)->load_sim_slots_finish (self,
+ res,
+ &sim_slots,
+ &primary_sim_slot,
+ &error))
+ mm_obj_warn (self, "couldn't query SIM slots: %s", error->message);
+
+ if (sim_slots) {
+ MMBaseSim *primary_sim = NULL;
+ GPtrArray *sim_slot_paths_array;
+ g_auto(GStrv) sim_slot_paths = NULL;
+ guint i;
+
+ g_assert (primary_sim_slot);
+ g_assert_cmpuint (primary_sim_slot, <=, sim_slots->len);
+
+ sim_slot_paths_array = g_ptr_array_new ();
+ for (i = 0; i < sim_slots->len; i++) {
+ MMBaseSim *sim;
+ const gchar *sim_path;
+
+ sim = MM_BASE_SIM (g_ptr_array_index (sim_slots, i));
+ if (!sim) {
+ g_ptr_array_add (sim_slot_paths_array, g_strdup ("/"));
+ continue;
+ }
+
+ sim_path = mm_base_sim_get_path (sim);
+ g_ptr_array_add (sim_slot_paths_array, g_strdup (sim_path));
+ }
+ g_ptr_array_add (sim_slot_paths_array, NULL);
+ sim_slot_paths = (GStrv) g_ptr_array_free (sim_slot_paths_array, FALSE);
+
+ mm_gdbus_modem_set_sim_slots (ctx->skeleton, (const gchar *const *)sim_slot_paths);
+ mm_gdbus_modem_set_primary_sim_slot (ctx->skeleton, primary_sim_slot);
+
+ /* If loading SIM slots is supported, we also expose already the primary active SIM object */
+ if (primary_sim_slot) {
+ primary_sim = g_ptr_array_index (sim_slots, primary_sim_slot - 1);
+ if (primary_sim)
+ g_object_bind_property (primary_sim, MM_BASE_SIM_PATH,
+ ctx->skeleton, "sim",
+ G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE);
+ }
+ g_object_set (self,
+ MM_IFACE_MODEM_SIM, primary_sim,
+ MM_IFACE_MODEM_SIM_SLOTS, sim_slots,
+ NULL);
+ }
+
+ /* Go on to next step */
+ ctx->step++;
+ interface_initialization_step (task);
+}
+
+static void
modem_update_lock_info_ready (MMIfaceModem *self,
GAsyncResult *res,
GTask *task)
@@ -5090,6 +5158,22 @@ interface_initialization_step (GTask *task)
ctx->step++;
/* fall-through */
+ case INITIALIZATION_STEP_SIM_SLOTS:
+ /* If the modem doesn't need any SIM (not implemented by plugin, or not
+ * needed in CDMA-only modems), or if we don't know how to query
+ * for SIM slots */
+ if (!mm_gdbus_modem_get_sim_slots (ctx->skeleton) &&
+ !mm_iface_modem_is_cdma_only (self) &&
+ MM_IFACE_MODEM_GET_INTERFACE (self)->load_sim_slots &&
+ MM_IFACE_MODEM_GET_INTERFACE (self)->load_sim_slots_finish) {
+ MM_IFACE_MODEM_GET_INTERFACE (self)->load_sim_slots (MM_IFACE_MODEM (self),
+ (GAsyncReadyCallback)load_sim_slots_ready,
+ task);
+ return;
+ }
+ ctx->step++;
+ /* fall-through */
+
case INITIALIZATION_STEP_UNLOCK_REQUIRED:
/* Only check unlock required if we were previously not unlocked */
if (mm_gdbus_modem_get_unlock_required (ctx->skeleton) != MM_MODEM_LOCK_NONE) {
@@ -5686,6 +5770,14 @@ iface_modem_init (gpointer g_iface)
g_object_interface_install_property
(g_iface,
+ g_param_spec_boxed (MM_IFACE_MODEM_SIM_SLOTS,
+ "SIM slots",
+ "SIM objects in SIM slots",
+ MM_TYPE_OBJECT_ARRAY,
+ G_PARAM_READWRITE));
+
+ g_object_interface_install_property
+ (g_iface,
g_param_spec_enum (MM_IFACE_MODEM_STATE,
"State",
"State of the modem",
diff --git a/src/mm-iface-modem.h b/src/mm-iface-modem.h
index 2df3b59c..0393155d 100644
--- a/src/mm-iface-modem.h
+++ b/src/mm-iface-modem.h
@@ -35,6 +35,7 @@
#define MM_IFACE_MODEM_DBUS_SKELETON "iface-modem-dbus-skeleton"
#define MM_IFACE_MODEM_STATE "iface-modem-state"
#define MM_IFACE_MODEM_SIM "iface-modem-sim"
+#define MM_IFACE_MODEM_SIM_SLOTS "iface-modem-sim-slots"
#define MM_IFACE_MODEM_BEARER_LIST "iface-modem-bearer-list"
#define MM_IFACE_MODEM_SIM_HOT_SWAP_SUPPORTED "iface-modem-sim-hot-swap-supported"
#define MM_IFACE_MODEM_SIM_HOT_SWAP_CONFIGURED "iface-modem-sim-hot-swap-configured"
@@ -343,6 +344,16 @@ struct _MMIfaceModem {
GAsyncResult *res,
GError **error);
+ /* Create SIMs in all SIM slots */
+ void (* load_sim_slots) (MMIfaceModem *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+ gboolean (* load_sim_slots_finish) (MMIfaceModem *self,
+ GAsyncResult *res,
+ GPtrArray **sim_slots,
+ guint *primary_sim_slot,
+ GError **error);
+
/* Create bearer */
void (*create_bearer) (MMIfaceModem *self,
MMBearerProperties *properties,
diff --git a/src/mm-private-boxed-types.c b/src/mm-private-boxed-types.c
index 465649b5..a94dd2c4 100644
--- a/src/mm-private-boxed-types.c
+++ b/src/mm-private-boxed-types.c
@@ -171,6 +171,35 @@ mm_pointer_array_get_type (void)
return g_define_type_id__volatile;
}
+static GPtrArray *
+object_array_copy (GPtrArray *object_array)
+{
+ return g_ptr_array_ref (object_array);
+}
+
+static void
+object_array_free (GPtrArray *object_array)
+{
+ g_ptr_array_unref (object_array);
+}
+
+GType
+mm_object_array_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile)) {
+ GType g_define_type_id =
+ g_boxed_type_register_static (g_intern_static_string ("MMObjectArray"),
+ (GBoxedCopyFunc) object_array_copy,
+ (GBoxedFreeFunc) object_array_free);
+
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+
static void
async_method_free (MMAsyncMethod *method)
{
diff --git a/src/mm-private-boxed-types.h b/src/mm-private-boxed-types.h
index fcdcbb10..8a7d5fcb 100644
--- a/src/mm-private-boxed-types.h
+++ b/src/mm-private-boxed-types.h
@@ -34,6 +34,9 @@ GType mm_str_pair_array_get_type (void) G_GNUC_CONST;
GType mm_pointer_array_get_type (void) G_GNUC_CONST;
#define MM_TYPE_POINTER_ARRAY (mm_pointer_array_get_type ())
+GType mm_object_array_get_type (void) G_GNUC_CONST;
+#define MM_TYPE_OBJECT_ARRAY (mm_object_array_get_type ())
+
typedef struct {
GCallback async;
GCallback finish;