<div dir="ltr"><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">Hi Aleksander,<br><br>I fixed the memory leak (GRegex) according to your code review<br><br>---<br><br>MMBroadbandModemTelit:<br> * added logic to set MMBroadbandModem's SIM_HOT_SWAP property to TRUE<br> * added function to enable QSS unsolicited<br> * added QSS unsolicited handler<br>---<br> plugins/telit/mm-broadband-modem-telit.c | 143 ++++++++++++++++++++++++++++++-<br> 1 files changed, 142 insertions(+), 1 deletions(-)<br><br>diff --git a/plugins/telit/mm-broadband-modem-telit.c b/plugins/telit/mm-broadband-modem-telit.c<br>index 8baf2cf..ca64e82 100644<br>--- a/plugins/telit/mm-broadband-modem-telit.c<br>+++ b/plugins/telit/mm-broadband-modem-telit.c<br>@@ -43,6 +43,144 @@ G_DEFINE_TYPE_EXTENDED (MMBroadbandModemTelit, mm_broadband_modem_telit, MM_TYPE<br>                         G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_3GPP, iface_modem_3gpp_init));<br> <br> /*****************************************************************************/<br>+/* Setup SIM hot swap (Modem interface) */<br>+<br>+static void<br>+telit_qss_unsolicited_handler (MMPortSerialAt *port,<br>+                               GMatchInfo *match_info,<br>+                               MMBroadbandModemTelit *self)<br>+{<br>+    guint qss;<br>+    gboolean is_sim_missing;<br>+<br>+    if (!mm_get_uint_from_match_info (match_info, 1, &qss))<br>+        return;<br>+<br>+    switch (qss) {<br>+        case 0:<br>+            mm_info ("QSS: SIM removed");<br>+            break;<br>+        case 1:<br>+            mm_info ("QSS: SIM inserted");<br>+            break;<br>+        case 2:<br>+            mm_info ("QSS: SIM inserted and PIN unlocked");<br>+            break;<br>+        case 3:<br>+            mm_info ("QSS: SIM inserted and PIN locked");<br>+            break;<br>+        default:<br>+            mm_warn ("QSS: unknown QSS value %d", qss);<br>+            break;<br>+    }<br>+<br>+    is_sim_missing = (qss == 0) ? TRUE : FALSE;<br>+    mm_broadband_modem_update_sim_hot_swap_status (MM_BROADBAND_MODEM (self), is_sim_missing);<br>+}<br>+<br>+typedef struct {<br>+    MMBroadbandModemTelit *self;<br>+    GSimpleAsyncResult *result;<br>+} ToggleQssUnsolicitedContext;<br>+<br>+static void<br>+toggle_qss_unsolicited_context_complete_and_free (ToggleQssUnsolicitedContext *ctx)<br>+{<br>+    g_simple_async_result_complete (ctx->result);<br>+    g_object_unref (ctx->result);<br>+    g_object_unref (ctx->self);<br>+    g_slice_free (ToggleQssUnsolicitedContext, ctx);<br>+}<br>+<br>+static gboolean<br>+modem_setup_sim_hot_swap_finish (MMIfaceModem *self,<br>+                                 GAsyncResult *res,<br>+                                 GError **error)<br>+{<br>+    return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error);<br>+}<br>+<br>+static void<br>+telit_qss_toggle_ready (MMBaseModem *self,<br>+                        GAsyncResult *res,<br>+                        ToggleQssUnsolicitedContext *ctx)<br>+{<br>+    GError *error = NULL;<br>+<br>+    mm_base_modem_at_command_finish (self, res, &error);<br>+    if (error) {<br>+        mm_warn ("Enable QSS failed: %s", error->message);<br>+        g_simple_async_result_set_error (ctx->result,<br>+                                         MM_CORE_ERROR,<br>+                                         MM_CORE_ERROR_FAILED,<br>+                                         "Could not enable QSS");<br>+    } else {<br>+        MMPortSerialAt *primary;<br>+        MMPortSerialAt *secondary;<br>+        GRegex *pattern;<br>+<br>+        pattern = g_regex_new ("#QSS:\\s*([0-3])\\r\\n", G_REGEX_RAW, 0, NULL);<br>+        g_assert (pattern);<br>+<br>+        primary = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (ctx->self));<br>+        mm_port_serial_at_add_unsolicited_msg_handler (<br>+            primary,<br>+            pattern,<br>+            (MMPortSerialAtUnsolicitedMsgFn)telit_qss_unsolicited_handler,<br>+            ctx->self,<br>+            NULL);<br>+<br>+        secondary = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (ctx->self));<br>+        if (secondary)<br>+            mm_port_serial_at_add_unsolicited_msg_handler (<br>+                secondary,<br>+                pattern,<br>+                (MMPortSerialAtUnsolicitedMsgFn)telit_qss_unsolicited_handler,<br>+                ctx->self,<br>+                NULL);<br>+<br>+        g_regex_unref (pattern);<br>+        g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);<br>+<br>+    }<br>+<br>+    toggle_qss_unsolicited_context_complete_and_free (ctx);<br>+}<br>+<br>+<br>+static void<br>+modem_setup_sim_hot_swap (MMIfaceModem *self,<br>+                          GAsyncReadyCallback callback,<br>+                          gpointer user_data)<br>+{<br>+    ToggleQssUnsolicitedContext *ctx;<br>+    MMPortSerialAt *port;<br>+<br>+    mm_dbg ("Telit SIM hot swap: Enable QSS");<br>+<br>+    ctx = g_slice_new0 (ToggleQssUnsolicitedContext);<br>+    ctx->self = g_object_ref (MM_BROADBAND_MODEM_TELIT (self));<br>+    ctx->result = g_simple_async_result_new (G_OBJECT (self),<br>+                                             callback,<br>+                                             user_data,<br>+                                             modem_setup_sim_hot_swap);<br>+<br>+    port = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self));<br>+    if (!port)<br>+        port = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self));<br>+<br>+    mm_base_modem_at_command_full (MM_BASE_MODEM (self),<br>+                                   port,<br>+                                   "#QSS=1",<br>+                                   3,<br>+                                   FALSE,<br>+                                   FALSE, /* raw */<br>+                                   NULL, /* cancellable */<br>+                                   (GAsyncReadyCallback) telit_qss_toggle_ready,<br>+                                   ctx);<br>+}<br>+<br>+/*****************************************************************************/<br> /* Set current bands (Modem interface) */<br> <br> static gboolean<br>@@ -214,7 +352,7 @@ load_bands_ready (MMBaseModem *self,<br>     else<br>         g_simple_async_result_set_op_res_gpointer (ctx->result, bands, (GDestroyNotify)g_array_unref);<br> <br>-    load_bands_context_complete_and_free(ctx);<br>+    load_bands_context_complete_and_free (ctx);<br> }<br> <br> static void<br>@@ -1017,6 +1155,7 @@ mm_broadband_modem_telit_new (const gchar *device,<br>                          MM_BASE_MODEM_PLUGIN, plugin,<br>                          MM_BASE_MODEM_VENDOR_ID, vendor_id,<br>                          MM_BASE_MODEM_PRODUCT_ID, product_id,<br>+                         MM_IFACE_MODEM_SIM_HOT_SWAP_SUPPORTED, TRUE,<br>                          NULL);<br> }<br> <br>@@ -1052,6 +1191,8 @@ iface_modem_init (MMIfaceModem *iface)<br>     iface->load_current_modes_finish = load_current_modes_finish;<br>     iface->set_current_modes = set_current_modes;<br>     iface->set_current_modes_finish = set_current_modes_finish;<br>+    iface->setup_sim_hot_swap = modem_setup_sim_hot_swap;<br>+    iface->setup_sim_hot_swap_finish = modem_setup_sim_hot_swap_finish;<br> }<br> <br> static void<br><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On 11 July 2016 at 14:14, 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"><div dir="ltr"><div class="gmail_extra"><span class=""><br><div class="gmail_quote">On 11 July 2016 at 14:09, Aleksander Morgado <span dir="ltr"><<a href="mailto:aleksander@aleksander.es" target="_blank">aleksander@aleksander.es</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div>You shouldn't be passing the return of g_regex_new() directly to<br>
mm_port_serial_at_add_unsolicited_msg_handler(), as that method takes<br>
its own reference of the GRegex, and therefore the regex would be<br>
leaking afterwards. You should g_regex_new() and store it in a local<br>
variable, pass that variable to<br>
mm_port_serial_at_add_unsolicited_msg_handler() and then<br>
g_regex_unref() the variable.</div></blockquote></div><br><br></span><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">​Oh, sorry, I missed that point in the first review​</div></div></div>
</blockquote></div><br></div>