diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2016-11-25 22:30:42 +0100 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2017-01-16 11:24:11 +0100 |
commit | b9c92829771429a1b5419594052efb2e679d8d32 (patch) | |
tree | f7bebcdcda0b6f64de4283c7186d546e26048a22 /src | |
parent | 117775369f0b7e4e8151d4ebf0a249a9e50a5c1a (diff) | |
download | external_libqmi-b9c92829771429a1b5419594052efb2e679d8d32.zip external_libqmi-b9c92829771429a1b5419594052efb2e679d8d32.tar.gz external_libqmi-b9c92829771429a1b5419594052efb2e679d8d32.tar.bz2 |
qmi-firmware-update: allow selecting multiple image files to download
Diffstat (limited to 'src')
-rw-r--r-- | src/qmi-firmware-update/qfu-main.c | 42 | ||||
-rw-r--r-- | src/qmi-firmware-update/qfu-updater.c | 90 | ||||
-rw-r--r-- | src/qmi-firmware-update/qfu-updater.h | 1 |
3 files changed, 117 insertions, 16 deletions
diff --git a/src/qmi-firmware-update/qfu-main.c b/src/qmi-firmware-update/qfu-main.c index e3556d0..85d4038 100644 --- a/src/qmi-firmware-update/qfu-main.c +++ b/src/qmi-firmware-update/qfu-main.c @@ -41,18 +41,23 @@ /*****************************************************************************/ /* Main options */ -static gchar *device_str; -static gboolean device_open_proxy_flag; -static gboolean device_open_mbim_flag; -static gboolean verbose_flag; -static gboolean silent_flag; -static gboolean version_flag; +static gchar *device_str; +static gchar **image_strv; +static gboolean device_open_proxy_flag; +static gboolean device_open_mbim_flag; +static gboolean verbose_flag; +static gboolean silent_flag; +static gboolean version_flag; static GOptionEntry main_entries[] = { { "device", 'd', 0, G_OPTION_ARG_FILENAME, &device_str, "Specify device path.", "[PATH]" }, + { "image", 'i', 0, G_OPTION_ARG_FILENAME_ARRAY, &image_strv, + "Specify image to download to the device. May be given multiple times.", + "[PATH]" + }, { "device-open-proxy", 'p', 0, G_OPTION_ARG_NONE, &device_open_proxy_flag, "Request to use the 'qmi-proxy' proxy.", NULL @@ -205,7 +210,9 @@ int main (int argc, char **argv) GError *error = NULL; GOptionContext *context; QfuUpdater *updater; - GFile *cdc_wdm_file; + GFile *device_file; + GList *image_file_list = NULL; + guint i; setlocale (LC_ALL, ""); @@ -234,6 +241,12 @@ int main (int argc, char **argv) goto out; } + /* No images given? */ + if (!image_strv) { + g_printerr ("error: no image path(s) specified\n"); + goto out; + } + /* Create runtime context */ loop = g_main_loop_new (NULL, FALSE); cancellable = g_cancellable_new (); @@ -244,14 +257,21 @@ int main (int argc, char **argv) g_unix_signal_add (SIGHUP, (GSourceFunc)signals_handler, GINT_TO_POINTER (SIGHUP)); g_unix_signal_add (SIGTERM, (GSourceFunc)signals_handler, GINT_TO_POINTER (SIGTERM)); - /* Create updater and run it */ - cdc_wdm_file = g_file_new_for_commandline_arg (device_str); - updater = qfu_updater_new (cdc_wdm_file, + /* Create list of image files */ + for (i = 0; image_strv[i]; i++) + image_file_list = g_list_append (image_file_list, g_file_new_for_commandline_arg (image_strv[i])); + + /* Create updater */ + device_file = g_file_new_for_commandline_arg (device_str); + updater = qfu_updater_new (device_file, + image_file_list, device_open_proxy_flag, device_open_mbim_flag); - qfu_updater_run (updater, cancellable, (GAsyncReadyCallback) run_ready, NULL); + g_object_unref (device_file); + g_list_free_full (image_file_list, (GDestroyNotify) g_object_unref); /* Run! */ + qfu_updater_run (updater, cancellable, (GAsyncReadyCallback) run_ready, NULL); g_main_loop_run (loop); out: diff --git a/src/qmi-firmware-update/qfu-updater.c b/src/qmi-firmware-update/qfu-updater.c index 3f06a2e..6db403a 100644 --- a/src/qmi-firmware-update/qfu-updater.c +++ b/src/qmi-firmware-update/qfu-updater.c @@ -32,6 +32,7 @@ G_DEFINE_TYPE (QfuUpdater, qfu_updater, G_TYPE_OBJECT) struct _QfuUpdaterPrivate { /* Inputs */ GFile *cdc_wdm_file; + GList *image_file_list; gboolean device_open_proxy; gboolean device_open_mbim; }; @@ -43,12 +44,19 @@ static const gchar *cdc_wdm_subsys[] = { "usbmisc", "usb", NULL }; typedef enum { RUN_CONTEXT_STEP_USB_INFO = 0, + RUN_CONTEXT_STEP_SELECT_IMAGE, + RUN_CONTEXT_STEP_CLEANUP_IMAGE, RUN_CONTEXT_STEP_LAST } RunContextStep; typedef struct { /* Context step */ RunContextStep step; + /* List of pending image files to download */ + GList *pending_images; + /* Current image being downloaded */ + GFile *current_image; + GFileInfo *current_image_info; /* USB info */ gchar *sysfs_path; } RunContext; @@ -56,6 +64,11 @@ typedef struct { static void run_context_free (RunContext *ctx) { + if (ctx->current_image_info) + g_object_unref (ctx->current_image_info); + if (ctx->current_image) + g_object_unref (ctx->current_image); + g_list_free_full (ctx->pending_images, (GDestroyNotify) g_object_unref); g_free (ctx->sysfs_path); g_slice_free (RunContext, ctx); } @@ -78,18 +91,76 @@ run_context_step_cb (GTask *task) } static void -run_context_step_next (GTask *task) +run_context_step_next (GTask *task, RunContextStep next) { RunContext *ctx; ctx = (RunContext *) g_task_get_task_data (task); - ctx->step++; + ctx->step = next; /* Schedule next step in an idle */ g_idle_add ((GSourceFunc) run_context_step_cb, task); } static void +run_context_step_cleanup_image (GTask *task) +{ + RunContext *ctx; + + ctx = (RunContext *) g_task_get_task_data (task); + + g_assert (ctx->current_image); + g_assert (ctx->current_image_info); + + g_clear_object (&ctx->current_image); + g_clear_object (&ctx->current_image_info); + + /* Select next image */ + run_context_step_next (task, RUN_CONTEXT_STEP_SELECT_IMAGE); +} + +static void +run_context_step_select_image (GTask *task) +{ + RunContext *ctx; + GError *error = NULL; + + ctx = (RunContext *) g_task_get_task_data (task); + + g_assert (!ctx->current_image); + g_assert (!ctx->current_image_info); + + /* If no more files to download, we're done! */ + if (!ctx->pending_images) { + g_debug ("[qfu-updater] no more files to download"); + run_context_step_next (task, RUN_CONTEXT_STEP_LAST); + return; + } + + /* Select new current image */ + ctx->current_image = G_FILE (ctx->pending_images->data); + ctx->pending_images = g_list_delete_link (ctx->pending_images, ctx->pending_images); + ctx->current_image_info = g_file_query_info (ctx->current_image, + G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME "," G_FILE_ATTRIBUTE_STANDARD_SIZE, + G_FILE_QUERY_INFO_NONE, + g_task_get_cancellable (task), + &error); + if (!ctx->current_image_info) { + g_prefix_error (&error, "couldn't get image file info: "); + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + g_debug ("[qfu-updater] selected file '%s' (%" G_GOFFSET_FORMAT " bytes)", + g_file_info_get_display_name (ctx->current_image_info), + g_file_info_get_size (ctx->current_image_info)); + + /* Go on */ + run_context_step_next (task, ctx->step + 1); +} + +static void run_context_step_usb_info (GTask *task) { QfuUpdater *self; @@ -109,12 +180,14 @@ run_context_step_usb_info (GTask *task) } g_debug ("[qfu-updater] device sysfs path: %s", ctx->sysfs_path); - run_context_step_next (task); + run_context_step_next (task, ctx->step + 1); } typedef void (* RunContextStepFunc) (GTask *task); static const RunContextStepFunc run_context_step_func[] = { - [RUN_CONTEXT_STEP_USB_INFO] = run_context_step_usb_info, + [RUN_CONTEXT_STEP_USB_INFO] = run_context_step_usb_info, + [RUN_CONTEXT_STEP_SELECT_IMAGE] = run_context_step_select_image, + [RUN_CONTEXT_STEP_CLEANUP_IMAGE] = run_context_step_cleanup_image, }; G_STATIC_ASSERT (G_N_ELEMENTS (run_context_step_func) == RUN_CONTEXT_STEP_LAST); @@ -133,7 +206,6 @@ run_context_step (GTask *task) } if (ctx->step < G_N_ELEMENTS (run_context_step_func)) { - g_debug ("[qfu-updater] running step %u/%lu...", ctx->step + 1, G_N_ELEMENTS (run_context_step_func)); run_context_step_func [ctx->step] (task); return; } @@ -153,6 +225,7 @@ qfu_updater_run (QfuUpdater *self, GTask *task; ctx = g_slice_new0 (RunContext); + ctx->pending_images = g_list_copy_deep (self->priv->image_file_list, (GCopyFunc) g_object_ref, NULL); task = g_task_new (self, cancellable, callback, user_data); g_task_set_task_data (task, ctx, (GDestroyNotify) run_context_free); @@ -164,17 +237,20 @@ qfu_updater_run (QfuUpdater *self, QfuUpdater * qfu_updater_new (GFile *cdc_wdm_file, + GList *image_file_list, gboolean device_open_proxy, gboolean device_open_mbim) { QfuUpdater *self; g_assert (G_IS_FILE (cdc_wdm_file)); + g_assert (image_file_list); self = g_object_new (QFU_TYPE_UPDATER, NULL); self->priv->cdc_wdm_file = g_object_ref (cdc_wdm_file); self->priv->device_open_proxy = device_open_proxy; self->priv->device_open_mbim = device_open_mbim; + self->priv->image_file_list = g_list_copy_deep (image_file_list, (GCopyFunc) g_object_ref, NULL); return self; } @@ -191,6 +267,10 @@ dispose (GObject *object) QfuUpdater *self = QFU_UPDATER (object); g_clear_object (&self->priv->cdc_wdm_file); + if (self->priv->image_file_list) { + g_list_free_full (self->priv->image_file_list, (GDestroyNotify) g_object_unref); + self->priv->image_file_list = NULL; + } G_OBJECT_CLASS (qfu_updater_parent_class)->dispose (object); } diff --git a/src/qmi-firmware-update/qfu-updater.h b/src/qmi-firmware-update/qfu-updater.h index df36a00..46c3bbc 100644 --- a/src/qmi-firmware-update/qfu-updater.h +++ b/src/qmi-firmware-update/qfu-updater.h @@ -49,6 +49,7 @@ struct _QfuUpdaterClass { GType qfu_updater_get_type (void); QfuUpdater *qfu_updater_new (GFile *cdc_wdm_file, + GList *image_file_list, gboolean device_open_proxy, gboolean device_open_mbim); void qfu_updater_run (QfuUpdater *self, |