aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlo Lobrano <c.lobrano@gmail.com>2022-02-18 11:31:44 +0100
committerAleksander Morgado <aleksander@aleksander.es>2022-03-29 14:18:55 +0000
commit3df96a42558aabca9d41bed0a9799b623fd83ffd (patch)
tree16021e4620eb931743d96f3cdb740577612582c1
parentafd3ce86c9c6801cd245e943c171fe2de20c9d7b (diff)
telit: override load revision
Currently, firmware revision string is obtained via AT+CGMR or AT+GMR commands from the default mm-broadband-modem. For a class of Telit modems however this command does not return the actual Telit Software Package version, but the "Modem FW Version", which is only a component of the whole firmware. For this class of modems, the correct string is obtained with "AT#SWPKGV" command. This change overrides load_revision* functions to add the ability to parse "AT#SWPKGV" command for the modems that support it, and falls back to the same logic that was implemented in mm-broadband-modem otherwise.
-rw-r--r--plugins/telit/mm-broadband-modem-telit.c2
-rw-r--r--plugins/telit/mm-modem-helpers-telit.c51
-rw-r--r--plugins/telit/mm-modem-helpers-telit.h2
-rw-r--r--plugins/telit/mm-shared-telit.c84
-rw-r--r--plugins/telit/mm-shared-telit.h8
-rw-r--r--plugins/telit/tests/test-mm-modem-helpers-telit.c28
6 files changed, 175 insertions, 0 deletions
diff --git a/plugins/telit/mm-broadband-modem-telit.c b/plugins/telit/mm-broadband-modem-telit.c
index 3dd9ba36..d1ac79af 100644
--- a/plugins/telit/mm-broadband-modem-telit.c
+++ b/plugins/telit/mm-broadband-modem-telit.c
@@ -1420,6 +1420,8 @@ iface_modem_init (MMIfaceModem *iface)
iface->set_current_bands_finish = mm_shared_telit_modem_set_current_bands_finish;
iface->load_current_bands = mm_shared_telit_modem_load_current_bands;
iface->load_current_bands_finish = mm_shared_telit_modem_load_current_bands_finish;
+ iface->load_revision = mm_shared_telit_modem_load_revision;
+ iface->load_revision_finish = mm_shared_telit_modem_load_revision_finish;
iface->load_supported_bands = mm_shared_telit_modem_load_supported_bands;
iface->load_supported_bands_finish = mm_shared_telit_modem_load_supported_bands_finish;
iface->load_unlock_retries_finish = modem_load_unlock_retries_finish;
diff --git a/plugins/telit/mm-modem-helpers-telit.c b/plugins/telit/mm-modem-helpers-telit.c
index d163bf1f..86d80cbf 100644
--- a/plugins/telit/mm-modem-helpers-telit.c
+++ b/plugins/telit/mm-modem-helpers-telit.c
@@ -852,3 +852,54 @@ mm_telit_build_modes_list (void)
return combinations;
}
+
+/*****************************************************************************/
+/* Software Package version response parser */
+
+gchar *
+mm_telit_parse_swpkgv_response (const gchar *response)
+{
+ gchar *version = NULL;
+ g_autofree gchar *base_version = NULL;
+ g_autofree gchar *ext_version = NULL;
+ g_autofree gchar *production_version = NULL;
+ g_autoptr(GRegex) r = NULL;
+ g_autoptr(GMatchInfo) match_info = NULL;
+ guint matches;
+
+ /* We are interested only in the first line: "Telit Software Package version"
+ * which is composed by up to three parts:
+ * - base version: "ab.cde.fgh"
+ * - extended version (e.g. alpha, beta, test version): "Axyz", "Bxyz", or "Txyz"
+ * - production parameter version (e.g. P0F.012345)
+ */
+ r = g_regex_new ("(?P<Base>\\d{2}.\\d{2}.\\d{3})(?P<Ext>-[ABT]\\d{3})?(?P<Prod>-\\w\\d\\w\\.\\d+)?",
+ G_REGEX_RAW | G_REGEX_MULTILINE | G_REGEX_NEWLINE_CRLF,
+ G_REGEX_MATCH_NEWLINE_CR,
+ NULL);
+ g_assert (r != NULL);
+
+ if (!g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, NULL)) {
+ return NULL;
+ }
+
+ matches = g_match_info_get_match_count (match_info);
+ if (matches < 2 || matches > 4) {
+ return NULL;
+ }
+
+ base_version = g_match_info_fetch_named (match_info, "Base");
+ ext_version = g_match_info_fetch_named (match_info, "Ext");
+ production_version = g_match_info_fetch_named (match_info, "Prod");
+
+ if (base_version && !ext_version && !production_version)
+ version = g_strdup (base_version);
+ else if (base_version && ext_version && !production_version)
+ version = g_strdup_printf("%s%s", base_version, ext_version);
+ else if (base_version && !ext_version && production_version)
+ version = g_strdup_printf("%s%s", base_version, production_version);
+ else if (base_version && ext_version && production_version)
+ version = g_strdup_printf("%s%s%s", base_version, ext_version, production_version);
+
+ return version;
+}
diff --git a/plugins/telit/mm-modem-helpers-telit.h b/plugins/telit/mm-modem-helpers-telit.h
index 718bb60d..4bb7fc34 100644
--- a/plugins/telit/mm-modem-helpers-telit.h
+++ b/plugins/telit/mm-modem-helpers-telit.h
@@ -65,4 +65,6 @@ typedef enum { /*< underscore_name=mm_telit_csim_lock_state >*/
GArray *mm_telit_build_modes_list (void);
+gchar *mm_telit_parse_swpkgv_response (const gchar *response);
+
#endif /* MM_MODEM_HELPERS_TELIT_H */
diff --git a/plugins/telit/mm-shared-telit.c b/plugins/telit/mm-shared-telit.c
index 7f45a639..9654b67e 100644
--- a/plugins/telit/mm-shared-telit.c
+++ b/plugins/telit/mm-shared-telit.c
@@ -616,6 +616,90 @@ mm_shared_telit_set_current_modes (MMIfaceModem *self,
}
/*****************************************************************************/
+/* Revision loading */
+
+gchar *
+mm_shared_telit_modem_load_revision_finish (MMIfaceModem *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ GVariant *result;
+ gchar *revision = NULL;
+
+ result = mm_base_modem_at_sequence_finish (MM_BASE_MODEM (self), res, NULL, error);
+ if (result) {
+ revision = g_variant_dup_string (result, NULL);
+ }
+ return revision;
+}
+
+/*
+ * parse AT#SWPKGV command
+ * Execution command returns the software package version without #SWPKGV: command echo.
+ * The response is as follows:
+ *
+ * AT#SWPKGV
+ * <Telit Software Package Version>-<Production Parameters Version>
+ * <Modem FW Version> (Usually the same value returned by AT+GMR)
+ * <Production Parameters Version>
+ * <Application FW Version>
+ */
+static MMBaseModemAtResponseProcessorResult
+software_package_version_ready (MMBaseModem *self,
+ gpointer none,
+ const gchar *command,
+ const gchar *response,
+ gboolean last_command,
+ const GError *error,
+ GVariant **result,
+ GError **result_error)
+{
+ gchar *version = NULL;
+
+ if (error) {
+ *result = NULL;
+
+ /* Ignore AT errors (ie, ERROR or CMx ERROR) */
+ if (error->domain != MM_MOBILE_EQUIPMENT_ERROR || last_command) {
+ *result_error = g_error_copy (error);
+ return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_FAILURE;
+ }
+
+ *result_error = NULL;
+ return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_CONTINUE;
+ }
+
+ version = mm_telit_parse_swpkgv_response (response);
+ if (!version)
+ return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_CONTINUE;
+
+ *result = g_variant_new_take_string (version);
+ return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_SUCCESS;
+}
+
+static const MMBaseModemAtCommand revisions[] = {
+ { "#SWPKGV", 3, TRUE, software_package_version_ready },
+ { "+CGMR", 3, TRUE, mm_base_modem_response_processor_string_ignore_at_errors },
+ { "+GMR", 3, TRUE, mm_base_modem_response_processor_string_ignore_at_errors },
+ { NULL }
+};
+
+void
+mm_shared_telit_modem_load_revision (MMIfaceModem *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ mm_obj_dbg (self, "loading revision...");
+ mm_base_modem_at_sequence (
+ MM_BASE_MODEM (self),
+ revisions,
+ NULL, /* response_processor_context */
+ NULL, /* response_processor_context_free */
+ callback,
+ user_data);
+}
+
+/*****************************************************************************/
static void
shared_telit_init (gpointer g_iface)
diff --git a/plugins/telit/mm-shared-telit.h b/plugins/telit/mm-shared-telit.h
index 9981dd9b..56f55de0 100644
--- a/plugins/telit/mm-shared-telit.h
+++ b/plugins/telit/mm-shared-telit.h
@@ -90,4 +90,12 @@ void mm_shared_telit_modem_set_current_bands (MMIfaceModem *self,
GAsyncReadyCallback callback,
gpointer user_data);
+void mm_shared_telit_modem_load_revision (MMIfaceModem *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gchar * mm_shared_telit_modem_load_revision_finish (MMIfaceModem *self,
+ GAsyncResult *res,
+ GError **error);
+
#endif /* MM_SHARED_TELIT_H */
diff --git a/plugins/telit/tests/test-mm-modem-helpers-telit.c b/plugins/telit/tests/test-mm-modem-helpers-telit.c
index e957f7d6..ace6fcb3 100644
--- a/plugins/telit/tests/test-mm-modem-helpers-telit.c
+++ b/plugins/telit/tests/test-mm-modem-helpers-telit.c
@@ -611,6 +611,33 @@ test_telit_parse_qss_query (void)
}
}
+static void
+test_telit_parse_swpkgv_response (void)
+{
+ static struct {
+ const gchar *response;
+ const gchar *expected;
+ } tt [] = {
+ {"\n\r12.34.567\n\rM0F.223004-B001\n\rP0F.224700\n\rA0F.223004-B001\n\r\n\rOK\n\r", "12.34.567"},
+ {"\n\r13.35.568-A123\n\rM0F.223004-B001\n\rP0F.224700\n\rA0F.223004-B001\n\r\n\rOK\n\r", "13.35.568-A123"},
+ {"\n\r14.36.569-B124\n\rM0F.223004-B001\n\rP0F.224700\n\rA0F.223004-B001\n\r\n\rOK\n\r", "14.36.569-B124"},
+ {"\n\r15.37.570-T125\n\rM0F.223004-B001\n\rP0F.224700\n\rA0F.223004-B001\n\r\n\rOK\n\r", "15.37.570-T125"},
+ {"\n\r16.38.571-P0F.224700\n\rM0F.223004-B001\n\rP0F.224700\n\rA0F.223004-B001\n\r\n\rOK\n\r", "16.38.571-P0F.224700"},
+ /* real example from LE910C1-EUX */
+ {"\n\r25.30.224-B001-P0F.224700\n\rM0F.223004-B001\n\rP0F.224700\n\rA0F.223004-B001\n\r\n\rOK\n\r", "25.30.224-B001-P0F.224700"},
+ };
+ guint i;
+
+ for (i = 0; i < G_N_ELEMENTS (tt); i++) {
+ gchar *actual = NULL;
+
+ actual = mm_telit_parse_swpkgv_response(tt[i].response);
+
+ g_assert_cmpstr (tt[i].expected, ==, actual);
+ g_free (actual);
+ }
+}
+
/******************************************************************************/
int main (int argc, char **argv)
@@ -625,5 +652,6 @@ int main (int argc, char **argv)
g_test_add_func ("/MM/telit/bands/current/set_bands/3g", test_telit_get_3g_bnd_flag);
g_test_add_func ("/MM/telit/bands/current/set_bands/4g", test_telit_get_4g_bnd_flag);
g_test_add_func ("/MM/telit/qss/query", test_telit_parse_qss_query);
+ g_test_add_func ("/MM/telit/swpkv/parse_response", test_telit_parse_swpkgv_response);
return g_test_run ();
}