aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2020-08-01 09:59:37 +0200
committerAleksander Morgado <aleksander@aleksander.es>2020-08-28 14:59:06 +0000
commit924cf1af3c5e1aec1df680d50e4b9ae6dd8e0ba9 (patch)
tree48c1492b1412ca81b3e0abfc860d55a60a5d47cd /src
parent5041b9c99b8587185b629715e3466d31a619abf3 (diff)
api,modem: new 'SetPrimarySimSlot' method
This new method allows changing the SIM slot considered as primary, when the modem supports multiple SIM slots. The generic handling of this method will make sure that the modem object and all its SIM objects are re-probed from scratch as soon as a successful SIM slot switch happens. Implementations may report MM_CORE_ERROR_EXISTS when the switch doesn't need to happen (e.g. if the requested SIM slot is already the active one).
Diffstat (limited to 'src')
-rw-r--r--src/mm-iface-modem.c112
-rw-r--r--src/mm-iface-modem.h9
2 files changed, 121 insertions, 0 deletions
diff --git a/src/mm-iface-modem.c b/src/mm-iface-modem.c
index 9045d290..955453be 100644
--- a/src/mm-iface-modem.c
+++ b/src/mm-iface-modem.c
@@ -957,6 +957,117 @@ handle_list_bearers (MmGdbusModem *skeleton,
/*****************************************************************************/
+typedef struct {
+ MmGdbusModem *skeleton;
+ GDBusMethodInvocation *invocation;
+ MMIfaceModem *self;
+ guint requested_sim_slot;
+} HandleSetPrimarySimSlotContext;
+
+static void
+handle_set_primary_sim_slot_context_free (HandleSetPrimarySimSlotContext *ctx)
+{
+ g_clear_object (&ctx->skeleton);
+ g_clear_object (&ctx->invocation);
+ g_clear_object (&ctx->self);
+ g_free (ctx);
+}
+
+static void
+set_primary_sim_slot_ready (MMIfaceModem *self,
+ GAsyncResult *res,
+ HandleSetPrimarySimSlotContext *ctx)
+{
+ g_autoptr(GError) error = NULL;
+
+ if (!MM_IFACE_MODEM_GET_INTERFACE (self)->set_primary_sim_slot_finish (self, res, &error)) {
+ /* If the implementation returns EXISTS, we're already in the requested SIM slot,
+ * so we can safely return a success on the operation and skip the reprobing */
+ if (!g_error_matches (error, MM_CORE_ERROR, MM_CORE_ERROR_EXISTS)) {
+ mm_obj_warn (self, "couldn't process primary SIM update request: %s", error->message);
+ g_dbus_method_invocation_take_error (ctx->invocation, g_steal_pointer (&error));
+ handle_set_primary_sim_slot_context_free (ctx);
+ return;
+ }
+ mm_obj_dbg (self, "ignoring SIM update request: %s", error->message);
+ } else {
+ /* Notify about the SIM swap, which will disable and reprobe the device.
+ * There is no need to update the PrimarySimSlot property, as this value will be
+ * reloaded automatically during the reprobe. */
+ mm_base_modem_process_sim_switch (MM_BASE_MODEM (self));
+ }
+
+ mm_gdbus_modem_complete_set_primary_sim_slot (ctx->skeleton, ctx->invocation);
+ handle_set_primary_sim_slot_context_free (ctx);
+}
+
+static void
+handle_set_primary_sim_slot_auth_ready (MMBaseModem *self,
+ GAsyncResult *res,
+ HandleSetPrimarySimSlotContext *ctx)
+{
+ GError *error = NULL;
+ const gchar *const *sim_slot_paths;
+
+ if (!mm_base_modem_authorize_finish (self, res, &error)) {
+ g_dbus_method_invocation_take_error (ctx->invocation, error);
+ handle_set_primary_sim_slot_context_free (ctx);
+ return;
+ }
+
+ /* If SIM switching is not implemented, report an error */
+ if (!MM_IFACE_MODEM_GET_INTERFACE (self)->set_primary_sim_slot ||
+ !MM_IFACE_MODEM_GET_INTERFACE (self)->set_primary_sim_slot_finish) {
+ g_dbus_method_invocation_return_error (ctx->invocation,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_UNSUPPORTED,
+ "Cannot switch sim: "
+ "operation not supported");
+ handle_set_primary_sim_slot_context_free (ctx);
+ return;
+ }
+
+ /* Validate SIM slot number */
+ sim_slot_paths = mm_gdbus_modem_get_sim_slots (ctx->skeleton);
+ if (ctx->requested_sim_slot > g_strv_length ((gchar **)sim_slot_paths)) {
+ g_dbus_method_invocation_return_error (ctx->invocation,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_INVALID_ARGS,
+ "Cannot switch sim: requested SIM slot number is out of bounds");
+ handle_set_primary_sim_slot_context_free (ctx);
+ return;
+ }
+
+ MM_IFACE_MODEM_GET_INTERFACE (self)->set_primary_sim_slot (MM_IFACE_MODEM (self),
+ ctx->requested_sim_slot,
+ (GAsyncReadyCallback)set_primary_sim_slot_ready,
+ ctx);
+}
+
+static gboolean
+handle_set_primary_sim_slot (MmGdbusModem *skeleton,
+ GDBusMethodInvocation *invocation,
+ guint sim_slot,
+ MMIfaceModem *self)
+{
+ HandleSetPrimarySimSlotContext *ctx;
+
+ ctx = g_new0 (HandleSetPrimarySimSlotContext, 1);
+ ctx->skeleton = g_object_ref (skeleton);
+ ctx->invocation = g_object_ref (invocation);
+ ctx->self = g_object_ref (self);
+ ctx->requested_sim_slot = sim_slot;
+
+ mm_base_modem_authorize (MM_BASE_MODEM (self),
+ invocation,
+ MM_AUTHORIZATION_DEVICE_CONTROL,
+ (GAsyncReadyCallback)handle_set_primary_sim_slot_auth_ready,
+ ctx);
+ return TRUE;
+}
+
+/*****************************************************************************/
+
void
mm_iface_modem_update_access_technologies (MMIfaceModem *self,
MMModemAccessTechnology new_access_tech,
@@ -5362,6 +5473,7 @@ interface_initialization_step (GTask *task)
"signal::handle-enable", G_CALLBACK (handle_enable), self,
"signal::handle-set-current-bands", G_CALLBACK (handle_set_current_bands), self,
"signal::handle-set-current-modes", G_CALLBACK (handle_set_current_modes), self,
+ "signal::handle-set-primary-sim-slot", G_CALLBACK (handle_set_primary_sim_slot), self,
NULL);
/* Finally, export the new interface, even if we got errors, but only if not
diff --git a/src/mm-iface-modem.h b/src/mm-iface-modem.h
index 0393155d..c40323fc 100644
--- a/src/mm-iface-modem.h
+++ b/src/mm-iface-modem.h
@@ -354,6 +354,15 @@ struct _MMIfaceModem {
guint *primary_sim_slot,
GError **error);
+ /* Set primary SIM slot */
+ void (* set_primary_sim_slot) (MMIfaceModem *self,
+ guint sim_slot,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+ gboolean (* set_primary_sim_slot_finish) (MMIfaceModem *self,
+ GAsyncResult *res,
+ GError **error);
+
/* Create bearer */
void (*create_bearer) (MMIfaceModem *self,
MMBearerProperties *properties,