aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2016-12-05 18:55:31 +0100
committerAleksander Morgado <aleksander@aleksander.es>2017-01-16 11:24:14 +0100
commitd6fccedd7b67567b1bef9323391364c6721feb19 (patch)
tree14d73292b2e8f376b969dab148519463227c3345
parent99120ad04aa971257ab0dc4508354bb0664ffc86 (diff)
downloadexternal_libqmi-d6fccedd7b67567b1bef9323391364c6721feb19.zip
external_libqmi-d6fccedd7b67567b1bef9323391364c6721feb19.tar.gz
external_libqmi-d6fccedd7b67567b1bef9323391364c6721feb19.tar.bz2
qmi-firmware-update: implement support for direct QDL download
i.e. without going through the QMI triggered reboot.
-rw-r--r--src/qmi-firmware-update/qfu-main.c25
-rw-r--r--src/qmi-firmware-update/qfu-operation-update.c112
-rw-r--r--src/qmi-firmware-update/qfu-operation.h18
-rw-r--r--src/qmi-firmware-update/qfu-updater.c161
-rw-r--r--src/qmi-firmware-update/qfu-updater.h3
5 files changed, 219 insertions, 100 deletions
diff --git a/src/qmi-firmware-update/qfu-main.c b/src/qmi-firmware-update/qfu-main.c
index 73f02ea..df157fa 100644
--- a/src/qmi-firmware-update/qfu-main.c
+++ b/src/qmi-firmware-update/qfu-main.c
@@ -49,6 +49,10 @@ static gchar *carrier_str;
static gboolean device_open_proxy_flag;
static gboolean device_open_mbim_flag;
+/* Update (QDL mode) */
+static gboolean action_update_qdl_flag;
+static gchar *serial_str;
+
/* Verify */
static gboolean action_verify_flag;;
@@ -91,6 +95,18 @@ static GOptionEntry context_update_entries[] = {
{ NULL }
};
+static GOptionEntry context_update_qdl_entries[] = {
+ { "update-qdl", 'U', 0, G_OPTION_ARG_NONE, &action_update_qdl_flag,
+ "Launch firmware update process in QDL mode.",
+ NULL
+ },
+ { "serial", 's', 0, G_OPTION_ARG_FILENAME, &serial_str,
+ "Specify QDL serial device path (e.g. /dev/ttyUSB0).",
+ "[PATH]"
+ },
+ { NULL }
+};
+
static GOptionEntry context_verify_entries[] = {
{ "verify", 'z', 0, G_OPTION_ARG_NONE, &action_verify_flag,
"Analyze and Verify firmware images.",
@@ -242,6 +258,10 @@ int main (int argc, char **argv)
g_option_group_add_entries (group, context_update_entries);
g_option_context_add_group (context, group);
+ group = g_option_group_new ("update-qdl", "Update options (QDL mode)", "", NULL, NULL);
+ g_option_group_add_entries (group, context_update_qdl_entries);
+ g_option_context_add_group (context, group);
+
group = g_option_group_new ("verify", "Verify options", "", NULL, NULL);
g_option_group_add_entries (group, context_verify_entries);
g_option_context_add_group (context, group);
@@ -274,7 +294,7 @@ int main (int argc, char **argv)
qmi_utils_set_traces_enabled (TRUE);
/* We don't allow multiple actions at the same time */
- n_actions = (action_verify_flag + action_update_flag);
+ n_actions = (action_verify_flag + action_update_flag + action_update_qdl_flag);
if (n_actions == 0) {
g_printerr ("error: no actions specified\n");
goto out;
@@ -299,6 +319,9 @@ int main (int argc, char **argv)
carrier_str,
device_open_proxy_flag,
device_open_mbim_flag);
+ else if (action_update_qdl_flag)
+ result = qfu_operation_update_qdl_run ((const gchar **) image_strv,
+ serial_str);
else if (action_verify_flag)
result = qfu_operation_verify_run ((const gchar **) image_strv);
else
diff --git a/src/qmi-firmware-update/qfu-operation-update.c b/src/qmi-firmware-update/qfu-operation-update.c
index a989cdc..53396c1 100644
--- a/src/qmi-firmware-update/qfu-operation-update.c
+++ b/src/qmi-firmware-update/qfu-operation-update.c
@@ -72,6 +72,47 @@ run_ready (QfuUpdater *updater,
g_idle_add ((GSourceFunc) g_main_loop_quit, operation->loop);
}
+static gboolean
+operation_update_run (QfuUpdater *updater,
+ const gchar **images)
+{
+ UpdateOperation operation = {
+ .loop = NULL,
+ .cancellable = NULL,
+ .result = FALSE,
+ };
+ GList *image_file_list = NULL;
+ guint i;
+
+ g_assert (images);
+ g_assert (QFU_IS_UPDATER (updater));
+
+ /* Create runtime context */
+ operation.loop = g_main_loop_new (NULL, FALSE);
+ operation.cancellable = g_cancellable_new ();
+
+ /* Setup signals */
+ g_unix_signal_add (SIGINT, (GSourceFunc) signal_handler, &operation);
+ g_unix_signal_add (SIGHUP, (GSourceFunc) signal_handler, &operation);
+ g_unix_signal_add (SIGTERM, (GSourceFunc) signal_handler, &operation);
+
+ /* Create list of image files */
+ for (i = 0; images[i]; i++)
+ image_file_list = g_list_append (image_file_list, g_file_new_for_commandline_arg (images[i]));
+
+ /* Run! */
+ qfu_updater_run (updater, image_file_list, operation.cancellable, (GAsyncReadyCallback) run_ready, &operation);
+ g_list_free_full (image_file_list, (GDestroyNotify) g_object_unref);
+ g_main_loop_run (operation.loop);
+
+ if (operation.cancellable)
+ g_object_unref (operation.cancellable);
+ if (operation.loop)
+ g_main_loop_unref (operation.loop);
+
+ return operation.result;
+}
+
gboolean
qfu_operation_update_run (const gchar **images,
const gchar *device,
@@ -81,78 +122,77 @@ qfu_operation_update_run (const gchar **images,
gboolean device_open_proxy,
gboolean device_open_mbim)
{
- UpdateOperation operation = {
- .loop = NULL,
- .cancellable = NULL,
- .result = FALSE,
- };
QfuUpdater *updater = NULL;
GFile *device_file = NULL;
- GList *image_file_list = NULL;
- guint i;
+ gboolean result;
g_assert (images);
/* No device path given? */
if (!device) {
g_printerr ("error: no device path specified\n");
- goto out;
+ return FALSE;
}
/* No firmware version given? */
if (!firmware_version) {
g_printerr ("error: no firmware version specified\n");
- goto out;
+ return FALSE;
}
/* No config version given? */
if (!config_version) {
g_printerr ("error: no config version specified\n");
- goto out;
+ return FALSE;
}
/* No carrier given? */
if (!carrier) {
g_printerr ("error: no carrier specified\n");
- goto out;
+ return FALSE;
}
- /* Create runtime context */
- operation.loop = g_main_loop_new (NULL, FALSE);
- operation.cancellable = g_cancellable_new ();
-
- /* Setup signals */
- g_unix_signal_add (SIGINT, (GSourceFunc) signal_handler, &operation);
- g_unix_signal_add (SIGHUP, (GSourceFunc) signal_handler, &operation);
- g_unix_signal_add (SIGTERM, (GSourceFunc) signal_handler, &operation);
-
- /* Create list of image files */
- for (i = 0; images[i]; i++)
- image_file_list = g_list_append (image_file_list, g_file_new_for_commandline_arg (images[i]));
-
/* Create updater */
device_file = g_file_new_for_commandline_arg (device);
updater = qfu_updater_new (device_file,
firmware_version,
config_version,
carrier,
- image_file_list,
device_open_proxy,
device_open_mbim);
g_object_unref (device_file);
- g_list_free_full (image_file_list, (GDestroyNotify) g_object_unref);
/* Run! */
- qfu_updater_run (updater, operation.cancellable, (GAsyncReadyCallback) run_ready, &operation);
- g_main_loop_run (operation.loop);
+ result = operation_update_run (updater, images);
-out:
- if (updater)
- g_object_unref (updater);
- if (operation.cancellable)
- g_object_unref (operation.cancellable);
- if (operation.loop)
- g_main_loop_unref (operation.loop);
+ g_object_unref (updater);
+ return result;
+}
- return operation.result;
+gboolean
+qfu_operation_update_qdl_run (const gchar **images,
+ const gchar *serial)
+{
+ QfuUpdater *updater = NULL;
+ GFile *serial_file = NULL;
+ gboolean result;
+
+ g_assert (images);
+
+ /* No device path given? */
+ if (!serial) {
+ g_printerr ("error: no serial path specified\n");
+ return FALSE;
+ }
+
+ /* Create updater */
+ serial_file = g_file_new_for_commandline_arg (serial);
+ updater = qfu_updater_new_qdl (serial_file);
+ g_object_unref (serial_file);
+
+ /* Run! */
+ result = operation_update_run (updater, images);
+
+ g_object_unref (updater);
+ return result;
}
diff --git a/src/qmi-firmware-update/qfu-operation.h b/src/qmi-firmware-update/qfu-operation.h
index 296d315..29b7856 100644
--- a/src/qmi-firmware-update/qfu-operation.h
+++ b/src/qmi-firmware-update/qfu-operation.h
@@ -26,14 +26,16 @@
G_BEGIN_DECLS
-gboolean qfu_operation_update_run (const gchar **images,
- const gchar *device,
- const gchar *firmware_version,
- const gchar *config_version,
- const gchar *carrier,
- gboolean device_open_proxy,
- gboolean device_open_mbim);
-gboolean qfu_operation_verify_run (const gchar **images);
+gboolean qfu_operation_update_run (const gchar **images,
+ const gchar *device,
+ const gchar *firmware_version,
+ const gchar *config_version,
+ const gchar *carrier,
+ gboolean device_open_proxy,
+ gboolean device_open_mbim);
+gboolean qfu_operation_update_qdl_run (const gchar **images,
+ const gchar *serial);
+gboolean qfu_operation_verify_run (const gchar **images);
G_END_DECLS
diff --git a/src/qmi-firmware-update/qfu-updater.c b/src/qmi-firmware-update/qfu-updater.c
index 6edfcb1..3b3b7c2 100644
--- a/src/qmi-firmware-update/qfu-updater.c
+++ b/src/qmi-firmware-update/qfu-updater.c
@@ -35,15 +35,21 @@
G_DEFINE_TYPE (QfuUpdater, qfu_updater, G_TYPE_OBJECT)
+typedef enum {
+ UPDATER_TYPE_UNKNOWN,
+ UPDATER_TYPE_GENERIC,
+ UPDATER_TYPE_QDL,
+} UpdaterType;
+
struct _QfuUpdaterPrivate {
- /* Inputs */
- GFile *cdc_wdm_file;
- gchar *firmware_version;
- gchar *config_version;
- gchar *carrier;
- GList *image_file_list;
- gboolean device_open_proxy;
- gboolean device_open_mbim;
+ UpdaterType type;
+ GFile *cdc_wdm_file;
+ GFile *serial_file;
+ gchar *firmware_version;
+ gchar *config_version;
+ gchar *carrier;
+ gboolean device_open_proxy;
+ gboolean device_open_mbim;
};
static const gchar *cdc_wdm_subsys[] = { "usbmisc", "usb", NULL };
@@ -73,31 +79,33 @@ typedef enum {
} RunContextStep;
typedef struct {
+ /* Device files and common USB sysfs path*/
+ GFile *cdc_wdm_file;
+ GFile *serial_file;
+ gchar *sysfs_path;
+
/* Context step */
RunContextStep step;
- /* List of pending QfuImages to download */
- GList *pending_images;
- /* Current image being downloaded */
+
+ /* List of pending QfuImages to download, and the current one being
+ * processed. */
+ GList *pending_images;
QfuImage *current_image;
- /* USB info */
- gchar *sysfs_path;
+
/* QMI device and client */
QmiDevice *qmi_device;
QmiClientDms *qmi_client;
gint qmi_client_retries;
- /* TTY file */
- GFile *tty;
+
/* QDL device */
- QfuQdlDevice *qdl;
+ QfuQdlDevice *qdl_device;
} RunContext;
static void
run_context_free (RunContext *ctx)
{
- if (ctx->qdl)
- g_object_unref (&ctx->qdl);
- if (ctx->tty)
- g_object_unref (ctx->tty);
+ if (ctx->qdl_device)
+ g_object_unref (&ctx->qdl_device);
if (ctx->qmi_client) {
g_assert (ctx->qmi_device);
qmi_device_release_client (ctx->qmi_device,
@@ -114,6 +122,10 @@ run_context_free (RunContext *ctx)
g_object_unref (ctx->current_image);
g_list_free_full (ctx->pending_images, (GDestroyNotify) g_object_unref);
g_free (ctx->sysfs_path);
+ if (ctx->serial_file)
+ g_object_unref (ctx->serial_file);
+ if (ctx->cdc_wdm_file)
+ g_object_unref (ctx->cdc_wdm_file);
g_slice_free (RunContext, ctx);
}
@@ -153,21 +165,22 @@ wait_for_cdc_wdm_ready (gpointer unused,
{
GError *error = NULL;
RunContext *ctx;
- gchar *tty_path;
+ gchar *path;
ctx = (RunContext *) g_task_get_task_data (task);
- ctx->tty = qfu_udev_helper_wait_for_device_finish (res, &error);
- if (!ctx->tty) {
+ g_assert (!ctx->cdc_wdm_file);
+ ctx->cdc_wdm_file = qfu_udev_helper_wait_for_device_finish (res, &error);
+ if (!ctx->cdc_wdm_file) {
g_prefix_error (&error, "error waiting for cdc-wdm: ");
g_task_return_error (task, error);
g_object_unref (task);
return;
}
- tty_path = g_file_get_path (ctx->tty);
- g_debug ("[qfu-updater] cdc-wdm device found: %s", tty_path);
- g_free (tty_path);
+ path = g_file_get_path (ctx->cdc_wdm_file);
+ g_debug ("[qfu-updater] cdc-wdm device found: %s", path);
+ g_free (path);
/* Go on */
run_context_step_next (task, ctx->step + 1);
@@ -180,8 +193,6 @@ run_context_step_wait_for_cdc_wdm (GTask *task)
ctx = (RunContext *) g_task_get_task_data (task);
- g_print ("rebooting in normal mode...\n");
-
g_debug ("[qfu-updater] now waiting for cdc-wdm device...");
qfu_udev_helper_wait_for_device (QFU_UDEV_HELPER_WAIT_FOR_DEVICE_TYPE_CDC_WDM,
ctx->sysfs_path,
@@ -194,14 +205,26 @@ static void
run_context_step_cleanup_qdl_device (GTask *task)
{
RunContext *ctx;
+ QfuUpdater *self;
ctx = (RunContext *) g_task_get_task_data (task);
+ self = g_task_get_source_object (task);
- g_assert (ctx->qdl);
+ g_assert (ctx->qdl_device);
+ g_assert (ctx->serial_file);
g_debug ("[qfu-updater] QDL reset");
- qfu_qdl_device_reset (ctx->qdl, g_task_get_cancellable (task), NULL);
- g_clear_object (&ctx->qdl);
+ qfu_qdl_device_reset (ctx->qdl_device, g_task_get_cancellable (task), NULL);
+ g_clear_object (&ctx->qdl_device);
+ g_clear_object (&ctx->serial_file);
+
+ g_print ("rebooting in normal mode...\n");
+
+ /* If we were running in QDL mode, we don't even wait for the reboot to finish */
+ if (self->priv->type == UPDATER_TYPE_QDL) {
+ run_context_step_next (task, RUN_CONTEXT_STEP_LAST);
+ return;
+ }
run_context_step_next (task, ctx->step + 1);
}
@@ -251,19 +274,19 @@ run_context_step_download_image (GTask *task)
aux);
g_free (aux);
- if (!qfu_qdl_device_hello (ctx->qdl, cancellable, &error)) {
+ if (!qfu_qdl_device_hello (ctx->qdl_device, cancellable, &error)) {
g_prefix_error (&error, "couldn't send greetings to device: ");
goto out;
}
- if (!qfu_qdl_device_ufopen (ctx->qdl, ctx->current_image, cancellable, &error)) {
+ if (!qfu_qdl_device_ufopen (ctx->qdl_device, ctx->current_image, cancellable, &error)) {
g_prefix_error (&error, "couldn't open session: ");
goto out;
}
n_chunks = qfu_image_get_n_data_chunks (ctx->current_image);
for (sequence = 0; sequence < n_chunks; sequence++) {
- if (!qfu_qdl_device_ufwrite (ctx->qdl, ctx->current_image, sequence, cancellable, &error)) {
+ if (!qfu_qdl_device_ufwrite (ctx->qdl_device, ctx->current_image, sequence, cancellable, &error)) {
g_prefix_error (&error, "couldn't write in session: ");
goto out;
}
@@ -271,7 +294,7 @@ run_context_step_download_image (GTask *task)
g_debug ("[qfu-updater] all chunks ack-ed");
- if (!qfu_qdl_device_ufclose (ctx->qdl, cancellable, &error)) {
+ if (!qfu_qdl_device_ufclose (ctx->qdl_device, cancellable, &error)) {
g_prefix_error (&error, "couldn't close session: ");
goto out;
}
@@ -325,9 +348,10 @@ run_context_step_qdl_device (GTask *task)
ctx = (RunContext *) g_task_get_task_data (task);
- g_assert (!ctx->qdl);
- ctx->qdl = qfu_qdl_device_new (ctx->tty, g_task_get_cancellable (task), &error);
- if (!ctx->qdl) {
+ g_assert (ctx->serial_file);
+ g_assert (!ctx->qdl_device);
+ ctx->qdl_device = qfu_qdl_device_new (ctx->serial_file, g_task_get_cancellable (task), &error);
+ if (!ctx->qdl_device) {
g_prefix_error (&error, "error creating device: ");
g_task_return_error (task, error);
g_object_unref (task);
@@ -344,21 +368,22 @@ wait_for_tty_ready (gpointer unused,
{
GError *error = NULL;
RunContext *ctx;
- gchar *tty_path;
+ gchar *path;
ctx = (RunContext *) g_task_get_task_data (task);
- ctx->tty = qfu_udev_helper_wait_for_device_finish (res, &error);
- if (!ctx->tty) {
+ g_assert (!ctx->serial_file);
+ ctx->serial_file = qfu_udev_helper_wait_for_device_finish (res, &error);
+ if (!ctx->serial_file) {
g_prefix_error (&error, "error waiting for TTY: ");
g_task_return_error (task, error);
g_object_unref (task);
return;
}
- tty_path = g_file_get_path (ctx->tty);
- g_debug ("[qfu-updater] TTY device found: %s", tty_path);
- g_free (tty_path);
+ path = g_file_get_path (ctx->serial_file);
+ g_debug ("[qfu-updater] TTY device found: %s", path);
+ g_free (path);
/* Go on */
run_context_step_next (task, ctx->step + 1);
@@ -410,6 +435,7 @@ qmi_client_release_ready (QmiDevice *device,
g_debug ("[qfu-updater] QMI device closed");
g_clear_object (&ctx->qmi_device);
+ g_clear_object (&ctx->cdc_wdm_file);
/* Go on */
run_context_step_next (task, ctx->step + 1);
@@ -754,6 +780,7 @@ run_context_step_qmi_device (GTask *task)
self = g_task_get_source_object (task);
g_debug ("[qfu-updater] creating QMI device...");
+ g_assert (self->priv->cdc_wdm_file);
qmi_device_new (self->priv->cdc_wdm_file,
g_task_get_cancellable (task),
(GAsyncReadyCallback) qmi_device_ready,
@@ -770,6 +797,8 @@ run_context_step_usb_info (GTask *task)
ctx = (RunContext *) g_task_get_task_data (task);
self = g_task_get_source_object (task);
+ g_assert (self->priv->cdc_wdm_file);
+
g_debug ("[qfu-updater] looking for device sysfs path...");
ctx->sysfs_path = qfu_udev_helper_get_sysfs_path (self->priv->cdc_wdm_file, cdc_wdm_subsys, &error);
if (!ctx->sysfs_path) {
@@ -835,6 +864,7 @@ image_sort_by_size (QfuImage *a, QfuImage *b)
void
qfu_updater_run (QfuUpdater *self,
+ GList *image_file_list,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
@@ -843,13 +873,15 @@ qfu_updater_run (QfuUpdater *self,
GTask *task;
GList *l;
+ g_assert (image_file_list);
+
ctx = g_slice_new0 (RunContext);
task = g_task_new (self, cancellable, callback, user_data);
g_task_set_task_data (task, ctx, (GDestroyNotify) run_context_free);
/* Build QfuImage objects for each image file given */
- for (l = self->priv->image_file_list; l; l = g_list_next (l)) {
+ for (l = image_file_list; l; l = g_list_next (l)) {
GError *error = NULL;
QfuImage *image;
@@ -866,8 +898,19 @@ qfu_updater_run (QfuUpdater *self,
* the use case anyway, first flash e.g. the .cwe file, then the .nvu one. */
ctx->pending_images = g_list_sort (ctx->pending_images, (GCompareFunc) image_sort_by_size);
- /* Define amount of retries trying to allocate a QMI DMS client */
- ctx->qmi_client_retries = QMI_CLIENT_RETRIES;
+ switch (self->priv->type) {
+ case UPDATER_TYPE_GENERIC:
+ ctx->step = RUN_CONTEXT_STEP_USB_INFO;
+ ctx->qmi_client_retries = QMI_CLIENT_RETRIES;
+ ctx->cdc_wdm_file = g_object_ref (self->priv->cdc_wdm_file);
+ break;
+ case UPDATER_TYPE_QDL:
+ ctx->step = RUN_CONTEXT_STEP_QDL_DEVICE;
+ ctx->serial_file = g_object_ref (self->priv->serial_file);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
run_context_step (task);
}
@@ -879,23 +922,35 @@ qfu_updater_new (GFile *cdc_wdm_file,
const gchar *firmware_version,
const gchar *config_version,
const gchar *carrier,
- 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->type = UPDATER_TYPE_GENERIC;
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->firmware_version = g_strdup (firmware_version);
self->priv->config_version = g_strdup (config_version);
self->priv->carrier = g_strdup (carrier);
- self->priv->image_file_list = g_list_copy_deep (image_file_list, (GCopyFunc) g_object_ref, NULL);
+
+ return self;
+}
+
+QfuUpdater *
+qfu_updater_new_qdl (GFile *serial_file)
+{
+ QfuUpdater *self;
+
+ g_assert (G_IS_FILE (serial_file));
+
+ self = g_object_new (QFU_TYPE_UPDATER, NULL);
+ self->priv->type = UPDATER_TYPE_QDL;
+ self->priv->serial_file = g_object_ref (serial_file);
return self;
}
@@ -904,6 +959,7 @@ static void
qfu_updater_init (QfuUpdater *self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, QFU_TYPE_UPDATER, QfuUpdaterPrivate);
+ self->priv->type = UPDATER_TYPE_UNKNOWN;
}
static void
@@ -911,11 +967,8 @@ dispose (GObject *object)
{
QfuUpdater *self = QFU_UPDATER (object);
+ g_clear_object (&self->priv->serial_file);
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 b978792..56ff6b5 100644
--- a/src/qmi-firmware-update/qfu-updater.h
+++ b/src/qmi-firmware-update/qfu-updater.h
@@ -52,10 +52,11 @@ QfuUpdater *qfu_updater_new (GFile *cdc_wdm_file,
const gchar *firmware_version,
const gchar *config_version,
const gchar *carrier,
- GList *image_file_list,
gboolean device_open_proxy,
gboolean device_open_mbim);
+QfuUpdater *qfu_updater_new_qdl (GFile *serial_file);
void qfu_updater_run (QfuUpdater *self,
+ GList *image_file_list,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);