diff options
Diffstat (limited to 'src/qmi-firmware-update')
-rw-r--r-- | src/qmi-firmware-update/Makefile.am | 9 | ||||
-rw-r--r-- | src/qmi-firmware-update/qfu-updater.c | 148 | ||||
-rw-r--r-- | src/qmi-firmware-update/qfu-utils.c | 179 | ||||
-rw-r--r-- | src/qmi-firmware-update/qfu-utils.h | 12 | ||||
-rw-r--r-- | src/qmi-firmware-update/test/Makefile.am | 4 |
5 files changed, 222 insertions, 130 deletions
diff --git a/src/qmi-firmware-update/Makefile.am b/src/qmi-firmware-update/Makefile.am index b165e2a..a9c3583 100644 --- a/src/qmi-firmware-update/Makefile.am +++ b/src/qmi-firmware-update/Makefile.am @@ -9,10 +9,15 @@ libutils_la_SOURCES = \ libutils_la_CPPFLAGS = \ $(GLIB_CFLAGS) \ + -I$(top_srcdir)/src/libqmi-glib \ + -I$(top_srcdir)/src/libqmi-glib/generated \ + -I$(top_builddir)/src/libqmi-glib \ + -I$(top_builddir)/src/libqmi-glib/generated \ $(NULL) libutils_la_LIBADD = \ - $(GLIB_CFLAGS) \ + $(top_builddir)/src/libqmi-glib/libqmi-glib.la \ + $(GLIB_LDFLAGS) \ $(NULL) bin_PROGRAMS = qmi-firmware-update @@ -73,7 +78,6 @@ qmi_firmware_update_SOURCES = \ qfu-qdl-device.h qfu-qdl-device.c \ qfu-reseter.h qfu-reseter.c \ qfu-at-device.h qfu-at-device.c \ - qfu-utils.h qfu-utils.c \ $(NULL) qmi_firmware_update_LDADD = \ @@ -81,7 +85,6 @@ qmi_firmware_update_LDADD = \ $(GUDEV_LIBS) \ $(GLIB_LIBS) \ $(builddir)/libutils.la \ - $(top_builddir)/src/libqmi-glib/libqmi-glib.la \ $(NULL) # Request to build enum types before anything else diff --git a/src/qmi-firmware-update/qfu-updater.c b/src/qmi-firmware-update/qfu-updater.c index 0cdaba4..55cd52b 100644 --- a/src/qmi-firmware-update/qfu-updater.c +++ b/src/qmi-firmware-update/qfu-updater.c @@ -60,11 +60,7 @@ struct _QfuUpdaterPrivate { /******************************************************************************/ /* Run */ -#define QMI_CLIENT_RETRIES 3 - typedef enum { - RUN_CONTEXT_STEP_QMI_DEVICE, - RUN_CONTEXT_STEP_QMI_DEVICE_OPEN, RUN_CONTEXT_STEP_QMI_CLIENT, RUN_CONTEXT_STEP_GET_FIRMWARE_PREFERENCE, RUN_CONTEXT_STEP_SET_FIRMWARE_PREFERENCE, @@ -97,7 +93,6 @@ typedef struct { /* QMI device and client */ QmiDevice *qmi_device; QmiClientDms *qmi_client; - gint qmi_client_retries; /* QDL device */ QfuQdlDevice *qdl_device; @@ -576,7 +571,7 @@ run_context_step_reset (GTask *task) } /* Boothold reset */ - reseter = qfu_reseter_new (self->priv->device_selection); + reseter = qfu_reseter_new (self->priv->device_selection, ctx->qmi_client); qfu_reseter_run (reseter, g_task_get_cancellable (task), (GAsyncReadyCallback) reseter_run_ready, @@ -973,152 +968,52 @@ run_context_step_get_firmware_preference (GTask *task) } static void -qmi_client_ready (QmiDevice *device, - GAsyncResult *res, - GTask *task) +new_client_dms_ready (gpointer unused, + GAsyncResult *res, + GTask *task) { RunContext *ctx; GError *error = NULL; ctx = (RunContext *) g_task_get_task_data (task); - ctx->qmi_client = QMI_CLIENT_DMS (qmi_device_allocate_client_finish (device, res, &error)); - if (!ctx->qmi_client) { - /* If this was the last attempt, error out */ - if (!ctx->qmi_client_retries) { - g_prefix_error (&error, "couldn't allocate DMS QMI client: "); - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Retry allocation */ - g_debug ("[qfu-updater: DMS QMI client allocation failed: %s", error->message); - g_error_free (error); - - g_debug ("[qfu-updater: retrying..."); - run_context_step_next (task, ctx->step); - return; - } - - g_debug ("[qfu-updater] DMS QMI client allocated"); - - /* Go on */ - run_context_step_next (task, ctx->step + 1); -} - -static void -run_context_step_qmi_client (GTask *task) -{ - RunContext *ctx; - - ctx = (RunContext *) g_task_get_task_data (task); - - /* Consume one retry attempt */ - ctx->qmi_client_retries--; - g_assert (ctx->qmi_client_retries >= 0); - - g_debug ("[qfu-updater] allocating new DMS QMI client..."); - qmi_device_allocate_client (ctx->qmi_device, - QMI_SERVICE_DMS, - QMI_CID_NONE, - 10, - g_task_get_cancellable (task), - (GAsyncReadyCallback) qmi_client_ready, - task); -} - -static void -qmi_device_open_ready (QmiDevice *device, - GAsyncResult *res, - GTask *task) -{ - RunContext *ctx; - GError *error = NULL; - - ctx = (RunContext *) g_task_get_task_data (task); - - if (!qmi_device_open_finish (device, res, &error)) { - g_prefix_error (&error, "couldn't open QMI device: "); - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - g_debug ("[qfu-updater] QMI device open"); - - /* Go on */ - run_context_step_next (task, ctx->step + 1); -} - -static void -run_context_step_qmi_device_open (GTask *task) -{ - QfuUpdater *self; - RunContext *ctx; - QmiDeviceOpenFlags flags = QMI_DEVICE_OPEN_FLAGS_NONE; - - ctx = (RunContext *) g_task_get_task_data (task); - self = g_task_get_source_object (task); - - if (self->priv->device_open_proxy) - flags |= QMI_DEVICE_OPEN_FLAGS_PROXY; - - if (self->priv->device_open_mbim) - flags |= QMI_DEVICE_OPEN_FLAGS_MBIM; + g_assert (!ctx->qmi_device); + g_assert (!ctx->qmi_client); - g_debug ("[qfu-updater] opening QMI device..."); - qmi_device_open (ctx->qmi_device, - flags, - 20, - g_task_get_cancellable (task), - (GAsyncReadyCallback) qmi_device_open_ready, - task); -} - -static void -qmi_device_ready (GObject *source, - GAsyncResult *res, - GTask *task) -{ - RunContext *ctx; - GError *error = NULL; - - ctx = (RunContext *) g_task_get_task_data (task); - - ctx->qmi_device = qmi_device_new_finish (res, &error); - if (!ctx->qmi_device) { - g_prefix_error (&error, "couldn't create QMI device: "); + if (!qfu_utils_new_client_dms_finish (res, + &ctx->qmi_device, + &ctx->qmi_client, + &error)) { g_task_return_error (task, error); g_object_unref (task); return; } - g_debug ("[qfu-updater] QMI device created"); - /* Go on */ run_context_step_next (task, ctx->step + 1); } static void -run_context_step_qmi_device (GTask *task) +run_context_step_qmi_client (GTask *task) { RunContext *ctx; + QfuUpdater *self; ctx = (RunContext *) g_task_get_task_data (task); + self = g_task_get_source_object (task); - g_debug ("[qfu-updater] creating QMI device..."); + g_debug ("[qfu-updater] creating QMI DMS client..."); g_assert (ctx->cdc_wdm_file); - qmi_device_new (ctx->cdc_wdm_file, - g_task_get_cancellable (task), - (GAsyncReadyCallback) qmi_device_ready, - task); + qfu_utils_new_client_dms (ctx->cdc_wdm_file, + self->priv->device_open_proxy, + self->priv->device_open_mbim, + g_task_get_cancellable (task), + (GAsyncReadyCallback) new_client_dms_ready, + task); } typedef void (* RunContextStepFunc) (GTask *task); static const RunContextStepFunc run_context_step_func[] = { - [RUN_CONTEXT_STEP_QMI_DEVICE] = run_context_step_qmi_device, - [RUN_CONTEXT_STEP_QMI_DEVICE_OPEN] = run_context_step_qmi_device_open, [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, @@ -1217,8 +1112,7 @@ qfu_updater_run (QfuUpdater *self, switch (self->priv->type) { case UPDATER_TYPE_GENERIC: - ctx->step = RUN_CONTEXT_STEP_QMI_DEVICE; - ctx->qmi_client_retries = QMI_CLIENT_RETRIES; + ctx->step = RUN_CONTEXT_STEP_QMI_CLIENT; ctx->cdc_wdm_file = qfu_device_selection_get_single_cdc_wdm (self->priv->device_selection); if (!ctx->cdc_wdm_file) { g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, diff --git a/src/qmi-firmware-update/qfu-utils.c b/src/qmi-firmware-update/qfu-utils.c index 4e0b6e3..2fe1551 100644 --- a/src/qmi-firmware-update/qfu-utils.c +++ b/src/qmi-firmware-update/qfu-utils.c @@ -213,3 +213,182 @@ out: return result; } + +/******************************************************************************/ + +#define QMI_CLIENT_RETRIES 3 + +typedef struct { + QmiDevice *qmi_device; + gboolean device_open_proxy; + gboolean device_open_mbim; + gint qmi_client_retries; + QmiClientDms *qmi_client; +} NewClientDmsContext; + +static void +new_client_dms_context_free (NewClientDmsContext *ctx) +{ + if (ctx->qmi_client) + g_object_unref (ctx->qmi_client); + if (ctx->qmi_device) + g_object_unref (ctx->qmi_device); + g_slice_free (NewClientDmsContext, ctx); +} + +gboolean +qfu_utils_new_client_dms_finish (GAsyncResult *res, + QmiDevice **qmi_device, + QmiClientDms **qmi_client, + GError **error) +{ + NewClientDmsContext *ctx; + + if (!g_task_propagate_boolean (G_TASK (res), error)) + return FALSE; + + ctx = (NewClientDmsContext *) g_task_get_task_data (G_TASK (res)); + if (qmi_device) + *qmi_device = g_object_ref (ctx->qmi_device); + if (qmi_client) + *qmi_client = g_object_ref (ctx->qmi_client); + return TRUE; +} + +static void retry_allocate_qmi_client (GTask *task); + +static void +qmi_client_ready (QmiDevice *device, + GAsyncResult *res, + GTask *task) +{ + NewClientDmsContext *ctx; + GError *error = NULL; + + ctx = (NewClientDmsContext *) g_task_get_task_data (task); + + ctx->qmi_client = QMI_CLIENT_DMS (qmi_device_allocate_client_finish (device, res, &error)); + if (!ctx->qmi_client) { + /* If this was the last attempt, error out */ + if (!ctx->qmi_client_retries) { + g_prefix_error (&error, "couldn't allocate DMS QMI client: "); + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + /* Retry allocation */ + g_debug ("[qfu,utils] DMS QMI client allocation failed: %s", error->message); + g_error_free (error); + + g_debug ("[qfu,utils] retrying..."); + retry_allocate_qmi_client (task); + return; + } + + g_debug ("[qfu,utils] DMS QMI client allocated"); + g_task_return_boolean (task, TRUE); + g_object_unref (task); +} + +static void +retry_allocate_qmi_client (GTask *task) +{ + NewClientDmsContext *ctx; + + ctx = (NewClientDmsContext *) g_task_get_task_data (task); + + /* Consume one retry attempt */ + ctx->qmi_client_retries--; + g_assert (ctx->qmi_client_retries >= 0); + + g_debug ("[qfu,utils] allocating new DMS QMI client..."); + qmi_device_allocate_client (ctx->qmi_device, + QMI_SERVICE_DMS, + QMI_CID_NONE, + 10, + g_task_get_cancellable (task), + (GAsyncReadyCallback) qmi_client_ready, + task); +} + +static void +qmi_device_open_ready (QmiDevice *device, + GAsyncResult *res, + GTask *task) +{ + GError *error = NULL; + + if (!qmi_device_open_finish (device, res, &error)) { + g_prefix_error (&error, "couldn't open QMI device: "); + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + g_debug ("[qfu,utils] QMI device open"); + retry_allocate_qmi_client (task); +} + +static void +qmi_device_ready (GObject *source, + GAsyncResult *res, + GTask *task) +{ + NewClientDmsContext *ctx; + GError *error = NULL; + QmiDeviceOpenFlags flags = QMI_DEVICE_OPEN_FLAGS_NONE; + + ctx = (NewClientDmsContext *) g_task_get_task_data (task); + + ctx->qmi_device = qmi_device_new_finish (res, &error); + if (!ctx->qmi_device) { + g_prefix_error (&error, "couldn't create QMI device: "); + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + g_debug ("[qfu,utils] QMI device created"); + + if (ctx->device_open_proxy) + flags |= QMI_DEVICE_OPEN_FLAGS_PROXY; + if (ctx->device_open_mbim) + flags |= QMI_DEVICE_OPEN_FLAGS_MBIM; + + g_debug ("[qfu,utils] opening QMI device (%s proxy, %s mode)...", + ctx->device_open_proxy ? "with" : "without", + ctx->device_open_mbim ? "mbim" : "qmi"); + qmi_device_open (ctx->qmi_device, + flags, + 20, + g_task_get_cancellable (task), + (GAsyncReadyCallback) qmi_device_open_ready, + task); +} + +void +qfu_utils_new_client_dms (GFile *cdc_wdm_file, + gboolean device_open_proxy, + gboolean device_open_mbim, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask *task; + NewClientDmsContext *ctx; + + ctx = g_slice_new0 (NewClientDmsContext); + ctx->device_open_proxy = device_open_proxy; + ctx->device_open_mbim = device_open_mbim; + ctx->qmi_client_retries = QMI_CLIENT_RETRIES; + + task = g_task_new (NULL, cancellable, callback, user_data); + g_task_set_task_data (task, ctx, (GDestroyNotify) new_client_dms_context_free); + + g_debug ("[qfu,utils] creating QMI device..."); + qmi_device_new (cdc_wdm_file, + g_task_get_cancellable (task), + (GAsyncReadyCallback) qmi_device_ready, + task); +} diff --git a/src/qmi-firmware-update/qfu-utils.h b/src/qmi-firmware-update/qfu-utils.h index 8180a83..076520e 100644 --- a/src/qmi-firmware-update/qfu-utils.h +++ b/src/qmi-firmware-update/qfu-utils.h @@ -25,6 +25,7 @@ #include <glib.h> #include <gio/gio.h> +#include <libqmi-glib.h> G_BEGIN_DECLS @@ -43,6 +44,17 @@ gboolean qfu_utils_parse_cwe_version_string (const gchar *version, gchar **carrier, GError **error); +void qfu_utils_new_client_dms (GFile *cdc_wdm_file, + gboolean device_open_proxy, + gboolean device_open_mbim, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean qfu_utils_new_client_dms_finish (GAsyncResult *res, + QmiDevice **qmi_device, + QmiClientDms **qmi_client, + GError **error); + G_END_DECLS #endif /* QFU_UTILS_H */ diff --git a/src/qmi-firmware-update/test/Makefile.am b/src/qmi-firmware-update/test/Makefile.am index 7ef33d3..36cf8ea 100644 --- a/src/qmi-firmware-update/test/Makefile.am +++ b/src/qmi-firmware-update/test/Makefile.am @@ -13,6 +13,10 @@ test_utils_SOURCES = \ test_utils_CPPFLAGS = \ $(GLIB_CFLAGS) \ -I$(top_srcdir) \ + -I$(top_srcdir)/src/libqmi-glib \ + -I$(top_srcdir)/src/libqmi-glib/generated \ + -I$(top_builddir)/src/libqmi-glib \ + -I$(top_builddir)/src/libqmi-glib/generated \ -I$(top_srcdir)/src/qmi-firmware-update \ -I$(top_builddir)/src/qmi-firmware-update \ -DLIBQMI_GLIB_COMPILATION \ |