[PATCH] telit: enable 'SIM ready' notifications with #QSS=2

Aleksander Morgado aleksander at aleksander.es
Tue Mar 14 23:37:52 UTC 2017


It will allow us to avoid totally or partially the after-sim-unlock
explicit wait time that we're forcing.

https://bugs.freedesktop.org/show_bug.cgi?id=100206
---

Hey Carlo & Daniele,

I tried to enable #QSS=2 to see if I could get "#QSS: 3" indications:
   3 - SIM INSERTED and READY (SMS and Phonebook access are possible).

But looks like the HW I have doesn't emit any #QSS indication for some reason, any idea why? E.g. even if I remove the SIM and insert it again I get no "#QSS: 0" or "#QSS: 1" indication. Any idea why?

Could you also review and test the patch with a device that supports "#QSS: 3" indications? I'm still not very convinced whether this is worth it to avoid the 1s timeout in the after-sim-unlock step, truth be told, but maybe if this setup works (i.e. we get a #QSS notification as soon as the SIM is completely ready) we could extend the timeout to a value a bit bigger just in case, like 5s?

What do you think?

---
 plugins/telit/mm-broadband-modem-telit.c | 106 ++++++++++++++++++++++++++-----
 plugins/telit/mm-broadband-modem-telit.h |   2 +
 2 files changed, 91 insertions(+), 17 deletions(-)

diff --git a/plugins/telit/mm-broadband-modem-telit.c b/plugins/telit/mm-broadband-modem-telit.c
index 8bc9d1e5..76bcb1d4 100644
--- a/plugins/telit/mm-broadband-modem-telit.c
+++ b/plugins/telit/mm-broadband-modem-telit.c
@@ -42,40 +42,83 @@ G_DEFINE_TYPE_EXTENDED (MMBroadbandModemTelit, mm_broadband_modem_telit, MM_TYPE
                         G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init)
                         G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_3GPP, iface_modem_3gpp_init));

+struct _MMBroadbandModemTelitPrivate {
+    /* Whether the SIM ready notification has been received */
+    gboolean  sim_ready;
+    GTask    *sim_ready_task;
+    guint     sim_ready_timeout_id;
+};

 /*****************************************************************************/
 /* After Sim Unlock (Modem interface) */
+
+/* A short delay is necessary with some SIMs when they have just been
+ * unlocked. Using up to 1 second as secure margin. */
+#define SIM_READY_TIMEOUT_SECS 1
+
 static gboolean
 modem_after_sim_unlock_finish (MMIfaceModem *self,
                                GAsyncResult *res,
                                GError **error)
 {
-    return TRUE;
+    return g_task_propagate_boolean (G_TASK (res), error);
 }

 static gboolean
-after_sim_unlock_ready (GSimpleAsyncResult *result)
+after_sim_unlock_ready (MMBroadbandModemTelit *self)
 {
-    g_simple_async_result_complete (result);
-    g_object_unref (result);
+    g_assert (self->priv->sim_ready_timeout_id);
+    g_assert (self->priv->sim_ready_task);
+
+    self->priv->sim_ready_timeout_id = 0;
+
+    g_task_return_boolean (self->priv->sim_ready_task, TRUE);
+    g_clear_object (&self->priv->sim_ready_task);
+
     return G_SOURCE_REMOVE;
 }

 static void
-modem_after_sim_unlock (MMIfaceModem *self,
-                        GAsyncReadyCallback callback,
-                        gpointer user_data)
+modem_after_sim_unlock_cancel (MMBroadbandModemTelit *self)
 {
-    GSimpleAsyncResult *result;
+    /* Cancel the after-sim-unlock wait timeout */
+    if (self->priv->sim_ready_timeout_id) {
+        g_source_remove (self->priv->sim_ready_timeout_id);
+        self->priv->sim_ready_timeout_id = 0;
+    }

-    result = g_simple_async_result_new (G_OBJECT (self),
-                                        callback,
-                                        user_data,
-                                        modem_after_sim_unlock);
+    /* Complete after-sim-unlock wait task with error */
+    if (self->priv->sim_ready_task) {
+        g_task_return_new_error (self->priv->sim_ready_task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "SIM removed");
+        g_clear_object (&self->priv->sim_ready_task);
+    }
+}
+
+static void
+modem_after_sim_unlock (MMIfaceModem        *_self,
+                        GAsyncReadyCallback  callback,
+                        gpointer             user_data)
+{
+    MMBroadbandModemTelit *self;
+
+    self = MM_BROADBAND_MODEM_TELIT (_self);
+
+    g_assert (!self->priv->sim_ready_task);
+    g_assert (!self->priv->sim_ready_timeout_id);
+
+    /* Create new task that we store in the private info, so that it can be
+     * completed early when unsolicited messages arrive. */
+    self->priv->sim_ready_task = g_task_new (self, NULL, callback, user_data);

-    /* A short delay is necessary with some SIMs when
-    they have just been unlocked. Using 1 second as secure margin. */
-    g_timeout_add_seconds (1, (GSourceFunc) after_sim_unlock_ready, result);
+    /* If SIM ready already reported, we're done */
+    if (self->priv->sim_ready) {
+        g_task_return_boolean (self->priv->sim_ready_task, TRUE);
+        g_clear_object (&self->priv->sim_ready_task);
+        return;
+    }
+
+    /* Wait for SIM readiness */
+    self->priv->sim_ready_timeout_id = g_timeout_add_seconds (SIM_READY_TIMEOUT_SECS, (GSourceFunc) after_sim_unlock_ready, self);
 }

 /*****************************************************************************/
