aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2016-11-25 22:30:42 +0100
committerAleksander Morgado <aleksander@aleksander.es>2017-01-16 11:24:11 +0100
commitb9c92829771429a1b5419594052efb2e679d8d32 (patch)
treef7bebcdcda0b6f64de4283c7186d546e26048a22 /src
parent117775369f0b7e4e8151d4ebf0a249a9e50a5c1a (diff)
downloadexternal_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.c42
-rw-r--r--src/qmi-firmware-update/qfu-updater.c90
-rw-r--r--src/qmi-firmware-update/qfu-updater.h1
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,