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.
This commit is contained in:
committed by
Aleksander Morgado
parent
afd3ce86c9
commit
3df96a4255
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -615,6 +615,90 @@ mm_shared_telit_set_current_modes (MMIfaceModem *self,
|
||||
g_free (command);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* 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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 ();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user