diff options
author | Carlo Lobrano <c.lobrano@gmail.com> | 2022-02-18 11:31:44 +0100 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2022-03-29 14:18:55 +0000 |
commit | 3df96a42558aabca9d41bed0a9799b623fd83ffd (patch) | |
tree | 16021e4620eb931743d96f3cdb740577612582c1 | |
parent | afd3ce86c9c6801cd245e943c171fe2de20c9d7b (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.c | 2 | ||||
-rw-r--r-- | plugins/telit/mm-modem-helpers-telit.c | 51 | ||||
-rw-r--r-- | plugins/telit/mm-modem-helpers-telit.h | 2 | ||||
-rw-r--r-- | plugins/telit/mm-shared-telit.c | 84 | ||||
-rw-r--r-- | plugins/telit/mm-shared-telit.h | 8 | ||||
-rw-r--r-- | plugins/telit/tests/test-mm-modem-helpers-telit.c | 28 |
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 (); } |