@@ -94,6 +137,10 @@ telit_qss_unsolicited_handler (MMPortSerialAt *port,
     switch (qss) {
         case 0:
             mm_info ("QSS: SIM removed");
+
+            /* Flag as not ready */
+            self->priv->sim_ready = FALSE;
+            modem_after_sim_unlock_cancel (self);
             break;
         case 1:
             mm_info ("QSS: SIM inserted");
@@ -102,7 +149,8 @@ telit_qss_unsolicited_handler (MMPortSerialAt *port,
             mm_info ("QSS: SIM inserted and PIN unlocked");
             break;
         case 3:
-            mm_info ("QSS: SIM inserted and PIN locked");
+            mm_info ("QSS: SIM inserted and Ready");
+            self->priv->sim_ready = TRUE;
             break;
         default:
             mm_warn ("QSS: unknown QSS value %d", qss);
@@ -203,9 +251,12 @@ modem_setup_sim_hot_swap (MMIfaceModem *self,
     if (!port)
         port = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self));

+    /* We enable QSS=2 so that we get notifications not only of SIM inserted or
+     * not inserted, but also when the SIM is unlocked and ready for SMS and
+     * phonebook access */
     mm_base_modem_at_command_full (MM_BASE_MODEM (self),
                                    port,
-                                   "#QSS=1",
+                                   "#QSS=2",
                                    3,
                                    FALSE,
                                    FALSE, /* raw */
@@ -1259,6 +1310,22 @@ mm_broadband_modem_telit_new (const gchar *device,
 static void
 mm_broadband_modem_telit_init (MMBroadbandModemTelit *self)
 {
+    /* Initialize private data */
+    self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, MM_TYPE_BROADBAND_MODEM_TELIT, MMBroadbandModemTelitPrivate);
+}
+
+static void
+finalize (GObject *object)
+{
+    MMBroadbandModemTelit *self = MM_BROADBAND_MODEM_TELIT (object);
+
+    /* The after sim unlock step takes a full reference of the modem object in
+     * the GTask, and therefore, the object will never be unref-ed while this
+     * operation is pending */
+    g_assert (!self->priv->sim_ready_timeout_id);
+    g_assert (!self->priv->sim_ready_task);
+
+    G_OBJECT_CLASS (mm_broadband_modem_telit_parent_class)->finalize (object);
 }

 static void
@@ -1304,4 +1371,9 @@ iface_modem_3gpp_init (MMIfaceModem3gpp *iface)
 static void
 mm_broadband_modem_telit_class_init (MMBroadbandModemTelitClass *klass)
 {
+    GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+    g_type_class_add_private (object_class, sizeof (MMBroadbandModemTelitPrivate));
+
+    object_class->finalize = finalize;
 }
diff --git a/plugins/telit/mm-broadband-modem-telit.h b/plugins/telit/mm-broadband-modem-telit.h
index 50e6365f..f68465e7 100644
--- a/plugins/telit/mm-broadband-modem-telit.h
+++ b/plugins/telit/mm-broadband-modem-telit.h
@@ -29,9 +29,11 @@

 typedef struct _MMBroadbandModemTelit MMBroadbandModemTelit;
 typedef struct _MMBroadbandModemTelitClass MMBroadbandModemTelitClass;
+typedef struct _MMBroadbandModemTelitPrivate MMBroadbandModemTelitPrivate;

 struct _MMBroadbandModemTelit {
     MMBroadbandModem parent;
+    MMBroadbandModemTelitPrivate *priv;
 };

 struct _MMBroadbandModemTelitClass{
--
2.12.0


More information about the ModemManager-devel mailing list