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

Daniele Palmas dnlplm at gmail.com
Wed Mar 15 08:34:35 UTC 2017


Hi Aleksander,

2017-03-15 0:37 GMT+01:00 Aleksander Morgado <aleksander at aleksander.es>:
> 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?

If I'm not wrong you are using a LE866: which firmware version do you
have? I do not have direct experience with that modem, but as far as I
know there were issues with #QSS in older versions.

> E.g. even if I remove the SIM and insert it again I get no "#QSS: 0" or "#QSS: 1" indication. Any idea why?

Are you using an EVK or a custom design? I'm taking a look at the user
guides and it seems to me that SIM detection needs a gpio pin and
AT#SIMINCFG to be sent since for LE866 the default value  for the
first parameter is 0 (no gpio pin selected): please take a look at
http://www.telit.com/fileadmin/user_upload/media/products/cellular/4_G/LE866/1VV0301355_LE866_Hardware_Design_Guide_r0.pdf
page 53 and http://www.telit.com/fileadmin/user_upload/media/products/cellular/4_G/LE866/Telit_LE866_AT_Commands_Reference_Guide_r5.pdf
SIMIN pin configuration #SIMINCFG

Daniele

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