summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2017-01-13 22:57:04 +0100
committerAleksander Morgado <aleksander@aleksander.es>2017-01-16 11:24:16 +0100
commit3bc72338fa30f83d1618eb47d8d69821c81a1948 (patch)
tree9ad63265b68bb23865c8c215ff90e7c97ea3c14b
parent4c37ab59f05cbff952b085d6b187b366dc3772eb (diff)
downloadlibqmi-3bc72338fa30f83d1618eb47d8d69821c81a1948.tar.gz
qmi-firmware-update: load capabilities of the modem early
Only for the update operation, though.
-rw-r--r--src/qmi-firmware-update/qfu-reseter.c2
-rw-r--r--src/qmi-firmware-update/qfu-updater.c102
-rw-r--r--src/qmi-firmware-update/qfu-utils.c154
-rw-r--r--src/qmi-firmware-update/qfu-utils.h4
4 files changed, 201 insertions, 61 deletions
diff --git a/src/qmi-firmware-update/qfu-reseter.c b/src/qmi-firmware-update/qfu-reseter.c
index 17f7913e..fedd85ee 100644
--- a/src/qmi-firmware-update/qfu-reseter.c
+++ b/src/qmi-firmware-update/qfu-reseter.c
@@ -248,6 +248,7 @@ new_client_dms_ready (gpointer unused,
if (!qfu_utils_new_client_dms_finish (res,
&ctx->qmi_device,
&ctx->qmi_client,
+ NULL, NULL, NULL,
&error)) {
/* Jump to AT-based boothold */
g_debug ("[qfu-reseter] error: couldn't allocate QMI client: %s", error->message);
@@ -304,6 +305,7 @@ qfu_reseter_run (QfuReseter *self,
qfu_utils_new_client_dms (ctx->cdc_wdm,
self->priv->device_open_proxy,
self->priv->device_open_mbim,
+ FALSE,
cancellable,
(GAsyncReadyCallback) new_client_dms_ready,
task);
diff --git a/src/qmi-firmware-update/qfu-updater.c b/src/qmi-firmware-update/qfu-updater.c
index c7a34ae7..ea4c13f9 100644
--- a/src/qmi-firmware-update/qfu-updater.c
+++ b/src/qmi-firmware-update/qfu-updater.c
@@ -85,6 +85,11 @@ typedef struct {
/* Context step */
RunContextStep step;
+ /* Before/after info and capabilities */
+ gchar *revision;
+ gboolean supports_stored_image_management;
+ gboolean supports_firmware_preference_management;
+
/* List of pending QfuImages to download, and the current one being
* processed. */
GList *pending_images;
@@ -109,6 +114,7 @@ typedef struct {
static void
run_context_free (RunContext *ctx)
{
+ g_free (ctx->revision);
g_free (ctx->firmware_version);
g_free (ctx->config_version);
g_free (ctx->carrier);
@@ -617,7 +623,7 @@ set_firmware_preference_ready (QmiClientDms *client,
/* list images we need to download? */
if (qmi_message_dms_set_firmware_preference_output_get_image_download_list (output, &array, &error)) {
if (!array->len) {
- g_print ("device already reports the given firmware/config version: nothing to do\n");
+ g_print ("device already contains the given firmware/config version: nothing to do\n");
g_list_free_full (ctx->pending_images, (GDestroyNotify) g_object_unref);
ctx->pending_images = NULL;
next_step = RUN_CONTEXT_STEP_CLEANUP_QMI_DEVICE;
@@ -862,30 +868,16 @@ validate_firmware_config_carrier (QfuUpdater *self,
}
static void
-get_firmware_preference_ready (QmiClientDms *client,
- GAsyncResult *res,
- GTask *task)
+run_context_step_get_firmware_preference (GTask *task)
{
- QfuUpdater *self;
- RunContext *ctx;
- GError *error = NULL;
- QmiMessageDmsGetFirmwarePreferenceOutput *output;
- GArray *array;
- guint i;
+ RunContext *ctx;
+ QfuUpdater *self;
+ GError *error = NULL;
ctx = (RunContext *) g_task_get_task_data (task);
self = g_task_get_source_object (task);
- output = qmi_client_dms_get_firmware_preference_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_get_firmware_preference_output_get_result (output, NULL)) {
- qmi_message_dms_get_firmware_preference_output_unref (output);
+ if (!ctx->supports_firmware_preference_management) {
/* Firmware preference setting not supported; fail if we got those settings explicitly */
if (self->priv->firmware_version || self->priv->config_version || self->priv->carrier) {
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED,
@@ -900,28 +892,6 @@ get_firmware_preference_ready (QmiClientDms *client,
return;
}
- qmi_message_dms_get_firmware_preference_output_get_list (output, &array, NULL);
-
- if (array->len > 0) {
- for (i = 0; i < array->len; i++) {
- QmiMessageDmsGetFirmwarePreferenceOutputListImage *image;
- gchar *unique_id_str;
-
- image = &g_array_index (array, QmiMessageDmsGetFirmwarePreferenceOutputListImage, i);
- unique_id_str = qfu_utils_get_firmware_image_unique_id_printable (image->unique_id);
-
- g_debug ("[qfu-updater] [image %u]", i);
- g_debug ("[qfu-updater] \tImage type: '%s'", qmi_dms_firmware_image_type_get_string (image->type));
- g_debug ("[qfu-updater] \tUnique ID: '%s'", unique_id_str);
- g_debug ("[qfu-updater] \tBuild ID: '%s'", image->build_id);
-
- g_free (unique_id_str);
- }
- } else
- g_debug ("[qfu-updater] no images specified");
-
- qmi_message_dms_get_firmware_preference_output_unref (output);
-
/* Firmware preference setting is supported so we require firmware/config/carrier */
if (!validate_firmware_config_carrier (self, ctx, &error)) {
g_task_return_error (task, error);
@@ -934,22 +904,6 @@ get_firmware_preference_ready (QmiClientDms *client,
}
static void
-run_context_step_get_firmware_preference (GTask *task)
-{
- RunContext *ctx;
-
- ctx = (RunContext *) g_task_get_task_data (task);
-
- g_debug ("[qfu-updater] getting firmware preference...");
- qmi_client_dms_get_firmware_preference (ctx->qmi_client,
- NULL,
- 10,
- g_task_get_cancellable (task),
- (GAsyncReadyCallback) get_firmware_preference_ready,
- task);
-}
-
-static void
new_client_dms_ready (gpointer unused,
GAsyncResult *res,
GTask *task)
@@ -965,6 +919,9 @@ new_client_dms_ready (gpointer unused,
if (!qfu_utils_new_client_dms_finish (res,
&ctx->qmi_device,
&ctx->qmi_client,
+ &ctx->revision,
+ &ctx->supports_stored_image_management,
+ &ctx->supports_firmware_preference_management,
&error)) {
g_task_return_error (task, error);
g_object_unref (task);
@@ -989,6 +946,7 @@ run_context_step_qmi_client (GTask *task)
qfu_utils_new_client_dms (ctx->cdc_wdm_file,
self->priv->device_open_proxy,
self->priv->device_open_mbim,
+ TRUE,
g_task_get_cancellable (task),
(GAsyncReadyCallback) new_client_dms_ready,
task);
@@ -1032,6 +990,34 @@ run_context_step (GTask *task)
}
g_debug ("[qfu-updater] operation finished");
+
+ /* Dump output report */
+ g_print ("\n"
+ "--------------------------------------------------\n");
+
+ g_print ("\n"
+ " original revision was:\n"
+ " %s\n", ctx->revision);
+
+ if (ctx->supports_stored_image_management)
+ g_print ("\n"
+ " NOTE: this device supports stored image management\n"
+ " with qmicli operations:\n"
+ " --dms-list-stored-images\n"
+ " --dms-select-stored-image\n"
+ " --dms-delete-stored-image\n");
+
+ if (ctx->supports_firmware_preference_management)
+ g_print ("\n"
+ " NOTE: this device supports firmware preference management\n"
+ " with qmicli operations:\n"
+ " --dms-get-firmware-preference\n"
+ " --dms-set-firmware-preference\n");
+
+ g_print ("\n"
+ "--------------------------------------------------\n"
+ "\n");
+
g_task_return_boolean (task, TRUE);
g_object_unref (task);
}
diff --git a/src/qmi-firmware-update/qfu-utils.c b/src/qmi-firmware-update/qfu-utils.c
index 2fe15514..de47ee35 100644
--- a/src/qmi-firmware-update/qfu-utils.c
+++ b/src/qmi-firmware-update/qfu-utils.c
@@ -224,6 +224,14 @@ typedef struct {
gboolean device_open_mbim;
gint qmi_client_retries;
QmiClientDms *qmi_client;
+
+ gboolean load_capabilities;
+ gchar *revision;
+ gboolean revision_done;
+ gboolean supports_stored_image_management;
+ gboolean supports_stored_image_management_done;
+ gboolean supports_firmware_preference_management;
+ gboolean supports_firmware_preference_management_done;
} NewClientDmsContext;
static void
@@ -233,6 +241,7 @@ new_client_dms_context_free (NewClientDmsContext *ctx)
g_object_unref (ctx->qmi_client);
if (ctx->qmi_device)
g_object_unref (ctx->qmi_device);
+ g_free (ctx->revision);
g_slice_free (NewClientDmsContext, ctx);
}
@@ -240,6 +249,9 @@ gboolean
qfu_utils_new_client_dms_finish (GAsyncResult *res,
QmiDevice **qmi_device,
QmiClientDms **qmi_client,
+ gchar **revision,
+ gboolean *supports_stored_image_management,
+ gboolean *supports_firmware_preference_management,
GError **error)
{
NewClientDmsContext *ctx;
@@ -247,14 +259,132 @@ qfu_utils_new_client_dms_finish (GAsyncResult *res,
if (!g_task_propagate_boolean (G_TASK (res), error))
return FALSE;
- ctx = (NewClientDmsContext *) g_task_get_task_data (G_TASK (res));
+ ctx = 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);
+ if (revision)
+ *revision = (ctx->revision ? g_strdup (ctx->revision) : NULL);
+ if (supports_stored_image_management)
+ *supports_stored_image_management = ctx->supports_stored_image_management;
+ if (supports_firmware_preference_management)
+ *supports_firmware_preference_management = ctx->supports_firmware_preference_management;
return TRUE;
}
+static void
+check_capabilities_done (GTask *task)
+{
+ NewClientDmsContext *ctx;
+
+ ctx = g_task_get_task_data (task);
+
+ if (!ctx->revision_done ||
+ !ctx->supports_stored_image_management_done ||
+ !ctx->supports_firmware_preference_management_done)
+ return;
+
+ /* All done! */
+ g_task_return_boolean (task, TRUE);
+ g_object_unref (task);
+}
+
+static void
+dms_get_revision_ready (QmiClientDms *client,
+ GAsyncResult *res,
+ GTask *task)
+{
+ QmiMessageDmsGetRevisionOutput *output;
+ const gchar *str = NULL;
+ NewClientDmsContext *ctx;
+
+ ctx = g_task_get_task_data (task);
+
+ output = qmi_client_dms_get_revision_finish (client, res, NULL);
+ if (output && qmi_message_dms_get_revision_output_get_result (output, NULL))
+ qmi_message_dms_get_revision_output_get_revision (output, &str, NULL);
+
+ if (str) {
+ g_debug ("[qfu,utils] current revision loaded: %s", str);
+ ctx->revision = g_strdup (str);
+ }
+
+ if (output)
+ qmi_message_dms_get_revision_output_unref (output);
+
+ ctx->revision_done = TRUE;
+ check_capabilities_done (task);
+}
+
+static void
+dms_list_stored_images_ready (QmiClientDms *client,
+ GAsyncResult *res,
+ GTask *task)
+{
+ QmiMessageDmsListStoredImagesOutput *output;
+ NewClientDmsContext *ctx;
+
+ ctx = g_task_get_task_data (task);
+
+ output = qmi_client_dms_list_stored_images_finish (client, res, NULL);
+ ctx->supports_stored_image_management = (output && qmi_message_dms_list_stored_images_output_get_result (output, NULL));
+
+ if (output)
+ qmi_message_dms_list_stored_images_output_unref (output);
+
+ ctx->supports_stored_image_management_done = TRUE;
+ check_capabilities_done (task);
+}
+
+static void
+dms_get_firmware_preference_ready (QmiClientDms *client,
+ GAsyncResult *res,
+ GTask *task)
+{
+ QmiMessageDmsGetFirmwarePreferenceOutput *output;
+ NewClientDmsContext *ctx;
+
+ ctx = g_task_get_task_data (task);
+
+ output = qmi_client_dms_get_firmware_preference_finish (client, res, NULL);
+ ctx->supports_firmware_preference_management = (output && qmi_message_dms_get_firmware_preference_output_get_result (output, NULL));
+
+ /* Log the current firmware preference */
+ if (ctx->supports_firmware_preference_management) {
+ GArray *array;
+ guint i;
+
+ g_debug ("[qfu,utils] current firmware preference loaded:");
+
+ qmi_message_dms_get_firmware_preference_output_get_list (output, &array, NULL);
+
+ if (array->len > 0) {
+ for (i = 0; i < array->len; i++) {
+ QmiMessageDmsGetFirmwarePreferenceOutputListImage *image;
+ gchar *unique_id_str;
+
+ image = &g_array_index (array, QmiMessageDmsGetFirmwarePreferenceOutputListImage, i);
+ unique_id_str = qfu_utils_get_firmware_image_unique_id_printable (image->unique_id);
+
+ g_debug ("[qfu,utils] [image %u]", i);
+ g_debug ("[qfu,utils] \tImage type: '%s'", qmi_dms_firmware_image_type_get_string (image->type));
+ g_debug ("[qfu,utils] \tUnique ID: '%s'", unique_id_str);
+ g_debug ("[qfu,utils] \tBuild ID: '%s'", image->build_id);
+
+ g_free (unique_id_str);
+ }
+ } else
+ g_debug ("[qfu,utils] no images specified");
+ }
+
+ if (output)
+ qmi_message_dms_get_firmware_preference_output_unref (output);
+
+ ctx->supports_firmware_preference_management_done = TRUE;
+ check_capabilities_done (task);
+}
+
static void retry_allocate_qmi_client (GTask *task);
static void
@@ -287,8 +417,24 @@ qmi_client_ready (QmiDevice *device,
}
g_debug ("[qfu,utils] DMS QMI client allocated");
- g_task_return_boolean (task, TRUE);
- g_object_unref (task);
+
+ /* If loading capabilities not required, we're done */
+ if (!ctx->load_capabilities) {
+ g_task_return_boolean (task, TRUE);
+ g_object_unref (task);
+ return;
+ }
+
+ /* Query capabilities */
+ qmi_client_dms_get_revision (ctx->qmi_client,
+ NULL, 10, g_task_get_cancellable (task),
+ (GAsyncReadyCallback) dms_get_revision_ready, task);
+ qmi_client_dms_list_stored_images (ctx->qmi_client,
+ NULL, 10, g_task_get_cancellable (task),
+ (GAsyncReadyCallback) dms_list_stored_images_ready, task);
+ qmi_client_dms_get_firmware_preference (ctx->qmi_client,
+ NULL, 10, g_task_get_cancellable (task),
+ (GAsyncReadyCallback) dms_get_firmware_preference_ready, task);
}
static void
@@ -371,6 +517,7 @@ void
qfu_utils_new_client_dms (GFile *cdc_wdm_file,
gboolean device_open_proxy,
gboolean device_open_mbim,
+ gboolean load_capabilities,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
@@ -381,6 +528,7 @@ qfu_utils_new_client_dms (GFile *cdc_wdm_file,
ctx = g_slice_new0 (NewClientDmsContext);
ctx->device_open_proxy = device_open_proxy;
ctx->device_open_mbim = device_open_mbim;
+ ctx->load_capabilities = load_capabilities;
ctx->qmi_client_retries = QMI_CLIENT_RETRIES;
task = g_task_new (NULL, cancellable, callback, user_data);
diff --git a/src/qmi-firmware-update/qfu-utils.h b/src/qmi-firmware-update/qfu-utils.h
index 076520eb..95e7c2f3 100644
--- a/src/qmi-firmware-update/qfu-utils.h
+++ b/src/qmi-firmware-update/qfu-utils.h
@@ -47,12 +47,16 @@ gboolean qfu_utils_parse_cwe_version_string (const gchar *version,
void qfu_utils_new_client_dms (GFile *cdc_wdm_file,
gboolean device_open_proxy,
gboolean device_open_mbim,
+ gboolean load_capabilities,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean qfu_utils_new_client_dms_finish (GAsyncResult *res,
QmiDevice **qmi_device,
QmiClientDms **qmi_client,
+ gchar **revision,
+ gboolean *supports_stored_image_management,
+ gboolean *supports_firmware_preference_management,
GError **error);
G_END_DECLS