<div dir="ltr"><div>This is a new revision of the patch incorporating your feedback.</div><div><br></div><div><br></div><div>Add support for querying the real-time clock to the Telit plugin.</div><div>Tested with a Telit HE910 modem.</div><div>---</div><div> .gitignore                                     |   1 +</div><div> plugins/Makefile.am                            |  15 +++</div><div> plugins/telit/mm-broadband-modem-telit.c       | 101 +++++++++++++++++++-</div><div> plugins/telit/mm-modem-helpers-telit.c         |  97 +++++++++++++++++++</div><div> plugins/telit/mm-modem-helpers-telit.h         |  29 ++++++</div><div> plugins/telit/tests/test-modem-helpers-telit.c | 126 +++++++++++++++++++++++++</div><div> 6 files changed, 368 insertions(+), 1 deletion(-)</div><div> create mode 100644 plugins/telit/mm-modem-helpers-telit.c</div><div> create mode 100644 plugins/telit/mm-modem-helpers-telit.h</div><div> create mode 100644 plugins/telit/tests/test-modem-helpers-telit.c</div><div><br></div><div>diff --git a/.gitignore b/.gitignore</div><div>index 08366fd..3c020e6 100644</div><div>--- a/.gitignore</div><div>+++ b/.gitignore</div><div>@@ -160,6 +160,7 @@ Makefile.in</div><div> /plugins/test-modem-helpers-cinterion*</div><div> /plugins/test-modem-helpers-icera*</div><div> /plugins/test-modem-helpers-mbm*</div><div>+/plugins/test-modem-helpers-telit*</div><div> /plugins/test-service-*</div><div> </div><div> /test/lsudev</div><div>diff --git a/plugins/Makefile.am b/plugins/Makefile.am</div><div>index 1e30b1a..7759e7f 100644</div><div>--- a/plugins/Makefile.am</div><div>+++ b/plugins/Makefile.am</div><div>@@ -540,12 +540,27 @@ libmm_plugin_via_la_LDFLAGS = $(PLUGIN_COMMON_LINKER_FLAGS)</div><div> libmm_plugin_telit_la_SOURCES = \</div><div> <span class="" style="white-space:pre">  </span>telit/mm-plugin-telit.c \</div><div> <span class="" style="white-space:pre">        </span>telit/mm-plugin-telit.h \</div><div>+<span class="" style="white-space:pre"> </span>telit/mm-modem-helpers-telit.c \</div><div>+<span class="" style="white-space:pre">  </span>telit/mm-modem-helpers-telit.h \</div><div> <span class="" style="white-space:pre"> </span>telit/mm-broadband-modem-telit.c \</div><div> <span class="" style="white-space:pre">       </span>telit/mm-broadband-modem-telit.h</div><div> libmm_plugin_telit_la_CPPFLAGS = $(PLUGIN_COMMON_COMPILER_FLAGS)</div><div> libmm_plugin_telit_la_LDFLAGS = $(PLUGIN_COMMON_LINKER_FLAGS)</div><div> udevrules_DATA += telit/77-mm-telit-port-types.rules</div><div> </div><div>+noinst_PROGRAMS += test-modem-helpers-telit</div><div>+test_modem_helpers_telit_SOURCES = \</div><div>+<span class="" style="white-space:pre">      </span>telit/mm-modem-helpers-telit.c \</div><div>+<span class="" style="white-space:pre">  </span>telit/mm-modem-helpers-telit.h \</div><div>+<span class="" style="white-space:pre">  </span>telit/tests/test-modem-helpers-telit.c</div><div>+test_modem_helpers_telit_CPPFLAGS = \</div><div>+<span class="" style="white-space:pre">       </span>-I$(top_srcdir)/plugins/telit \</div><div>+<span class="" style="white-space:pre">   </span>$(PLUGIN_COMMON_COMPILER_FLAGS)</div><div>+test_modem_helpers_telit_LDADD = \</div><div>+       $(top_builddir)/libmm-glib/<a href="http://libmm-glib.la">libmm-glib.la</a> \</div><div>+       $(top_builddir)/src/<a href="http://libmodem-helpers.la">libmodem-helpers.la</a></div><div>+test_modem_helpers_telit_LDFLAGS = $(PLUGIN_COMMON_LINKER_FLAGS)</div><div>+</div><div> # MTK</div><div> libmm_plugin_mtk_la_SOURCES = \</div><div> <span class="" style="white-space:pre">     </span>mtk/mm-plugin-mtk.c \</div><div>diff --git a/plugins/telit/mm-broadband-modem-telit.c b/plugins/telit/mm-broadband-modem-telit.c</div><div>index 5e1dbff..f102549 100644</div><div>--- a/plugins/telit/mm-broadband-modem-telit.c</div><div>+++ b/plugins/telit/mm-broadband-modem-telit.c</div><div>@@ -27,14 +27,18 @@</div><div> #include "mm-log.h"</div><div> #include "mm-errors-types.h"</div><div> #include "mm-modem-helpers.h"</div><div>+#include "mm-modem-helpers-telit.h"</div><div> #include "mm-base-modem-at.h"</div><div> #include "mm-iface-modem.h"</div><div>+#include "mm-iface-modem-time.h"</div><div> #include "mm-broadband-modem-telit.h"</div><div> </div><div> static void iface_modem_init (MMIfaceModem *iface);</div><div>+static void iface_modem_time_init (MMIfaceModemTime *iface);</div><div> </div><div> G_DEFINE_TYPE_EXTENDED (MMBroadbandModemTelit, mm_broadband_modem_telit, MM_TYPE_BROADBAND_MODEM, 0,</div><div>-                        G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init));</div><div>+                        G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init)</div><div>+                        G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_TIME, iface_modem_time_init));</div><div> </div><div> /*****************************************************************************/</div><div> /* Load access technologies (Modem interface) */</div><div>@@ -175,6 +179,90 @@ load_access_technologies (MMIfaceModem *self,</div><div> }</div><div> </div><div> /*****************************************************************************/</div><div>+/* Load network time (Time interface) */</div><div>+</div><div>+static gchar *</div><div>+modem_time_load_network_time_finish (MMIfaceModemTime *self,</div><div>+                                     GAsyncResult *res,</div><div>+                                     GError **error)</div><div>+{</div><div>+    const gchar *response;</div><div>+    gchar *result = NULL;</div><div>+</div><div>+    response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error);</div><div>+    if (response)</div><div>+        mm_telit_parse_cclk_response (response, &result, NULL, error);</div><div>+    return result;</div><div>+}</div><div>+</div><div>+static void</div><div>+modem_time_load_network_time (MMIfaceModemTime *self,</div><div>+                              GAsyncReadyCallback callback,</div><div>+                              gpointer user_data)</div><div>+{</div><div>+    mm_base_modem_at_command (MM_BASE_MODEM (self),</div><div>+                              "+CCLK?",</div><div>+                              3,</div><div>+                              FALSE,</div><div>+                              callback,</div><div>+                              user_data);</div><div>+}</div><div>+</div><div>+/*****************************************************************************/</div><div>+/* Load network timezone (Time interface) */</div><div>+</div><div>+static MMNetworkTimezone *</div><div>+modem_time_load_network_timezone_finish (MMIfaceModemTime *self,</div><div>+                                         GAsyncResult *res,</div><div>+                                         GError **error)</div><div>+{</div><div>+    const gchar *response;</div><div>+    MMNetworkTimezone *tz = NULL;</div><div>+</div><div>+    response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, NULL);</div><div>+    if (response)</div><div>+        mm_telit_parse_cclk_response (response, NULL, &tz, error);</div><div>+    return tz;</div><div>+}</div><div>+</div><div>+static void</div><div>+modem_time_load_network_timezone (MMIfaceModemTime *self,</div><div>+                                  GAsyncReadyCallback callback,</div><div>+                                  gpointer user_data)</div><div>+{</div><div>+    mm_base_modem_at_command (MM_BASE_MODEM (self),</div><div>+                              "+CCLK?",</div><div>+                              3,</div><div>+                              FALSE,</div><div>+                              callback,</div><div>+                              user_data);</div><div>+}</div><div>+</div><div>+/*****************************************************************************/</div><div>+/* Check support (Time interface) */</div><div>+</div><div>+static gboolean</div><div>+modem_time_check_support_finish (MMIfaceModemTime *self,</div><div>+                                 GAsyncResult *res,</div><div>+                                 GError **error)</div><div>+{</div><div>+    return !!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error);</div><div>+}</div><div>+</div><div>+static void</div><div>+modem_time_check_support (MMIfaceModemTime *self,</div><div>+                          GAsyncReadyCallback callback,</div><div>+                          gpointer user_data)</div><div>+{</div><div>+    mm_base_modem_at_command (MM_BASE_MODEM (self),</div><div>+                              "+CCLK?",</div><div>+                              3,</div><div>+                              TRUE,</div><div>+                              callback,</div><div>+                              user_data);</div><div>+}</div><div>+</div><div>+/*****************************************************************************/</div><div> </div><div> MMBroadbandModemTelit *</div><div> mm_broadband_modem_telit_new (const gchar *device,</div><div>@@ -205,6 +293,17 @@ iface_modem_init (MMIfaceModem *iface)</div><div> }</div><div> </div><div> static void</div><div>+iface_modem_time_init (MMIfaceModemTime *iface)</div><div>+{</div><div>+    iface->check_support = modem_time_check_support;</div><div>+    iface->check_support_finish = modem_time_check_support_finish;</div><div>+    iface->load_network_time = modem_time_load_network_time;</div><div>+    iface->load_network_time_finish = modem_time_load_network_time_finish;</div><div>+    iface->load_network_timezone = modem_time_load_network_timezone;</div><div>+    iface->load_network_timezone_finish = modem_time_load_network_timezone_finish;</div><div>+}</div><div>+</div><div>+static void</div><div> mm_broadband_modem_telit_class_init (MMBroadbandModemTelitClass *klass)</div><div> {</div><div> }</div><div>diff --git a/plugins/telit/mm-modem-helpers-telit.c b/plugins/telit/mm-modem-helpers-telit.c</div><div>new file mode 100644</div><div>index 0000000..19f6625</div><div>--- /dev/null</div><div>+++ b/plugins/telit/mm-modem-helpers-telit.c</div><div>@@ -0,0 +1,97 @@</div><div>+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */</div><div>+/*</div><div>+ * This program is free software; you can redistribute it and/or modify</div><div>+ * it under the terms of the GNU General Public License as published by</div><div>+ * the Free Software Foundation; either version 2 of the License, or</div><div>+ * (at your option) any later version.</div><div>+ *</div><div>+ * This program is distributed in the hope that it will be useful,</div><div>+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</div><div>+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</div><div>+ * GNU General Public License for more details:</div><div>+ *</div><div>+ * Copyright (C) 2015 Google Inc.</div><div>+ *</div><div>+ */</div><div>+</div><div>+#include <ModemManager.h></div><div>+#define _LIBMM_INSIDE_MM</div><div>+#include <libmm-glib.h></div><div>+</div><div>+#include "mm-modem-helpers.h"</div><div>+#include "mm-modem-helpers-telit.h"</div><div>+</div><div>+/*****************************************************************************/</div><div>+/* +CCLK response parser */</div><div>+</div><div>+gboolean</div><div>+mm_telit_parse_cclk_response (const char *response,</div><div>+                              gchar **iso8601p,</div><div>+                              MMNetworkTimezone **tzp,</div><div>+                              GError **error)</div><div>+{</div><div>+    GRegex *r;</div><div>+    GMatchInfo *match_info = NULL;</div><div>+    GError *match_error = NULL;</div><div>+    guint year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0;</div><div>+    gint tz = 0;</div><div>+    gboolean ret = FALSE;</div><div>+</div><div>+    g_assert (iso8601p || tzp); /* at least one */</div><div>+</div><div>+    /* Sample reply: +CCLK: "15/03/05,14:14:26-32" */</div><div>+    r = g_regex_new ("[+]CCLK: \"(\\d+)/(\\d+)/(\\d+),(\\d+):(\\d+):(\\d+)([-+]\\d+)\"", 0, 0, NULL);</div><div>+    g_assert (r != NULL);</div><div>+</div><div>+    if (!g_regex_match_full (r, response, -1, 0, 0, &match_info, &match_error)) {</div><div>+        if (match_error) {</div><div>+            g_propagate_error (error, match_error);</div><div>+            g_prefix_error (error, "Could not parse +CCLK results: ");</div><div>+        } else {</div><div>+            g_set_error_literal (error,</div><div>+                                 MM_CORE_ERROR,</div><div>+                                 MM_CORE_ERROR_FAILED,</div><div>+                                 "Couldn't match +CCLK reply");</div><div>+        }</div><div>+    } else {</div><div>+        /* Remember that g_match_info_get_match_count() includes match #0 */</div><div>+        g_assert (g_match_info_get_match_count (match_info) >= 8);</div><div>+</div><div>+        if (mm_get_uint_from_match_info (match_info, 1, &year) &&</div><div>+            mm_get_uint_from_match_info (match_info, 2, &month) &&</div><div>+            mm_get_uint_from_match_info (match_info, 3, &day) &&</div><div>+            mm_get_uint_from_match_info (match_info, 4, &hour) &&</div><div>+            mm_get_uint_from_match_info (match_info, 5, &minute) &&</div><div>+            mm_get_uint_from_match_info (match_info, 6, &second) &&</div><div>+            mm_get_int_from_match_info  (match_info, 7, &tz)) {</div><div>+            /* adjust year */</div><div>+            year += 2000;</div><div>+            /*</div><div>+             * tz = timezone offset in 15 minute intervals</div><div>+             */</div><div>+            if (iso8601p) {</div><div>+                /* Return ISO-8601 format date/time string */</div><div>+                *iso8601p = mm_new_iso8601_time (year, month, day, hour,</div><div>+                                                 minute, second,</div><div>+                                                 TRUE, (tz * 15));</div><div>+            }</div><div>+            if (tzp) {</div><div>+                *tzp = mm_network_timezone_new ();</div><div>+                mm_network_timezone_set_offset (*tzp, tz * 15);</div><div>+            }</div><div>+</div><div>+            ret = TRUE;</div><div>+        } else {</div><div>+            g_set_error_literal (error,</div><div>+                                 MM_CORE_ERROR,</div><div>+                                 MM_CORE_ERROR_FAILED,</div><div>+                                 "Failed to parse +CCLK reply");</div><div>+        }</div><div>+    }</div><div>+</div><div>+    if (match_info)</div><div>+        g_match_info_free (match_info);</div><div>+    g_regex_unref (r);</div><div>+</div><div>+    return ret;</div><div>+}</div><div>diff --git a/plugins/telit/mm-modem-helpers-telit.h b/plugins/telit/mm-modem-helpers-telit.h</div><div>new file mode 100644</div><div>index 0000000..7b45242</div><div>--- /dev/null</div><div>+++ b/plugins/telit/mm-modem-helpers-telit.h</div><div>@@ -0,0 +1,29 @@</div><div>+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */</div><div>+/*</div><div>+ * This program is free software; you can redistribute it and/or modify</div><div>+ * it under the terms of the GNU General Public License as published by</div><div>+ * the Free Software Foundation; either version 2 of the License, or</div><div>+ * (at your option) any later version.</div><div>+ *</div><div>+ * This program is distributed in the hope that it will be useful,</div><div>+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</div><div>+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</div><div>+ * GNU General Public License for more details:</div><div>+ *</div><div>+ * Copyright (C) 2015 Google Inc.</div><div>+ */</div><div>+</div><div>+#ifndef MM_MODEM_HELPERS_TELIT_H</div><div>+#define MM_MODEM_HELPERS_TELIT_H</div><div>+</div><div>+#include <libmm-glib.h></div><div>+</div><div>+/*****************************************************************************/</div><div>+/* +CCLK response parser */</div><div>+</div><div>+gboolean mm_telit_parse_cclk_response (const gchar *response,</div><div>+                                       gchar **iso8601p,</div><div>+                                       MMNetworkTimezone **tzp,</div><div>+                                       GError **error);</div><div>+</div><div>+#endif  /* MM_MODEM_HELPERS_TELIT_H */</div><div>diff --git a/plugins/telit/tests/test-modem-helpers-telit.c b/plugins/telit/tests/test-modem-helpers-telit.c</div><div>new file mode 100644</div><div>index 0000000..162a1c9</div><div>--- /dev/null</div><div>+++ b/plugins/telit/tests/test-modem-helpers-telit.c</div><div>@@ -0,0 +1,126 @@</div><div>+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */</div><div>+/*</div><div>+ * This program is free software; you can redistribute it and/or modify</div><div>+ * it under the terms of the GNU General Public License as published by</div><div>+ * the Free Software Foundation; either version 2 of the License, or</div><div>+ * (at your option) any later version.</div><div>+ *</div><div>+ * This program is distributed in the hope that it will be useful,</div><div>+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</div><div>+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</div><div>+ * GNU General Public License for more details:</div><div>+ *</div><div>+ * Copyright (C) 2015 Google Inc.</div><div>+ */</div><div>+</div><div>+#include <glib.h></div><div>+#include <glib-object.h></div><div>+#include <locale.h></div><div>+</div><div>+#include "mm-log.h"</div><div>+#include "mm-modem-helpers-telit.h"</div><div>+</div><div>+/*****************************************************************************/</div><div>+/* Test +CCLK responses */</div><div>+</div><div>+typedef struct {</div><div>+    const gchar *str;</div><div>+    gboolean ret;</div><div>+    gboolean test_iso8601;</div><div>+    gboolean test_tz;</div><div>+    gchar *iso8601;</div><div>+    gint32 offset;</div><div>+} CclkTest;</div><div>+</div><div>+static const CclkTest cclk_tests[] = {</div><div>+    { "+CCLK: \"14/08/05,04:00:21+40\"", TRUE, TRUE, FALSE,</div><div>+        "2014-08-05T04:00:21+10:00", 600 },</div><div>+    { "+CCLK: \"14/08/05,04:00:21+40\"", TRUE, FALSE, TRUE,</div><div>+        "2014-08-05T04:00:21+10:00", 600 },</div><div>+    { "+CCLK: \"14/08/05,04:00:21+40\"", TRUE, TRUE, TRUE,</div><div>+        "2014-08-05T04:00:21+10:00", 600 },</div><div>+</div><div>+    { "+CCLK: \"15/02/28,20:30:40-32\"", TRUE, TRUE, FALSE,</div><div>+        "2015-02-28T20:30:40-08:00", -480 },</div><div>+    { "+CCLK: \"15/02/28,20:30:40-32\"", TRUE, FALSE, TRUE,</div><div>+        "2015-02-28T20:30:40-08:00", -480 },</div><div>+    { "+CCLK: \"15/02/28,20:30:40-32\"", TRUE, TRUE, TRUE,</div><div>+        "2015-02-28T20:30:40-08:00", -480 },</div><div>+</div><div>+    { "+CCLK: \"XX/XX/XX,XX:XX:XX+XX\"", FALSE, TRUE, FALSE,</div><div>+        NULL, MM_NETWORK_TIMEZONE_OFFSET_UNKNOWN },</div><div>+</div><div>+    { NULL, FALSE, FALSE, FALSE, NULL, MM_NETWORK_TIMEZONE_OFFSET_UNKNOWN }</div><div>+};</div><div>+</div><div>+static void</div><div>+test_cclk (void)</div><div>+{</div><div>+    guint i;</div><div>+</div><div>+    for (i = 0; cclk_tests[i].str; i++) {</div><div>+        GError *error = NULL;</div><div>+        gchar *iso8601 = NULL;</div><div>+        MMNetworkTimezone *tz = NULL;</div><div>+        gboolean ret;</div><div>+</div><div>+        ret = mm_telit_parse_cclk_response (cclk_tests[i].str,</div><div>+                                            cclk_tests[i].test_iso8601 ? &iso8601 : NULL,</div><div>+                                            cclk_tests[i].test_tz ? &tz : NULL,</div><div>+                                            &error);</div><div>+</div><div>+        g_assert (ret == cclk_tests[i].ret);</div><div>+        g_assert (ret == (error ? FALSE : TRUE));</div><div>+</div><div>+        g_clear_error (&error);</div><div>+</div><div>+        if (cclk_tests[i].test_iso8601)</div><div>+            g_assert_cmpstr (cclk_tests[i].iso8601, ==, iso8601);</div><div>+</div><div>+        if (cclk_tests[i].test_tz) {</div><div>+            g_assert (mm_network_timezone_get_offset (tz) == cclk_tests[i].offset);</div><div>+            g_assert (mm_network_timezone_get_dst_offset (tz) == MM_NETWORK_TIMEZONE_OFFSET_UNKNOWN);</div><div>+            g_assert (mm_network_timezone_get_leap_seconds (tz) == MM_NETWORK_TIMEZONE_LEAP_SECONDS_UNKNOWN);</div><div>+        }</div><div>+</div><div>+        if (iso8601)</div><div>+            g_free (iso8601);</div><div>+</div><div>+        if (tz)</div><div>+            g_object_unref (tz);</div><div>+    }</div><div>+}</div><div>+</div><div>+/*****************************************************************************/</div><div>+</div><div>+void</div><div>+_mm_log (const char *loc,</div><div>+         const char *func,</div><div>+         guint32 level,</div><div>+         const char *fmt,</div><div>+         ...)</div><div>+{</div><div>+#if defined ENABLE_TEST_MESSAGE_TRACES</div><div>+    /* Dummy log function */</div><div>+    va_list args;</div><div>+    gchar *msg;</div><div>+</div><div>+    va_start (args, fmt);</div><div>+    msg = g_strdup_vprintf (fmt, args);</div><div>+    va_end (args);</div><div>+    g_print ("%s\n", msg);</div><div>+    g_free (msg);</div><div>+#endif</div><div>+}</div><div>+</div><div>+int main (int argc, char **argv)</div><div>+{</div><div>+    setlocale (LC_ALL, "");</div><div>+</div><div>+    g_type_init ();</div><div>+    g_test_init (&argc, &argv, NULL);</div><div>+</div><div>+    g_test_add_func ("/MM/telit/cclk", test_cclk);</div><div>+</div><div>+    return g_test_run ();</div><div>+}</div><div>-- </div><div>2.2.0.rc0.207.ga3a616c</div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Mar 11, 2015 at 11:41 AM, 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">Hey,<br>
<div><div class="h5"><br>
On Wed, Mar 11, 2015 at 6:49 PM, Jason Simmons <<a href="mailto:jsimmons@chromium.org">jsimmons@chromium.org</a>> wrote:<br>
> Add support for querying the real-time clock to the Telit plugin.<br>
> Tested with a Telit HE910 modem.<br>
> ---<br>
>  plugins/telit/mm-broadband-modem-telit.c | 174<br>
> ++++++++++++++++++++++++++++++-<br>
>  1 file changed, 173 insertions(+), 1 deletion(-)<br>
><br>
> diff --git a/plugins/telit/mm-broadband-modem-telit.c<br>
> b/plugins/telit/mm-broadband-modem-telit.c<br>
> index 5e1dbff..429a735 100644<br>
> --- a/plugins/telit/mm-broadband-modem-telit.c<br>
> +++ b/plugins/telit/mm-broadband-modem-telit.c<br>
> @@ -29,12 +29,15 @@<br>
>  #include "mm-modem-helpers.h"<br>
>  #include "mm-base-modem-at.h"<br>
>  #include "mm-iface-modem.h"<br>
> +#include "mm-iface-modem-time.h"<br>
>  #include "mm-broadband-modem-telit.h"<br>
><br>
>  static void iface_modem_init (MMIfaceModem *iface);<br>
> +static void iface_modem_time_init (MMIfaceModemTime *iface);<br>
><br>
>  G_DEFINE_TYPE_EXTENDED (MMBroadbandModemTelit, mm_broadband_modem_telit,<br>
> MM_TYPE_BROADBAND_MODEM, 0,<br>
> -                        G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM,<br>
> iface_modem_init));<br>
> +                        G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM,<br>
> iface_modem_init)<br>
> +                        G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_TIME,<br>
> iface_modem_time_init));<br>
><br>
><br>
> /*****************************************************************************/<br>
>  /* Load access technologies (Modem interface) */<br>
> @@ -175,6 +178,164 @@ load_access_technologies (MMIfaceModem *self,<br>
>  }<br>
><br>
><br>
> /*****************************************************************************/<br>
> +/* Load network time (Time interface) */<br>
> +<br>
> +static gboolean<br>
> +parse_cclk_reply (const char *response,<br>
> +                  gchar **iso8601p,<br>
> +                  MMNetworkTimezone **tzp,<br>
> +                  GError **error)<br>
<br>
</div></div>Could you put this in a mm-modem-helpers-telit.c|h set of files in the<br>
telit plugin, and add unit tests? You can check e.g. how that is done<br>
in the Huawei plugin for the ^TIME response parsers.<br>
<div><div class="h5"><br>
> +{<br>
> +    GRegex *r;<br>
> +    GMatchInfo *match_info = NULL;<br>
> +    GError *match_error = NULL;<br>
> +    guint year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0;<br>
> +    gint tz = 0;<br>
> +    gboolean ret = FALSE;<br>
> +<br>
> +    g_assert (iso8601p || tzp); /* at least one */<br>
> +<br>
> +    /* Sample reply: +CCLK: "15/03/05,14:14:26-32" */<br>
> +    r = g_regex_new ("[+]CCLK:<br>
> \"(\\d+)/(\\d+)/(\\d+),(\\d+):(\\d+):(\\d+)([-+]\\d+)\"", 0, 0, NULL);<br>
> +    g_assert (r != NULL);<br>
> +<br>
> +    if (!g_regex_match_full (r, response, -1, 0, 0, &match_info,<br>
> &match_error)) {<br>
> +        if (match_error) {<br>
> +            g_propagate_error (error, match_error);<br>
> +            g_prefix_error (error, "Could not parse +CCLK results: ");<br>
> +        } else {<br>
> +            g_set_error_literal (error,<br>
> +                                 MM_CORE_ERROR,<br>
> +                                 MM_CORE_ERROR_FAILED,<br>
> +                                 "Couldn't match +CCLK reply");<br>
> +        }<br>
> +    } else {<br>
> +        /* Remember that g_match_info_get_match_count() includes match #0<br>
> */<br>
> +        g_assert (g_match_info_get_match_count (match_info) >= 8);<br>
> +<br>
> +        if (mm_get_uint_from_match_info (match_info, 1, &year) &&<br>
> +            mm_get_uint_from_match_info (match_info, 2, &month) &&<br>
> +            mm_get_uint_from_match_info (match_info, 3, &day) &&<br>
> +            mm_get_uint_from_match_info (match_info, 4, &hour) &&<br>
> +            mm_get_uint_from_match_info (match_info, 5, &minute) &&<br>
> +            mm_get_uint_from_match_info (match_info, 6, &second) &&<br>
> +            mm_get_int_from_match_info  (match_info, 7, &tz)) {<br>
> +            /* adjust year */<br>
> +            year += 2000;<br>
> +            /*<br>
> +             * tz = timezone offset in 15 minute intervals<br>
> +             */<br>
> +            if (iso8601p) {<br>
> +                /* Return ISO-8601 format date/time string */<br>
> +                *iso8601p = mm_new_iso8601_time (year, month, day, hour,<br>
> +                                                 minute, second,<br>
> +                                                 TRUE, (tz * 15));<br>
> +            }<br>
> +            if (tzp) {<br>
> +                *tzp = mm_network_timezone_new ();<br>
> +                mm_network_timezone_set_offset (*tzp, tz * 15);<br>
> +            }<br>
> +<br>
> +            ret = TRUE;<br>
> +        } else {<br>
> +            g_set_error_literal (error,<br>
> +                                 MM_CORE_ERROR,<br>
> +                                 MM_CORE_ERROR_FAILED,<br>
> +                                 "Failed to parse +CCLK reply");<br>
> +        }<br>
> +    }<br>
> +<br>
> +    if (match_info)<br>
> +        g_match_info_free (match_info);<br>
> +    g_regex_unref (r);<br>
> +<br>
> +    return ret;<br>
> +}<br>
> +<br>
> +static gchar *<br>
> +modem_time_load_network_time_finish (MMIfaceModemTime *self,<br>
> +                                     GAsyncResult *res,<br>
> +                                     GError **error)<br>
> +{<br>
> +    const gchar *response;<br>
> +    gchar *result = NULL;<br>
> +<br>
> +    response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res,<br>
> error);<br>
> +    if (response)<br>
> +        parse_cclk_reply (response, &result, NULL, error);<br>
> +    return result;<br>
> +}<br>
> +<br>
> +static void<br>
> +modem_time_load_network_time (MMIfaceModemTime *self,<br>
> +                              GAsyncReadyCallback callback,<br>
> +                              gpointer user_data)<br>
> +{<br>
> +    mm_base_modem_at_command (MM_BASE_MODEM (self),<br>
> +                              "+CCLK?",<br>
> +                              3,<br>
> +                              FALSE,<br>
> +                              callback,<br>
> +                              user_data);<br>
> +}<br>
> +<br>
> +/*****************************************************************************/<br>
> +/* Load network timezone (Time interface) */<br>
> +<br>
> +static MMNetworkTimezone *<br>
> +modem_time_load_network_timezone_finish (MMIfaceModemTime *self,<br>
> +                                         GAsyncResult *res,<br>
> +                                         GError **error)<br>
> +{<br>
> +    const gchar *response;<br>
> +    MMNetworkTimezone *tz = NULL;<br>
> +<br>
> +    response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res,<br>
> NULL);<br>
> +    if (response)<br>
> +        parse_cclk_reply (response, NULL, &tz, error);<br>
> +    return tz;<br>
> +}<br>
> +<br>
> +static void<br>
> +modem_time_load_network_timezone (MMIfaceModemTime *self,<br>
> +                                  GAsyncReadyCallback callback,<br>
> +                                  gpointer user_data)<br>
> +{<br>
> +    mm_base_modem_at_command (MM_BASE_MODEM (self),<br>
> +                              "+CCLK?",<br>
> +                              3,<br>
> +                              FALSE,<br>
> +                              callback,<br>
> +                              user_data);<br>
> +}<br>
> +<br>
> +/*****************************************************************************/<br>
> +/* Check support (Time interface) */<br>
> +<br>
> +static gboolean<br>
> +modem_time_check_support_finish (MMIfaceModemTime *self,<br>
> +                                 GAsyncResult *res,<br>
> +                                 GError **error)<br>
> +{<br>
> +    g_debug("modem_time_check_support_finish");<br>
<br>
</div></div>That previous log message is not useful, please remove it.<br>
<span class=""><br>
> +    return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT<br>
> (res), error);<br>
<br>
</span>This is wrong. I see that it's also wrong in the novatel plugin, which<br>
does basically the same check.<br>
The correct way to finish() an at_command() operation is to call<br>
at_command_finish(). So, the proper code should be:<br>
<br>
    return !!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error);<br>
