<div dir="ltr"><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">Please, ignore the previous v3 patch... I wasn't compiling the right project and missed some errors.<br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On 4 September 2017 at 07:59, Carlo Lobrano <span dir="ltr"><<a href="mailto:c.lobrano@gmail.com" target="_blank">c.lobrano@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">When transitioning between power-low and power-on modes, Telit modems<br>
switch the SIM off/on, which leads to the emission of #QSS unsolicited not<br>
</span>related to actual SIM swaps.<br>
<br>
To handle this #QSS unsolicited, this patch:<br>
<span class=""><br>
* disables reacting on #QSS unsolicited when modem_power_down is received<br>
* implements modem_after_power_up that:<br>
    - checks whether the SIM has been changed, matching cached SIM<br>
      Identifier with the value in the current SIM. If SIM Identifier,<br>
</span>      is different, sim hot swap ports detected is called.<br>
<span class="">    - re-enables reacting on #QSS unsolicited<br>
---<br>
<br>
Hi Aleksander,<br>
<br>
</span>I should have fixed all the problems, but I'm still not sure about<br>
base-sim's implementation of mm_base_sim_load_sim_<wbr>identifier and<br>
mm_base_sim_load_sim_<wbr>identifier_finish.<br>
I saw that, generally, similar functions have their own ..._ready counterpart,<br>
and maybe a GTask that takes care of caller's callback,<br>
but I think I shouldn't need it and let the caller's callback do all the<br>
job. However, as I said, I'm not really sure this is right.<br>
<br>
---<br>
 plugins/telit/mm-broadband-<wbr>modem-telit.c | 181 ++++++++++++++++++++++++++++++<wbr>-<br>
 src/mm-base-sim.c                        |  51 +++++++++<br>
 src/mm-base-sim.h                        |  80 +++++++-------<br>
 3 files changed, 271 insertions(+), 41 deletions(-)<br>
<br>
diff --git a/plugins/telit/mm-broadband-<wbr>modem-telit.c b/plugins/telit/mm-broadband-<wbr>modem-telit.c<br>
index a9fc5f0..ac2c620 100644<br>
<span class="">--- a/plugins/telit/mm-broadband-<wbr>modem-telit.c<br>
+++ b/plugins/telit/mm-broadband-<wbr>modem-telit.c<br>
@@ -58,6 +58,7 @@ struct _MMBroadbandModemTelitPrivate {<br>
     MMTelitCsimLockState csim_lock_state;<br>
     GTask *csim_lock_task;<br>
     guint csim_lock_timeout_id;<br>
+    gboolean parse_qss;<br>
 };<br>
<br>
 /*****************************<wbr>******************************<wbr>******************/<br>
@@ -151,10 +152,15 @@ telit_qss_unsolicited_handler (MMPortSerialAt *port,<br>
     }<br>
<br>
     if (cur_qss_status != prev_qss_status)<br>
