<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>