<br>
This is, return TRUE if mm_base_modem_at_command_finish() returned a<br>
valid non-error string.<br>
<br>
Fixed that for Novatel:<br>
<a href="http://cgit.freedesktop.org/ModemManager/ModemManager/commit/?id=46b2aeae531ea47d3cf3d455305c40694d4f60b7" target="_blank">http://cgit.freedesktop.org/ModemManager/ModemManager/commit/?id=46b2aeae531ea47d3cf3d455305c40694d4f60b7</a><br>
<br>
With this change, we don't assume how<br>
mm_base_modem_at_command_finish() treats the GAsyncResult.<br>
<span class=""><br>
> +}<br>
> +<br>
> +static void<br>
> +modem_time_check_support (MMIfaceModemTime *self,<br>
> +                          GAsyncReadyCallback callback,<br>
> +                          gpointer user_data)<br>
> +{<br>
> +    g_debug("modem_time_check_support");<br>
<br>
</span>That previous log message is not useful, please remove it.<br>
<div><div class="h5"><br>
> +    mm_base_modem_at_command (MM_BASE_MODEM (self),<br>
> +                              "+CCLK?",<br>
> +                              3,<br>
> +                              TRUE,<br>
> +                              callback,<br>
> +                              user_data);<br>
> +}<br>
> +<br>
> +/*****************************************************************************/<br>
><br>
>  MMBroadbandModemTelit *<br>
>  mm_broadband_modem_telit_new (const gchar *device,<br>
> @@ -205,6 +366,17 @@ iface_modem_init (MMIfaceModem *iface)<br>
>  }<br>
><br>
>  static void<br>
> +iface_modem_time_init (MMIfaceModemTime *iface)<br>
> +{<br>
> +    iface->check_support = modem_time_check_support;<br>
> +    iface->check_support_finish = modem_time_check_support_finish;<br>
> +    iface->load_network_time = modem_time_load_network_time;<br>
> +    iface->load_network_time_finish = modem_time_load_network_time_finish;<br>
> +    iface->load_network_timezone = modem_time_load_network_timezone;<br>
> +    iface->load_network_timezone_finish =<br>
> modem_time_load_network_timezone_finish;<br>
> +}<br>
> +<br>
> +static void<br>
>  mm_broadband_modem_telit_class_init (MMBroadbandModemTelitClass *klass)<br>
>  {<br>
>  }<br>
> --<br>
> 2.2.0.rc0.207.ga3a616c<br>
><br>
><br>
</div></div>> _______________________________________________<br>
> ModemManager-devel mailing list<br>
> <a href="mailto:ModemManager-devel@lists.freedesktop.org">ModemManager-devel@lists.freedesktop.org</a><br>
> <a href="http://lists.freedesktop.org/mailman/listinfo/modemmanager-devel" target="_blank">http://lists.freedesktop.org/mailman/listinfo/modemmanager-devel</a><br>
><br>
<span class="HOEnZb"><font color="#888888"><br>
<br>
<br>
--<br>
Aleksander<br>
<a href="https://aleksander.es" target="_blank">https://aleksander.es</a><br>
</font></span></blockquote></div><br></div>