-        mm_dbg ("QSS handler: status changed '%s -> %s",<br>
+        mm_dbg ("QSS handler: status changed '%s -> %s'",<br>
                 mm_telit_qss_status_get_string (prev_qss_status),<br>
                 mm_telit_qss_status_get_string (cur_qss_status));<br>
<br>
+    if (self->priv->parse_qss == FALSE) {<br>
</span>+        mm_dbg ("QSS: message ignored");<br>
<span class="">+        return;<br>
+    }<br>
+<br>
     if ((prev_qss_status == QSS_STATUS_SIM_REMOVED && cur_qss_status != QSS_STATUS_SIM_REMOVED) ||<br>
         (prev_qss_status > QSS_STATUS_SIM_REMOVED && cur_qss_status == QSS_STATUS_SIM_REMOVED)) {<br>
         mm_info ("QSS handler: SIM swap detected");<br>
</span>@@ -903,14 +909,175 @@ modem_load_unlock_retries (MMIfaceModem *self,<br>
 }<br>
<br>
 /*****************************<wbr>******************************<wbr>******************/<br>
<span class="">+/* Modem after power up (Modem interface) */<br>
+typedef enum {<br>
+    AFTER_POWER_UP_STEP_FIRST,<br>
+    AFTER_POWER_UP_STEP_GET_SIM_<wbr>IDENTIFIER,<br>
+    AFTER_POWER_UP_STEP_ENABLE_<wbr>QSS_PARSING,<br>
+    AFTER_POWER_UP_STEP_LAST<br>
+} ModemAfterPowerUpStep;<br>
+<br>
+typedef struct {<br>
</span><span class="">+    gboolean has_sim_changed;<br>
+    guint retries;<br>
+    ModemAfterPowerUpStep step;<br>
</span><span class="">+} AfterPowerUpContext;<br>
+<br>
+static void after_power_up_step (GTask *task);<br>
+<br>
</span><span class="">+static gboolean<br>
+modem_after_power_up_finish (MMIfaceModem *self,<br>
+                             GAsyncResult *res,<br>
+                             GError **error)<br>
+{<br>
+    return g_task_propagate_boolean (G_TASK (res), error);<br>
+}<br>
+<br>
+static void<br>
</span>+load_sim_identifier_ready (MMBaseSim *sim,<br>
<span class="">+                           GAsyncResult *res,<br>
+                           GTask *task)<br>
+{<br>
+    AfterPowerUpContext *ctx;<br>
+    GError *error = NULL;<br>
+    gchar *current_simid;<br>
+    gchar *cached_simid;<br>
+<br>
+    ctx = g_task_get_task_data (task);<br>
+<br>
</span>+    cached_simid = (gchar *)mm_gdbus_sim_get_sim_<wbr>identifier (MM_GDBUS_SIM (sim));<br>
+    current_simid = mm_base_sim_load_sim_<wbr>identifier_finish (sim, res, &error);<br>
+<br>
+    if (error) {<br>
+        if (g_error_matches (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED)) {<br>
+            mm_warn ("could not load SIM identifier: %s", error->message);<br>
+            g_clear_error (error);<br>
<span class="">+            goto out;<br>
+        }<br>
+<br>
</span>+        if (ctx->retries-- > 0) {<br>
+            mm_warn ("could not load SIM identifier: %s (%d retries left)",<br>
+                     error->message, ctx->retries);<br>
<span class="">+            g_clear_error (&error);<br>
+            g_timeout_add_seconds (1, (GSourceFunc) after_power_up_step, task);<br>
+            return;<br>
+        }<br>
+<br>
</span>+        mm_warn ("could not load SIM identifier: %s", error->message);<br>
<span class="">+        g_clear_error (&error);<br>
+        goto out;<br>
+    }<br>
+<br>
+    if (g_strcmp0 (current_simid, cached_simid) != 0) {<br>
</span>+        mm_warn ("sim identifier has changed: possible SIM swap during power down/low");<br>
<span class="">+        ctx->has_sim_changed = TRUE;<br>
+    }<br>
+<br>
+out:<br>
+    g_free (current_simid);<br>
</span><span class="">+    ctx->step++;<br>
+    after_power_up_step (task);<br>
+}<br>
+<br>
+static void<br>
+after_power_up_step (GTask *task)<br>
+{<br>
+    AfterPowerUpContext *ctx;<br>
</span>+    MMBroadbandModemTelit *self;<br>
+    MMBaseSim *sim = NULL;<br>
<span class="">+<br>
+    ctx = g_task_get_task_data (task);<br>
</span>+    self = g_task_get_source_object (task);<br>
+<br>
+    g_object_get (MM_BROADBAND_MODEM_TELIT (self),<br>
<span class="">+                  MM_IFACE_MODEM_SIM, &sim,<br>
+                  NULL);<br>
+    if (!sim) {<br>
</span><span class="">+        g_task_return_new_error (task,<br>
+                                 MM_CORE_ERROR,<br>
+                                 MM_CORE_ERROR_FAILED,<br>
</span>+                                 "could not acquire sim object");<br>
<span class="">+        return;<br>
+    }<br>
+<br>
+    switch (ctx->step) {<br>
+    case AFTER_POWER_UP_STEP_FIRST:<br>
+        /* Fall back on next step */<br>
+        ctx->step++;<br>
+    case AFTER_POWER_UP_STEP_GET_SIM_<wbr>IDENTIFIER:<br>
</span>+        mm_base_sim_load_sim_<wbr>identifier (sim,<br>
+                                         (GAsyncReadyCallback)load_sim_<wbr>identifier_ready,<br>
+                                         task);<br>
+        g_object_unref (sim);<br>
<span class="">+        return;<br>
+    case AFTER_POWER_UP_STEP_ENABLE_<wbr>QSS_PARSING:<br>
</span>+        mm_dbg ("Stop ignoring #QSS");<br>
<span class="">+        self->priv->parse_qss = TRUE;<br>
</span><span class="">+<br>
+        /* Fall back on next step */<br>
+        ctx->step++;<br>
+    case AFTER_POWER_UP_STEP_LAST:<br>
+        if (ctx->has_sim_changed)<br>
</span>+            mm_broadband_modem_update_sim_<wbr>hot_swap_detected (MM_BROADBAND_MODEM (self));<br>
<span class="">+<br>
+        g_task_return_boolean (task, TRUE);<br>
+        g_object_unref (task);<br>
+        break;<br>
+    default:<br>
+        g_assert_not_reached ();<br>
+    }<br>
+}<br>
+<br>
</span><span class="">+static void<br>
+modem_after_power_up (MMIfaceModem *self,<br>
+                      GAsyncReadyCallback callback,<br>
+                      gpointer user_data)<br>
+{<br>
+    GTask *task;<br>
+    AfterPowerUpContext *ctx;<br>
+<br>
</span>+    ctx = g_new0 (AfterPowerUpContext, 1);<br>
<span class="">+    ctx->step = AFTER_POWER_UP_STEP_FIRST;<br>
+    ctx->has_sim_changed = FALSE;<br>
+    ctx->retries = 3;<br>
+<br>
+    task = g_task_new (self, NULL, callback, user_data);<br>
</span>+    g_task_set_task_data (task, ctx, (GDestroyNotify) g_free);<br>
<span class="">+<br>
+    after_power_up_step (task);<br>
+}<br>
+<br>
+<br>
+/****************************<wbr>******************************<wbr>*******************/<br>
 /* Modem power down (Modem interface) */<br>
<br>
+static void<br>
+telit_modem_power_down_ready (MMBaseModem *self,<br>
+                              GAsyncResult *res,<br>
+                              GTask *task)<br>
+{<br>
+    GError *error = NULL;<br>
+<br>
</span>+    if (mm_base_modem_at_command_<wbr>finish (self, res, &error)) {<br>
<span class="">+        mm_dbg ("Ignore #QSS unsolicited during power down/low");<br>
+        MM_BROADBAND_MODEM_TELIT (self)->priv->parse_qss = FALSE;<br>
+    }<br>
+<br>
</span>+    if (error) {<br>
+        mm_err ("modem power down: %s", error->message)<br>
+        g_clear_error (&error);<br>
+    }<br>
<span class="">+<br>
+    g_task_return_boolean (task, TRUE);<br>
+    g_object_unref (task);<br>
+}<br>
+<br>
 static gboolean<br>
 modem_power_down_finish (MMIfaceModem *self,<br>
                          GAsyncResult *res,<br>
                          GError **error)<br>
 {<br>
-    return !!mm_base_modem_at_command_<wbr>finish (MM_BASE_MODEM (self), res, error);<br>
+    return g_task_propagate_boolean (G_TASK (res), error);<br>
 }<br>
<br>
 static void<br>
</span>@@ -918,12 +1085,15 @@ modem_power_down (MMIfaceModem *self,<br>
<span class="">                   GAsyncReadyCallback callback,<br>
                   gpointer user_data)<br>
 {<br>
+    GTask *task;<br>
+<br>
+    task = g_task_new (self, NULL, callback, user_data);<br>
     mm_base_modem_at_command (MM_BASE_MODEM (self),<br>
                               "+CFUN=4",<br>
                               20,<br>
                               FALSE,<br>
-                              callback,<br>
-                              user_data);<br>
+                              (GAsyncReadyCallback) telit_modem_power_down_ready,<br>
+                              task);<br>
 }<br>
<br>
 /*****************************<wbr>******************************<wbr>******************/<br>
</span>@@ -1457,6 +1627,7 @@ mm_broadband_modem_telit_init (MMBroadbandModemTelit *self)<br>
<span class="">     self->priv->csim_lock_support = FEATURE_SUPPORT_UNKNOWN;<br>
     self->priv->csim_lock_state = CSIM_LOCK_STATE_UNKNOWN;<br>
     self->priv->qss_status = QSS_STATUS_UNKNOWN;<br>
+    self->priv->parse_qss = TRUE;<br>
 }<br>
