aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Caruso <ejcaruso@chromium.org>2017-07-11 10:58:23 -0700
committerAleksander Morgado <aleksander@aleksander.es>2017-07-12 11:15:07 +0200
commit3d9510b4fd5f4dc46df1476c067787f1dd3431a6 (patch)
tree68974c036f3fc3543161c0ebe9f56cac0fb329e1
parentfe384625aa59c117ec99b943c6e0b09deea48a0d (diff)
mm-broadband-modem-mbim: support SIM hot swapping
If an MBIM modem supports unsolicited notifications for subscriber ready status, we can use it to detect when SIM cards have been removed and reinserted. Upon detection we should re- probe the modem so that we can configure it for the new SIM.
-rw-r--r--src/mm-broadband-modem-mbim.c96
1 files changed, 93 insertions, 3 deletions
diff --git a/src/mm-broadband-modem-mbim.c b/src/mm-broadband-modem-mbim.c
index 8d8882b1..2d3d96fa 100644
--- a/src/mm-broadband-modem-mbim.c
+++ b/src/mm-broadband-modem-mbim.c
@@ -88,6 +88,10 @@ struct _MMBroadbandModemMbimPrivate {
/* Access technology updates */
MbimDataClass available_data_classes;
MbimDataClass highest_available_data_class;
+
+ /* For checking whether the SIM has been hot swapped */
+ gboolean sim_hot_swap_on;
+ MbimSubscriberReadyState last_ready_state;
};
/*****************************************************************************/
@@ -542,11 +546,13 @@ unlock_required_subscriber_ready_state_ready (MbimDevice *device,
GTask *task)
{
LoadUnlockRequiredContext *ctx;
+ MMBroadbandModemMbim *self;
MbimMessage *response;
GError *error = NULL;
MbimSubscriberReadyState ready_state = MBIM_SUBSCRIBER_READY_STATE_NOT_INITIALIZED;
ctx = g_task_get_task_data (task);
+ self = g_task_get_source_object (task);
response = mbim_device_command_finish (device, res, &error);
if (response &&
@@ -581,6 +587,8 @@ unlock_required_subscriber_ready_state_ready (MbimDevice *device,
}
}
+ self->priv->last_ready_state = ready_state;
+
/* Fatal errors are reported right away */
if (error) {
g_task_return_error (task, error);
@@ -1976,8 +1984,15 @@ basic_connect_notification_subscriber_ready_status (MMBroadbandModemMbim *self,
if (ready_state == MBIM_SUBSCRIBER_READY_STATE_INITIALIZED)
mm_iface_modem_update_own_numbers (MM_IFACE_MODEM (self), telephone_numbers);
- /* TODO: handle SIM removal using MBIM_SUBSCRIBER_READY_STATE_SIM_NOT_INSERTED */
+ if ((self->priv->last_ready_state != MBIM_SUBSCRIBER_READY_STATE_SIM_NOT_INSERTED &&
+ ready_state == MBIM_SUBSCRIBER_READY_STATE_SIM_NOT_INSERTED) ||
+ (self->priv->last_ready_state == MBIM_SUBSCRIBER_READY_STATE_SIM_NOT_INSERTED &&
+ ready_state != MBIM_SUBSCRIBER_READY_STATE_SIM_NOT_INSERTED)) {
+ /* SIM has been removed or reinserted, re-probe to ensure correct interfaces are exposed */
+ mm_broadband_modem_update_sim_hot_swap_detected (MM_BROADBAND_MODEM (self));
+ }
+ self->priv->last_ready_state = ready_state;
g_strfreev (telephone_numbers);
}
@@ -2271,7 +2286,8 @@ cleanup_unsolicited_events_3gpp (MMIfaceModem3gpp *self,
{
MM_BROADBAND_MODEM_MBIM (self)->priv->setup_flags &= ~PROCESS_NOTIFICATION_FLAG_SIGNAL_QUALITY;
MM_BROADBAND_MODEM_MBIM (self)->priv->setup_flags &= ~PROCESS_NOTIFICATION_FLAG_CONNECT;
- MM_BROADBAND_MODEM_MBIM (self)->priv->setup_flags &= ~PROCESS_NOTIFICATION_FLAG_SUBSCRIBER_INFO;
+ if (!MM_BROADBAND_MODEM_MBIM (self)->priv->sim_hot_swap_on)
+ MM_BROADBAND_MODEM_MBIM (self)->priv->setup_flags &= ~PROCESS_NOTIFICATION_FLAG_SUBSCRIBER_INFO;
MM_BROADBAND_MODEM_MBIM (self)->priv->setup_flags &= ~PROCESS_NOTIFICATION_FLAG_PACKET_SERVICE;
common_setup_cleanup_unsolicited_events (MM_BROADBAND_MODEM_MBIM (self), FALSE, callback, user_data);
}
@@ -2452,6 +2468,74 @@ modem_3gpp_enable_unsolicited_registration_events (MMIfaceModem3gpp *self,
}
/*****************************************************************************/
+/* Setup SIM hot swap */
+
+static gboolean
+modem_setup_sim_hot_swap_finish (MMIfaceModem *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ return g_task_propagate_boolean (G_TASK (res), error);
+}
+
+static void
+enable_subscriber_info_unsolicited_events_ready (MMBroadbandModemMbim *self,
+ GAsyncResult *res,
+ GTask *task)
+{
+ GError *error = NULL;
+
+ if (!common_enable_disable_unsolicited_events_finish (self, res, &error)) {
+ mm_dbg ("Failed to enable subscriber info events: %s", error->message);
+ self->priv->sim_hot_swap_on = FALSE;
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
+ }
+
+ g_task_return_boolean (task, TRUE);
+ g_object_unref (task);
+}
+
+static void
+setup_subscriber_info_unsolicited_events_ready (MMBroadbandModemMbim *self,
+ GAsyncResult *res,
+ GTask *task)
+{
+ GError *error = NULL;
+
+ if (!common_setup_cleanup_unsolicited_events_finish (self, res, &error)) {
+ mm_dbg ("Failed to set up subscriber info events: %s", error->message);
+ self->priv->sim_hot_swap_on = FALSE;
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
+ }
+
+ self->priv->enable_flags |= PROCESS_NOTIFICATION_FLAG_SUBSCRIBER_INFO;
+ common_enable_disable_unsolicited_events (self,
+ (GAsyncReadyCallback)enable_subscriber_info_unsolicited_events_ready,
+ task);
+}
+
+static void
+modem_setup_sim_hot_swap (MMIfaceModem *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GTask *task;
+
+ task = g_task_new (self, NULL, callback, user_data);
+
+ MM_BROADBAND_MODEM_MBIM (self)->priv->sim_hot_swap_on = TRUE;
+ MM_BROADBAND_MODEM_MBIM (self)->priv->setup_flags |= PROCESS_NOTIFICATION_FLAG_SUBSCRIBER_INFO;
+ common_setup_cleanup_unsolicited_events (MM_BROADBAND_MODEM_MBIM (self),
+ TRUE,
+ (GAsyncReadyCallback)setup_subscriber_info_unsolicited_events_ready,
+ task);
+}
+
+/*****************************************************************************/
/* Enable/Disable unsolicited events (3GPP interface) */
static gboolean
@@ -2469,7 +2553,8 @@ modem_3gpp_disable_unsolicited_events (MMIfaceModem3gpp *self,
{
MM_BROADBAND_MODEM_MBIM (self)->priv->enable_flags &= ~PROCESS_NOTIFICATION_FLAG_SIGNAL_QUALITY;
MM_BROADBAND_MODEM_MBIM (self)->priv->enable_flags &= ~PROCESS_NOTIFICATION_FLAG_CONNECT;
- MM_BROADBAND_MODEM_MBIM (self)->priv->enable_flags &= ~PROCESS_NOTIFICATION_FLAG_SUBSCRIBER_INFO;
+ if (!MM_BROADBAND_MODEM_MBIM (self)->priv->sim_hot_swap_on)
+ MM_BROADBAND_MODEM_MBIM (self)->priv->enable_flags &= ~PROCESS_NOTIFICATION_FLAG_SUBSCRIBER_INFO;
MM_BROADBAND_MODEM_MBIM (self)->priv->enable_flags &= ~PROCESS_NOTIFICATION_FLAG_PACKET_SERVICE;
common_enable_disable_unsolicited_events (MM_BROADBAND_MODEM_MBIM (self), callback, user_data);
}
@@ -3042,6 +3127,7 @@ mm_broadband_modem_mbim_new (const gchar *device,
MM_BASE_MODEM_PLUGIN, plugin,
MM_BASE_MODEM_VENDOR_ID, vendor_id,
MM_BASE_MODEM_PRODUCT_ID, product_id,
+ MM_IFACE_MODEM_SIM_HOT_SWAP_SUPPORTED, TRUE,
NULL);
}
@@ -3128,6 +3214,10 @@ iface_modem_init (MMIfaceModem *iface)
/* Create MBIM-specific bearer */
iface->create_bearer = modem_create_bearer;
iface->create_bearer_finish = modem_create_bearer_finish;
+
+ /* SIM hot swapping */
+ iface->setup_sim_hot_swap = modem_setup_sim_hot_swap;
+ iface->setup_sim_hot_swap_finish = modem_setup_sim_hot_swap_finish;
}
static void