<div dir="ltr"><div class="inbox-inbox-uyb8Gf"><div><div class="inbox-inbox-i3">>> +            csim_unlock_complete (self->priv->csim_lock_task);<br></div></div></div><div class="inbox-inbox-uyb8Gf"><div><div class="inbox-inbox-F3hlO">
> Reset the csim_lock_task pointer here to NULL, please.<br><br></div><div class="inbox-inbox-F3hlO">Can I do this inside csim_unlock_complete or there is a reason to do it outside this function?<br></div></div></div></div><br><div class="gmail_quote"><div dir="ltr">On Tue, 25 Jul 2017 at 14:28 Carlo Lobrano <<a href="mailto:c.lobrano@gmail.com">c.lobrano@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div>> Not sure you need to receive the GTask here from the timeout<br> > user_data, as you already have it in the private info. Instead, you<br> > could pass a reference to the MMBroadbandModemTelit object as<br> > user_data and receive "self" here.<br><br></div></div><div dir="ltr">Totally agree. I was unsure how to manage the two references and I didn't think I actually don't need it.</div><div dir="ltr"><br><br><div><br><div class="gmail_quote"><div dir="ltr">On Tue, 25 Jul 2017 at 14:10 Aleksander Morgado <<a href="mailto:aleksander@aleksander.es" target="_blank">aleksander@aleksander.es</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hey,<br>
<br>
On Mon, Jul 24, 2017 at 6:23 PM, Carlo Lobrano <<a href="mailto:c.lobrano@gmail.com" target="_blank">c.lobrano@gmail.com</a>> wrote:<br>
> With some modems, the lock/unlock of the SIM-ME interface with +CSIM=1/0<br>
> command is followed by #QSS unsolicited messages. With the current<br>
> implementation, this messages are mistaken for SIM swap events and so the<br>
> modem is first dropped and then re-probed.<br>
><br>
> With this patch, the plugin takes into account the SIM-ME lock state when<br>
> parsing #QSS unsolicited, so that the QSS handler can correctly<br>
> elaborate the messages that are not related to SIM swap events.<br>
> ---<br>
>  plugins/telit/mm-broadband-modem-telit.c | 90 ++++++++++++++++++++++++++++----<br>
>  plugins/telit/mm-modem-helpers-telit.h   |  9 ++++<br>
>  2 files changed, 90 insertions(+), 9 deletions(-)<br>
><br>
> diff --git a/plugins/telit/mm-broadband-modem-telit.c b/plugins/telit/mm-broadband-modem-telit.c<br>
> index e7650c0..3facc3e 100644<br>
> --- a/plugins/telit/mm-broadband-modem-telit.c<br>
> +++ b/plugins/telit/mm-broadband-modem-telit.c<br>
> @@ -44,6 +44,8 @@ G_DEFINE_TYPE_EXTENDED (MMBroadbandModemTelit, mm_broadband_modem_telit, MM_TYPE<br>
>                          G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init)<br>
>                          G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_3GPP, iface_modem_3gpp_init));<br>
><br>
> +#define CSIM_UNLOCK_MAX_TIMEOUT 3<br>
> +<br>
>  typedef enum {<br>
>      FEATURE_SUPPORT_UNKNOWN,<br>
>      FEATURE_NOT_SUPPORTED,<br>
> @@ -53,6 +55,9 @@ typedef enum {<br>
>  struct _MMBroadbandModemTelitPrivate {<br>
>      FeatureSupport csim_lock_support;<br>
>      MMTelitQssStatus qss_status;<br>
> +    MMTelitCsimLockState csim_lock_state;<br>
> +    GTask *csim_lock_task;<br>
> +    guint csim_lock_timeout_id;<br>
>  };<br>
><br>
>  /*****************************************************************************/<br>
> @@ -107,6 +112,7 @@ typedef struct {<br>
>  } QssSetupContext;<br>
><br>
>  static void qss_setup_step (GTask *task);<br>
> +static void csim_unlock_complete (GTask *task);<br>
><br>
>  static void<br>
>  telit_qss_unsolicited_handler (MMPortSerialAt *port,<br>
> @@ -122,14 +128,36 @@ telit_qss_unsolicited_handler (MMPortSerialAt *port,<br>
>      prev_qss_status = self->priv->qss_status;<br>
>      self->priv->qss_status = cur_qss_status;<br>
><br>
> +    if (self->priv->csim_lock_state >= CSIM_LOCK_STATE_LOCK_REQUESTED) {<br>
> +<br>
> +        if (prev_qss_status > QSS_STATUS_SIM_REMOVED && cur_qss_status == QSS_STATUS_SIM_REMOVED) {<br>
> +            mm_dbg ("QSS handler: #QSS=0 after +CSIM=1 -> CSIM locked!");<br>
> +            self->priv->csim_lock_state = CSIM_LOCK_STATE_LOCKED;<br>
> +        }<br>
> +<br>
> +        if (prev_qss_status == QSS_STATUS_SIM_REMOVED && cur_qss_status != QSS_STATUS_SIM_REMOVED) {<br>
> +            mm_dbg ("QSS handler: #QSS>=1 after +CSIM=0 -> CSIM unlocked!");<br>
> +            self->priv->csim_lock_state = CSIM_LOCK_STATE_UNLOCKED;<br>
> +<br>
> +            if (self->priv->csim_lock_timeout_id) {<br>
> +                g_source_remove (self->priv->csim_lock_timeout_id);<br>
> +                self->priv->csim_lock_timeout_id = 0;<br>
> +            }<br>
> +<br>
> +            csim_unlock_complete (self->priv->csim_lock_task);<br>
<br>
Reset the csim_lock_task pointer here to NULL, please.<br>
<br>
> +        }<br>
> +<br>
> +        return;<br>
> +    }<br>
> +<br>
>      if (cur_qss_status != prev_qss_status)<br>
> -        mm_dbg ("QSS: 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 ((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: SIM swap detected");<br>
> +        mm_info ("QSS handler: SIM swap detected");<br>
>          mm_broadband_modem_update_sim_hot_swap_detected (MM_BROADBAND_MODEM (self));<br>
>      }<br>
>  }<br>
> @@ -610,8 +638,9 @@ csim_unlock_ready (MMBaseModem  *_self,<br>
>      if (!response) {<br>
>          if (g_error_matches (error,<br>
>                               MM_MOBILE_EQUIPMENT_ERROR,<br>
> -                             MM_MOBILE_EQUIPMENT_ERROR_NOT_SUPPORTED))<br>
> +                             MM_MOBILE_EQUIPMENT_ERROR_NOT_SUPPORTED)) {<br>
>              self->priv->csim_lock_support = FEATURE_NOT_SUPPORTED;<br>
> +        }<br>
>          mm_warn ("Couldn't unlock SIM card: %s", error->message);<br>
>          g_error_free (error);<br>
>      }<br>
> @@ -703,6 +732,8 @@ csim_lock_ready (MMBaseModem  *_self,<br>
>              g_object_unref (task);<br>
>              return;<br>
>          }<br>
> +    } else {<br>
> +        self->priv->csim_lock_state = CSIM_LOCK_STATE_LOCK_REQUESTED;<br>
>      }<br>
><br>
>      if (self->priv->csim_lock_support != FEATURE_NOT_SUPPORTED) {<br>
> @@ -755,6 +786,42 @@ handle_csim_locking (GTask    *task,<br>
>  }<br>
><br>
>  static void<br>
> +csim_unlock_complete (GTask *task)<br>
> +{<br>
> +    MMBroadbandModemTelit *self;<br>
> +    LoadUnlockRetriesContext *ctx;<br>
> +<br>
> +    self = MM_BROADBAND_MODEM_TELIT (g_task_get_source_object (task));<br>
> +<br>
> +    ctx = g_task_get_task_data (task);<br>
> +    if (ctx->succeded_requests == 0) {<br>
> +        g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,<br>
> +                                 "Could not get any of the SIM unlock retries values");<br>
> +    } else {<br>
> +        g_task_return_pointer (task, g_object_ref (ctx->retries), g_object_unref);<br>
> +    }<br>
> +<br>
> +    g_object_unref (task);<br>
> +}<br>
> +<br>
> +static gboolean<br>
> +csim_unlock_periodic_check (GTask *task)<br>
> +{<br>
> +    MMBroadbandModemTelit *self;<br>
<br>
Not sure you need to receive the GTask here from the timeout<br>
user_data, as you already have it in the private info. Instead, you<br>
could pass a reference to the MMBroadbandModemTelit object as<br>
user_data and receive "self" here.<br>
<br>
> +<br>
> +    self = MM_BROADBAND_MODEM_TELIT (g_task_get_source_object (task));<br>
> +<br>
> +    if (self->priv->csim_lock_state != CSIM_LOCK_STATE_UNLOCKED) {<br>
> +        mm_warn ("CSIM is still locked after %d seconds. Trying to continue anyway", CSIM_UNLOCK_MAX_TIMEOUT);<br>
> +    }<br>
> +<br>
> +    self->priv->csim_lock_timeout_id = 0;<br>
> +    csim_unlock_complete (task);<br>
<br>
Reset the self->priv->csim_lock_task pointer here to NULL, please.<br>
<br>
> +<br>
<br>
If you passed a full reference to the modem object, you would unref it here.<br>
<br>
> +    return G_SOURCE_REMOVE;<br>
> +}<br>
> +<br>
> +static void<br>
>  load_unlock_retries_step (GTask *task)<br>
>  {<br>
>      MMBroadbandModemTelit *self;<br>
> @@ -805,12 +872,14 @@ load_unlock_retries_step (GTask *task)<br>
>              handle_csim_locking (task, FALSE);<br>
>              break;<br>
>          case LOAD_UNLOCK_RETRIES_STEP_LAST:<br>
> -            if (ctx->succeded_requests == 0)<br>
> -                g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,<br>
> -                                         "Could not get any of the SIM unlock retries values");<br>
> -            else<br>
> -                g_task_return_pointer (task, g_object_ref (ctx->retries), g_object_unref);<br>
> -            g_object_unref (task);<br>
> +            if (self->priv->csim_lock_state == CSIM_LOCK_STATE_LOCKED) {<br>
> +                mm_dbg ("CSIM is locked. Waiting for #QSS=1");<br>
> +                self->priv->csim_lock_task = task;<br>
> +                self->priv->csim_lock_timeout_id = g_timeout_add_seconds (CSIM_UNLOCK_MAX_TIMEOUT, (GSourceFunc) csim_unlock_periodic_check, task);<br>
<br>
As said above this logic is right, but given that you're storing the<br>
GTask in the private info, lets keep there the only valid reference to<br>
the GTask, otherwise the ownership of the GTask would be shared<br>
between the timeout and the private info<br>
<br>
So, instead, why not pass a full reference to the Modem object (i.e.<br>
g_object_ref (self)) as user_data in the timeout, and then unref that<br>
explicitly before returning G_SOURCE_REMOVE in<br>
csim_unlock_periodic_check(). This logic makes sure that the modem<br>
object will exist as long as the timeout exists (well, this was<br>
implicit already as we're using a GTask with a reference to the modem<br>
object...).<br>
<br>
> +            } else {<br>
> +                self->priv->csim_lock_state = CSIM_LOCK_STATE_UNLOCKED;<br>
> +                csim_unlock_complete (task);<br>
> +            }<br>
>              break;<br>
>          default:<br>
>              break;<br>
> @@ -1388,7 +1457,10 @@ mm_broadband_modem_telit_init (MMBroadbandModemTelit *self)<br>
>                                                MMBroadbandModemTelitPrivate);<br>
><br>
>      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->csim_lock_task = NULL;<br>
> +    self->priv->csim_lock_timeout_id = 0;<br>
<br>
No need to explicitly initialize the values to 0/NULL, just remove<br>
those, the private info is always initially initialized to 0. Note<br>
that for enums the approach is different, reading the code above we<br>
don't know if the UNKNOWN was 0 or -1 or what, so it makes sense to<br>
initialize the enum explicitly to a value even if that value may be 0.<br>
<br>
>  }<br>
><br>
<br>
I was going to suggest adding a pair of g_assert()s in e.g. finalize()<br>
to make sure that the timeout_id is 0 and the task pointer is NULL, as<br>
otherwise it would mean there's a logic error somewhere, but we don't<br>
have a finalize() defined, and just for this it probably doesn't make<br>
much sense, so nevermind.<br>
<br>
>  static void<br>
> diff --git a/plugins/telit/mm-modem-helpers-telit.h b/plugins/telit/mm-modem-helpers-telit.h<br>
> index 24c39e0..1cf76f0 100644<br>
> --- a/plugins/telit/mm-modem-helpers-telit.h<br>
> +++ b/plugins/telit/mm-modem-helpers-telit.h<br>
> @@ -110,4 +110,13 @@ typedef enum { /*< underscore_name=mm_telit_qss_status >*/<br>
><br>
>  MMTelitQssStatus mm_telit_parse_qss_query (const gchar *response, GError **error);<br>
><br>
> +/* CSIM lock state */<br>
> +typedef enum { /*< underscore_name=mm_telit_csim_lock_state >*/<br>
> +    CSIM_LOCK_STATE_UNKNOWN,<br>
> +    CSIM_LOCK_STATE_UNLOCKED,<br>
> +    CSIM_LOCK_STATE_LOCK_REQUESTED,<br>
> +    CSIM_LOCK_STATE_LOCKED,<br>
> +} MMTelitCsimLockState;<br>
> +<br>
> +<br>
>  #endif  /* MM_MODEM_HELPERS_TELIT_H */<br>
> --<br>
> 2.9.3<br>
><br>
> _______________________________________________<br>
> ModemManager-devel mailing list<br>
> <a href="mailto:ModemManager-devel@lists.freedesktop.org" target="_blank">ModemManager-devel@lists.freedesktop.org</a><br>
> <a href="https://lists.freedesktop.org/mailman/listinfo/modemmanager-devel" rel="noreferrer" target="_blank">https://lists.freedesktop.org/mailman/listinfo/modemmanager-devel</a><br>
<br>
<br>
<br>
--<br>
Aleksander<br>
<a href="https://aleksander.es" rel="noreferrer" target="_blank">https://aleksander.es</a><br>
</blockquote></div></div></div></blockquote></div>