<br>
 static void<br>
</span>@@ -1474,6 +1645,8 @@ iface_modem_init (MMIfaceModem *iface)<br>
<span class="">     iface->load_unlock_retries = modem_load_unlock_retries;<br>
     iface->reset = modem_reset;<br>
     iface->reset_finish = modem_reset_finish;<br>
</span><span class="">+    iface->modem_after_power_up = modem_after_power_up;<br>
+    iface->modem_after_power_up_<wbr>finish = modem_after_power_up_finish;<br>
     iface->modem_power_down = modem_power_down;<br>
     iface->modem_power_down_finish = modem_power_down_finish;<br>
     iface->load_access_<wbr>technologies = load_access_technologies;<br>
</span>diff --git a/src/mm-base-sim.c b/src/mm-base-sim.c<br>
index f3525e0..d03f342 100644<br>
--- a/src/mm-base-sim.c<br>
+++ b/src/mm-base-sim.c<br>
@@ -701,6 +701,57 @@ mm_base_sim_send_puk (MMBaseSim *self,<br>
 }<br>
<br>
 /*****************************<wbr>******************************<wbr>******************/<br>
+/* LOAD SIM IDENTIFIER */<br>
+gchar *<br>
+mm_base_sim_load_sim_<wbr>identifier_finish (MMBaseSim *self,<br>
+                                        GAsyncResult *res,<br>
+                                        GError **error) {<br>
+    GError *inner_error = NULL;<br>
+    gchar *simid;<br>
+<br>
+    if (g_async_result_is_tagged (res, mm_base_sim_load_sim_<wbr>identifier) ||<br>
+        !MM_BASE_SIM_GET_CLASS (self)->load_sim_identifier_<wbr>finish) {<br>
+        inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED,<br>
+                                   "not implemented");<br>
+        g_propagate_error (error, inner_error);<br>
+        return NULL;<br>
+    }<br>
+<br>
+    simid = MM_BASE_SIM_GET_CLASS (self)->load_sim_identifier_<wbr>finish (self, res, &inner_error);<br>
+    if (inner_error) {<br>
+        g_propagate_error (error, inner_error);<br>
+        return NULL;<br>
+    }<br>
+<br>
+    return simid;<br>
+}<br>
+<br>
+void<br>
+mm_base_sim_load_sim_<wbr>identifier (MMBaseSim *self,<br>
<span class="">+                                 GAsyncReadyCallback callback,<br>
+                                 gpointer user_data)<br>
+{<br>
</span>+    if (!MM_BASE_SIM_GET_CLASS (self)->load_sim_identifier &&<br>
+        !MM_BASE_SIM_GET_CLASS (self)->load_sim_identifier_<wbr>finish) {<br>
+        g_task_report_new_error (self,<br>
+                                 callback,<br>
+                                 user_data,<br>
+                                 mm_base_sim_load_sim_<wbr>identifier,<br>
+                                 MM_CORE_ERROR,<br>
+                                 MM_CORE_ERROR_UNSUPPORTED,<br>
+                                 "not implemented");<br>
+        return;<br>
+    }<br>
+<br>
+    MM_BASE_SIM_GET_CLASS (self)->load_sim_identifier (<br>
+            self,<br>
+            (GAsyncReadyCallback)callback,<br>
+            user_data);<br>
+<br>
+    return;<br>
+}<br>
+<br>
+/****************************<wbr>******************************<wbr>*******************/<br>
 /* SEND PIN (DBus call handling) */<br>
