diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2017-02-10 23:10:27 +0100 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2017-02-10 23:10:27 +0100 |
commit | a80fc06d1885e1512101914ac0282d8d15bc4843 (patch) | |
tree | 31ac793b9a082797f888b70b1323d406eb61c3aa | |
parent | e5a47f6a20fd00cb1b242a3e34b9cac2d4ac4725 (diff) | |
download | external_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.c | 66 |
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); |