diff options
author | mank.wang <mank.wang@quectel.com> | 2023-09-27 14:10:13 +0800 |
---|---|---|
committer | Aleksander Morgado <aleksandermj@chromium.org> | 2023-10-18 21:29:06 +0000 |
commit | 1b6e4c434998258c9342895593538946c11f6e05 (patch) | |
tree | a17a8dfddb376f1dc00625bed9c0f18acdeba6b1 /src/plugins/quectel/mm-shared-quectel.c | |
parent | 7b878765c6c8025ca7a4594af798a3d892e5bc58 (diff) |
quectel: avoid incorrect module version report after the upgrade
After LVFS upgrade, the module needs to be restarted. ModemManager
queries the module information, sometimes the module is not ready, and
the information queried by "mmcli -m any --firmware-status" is
incomplete,
It is now modified to re query once per second when obtaining
incomplete versions, up to a maximum of 16 times.
Signed-off-by: mank.wang <mank.wang@quectel.com>
Diffstat (limited to 'src/plugins/quectel/mm-shared-quectel.c')
-rw-r--r-- | src/plugins/quectel/mm-shared-quectel.c | 134 |
1 files changed, 109 insertions, 25 deletions
diff --git a/src/plugins/quectel/mm-shared-quectel.c b/src/plugins/quectel/mm-shared-quectel.c index 93153fff..c95ab200 100644 --- a/src/plugins/quectel/mm-shared-quectel.c +++ b/src/plugins/quectel/mm-shared-quectel.c @@ -59,6 +59,11 @@ typedef struct { GRegex *rdy_regex; } Private; +typedef struct { + MMFirmwareUpdateSettings *update_settings; + gint get_firmware_maximum_retry_int; +} LoadUpdateSettingsContext; + static void private_free (Private *priv) { @@ -210,22 +215,89 @@ quectel_get_firmware_update_methods (MMBaseModem *modem, return update_methods; } +static gboolean quectel_at_port_get_firmware_version_retry (GTask *task); + +/* Eg. Sometimes when the module is booted up and sends the command to acquire the version to the modem, + * the modem may not be ready. The standard app version number of the response was not obtained; + * Fwupd(LVFS) requires relatively complete version information to update firmware. If the version information is incorrect, + * the update may not be possible. Therefore, we will conduct another query, up to 16 times. + */ +#define QUECTEL_STD_AP_FIRMWARE_INVALID_MAXIMUM_RETRY 16 + +static void +quectel_at_port_get_firmware_version_retry_ready (MMBaseModem *modem, + GAsyncResult *res, + GTask *task) +{ + const gchar *version; + LoadUpdateSettingsContext *ctx; + + ctx = g_task_get_task_data (task); + version = mm_base_modem_at_command_finish (modem, res, NULL); + ctx->get_firmware_maximum_retry_int--; + + if (version) { + if (mm_quectel_check_standard_firmware_version_valid (version)) { + mm_obj_dbg (modem, "Valid firmware version:%s, re-update", version); + mm_firmware_update_settings_set_version (ctx->update_settings, version); + g_task_return_pointer (task, g_object_ref (ctx->update_settings), g_object_unref); + g_object_unref (task); + return; + } + } + /* When the maximum repeat fetch count is greater than or equal to 0, + * attempt to retrieve version information again. */ + if (ctx->get_firmware_maximum_retry_int >= 0) + g_timeout_add_seconds (1, (GSourceFunc) quectel_at_port_get_firmware_version_retry, task); + else { + mm_obj_dbg (modem, "Maximum retries to query firmware version reached: invalid firmware version received"); + g_task_return_pointer (task, g_object_ref (ctx->update_settings), g_object_unref); + g_object_unref (task); + } +} + +static gboolean +quectel_at_port_get_firmware_version_retry (GTask *task) +{ + MMBaseModem *self; + + self = g_task_get_source_object (task); + + /* Fetch full firmware info */ + mm_base_modem_at_command (self, + "+QGMR?", + 3, + FALSE, + (GAsyncReadyCallback) quectel_at_port_get_firmware_version_retry_ready, + task); + + return G_SOURCE_REMOVE; +} + static void quectel_at_port_get_firmware_version_ready (MMBaseModem *modem, GAsyncResult *res, GTask *task) { - MMFirmwareUpdateSettings *update_settings; - const gchar *version; + LoadUpdateSettingsContext *ctx; + const gchar *version; + gboolean ap_firmware_version_valid = TRUE; - update_settings = g_task_get_task_data (task); + ctx = g_task_get_task_data (task); version = mm_base_modem_at_command_finish (modem, res, NULL); if (version) - mm_firmware_update_settings_set_version (update_settings, version); + ap_firmware_version_valid = mm_quectel_check_standard_firmware_version_valid (version); - g_task_return_pointer (task, g_object_ref (update_settings), g_object_unref); - g_object_unref (task); + if (version && ap_firmware_version_valid) { + mm_firmware_update_settings_set_version (ctx->update_settings, version); + g_task_return_pointer (task, g_object_ref (ctx->update_settings), g_object_unref); + g_object_unref (task); + } else { + if (version) + mm_obj_dbg (modem, "Invalid firmware version %s return, retrying", version); + g_timeout_add_seconds (1, (GSourceFunc) quectel_at_port_get_firmware_version_retry, task); + } } #if defined WITH_MBIM @@ -237,17 +309,17 @@ quectel_mbim_port_get_firmware_version_ready (MbimDevice *device, g_autoptr(MbimMessage) response = NULL; guint32 version_id; g_autofree gchar *version_str = NULL; - MMFirmwareUpdateSettings *update_settings; + LoadUpdateSettingsContext *ctx; - update_settings = g_task_get_task_data (task); + ctx = g_task_get_task_data (task); response = mbim_device_command_finish (device, res, NULL); if (response && mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, NULL) && mbim_message_qdu_quectel_read_version_response_parse (response, &version_id, &version_str, NULL)) { - mm_firmware_update_settings_set_version (update_settings, version_str); + mm_firmware_update_settings_set_version (ctx->update_settings, version_str); } - g_task_return_pointer (task, g_object_ref (update_settings), g_object_unref); + g_task_return_pointer (task, g_object_ref (ctx->update_settings), g_object_unref); g_object_unref (task); } #endif @@ -257,16 +329,16 @@ qfastboot_test_ready (MMBaseModem *self, GAsyncResult *res, GTask *task) { - MMFirmwareUpdateSettings *update_settings; + LoadUpdateSettingsContext *ctx; - update_settings = g_task_get_task_data (task); + ctx = g_task_get_task_data (task); /* Set update method */ if (mm_base_modem_at_command_finish (self, res, NULL)) { - mm_firmware_update_settings_set_method (update_settings, MM_MODEM_FIRMWARE_UPDATE_METHOD_FASTBOOT); - mm_firmware_update_settings_set_fastboot_at (update_settings, "AT+QFASTBOOT"); + mm_firmware_update_settings_set_method (ctx->update_settings, MM_MODEM_FIRMWARE_UPDATE_METHOD_FASTBOOT); + mm_firmware_update_settings_set_fastboot_at (ctx->update_settings, "AT+QFASTBOOT"); } else - mm_firmware_update_settings_set_method (update_settings, MM_MODEM_FIRMWARE_UPDATE_METHOD_NONE); + mm_firmware_update_settings_set_method (ctx->update_settings, MM_MODEM_FIRMWARE_UPDATE_METHOD_NONE); /* Fetch full firmware info */ mm_base_modem_at_command (MM_BASE_MODEM (self), @@ -282,7 +354,7 @@ quectel_at_port_get_firmware_revision_ready (MMBaseModem *self, GAsyncResult *res, GTask *task) { - MMFirmwareUpdateSettings *update_settings; + LoadUpdateSettingsContext *ctx; MMModemFirmwareUpdateMethod update_methods; const gchar *revision; const gchar *name; @@ -290,8 +362,8 @@ quectel_at_port_get_firmware_revision_ready (MMBaseModem *self, g_autoptr(GPtrArray) ids = NULL; GError *error = NULL; - update_settings = g_task_get_task_data (task); - update_methods = mm_firmware_update_settings_get_method (update_settings); + ctx = g_task_get_task_data (task); + update_methods = mm_firmware_update_settings_get_method (ctx->update_settings); /* Set device ids */ ids = mm_iface_firmware_build_generic_device_ids (MM_IFACE_MODEM_FIRMWARE (self), &error); @@ -311,7 +383,7 @@ quectel_at_port_get_firmware_revision_ready (MMBaseModem *self, g_ptr_array_insert (ids, 0, g_strdup_printf ("%s&NAME_%s", id, name)); } - mm_firmware_update_settings_set_device_ids (update_settings, (const gchar **)ids->pdata); + mm_firmware_update_settings_set_device_ids (ctx->update_settings, (const gchar **)ids->pdata); /* Set update methods */ if (update_methods & MM_MODEM_FIRMWARE_UPDATE_METHOD_FIREHOSE) { @@ -333,6 +405,15 @@ quectel_at_port_get_firmware_revision_ready (MMBaseModem *self, } } +static void +load_update_settings_context_free (LoadUpdateSettingsContext *ctx) +{ + if (ctx->update_settings) + g_object_unref (ctx->update_settings); + + g_free (ctx); +} + void mm_shared_quectel_firmware_load_update_settings (MMIfaceModemFirmware *self, GAsyncReadyCallback callback, @@ -341,15 +422,17 @@ mm_shared_quectel_firmware_load_update_settings (MMIfaceModemFirmware *self, GTask *task; MMPortSerialAt *at_port; MMModemFirmwareUpdateMethod update_methods; - MMFirmwareUpdateSettings *update_settings; + LoadUpdateSettingsContext *ctx; task = g_task_new (self, NULL, callback, user_data); - + ctx = g_new0 (LoadUpdateSettingsContext, 1); + at_port = mm_base_modem_peek_best_at_port (MM_BASE_MODEM (self), NULL); if (at_port) { update_methods = quectel_get_firmware_update_methods (MM_BASE_MODEM (self), MM_PORT (at_port)); - update_settings = mm_firmware_update_settings_new (update_methods); - g_task_set_task_data (task, update_settings, g_object_unref); + ctx->update_settings = mm_firmware_update_settings_new (update_methods); + ctx->get_firmware_maximum_retry_int = QUECTEL_STD_AP_FIRMWARE_INVALID_MAXIMUM_RETRY; + g_task_set_task_data (task, ctx, (GDestroyNotify)load_update_settings_context_free); /* Fetch modem name */ mm_base_modem_at_command (MM_BASE_MODEM (self), @@ -373,10 +456,11 @@ mm_shared_quectel_firmware_load_update_settings (MMIfaceModemFirmware *self, g_autoptr(MbimMessage) message = NULL; update_methods = quectel_get_firmware_update_methods (MM_BASE_MODEM (self), MM_PORT (mbim)); - update_settings = mm_firmware_update_settings_new (update_methods); + ctx->update_settings = mm_firmware_update_settings_new (update_methods); + ctx->get_firmware_maximum_retry_int = QUECTEL_STD_AP_FIRMWARE_INVALID_MAXIMUM_RETRY; /* Fetch firmware info */ - g_task_set_task_data (task, update_settings, g_object_unref); + g_task_set_task_data (task, ctx, (GDestroyNotify)load_update_settings_context_free); message = mbim_message_qdu_quectel_read_version_set_new (MBIM_QDU_QUECTEL_VERSION_TYPE_FW_BUILD_ID, NULL); mbim_device_command (mm_port_mbim_peek_device (mbim), message, |