diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2017-01-16 14:30:16 +0100 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2017-01-16 22:16:38 +0100 |
commit | 6c1384ad4c21b5e7e2fe7e2651dfd00f13c203dd (patch) | |
tree | caa546cbf0757396d2337c334f8a6e18867c5fc3 | |
parent | 0fe1d178b3607ab614fab607b7d20aa0a0df6057 (diff) | |
download | external_libqmi-6c1384ad4c21b5e7e2fe7e2651dfd00f13c203dd.zip external_libqmi-6c1384ad4c21b5e7e2fe7e2651dfd00f13c203dd.tar.gz external_libqmi-6c1384ad4c21b5e7e2fe7e2651dfd00f13c203dd.tar.bz2 |
qmi-firmware-update: offline+reset based power cycle as helper
-rw-r--r-- | src/qmi-firmware-update/qfu-updater.c | 87 | ||||
-rw-r--r-- | src/qmi-firmware-update/qfu-utils.c | 119 | ||||
-rw-r--r-- | src/qmi-firmware-update/qfu-utils.h | 8 |
3 files changed, 151 insertions, 63 deletions
diff --git a/src/qmi-firmware-update/qfu-updater.c b/src/qmi-firmware-update/qfu-updater.c index 7ccd844..21b4559 100644 --- a/src/qmi-firmware-update/qfu-updater.c +++ b/src/qmi-firmware-update/qfu-updater.c @@ -83,8 +83,7 @@ typedef enum { RUN_CONTEXT_STEP_QMI_CLIENT, RUN_CONTEXT_STEP_GET_FIRMWARE_PREFERENCE, RUN_CONTEXT_STEP_SET_FIRMWARE_PREFERENCE, - RUN_CONTEXT_STEP_OFFLINE, - RUN_CONTEXT_STEP_RESET, + RUN_CONTEXT_STEP_POWER_CYCLE, RUN_CONTEXT_STEP_CLEANUP_QMI_DEVICE, RUN_CONTEXT_STEP_WAIT_FOR_TTY, RUN_CONTEXT_STEP_QDL_DEVICE, @@ -600,41 +599,32 @@ run_context_step_cleanup_qmi_device (GTask *task) run_context_step_next (task, ctx->step + 1); } + static void -reset_or_offline_ready (QmiClientDms *client, - GAsyncResult *res, - GTask *task) +reseter_run_ready (QfuReseter *reseter, + GAsyncResult *res, + GTask *task) { - QmiMessageDmsSetOperatingModeOutput *output; - GError *error = NULL; - RunContext *ctx; + GError *error = NULL; + RunContext *ctx; ctx = (RunContext *) g_task_get_task_data (task); - output = qmi_client_dms_set_operating_mode_finish (client, res, &error); - if (!output) { - g_prefix_error (&error, "QMI operation failed: couldn't set operating mode: "); - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - if (!qmi_message_dms_set_operating_mode_output_get_result (output, &error)) { - g_prefix_error (&error, "couldn't set operating mode: "); + if (!qfu_reseter_run_finish (reseter, res, &error)) { + g_prefix_error (&error, "boothold reseter operation failed: "); g_task_return_error (task, error); g_object_unref (task); - qmi_message_dms_set_operating_mode_output_unref (output); return; } - g_debug ("[qfu-updater] operating mode set successfully..."); + g_debug ("[qfu-updater] boothold reset requested successfully..."); /* Go on */ run_context_step_next (task, ctx->step + 1); } static void -reseter_run_ready (QfuReseter *reseter, +power_cycle_ready (QmiClientDms *qmi_client, GAsyncResult *res, GTask *task) { @@ -643,41 +633,34 @@ reseter_run_ready (QfuReseter *reseter, ctx = (RunContext *) g_task_get_task_data (task); - if (!qfu_reseter_run_finish (reseter, res, &error)) { - g_prefix_error (&error, "boothold reseter operation failed: "); + if (!qfu_utils_power_cycle_finish (qmi_client, res, &error)) { g_task_return_error (task, error); g_object_unref (task); return; } - g_debug ("[qfu-updater] boothold reset requested successfully..."); + g_debug ("[qfu-updater] reset requested successfully..."); /* Go on */ run_context_step_next (task, ctx->step + 1); } static void -run_context_step_reset (GTask *task) +run_context_step_power_cycle (GTask *task) { - QfuUpdater *self; - RunContext *ctx; - QmiMessageDmsSetOperatingModeInput *input; - QfuReseter *reseter; + RunContext *ctx; + QfuUpdater *self; + QfuReseter *reseter; ctx = (RunContext *) g_task_get_task_data (task); self = g_task_get_source_object (task); + g_debug ("[qfu-updater] power cycling..."); if (!ctx->boothold_reset) { - g_debug ("[qfu-updater] setting operating mode 'reset'..."); - input = qmi_message_dms_set_operating_mode_input_new (); - qmi_message_dms_set_operating_mode_input_set_mode (input, QMI_DMS_OPERATING_MODE_RESET, NULL); - qmi_client_dms_set_operating_mode (ctx->qmi_client, - input, - 10, - g_task_get_cancellable (task), - (GAsyncReadyCallback) reset_or_offline_ready, - task); - qmi_message_dms_set_operating_mode_input_unref (input); + qfu_utils_power_cycle (ctx->qmi_client, + g_task_get_cancellable (task), + (GAsyncReadyCallback) power_cycle_ready, + task); return; } @@ -690,27 +673,6 @@ run_context_step_reset (GTask *task) g_object_unref (reseter); } - -static void -run_context_step_offline (GTask *task) -{ - RunContext *ctx; - QmiMessageDmsSetOperatingModeInput *input; - - ctx = (RunContext *) g_task_get_task_data (task); - - g_debug ("[qfu-updater] setting operating mode 'offline'..."); - input = qmi_message_dms_set_operating_mode_input_new (); - qmi_message_dms_set_operating_mode_input_set_mode (input, QMI_DMS_OPERATING_MODE_OFFLINE, NULL); - qmi_client_dms_set_operating_mode (ctx->qmi_client, - input, - 10, - g_task_get_cancellable (task), - (GAsyncReadyCallback) reset_or_offline_ready, - task); - qmi_message_dms_set_operating_mode_input_unref (input); -} - static void set_firmware_preference_ready (QmiClientDms *client, GAsyncResult *res, @@ -1011,7 +973,7 @@ run_context_step_get_firmware_preference (GTask *task) /* Jump to the reset step and run boothold there */ ctx->boothold_reset = TRUE; - run_context_step_next (task, RUN_CONTEXT_STEP_RESET); + run_context_step_next (task, RUN_CONTEXT_STEP_POWER_CYCLE); return; } @@ -1082,8 +1044,7 @@ static const RunContextStepFunc run_context_step_func[] = { [RUN_CONTEXT_STEP_QMI_CLIENT] = run_context_step_qmi_client, [RUN_CONTEXT_STEP_GET_FIRMWARE_PREFERENCE] = run_context_step_get_firmware_preference, [RUN_CONTEXT_STEP_SET_FIRMWARE_PREFERENCE] = run_context_step_set_firmware_preference, - [RUN_CONTEXT_STEP_OFFLINE] = run_context_step_offline, - [RUN_CONTEXT_STEP_RESET] = run_context_step_reset, + [RUN_CONTEXT_STEP_POWER_CYCLE] = run_context_step_power_cycle, [RUN_CONTEXT_STEP_CLEANUP_QMI_DEVICE] = run_context_step_cleanup_qmi_device, [RUN_CONTEXT_STEP_WAIT_FOR_TTY] = run_context_step_wait_for_tty, [RUN_CONTEXT_STEP_QDL_DEVICE] = run_context_step_qdl_device, diff --git a/src/qmi-firmware-update/qfu-utils.c b/src/qmi-firmware-update/qfu-utils.c index de47ee3..14b19b7 100644 --- a/src/qmi-firmware-update/qfu-utils.c +++ b/src/qmi-firmware-update/qfu-utils.c @@ -540,3 +540,122 @@ qfu_utils_new_client_dms (GFile *cdc_wdm_file, (GAsyncReadyCallback) qmi_device_ready, task); } + +/******************************************************************************/ + +typedef enum { + POWER_CYCLE_STEP_OFFLINE, + POWER_CYCLE_STEP_RESET, + POWER_CYCLE_STEP_DONE, +} PowerCycleStep; + +typedef struct { + QmiClientDms *qmi_client; + PowerCycleStep step; +} PowerCycleContext; + +static void +power_cycle_context_free (PowerCycleContext *ctx) +{ + g_object_unref (ctx->qmi_client); + g_slice_free (PowerCycleContext, ctx); +} + +gboolean +qfu_utils_power_cycle_finish (QmiClientDms *qmi_client, + GAsyncResult *res, + GError **error) +{ + return g_task_propagate_boolean (G_TASK (res), error); +} + +static void power_cycle_step (GTask *task); + +static void +power_cycle_step_ready (QmiClientDms *qmi_client, + GAsyncResult *res, + GTask *task) +{ + QmiMessageDmsSetOperatingModeOutput *output; + GError *error = NULL; + PowerCycleContext *ctx; + + ctx = (PowerCycleContext *) g_task_get_task_data (task); + + output = qmi_client_dms_set_operating_mode_finish (qmi_client, res, &error); + if (!output) { + g_prefix_error (&error, "QMI operation failed: couldn't set operating mode: "); + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + if (!qmi_message_dms_set_operating_mode_output_get_result (output, &error)) { + g_prefix_error (&error, "couldn't set operating mode: "); + g_task_return_error (task, error); + g_object_unref (task); + qmi_message_dms_set_operating_mode_output_unref (output); + return; + } + + g_debug ("[qfu,utils] operating mode set successfully..."); + + /* Go on */ + ctx->step++; + power_cycle_step (task); +} + +static void +power_cycle_step (GTask *task) +{ + QmiMessageDmsSetOperatingModeInput *input; + QmiDmsOperatingMode mode; + PowerCycleContext *ctx; + + ctx = (PowerCycleContext *) g_task_get_task_data (task); + + switch (ctx->step) { + case POWER_CYCLE_STEP_OFFLINE: + mode = QMI_DMS_OPERATING_MODE_OFFLINE; + break; + case POWER_CYCLE_STEP_RESET: + mode = QMI_DMS_OPERATING_MODE_RESET; + break; + case POWER_CYCLE_STEP_DONE: + /* Finished! */ + g_task_return_boolean (task, TRUE); + g_object_unref (task); + return; + default: + g_assert_not_reached (); + } + + input = qmi_message_dms_set_operating_mode_input_new (); + qmi_message_dms_set_operating_mode_input_set_mode (input, mode, NULL); + qmi_client_dms_set_operating_mode (ctx->qmi_client, + input, + 10, + g_task_get_cancellable (task), + (GAsyncReadyCallback) power_cycle_step_ready, + task); + qmi_message_dms_set_operating_mode_input_unref (input); +} + +void +qfu_utils_power_cycle (QmiClientDms *qmi_client, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask *task; + PowerCycleContext *ctx; + + ctx = g_slice_new0 (PowerCycleContext); + ctx->step = POWER_CYCLE_STEP_OFFLINE; + ctx->qmi_client = g_object_ref (qmi_client); + + task = g_task_new (NULL, cancellable, callback, user_data); + g_task_set_task_data (task, ctx, (GDestroyNotify) power_cycle_context_free); + + power_cycle_step (task); +} diff --git a/src/qmi-firmware-update/qfu-utils.h b/src/qmi-firmware-update/qfu-utils.h index 95e7c2f..45dbb39 100644 --- a/src/qmi-firmware-update/qfu-utils.h +++ b/src/qmi-firmware-update/qfu-utils.h @@ -59,6 +59,14 @@ gboolean qfu_utils_new_client_dms_finish (GAsyncResult *res, gboolean *supports_firmware_preference_management, GError **error); +void qfu_utils_power_cycle (QmiClientDms *qmi_client, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean qfu_utils_power_cycle_finish (QmiClientDms *qmi_client, + GAsyncResult *res, + GError **error); + G_END_DECLS #endif /* QFU_UTILS_H */ |