aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2017-02-10 23:10:27 +0100
committerAleksander Morgado <aleksander@aleksander.es>2017-02-10 23:10:27 +0100
commita80fc06d1885e1512101914ac0282d8d15bc4843 (patch)
tree31ac793b9a082797f888b70b1323d406eb61c3aa
parente5a47f6a20fd00cb1b242a3e34b9cac2d4ac4725 (diff)
downloadexternal_libqmi-a80fc06d1885e1512101914ac0282d8d15bc4843.zip
external_libqmi-a80fc06d1885e1512101914ac0282d8d15bc4843.tar.gz
external_libqmi-a80fc06d1885e1512101914ac0282d8d15bc4843.tar.bz2
qmi-firmware-update: explicitly async-close QmiDevice before exiting
After an update operation, before exiting, we MUST close the QmiDevice using the asynchronous method, so that we wait for the inner 'MBIM close' message (when QMI over MBIM is being used). We don't want to leave the 'MBIM close done' message unread, as that seems to interfere with the next 'MBIM open' sequence. This sequence is incorrect: qmi-firmware-update ... --> mbim close (exit without reading response) qmi-firmware-update --> mbim open (seq 1) <-- mbim close done --> mbim open (seq 2) --> mbim open (seq 3) --> mbim open (seq 4) ... (times out) This sequence is correct: qmi-firmware-update ... --> mbim close <-- mbim close done (exit) qmi-firmware-update --> mbim open (seq 1) <-- mbim open done ...
-rw-r--r--src/qmi-firmware-update/qfu-updater.c66
1 files changed, 64 insertions, 2 deletions
diff --git a/src/qmi-firmware-update/qfu-updater.c b/src/qmi-firmware-update/qfu-updater.c
index 8323f40..ead15c9 100644
--- a/src/qmi-firmware-update/qfu-updater.c
+++ b/src/qmi-firmware-update/qfu-updater.c
@@ -96,6 +96,7 @@ typedef enum {
RUN_CONTEXT_STEP_WAIT_FOR_CDC_WDM,
RUN_CONTEXT_STEP_WAIT_FOR_BOOT,
RUN_CONTEXT_STEP_QMI_CLIENT_AFTER,
+ RUN_CONTEXT_STEP_CLEANUP_QMI_DEVICE_FULL,
RUN_CONTEXT_STEP_LAST
} RunContextStep;
@@ -354,6 +355,67 @@ run_context_step_next_no_idle (GTask *task, RunContextStep next)
}
static void
+close_ready (QmiDevice *dev,
+ GAsyncResult *res,
+ GTask *task)
+{
+ RunContext *ctx;
+ GError *error = NULL;
+
+ ctx = (RunContext *) g_task_get_task_data (task);
+
+ if (!qmi_device_close_finish (dev, res, &error)) {
+ g_warning ("[qfu-updater] couldn't close device: %s", error->message);
+ g_error_free (error);
+ } else
+ g_debug ("[qfu-updater] closed");
+
+ /* Go on */
+ run_context_step_next (task, ctx->step + 1);
+}
+
+static void
+release_client_ready (QmiDevice *dev,
+ GAsyncResult *res,
+ GTask *task)
+{
+ RunContext *ctx;
+ GError *error = NULL;
+
+ ctx = (RunContext *) g_task_get_task_data (task);
+
+ if (!qmi_device_release_client_finish (dev, res, &error)) {
+ g_warning ("[qfu-updater] couldn't release client: %s", error->message);
+ g_error_free (error);
+ } else
+ g_debug ("[qfu-updater] client released");
+
+ qmi_device_close_async (ctx->qmi_device,
+ 10,
+ g_task_get_cancellable (task),
+ (GAsyncReadyCallback) close_ready,
+ task);
+ g_clear_object (&ctx->qmi_device);
+}
+
+static void
+run_context_step_cleanup_qmi_device_full (GTask *task)
+{
+ RunContext *ctx;
+
+ ctx = (RunContext *) g_task_get_task_data (task);
+
+ qmi_device_release_client (ctx->qmi_device,
+ QMI_CLIENT (ctx->qmi_client),
+ QMI_DEVICE_RELEASE_CLIENT_FLAGS_RELEASE_CID,
+ 10,
+ g_task_get_cancellable (task),
+ (GAsyncReadyCallback) release_client_ready,
+ task);
+ g_clear_object (&ctx->qmi_client);
+}
+
+static void
new_client_dms_after_ready (gpointer unused,
GAsyncResult *res,
GTask *task)
@@ -778,7 +840,6 @@ run_context_step_cleanup_qmi_device (GTask *task)
g_object_unref (tmp);
}
-
static void
reseter_run_ready (QfuReseter *reseter,
GAsyncResult *res,
@@ -1264,8 +1325,9 @@ static const RunContextStepFunc run_context_step_func[] = {
[RUN_CONTEXT_STEP_CLEANUP_IMAGE] = run_context_step_cleanup_image,
[RUN_CONTEXT_STEP_CLEANUP_QDL_DEVICE] = run_context_step_cleanup_qdl_device,
[RUN_CONTEXT_STEP_WAIT_FOR_CDC_WDM] = run_context_step_wait_for_cdc_wdm,
- [RUN_CONTEXT_STEP_QMI_CLIENT_AFTER] = run_context_step_qmi_client_after,
[RUN_CONTEXT_STEP_WAIT_FOR_BOOT] = run_context_step_wait_for_boot,
+ [RUN_CONTEXT_STEP_QMI_CLIENT_AFTER] = run_context_step_qmi_client_after,
+ [RUN_CONTEXT_STEP_CLEANUP_QMI_DEVICE_FULL] = run_context_step_cleanup_qmi_device_full,
};
G_STATIC_ASSERT (G_N_ELEMENTS (run_context_step_func) == RUN_CONTEXT_STEP_LAST);