aboutsummaryrefslogtreecommitdiff
path: root/src/plugins/quectel/mm-shared-quectel.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/quectel/mm-shared-quectel.c')
-rw-r--r--src/plugins/quectel/mm-shared-quectel.c134
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,