<br>
 typedef struct {<br>
diff --git a/src/mm-base-sim.h b/src/mm-base-sim.h<br>
index 1903994..22f02c8 100644<br>
--- a/src/mm-base-sim.h<br>
+++ b/src/mm-base-sim.h<br>
@@ -50,8 +50,7 @@ struct _MMBaseSim {<br>
<br>
 struct _MMBaseSimClass {<br>
     MmGdbusSimSkeletonClass parent;<br>
-<br>
-    /* Load SIM identifier (async) */<br>
+/* Load SIM identifier (async) */<br>
     void    (* load_sim_identifier)        (MMBaseSim *self,<br>
                                             GAsyncReadyCallback callback,<br>
                                             gpointer user_data);<br>
@@ -129,40 +128,47 @@ struct _MMBaseSimClass {<br>
<br>
 GType mm_base_sim_get_type (void);<br>
<br>
-void         mm_base_sim_new               (MMBaseModem *modem,<br>
-                                            GCancellable *cancellable,<br>
-                                            GAsyncReadyCallback callback,<br>
-                                            gpointer user_data);<br>
-MMBaseSim   *mm_base_sim_new_finish        (GAsyncResult  *res,<br>
-                                            GError       **error);<br>
-<br>
-void         mm_base_sim_initialize        (MMBaseSim *self,<br>
-                                            GCancellable *cancellable,<br>
-                                            GAsyncReadyCallback callback,<br>
-                                            gpointer user_data);<br>
-gboolean     mm_base_sim_initialize_finish (MMBaseSim *self,<br>
-                                            GAsyncResult *result,<br>
-                                            GError **error);<br>
-<br>
-void         mm_base_sim_send_pin          (MMBaseSim *self,<br>
-                                            const gchar *pin,<br>
-                                            GAsyncReadyCallback callback,<br>
-                                            gpointer user_data);<br>
-gboolean     mm_base_sim_send_pin_finish   (MMBaseSim *self,<br>
-                                            GAsyncResult *res,<br>
-                                            GError **error);<br>
-<br>
-void         mm_base_sim_send_puk          (MMBaseSim *self,<br>
-                                            const gchar *puk,<br>
-                                            const gchar *new_pin,<br>
-                                            GAsyncReadyCallback callback,<br>
-                                            gpointer user_data);<br>
-gboolean     mm_base_sim_send_puk_finish   (MMBaseSim *self,<br>
-                                            GAsyncResult *res,<br>
-                                            GError **error);<br>
-<br>
-void         mm_base_sim_export            (MMBaseSim *self);<br>
-<br>
-const gchar *mm_base_sim_get_path          (MMBaseSim *sim);<br>
+void         mm_base_sim_new                        (MMBaseModem *modem,<br>
+                                                     GCancellable *cancellable,<br>
+                                                     GAsyncReadyCallback callback,<br>
+                                                     gpointer user_data);<br>
+MMBaseSim   *mm_base_sim_new_finish                 (GAsyncResult  *res,<br>
+                                                     GError       **error);<br>
+<br>
+void         mm_base_sim_initialize                 (MMBaseSim *self,<br>
+                                                     GCancellable *cancellable,<br>
+                                                     GAsyncReadyCallback callback,<br>
+                                                     gpointer user_data);<br>
+gboolean     mm_base_sim_initialize_finish          (MMBaseSim *self,<br>
+                                                     GAsyncResult *result,<br>
+                                                     GError **error);<br>
+<br>
+void         mm_base_sim_send_pin                   (MMBaseSim *self,<br>
+                                                     const gchar *pin,<br>
+                                                     GAsyncReadyCallback callback,<br>
+                                                     gpointer user_data);<br>
+gboolean     mm_base_sim_send_pin_finish            (MMBaseSim *self,<br>
+                                                     GAsyncResult *res,<br>
+                                                     GError **error);<br>
+<br>
+void         mm_base_sim_send_puk                   (MMBaseSim *self,<br>
+                                                     const gchar *puk,<br>
+                                                     const gchar *new_pin,<br>
+                                                     GAsyncReadyCallback callback,<br>
+                                                     gpointer user_data);<br>
+gboolean     mm_base_sim_send_puk_finish            (MMBaseSim *self,<br>
+                                                     GAsyncResult *res,<br>
+                                                     GError **error);<br>
+<br>
+void         mm_base_sim_export                     (MMBaseSim *self);<br>
+<br>
+const gchar *mm_base_sim_get_path                   (MMBaseSim *sim);<br>
+<br>
+void          mm_base_sim_load_sim_<wbr>identifier        (MMBaseSim *self,<br>
+                                                     GAsyncReadyCallback callback,<br>
+                                                     gpointer user_data);<br>
+gchar       *mm_base_sim_load_sim_<wbr>identifier_finish (MMBaseSim *self,<br>
+                                                     GAsyncResult *res,<br>
+                                                     GError **error);<br>
<br>
 #endif /* MM_BASE_SIM_H */<br>
<span class="HOEnZb"><font color="#888888">--<br>
2.9.3<br>
<br>
</font></span></blockquote></div><br></div>