From 40cd18fa976d521e99efca0a7eefc3b0b2029e84 Mon Sep 17 00:00:00 2001 From: Richard Hughes Date: Thu, 26 Aug 2021 07:52:29 +0100 Subject: [PATCH] Allow using a per-device global percentage completion It's actually quite hard to build a front-end for fwupd at the moment as you're never sure when the progress bar is going to zip back to 0% and start all over again. Some plugins go 0..100% for write, others go 0..100% for erase, then again for write, then *again* for verify. By creating a helper object we can easily split up the progress of the specific task, e.g. write_firmware(). We can encode at the plugin level "the erase takes 50% of the time, the write takes 40% and the read takes 10%". This means we can have a progressbar which goes up just once at a consistent speed. --- docs/tutorial.md | 9 +- libfwupdplugin/README.md | 6 + libfwupdplugin/fu-device-private.h | 2 + libfwupdplugin/fu-device.c | 202 +--- libfwupdplugin/fu-device.h | 58 +- libfwupdplugin/fu-plugin-private.h | 16 +- libfwupdplugin/fu-plugin-vfuncs.h | 8 +- libfwupdplugin/fu-plugin.c | 187 +++- libfwupdplugin/fu-progress.c | 921 ++++++++++++++++++ libfwupdplugin/fu-progress.h | 110 +++ libfwupdplugin/fu-self-test.c | 222 +++++ libfwupdplugin/fwupdplugin.h | 1 + libfwupdplugin/fwupdplugin.map | 30 +- libfwupdplugin/meson.build | 2 + plugins/altos/fu-altos-device.c | 40 +- plugins/analogix/fu-analogix-device.c | 56 +- plugins/ata/fu-ata-device.c | 20 +- plugins/bcm57xx/fu-bcm57xx-device.c | 62 +- plugins/bcm57xx/fu-bcm57xx-recovery-device.c | 79 +- plugins/ccgx/fu-ccgx-dmc-device.c | 132 ++- plugins/ccgx/fu-ccgx-hid-device.c | 15 +- plugins/ccgx/fu-ccgx-hpi-device.c | 52 +- plugins/colorhug/fu-colorhug-device.c | 51 +- plugins/cros-ec/fu-cros-ec-usb-device.c | 30 +- plugins/dell-dock/fu-dell-dock-hub.c | 30 +- plugins/dell-dock/fu-dell-dock-i2c-ec.c | 28 +- plugins/dell-dock/fu-dell-dock-i2c-mst.c | 123 ++- plugins/dell-dock/fu-dell-dock-i2c-tbt.c | 8 +- plugins/dell-dock/fu-dell-dock-status.c | 13 +- plugins/dell-dock/fu-dell-dock-usb-usb4.c | 14 +- plugins/dell-dock/fu-plugin-dell-dock.c | 3 +- plugins/dell/fu-self-test.c | 3 + plugins/dfu-csr/fu-dfu-csr-device.c | 25 +- plugins/dfu/fu-dfu-device.c | 124 +-- plugins/dfu/fu-dfu-device.h | 7 +- plugins/dfu/fu-dfu-target-avr.c | 111 ++- plugins/dfu/fu-dfu-target-private.h | 20 +- plugins/dfu/fu-dfu-target-stm.c | 87 +- plugins/dfu/fu-dfu-target.c | 184 ++-- plugins/dfu/fu-dfu-target.h | 13 +- plugins/dfu/fu-dfu-tool.c | 54 +- plugins/ebitdo/fu-ebitdo-device.c | 33 +- plugins/elantp/fu-elantp-hid-device.c | 45 +- plugins/elantp/fu-elantp-i2c-device.c | 45 +- plugins/emmc/fu-emmc-device.c | 27 +- plugins/ep963x/fu-ep963x-device.c | 33 +- plugins/fastboot/fu-fastboot-device.c | 110 ++- plugins/flashrom/fu-flashrom-device.c | 12 + .../flashrom/fu-flashrom-internal-device.c | 16 +- plugins/fresco-pd/fu-fresco-pd-device.c | 40 +- plugins/goodix-moc/fu-goodixmoc-device.c | 29 +- plugins/hailuck/fu-hailuck-bl-device.c | 37 +- plugins/hailuck/fu-hailuck-kbd-device.c | 15 +- plugins/hailuck/fu-hailuck-tp-device.c | 33 +- plugins/intel-spi/fu-ifd-device.c | 7 +- plugins/intel-spi/fu-intel-spi-device.c | 19 +- plugins/intel-spi/fu-intel-spi-device.h | 1 + plugins/jabra/fu-jabra-device.c | 3 +- plugins/jabra/fu-plugin-jabra.c | 3 +- .../fu-logitech-bulkcontroller-device.c | 28 +- .../fu-logitech-hidpp-bootloader-nordic.c | 29 +- .../fu-logitech-hidpp-bootloader-texas.c | 26 +- .../fu-logitech-hidpp-bootloader.c | 12 +- .../fu-logitech-hidpp-bootloader.h | 9 + .../logitech-hidpp/fu-logitech-hidpp-device.c | 33 +- .../logitech-hidpp/fu-logitech-hidpp-device.h | 5 +- .../logitech-hidpp/fu-logitech-hidpp-radio.c | 21 +- .../fu-logitech-hidpp-runtime-bolt.c | 2 +- .../fu-logitech-hidpp-runtime-unifying.c | 13 +- plugins/modem-manager/fu-firehose-updater.c | 33 +- plugins/modem-manager/fu-firehose-updater.h | 1 + plugins/modem-manager/fu-mbim-qdu-updater.c | 12 +- plugins/modem-manager/fu-mbim-qdu-updater.h | 1 + plugins/modem-manager/fu-mm-device.c | 81 +- .../modem-manager/fu-plugin-modem-manager.c | 9 +- plugins/nvme/fu-nvme-device.c | 30 +- plugins/optionrom/fu-optionrom-device.c | 2 +- .../parade-lspcon/fu-parade-lspcon-device.c | 75 +- plugins/pixart-rf/fu-pxi-ble-device.c | 58 +- plugins/pixart-rf/fu-pxi-receiver-device.c | 58 +- plugins/pixart-rf/fu-pxi-wireless-device.c | 66 +- plugins/realtek-mst/fu-realtek-mst-device.c | 92 +- plugins/redfish/fu-redfish-device.c | 34 +- plugins/redfish/fu-redfish-device.h | 5 +- plugins/redfish/fu-redfish-legacy-device.c | 20 +- plugins/redfish/fu-redfish-multipart-device.c | 16 +- plugins/redfish/fu-self-test.c | 3 + plugins/rts54hid/fu-rts54hid-device.c | 40 +- plugins/rts54hid/fu-rts54hid-module.c | 5 +- plugins/rts54hub/fu-rts54hub-device.c | 35 +- .../rts54hub/fu-rts54hub-rtd21xx-background.c | 27 +- .../rts54hub/fu-rts54hub-rtd21xx-foreground.c | 28 +- plugins/solokey/fu-solokey-device.c | 33 +- plugins/superio/fu-superio-device.c | 12 + plugins/superio/fu-superio-it55-device.c | 77 +- plugins/superio/fu-superio-it89-device.c | 132 ++- .../fu-synaptics-cxaudio-device.c | 34 +- .../synaptics-mst/fu-plugin-synaptics-mst.c | 3 +- .../synaptics-mst/fu-synaptics-mst-device.c | 58 +- .../synaptics-prometheus/fu-synaprom-config.c | 19 +- .../synaptics-prometheus/fu-synaprom-device.c | 154 ++- .../synaptics-prometheus/fu-synaprom-device.h | 6 +- .../synaptics-rmi/fu-synaptics-rmi-device.c | 13 +- .../fu-synaptics-rmi-hid-device.c | 21 +- .../fu-synaptics-rmi-ps2-device.c | 13 +- .../fu-synaptics-rmi-v5-device.c | 38 +- .../fu-synaptics-rmi-v5-device.h | 3 +- .../fu-synaptics-rmi-v7-device.c | 25 +- .../fu-synaptics-rmi-v7-device.h | 3 +- .../fu-system76-launch-device.c | 15 +- plugins/test/fu-plugin-test.c | 24 +- plugins/thelio-io/fu-thelio-io-device.c | 16 +- plugins/thunderbolt/fu-self-test.c | 20 +- plugins/thunderbolt/fu-thunderbolt-device.c | 30 +- plugins/uefi-capsule/fu-plugin-uefi-capsule.c | 5 +- plugins/uefi-capsule/fu-uefi-cod-device.c | 1 + plugins/uefi-capsule/fu-uefi-device.c | 12 + plugins/uefi-capsule/fu-uefi-grub-device.c | 1 + plugins/uefi-capsule/fu-uefi-nvram-device.c | 1 + plugins/uefi-capsule/fu-uefi-tool.c | 2 + plugins/uefi-dbx/fu-uefi-dbx-device.c | 17 +- plugins/vli/fu-vli-device.c | 54 +- plugins/vli/fu-vli-device.h | 16 +- plugins/vli/fu-vli-pd-device.c | 78 +- plugins/vli/fu-vli-pd-parade-device.c | 45 +- plugins/vli/fu-vli-usbhub-device.c | 113 ++- plugins/vli/fu-vli-usbhub-msp430-device.c | 24 +- plugins/vli/fu-vli-usbhub-pd-device.c | 33 +- plugins/vli/fu-vli-usbhub-rtd21xx-device.c | 41 +- plugins/wacom-raw/fu-wacom-aes-device.c | 25 +- plugins/wacom-raw/fu-wacom-device.c | 19 +- plugins/wacom-raw/fu-wacom-device.h | 5 +- plugins/wacom-raw/fu-wacom-emr-device.c | 20 +- plugins/wacom-usb/fu-plugin-wacom-usb.c | 3 +- plugins/wacom-usb/fu-wac-device.c | 47 +- plugins/wacom-usb/fu-wac-module-bluetooth.c | 42 +- plugins/wacom-usb/fu-wac-module-touch.c | 38 +- plugins/wacom-usb/fu-wac-module.c | 18 +- plugins/wacom-usb/fu-wac-module.h | 6 +- src/fu-engine.c | 202 +++- src/fu-engine.h | 8 +- src/fu-self-test.c | 25 +- src/fu-tool.c | 15 +- 143 files changed, 4709 insertions(+), 1531 deletions(-) create mode 100644 libfwupdplugin/fu-progress.c create mode 100644 libfwupdplugin/fu-progress.h diff --git a/docs/tutorial.md b/docs/tutorial.md index fa34bcb64..3e9bb25e1 100644 --- a/docs/tutorial.md +++ b/docs/tutorial.md @@ -146,6 +146,7 @@ and then calls the vfuncs to update the device. fu_plugin_write_firmware (FuPlugin *plugin, FuDevice *dev, GBytes *blob_fw, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -212,19 +213,19 @@ handle the device ID, although the registered plugin can change during the attach and detach phases. gboolean - fu_plugin_detach (FuPlugin *plugin, FuDevice *device, GError **error) + fu_plugin_detach (FuPlugin *plugin, FuDevice *device, FuProgress *progress, GError **error) { if (hardware_in_bootloader) return TRUE; - return _device_detach(device, error); + return _device_detach(device, progress, error); } gboolean - fu_plugin_attach (FuPlugin *plugin, FuDevice *device, GError **error) + fu_plugin_attach (FuPlugin *plugin, FuDevice *device, FuProgress *progress, GError **error) { if (!hardware_in_bootloader) return TRUE; - return _device_attach(device, error); + return _device_attach(device, progress, error); } gboolean diff --git a/libfwupdplugin/README.md b/libfwupdplugin/README.md index db2524b78..b848cd42c 100644 --- a/libfwupdplugin/README.md +++ b/libfwupdplugin/README.md @@ -18,6 +18,12 @@ Remember: Plugins should be upstream! * Migrate from fu_device_get_protocol() to fu_device_get_protocols() and fu_device_set_protocol() to fu_device_add_protocol() * Migrate from fu_device_has_custom_flag() to fu_device_has_private_flag() * Migrate from fu_udev_device_set_readonly() to fu_udev_device_set_flags() +* Migrate from fu_device_sleep_with_progress() to fu_progress_sleep() -- but be aware the unit of time has changed from *seconds* to *milliseconds* +* Migrate from fu_device_get_status() to fu_progress_get_status() +* Migrate from fu_device_set_status() to fu_progress_set_status() +* Migrate from fu_device_get_progress() to fu_progress_get_percentage() +* Migrate from fu_device_set_progress_full() to fu_progress_set_percentage_full() +* Migrate from fu_device_set_progress() to fu_progress_set_steps(), fu_progress_add_step() and fu_progress_done -- see the FuProgress docs for more details! ## Planned API/ABI changes for next release diff --git a/libfwupdplugin/fu-device-private.h b/libfwupdplugin/fu-device-private.h index 795012fa9..0135b703e 100644 --- a/libfwupdplugin/fu-device-private.h +++ b/libfwupdplugin/fu-device-private.h @@ -50,3 +50,5 @@ guint64 fu_device_get_private_flags(FuDevice *self); void fu_device_set_private_flags(FuDevice *self, guint64 flag); +void +fu_device_set_progress(FuDevice *self, FuProgress *progress); diff --git a/libfwupdplugin/fu-device.c b/libfwupdplugin/fu-device.c index 23eba03eb..957b14a24 100644 --- a/libfwupdplugin/fu-device.c +++ b/libfwupdplugin/fu-device.c @@ -54,7 +54,6 @@ typedef struct { GRWLock parent_guids_mutex; GPtrArray *parent_physical_ids; /* (nullable) */ guint remove_delay; /* ms */ - guint progress; guint battery_level; guint battery_threshold; guint request_cnts[FWUPD_REQUEST_KIND_LAST]; @@ -90,7 +89,6 @@ typedef struct { enum { PROP_0, - PROP_PROGRESS, PROP_BATTERY_LEVEL, PROP_BATTERY_THRESHOLD, PROP_PHYSICAL_ID, @@ -115,9 +113,6 @@ fu_device_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec FuDevice *self = FU_DEVICE(object); FuDevicePrivate *priv = GET_PRIVATE(self); switch (prop_id) { - case PROP_PROGRESS: - g_value_set_uint(value, priv->progress); - break; case PROP_BATTERY_LEVEL: g_value_set_uint(value, priv->battery_level); break; @@ -153,9 +148,6 @@ fu_device_set_property(GObject *object, guint prop_id, const GValue *value, GPar { FuDevice *self = FU_DEVICE(object); switch (prop_id) { - case PROP_PROGRESS: - fu_device_set_progress(self, g_value_get_uint(value)); - break; case PROP_BATTERY_LEVEL: fu_device_set_battery_level(self, g_value_get_uint(value)); break; @@ -3065,123 +3057,6 @@ fu_device_set_remove_delay(FuDevice *self, guint remove_delay) priv->remove_delay = remove_delay; } -/** - * fu_device_get_status: - * @self: a #FuDevice - * - * Returns what the device is currently doing. - * - * Returns: the status value, e.g. %FWUPD_STATUS_DEVICE_WRITE - * - * Since: 1.0.3 - **/ -FwupdStatus -fu_device_get_status(FuDevice *self) -{ - g_return_val_if_fail(FU_IS_DEVICE(self), 0); - return fwupd_device_get_status(FWUPD_DEVICE(self)); -} - -/** - * fu_device_set_status: - * @self: a #FuDevice - * @status: the status value, e.g. %FWUPD_STATUS_DEVICE_WRITE - * - * Sets what the device is currently doing. - * - * Since: 1.0.3 - **/ -void -fu_device_set_status(FuDevice *self, FwupdStatus status) -{ - g_return_if_fail(FU_IS_DEVICE(self)); - fwupd_device_set_status(FWUPD_DEVICE(self), status); -} - -/** - * fu_device_get_progress: - * @self: a #FuDevice - * - * Returns the progress completion. - * - * Returns: value in percent - * - * Since: 1.0.3 - **/ -guint -fu_device_get_progress(FuDevice *self) -{ - FuDevicePrivate *priv = GET_PRIVATE(self); - g_return_val_if_fail(FU_IS_DEVICE(self), 0); - return priv->progress; -} - -/** - * fu_device_set_progress: - * @self: a #FuDevice - * @progress: the progress percentage value - * - * Sets the progress completion. - * - * Since: 1.0.3 - **/ -void -fu_device_set_progress(FuDevice *self, guint progress) -{ - FuDevicePrivate *priv = GET_PRIVATE(self); - g_return_if_fail(FU_IS_DEVICE(self)); - if (priv->progress == progress) - return; - priv->progress = progress; - g_object_notify(G_OBJECT(self), "progress"); -} - -/** - * fu_device_set_progress_full: - * @self: a #FuDevice - * @progress_done: the bytes already done - * @progress_total: the total number of bytes - * - * Sets the progress completion using the raw progress values. - * - * Since: 1.0.3 - **/ -void -fu_device_set_progress_full(FuDevice *self, gsize progress_done, gsize progress_total) -{ - gdouble percentage = 0.f; - g_return_if_fail(FU_IS_DEVICE(self)); - if (progress_total > 0) - percentage = (100.f * (gdouble)progress_done) / (gdouble)progress_total; - fu_device_set_progress(self, (guint)percentage); -} - -/** - * fu_device_sleep_with_progress: - * @self: a #FuDevice - * @delay_secs: the delay in seconds - * - * Sleeps, setting the device progress from 0..100% as time continues. - * The value is gven in whole seconds as it does not make sense to show the - * progressbar advancing so quickly for durations of less than one second. - * - * Since: 1.5.0 - **/ -void -fu_device_sleep_with_progress(FuDevice *self, guint delay_secs) -{ - gulong delay_us_pc = (delay_secs * G_USEC_PER_SEC) / 100; - - g_return_if_fail(FU_IS_DEVICE(self)); - g_return_if_fail(delay_secs > 0); - - fu_device_set_progress(self, 0); - for (guint i = 0; i < 100; i++) { - g_usleep(delay_us_pc); - fu_device_set_progress(self, i + 1); - } -} - /** * fu_device_set_update_state: * @self: a #FuDevice @@ -3547,6 +3422,7 @@ fu_device_get_results(FuDevice *self, GError **error) * fu_device_write_firmware: * @self: a #FuDevice * @fw: firmware blob + * @progress: a #FuProgress * @flags: install flags, e.g. %FWUPD_INSTALL_FLAG_FORCE * @error: (nullable): optional return location for an error * @@ -3557,7 +3433,11 @@ fu_device_get_results(FuDevice *self, GError **error) * Since: 1.0.8 **/ gboolean -fu_device_write_firmware(FuDevice *self, GBytes *fw, FwupdInstallFlags flags, GError **error) +fu_device_write_firmware(FuDevice *self, + GBytes *fw, + FuProgress *progress, + FwupdInstallFlags flags, + GError **error) { FuDeviceClass *klass = FU_DEVICE_GET_CLASS(self); FuDevicePrivate *priv = GET_PRIVATE(self); @@ -3565,6 +3445,7 @@ fu_device_write_firmware(FuDevice *self, GBytes *fw, FwupdInstallFlags flags, GE g_autofree gchar *str = NULL; g_return_val_if_fail(FU_IS_DEVICE(self), FALSE); + g_return_val_if_fail(FU_IS_PROGRESS(progress), FALSE); g_return_val_if_fail(error == NULL || *error == NULL, FALSE); /* no plugin-specific method */ @@ -3574,6 +3455,7 @@ fu_device_write_firmware(FuDevice *self, GBytes *fw, FwupdInstallFlags flags, GE } /* prepare (e.g. decompress) firmware */ + fu_progress_set_status(progress, FWUPD_STATUS_DECOMPRESSING); firmware = fu_device_prepare_firmware(self, fw, flags, error); if (firmware == NULL) return FALSE; @@ -3581,7 +3463,7 @@ fu_device_write_firmware(FuDevice *self, GBytes *fw, FwupdInstallFlags flags, GE g_debug("installing onto %s:\n%s", fu_device_get_id(self), str); /* call vfunc */ - if (!klass->write_firmware(self, firmware, flags, error)) + if (!klass->write_firmware(self, firmware, progress, flags, error)) return FALSE; /* the device set an UpdateMessage (possibly from a quirk, or XML file) @@ -3633,7 +3515,6 @@ fu_device_prepare_firmware(FuDevice *self, GBytes *fw, FwupdInstallFlags flags, /* optionally subclassed */ if (klass->prepare_firmware != NULL) { - fu_device_set_status(self, FWUPD_STATUS_DECOMPRESSING); firmware = klass->prepare_firmware(self, fw, flags, error); if (firmware == NULL) return NULL; @@ -3674,6 +3555,7 @@ fu_device_prepare_firmware(FuDevice *self, GBytes *fw, FwupdInstallFlags flags, /** * fu_device_read_firmware: * @self: a #FuDevice + * @progress: a #FuProgress * @error: (nullable): optional return location for an error * * Reads firmware from the device by calling a plugin-specific vfunc. @@ -3688,12 +3570,13 @@ fu_device_prepare_firmware(FuDevice *self, GBytes *fw, FwupdInstallFlags flags, * Since: 1.0.8 **/ FuFirmware * -fu_device_read_firmware(FuDevice *self, GError **error) +fu_device_read_firmware(FuDevice *self, FuProgress *progress, GError **error) { FuDeviceClass *klass = FU_DEVICE_GET_CLASS(self); g_autoptr(GBytes) fw = NULL; g_return_val_if_fail(FU_IS_DEVICE(self), NULL); + g_return_val_if_fail(FU_IS_PROGRESS(progress), NULL); g_return_val_if_fail(error == NULL || *error == NULL, NULL); /* device does not support reading for verification CRCs */ @@ -3704,10 +3587,10 @@ fu_device_read_firmware(FuDevice *self, GError **error) /* call vfunc */ if (klass->read_firmware != NULL) - return klass->read_firmware(self, error); + return klass->read_firmware(self, progress, error); /* use the default FuFirmware when only ->dump_firmware is provided */ - fw = fu_device_dump_firmware(self, error); + fw = fu_device_dump_firmware(self, progress, error); if (fw == NULL) return NULL; return fu_firmware_new_from_bytes(fw); @@ -3716,6 +3599,7 @@ fu_device_read_firmware(FuDevice *self, GError **error) /** * fu_device_dump_firmware: * @self: a #FuDevice + * @progress: a #FuProgress * @error: (nullable): optional return location for an error * * Reads the raw firmware image from the device by calling a plugin-specific @@ -3728,11 +3612,12 @@ fu_device_read_firmware(FuDevice *self, GError **error) * Since: 1.5.0 **/ GBytes * -fu_device_dump_firmware(FuDevice *self, GError **error) +fu_device_dump_firmware(FuDevice *self, FuProgress *progress, GError **error) { FuDeviceClass *klass = FU_DEVICE_GET_CLASS(self); g_return_val_if_fail(FU_IS_DEVICE(self), NULL); + g_return_val_if_fail(FU_IS_PROGRESS(progress), NULL); g_return_val_if_fail(error == NULL || *error == NULL, NULL); /* use the default FuFirmware when only ->dump_firmware is provided */ @@ -3742,12 +3627,13 @@ fu_device_dump_firmware(FuDevice *self, GError **error) } /* proxy */ - return klass->dump_firmware(self, error); + return klass->dump_firmware(self, progress, error); } /** * fu_device_detach: * @self: a #FuDevice + * @progress: a #FuProgress * @error: (nullable): optional return location for an error * * Detaches a device from the application into bootloader mode. @@ -3757,11 +3643,12 @@ fu_device_dump_firmware(FuDevice *self, GError **error) * Since: 1.0.8 **/ gboolean -fu_device_detach(FuDevice *self, GError **error) +fu_device_detach(FuDevice *self, FuProgress *progress, GError **error) { FuDeviceClass *klass = FU_DEVICE_GET_CLASS(self); g_return_val_if_fail(FU_IS_DEVICE(self), FALSE); + g_return_val_if_fail(FU_IS_PROGRESS(progress), FALSE); g_return_val_if_fail(error == NULL || *error == NULL, FALSE); /* no plugin-specific method */ @@ -3769,12 +3656,13 @@ fu_device_detach(FuDevice *self, GError **error) return TRUE; /* call vfunc */ - return klass->detach(self, error); + return klass->detach(self, progress, error); } /** * fu_device_attach: * @self: a #FuDevice + * @progress: a #FuProgress * @error: (nullable): optional return location for an error * * Attaches a device from the bootloader into application mode. @@ -3784,11 +3672,12 @@ fu_device_detach(FuDevice *self, GError **error) * Since: 1.0.8 **/ gboolean -fu_device_attach(FuDevice *self, GError **error) +fu_device_attach(FuDevice *self, FuProgress *progress, GError **error) { FuDeviceClass *klass = FU_DEVICE_GET_CLASS(self); g_return_val_if_fail(FU_IS_DEVICE(self), FALSE); + g_return_val_if_fail(FU_IS_PROGRESS(progress), FALSE); g_return_val_if_fail(error == NULL || *error == NULL, FALSE); /* no plugin-specific method */ @@ -3796,7 +3685,7 @@ fu_device_attach(FuDevice *self, GError **error) return TRUE; /* call vfunc */ - return klass->attach(self, error); + return klass->attach(self, progress, error); } /** @@ -4126,6 +4015,30 @@ fu_device_rescan(FuDevice *self, GError **error) return TRUE; } +/** + * fu_device_set_progress: + * @self: a #FuDevice + * @progress: a #FuProgress + * + * Sets steps on the progress object used to write firmware. + * + * Since: 1.7.0 + **/ +void +fu_device_set_progress(FuDevice *self, FuProgress *progress) +{ + FuDeviceClass *klass = FU_DEVICE_GET_CLASS(self); + + g_return_if_fail(FU_IS_DEVICE(self)); + g_return_if_fail(FU_IS_PROGRESS(progress)); + g_return_if_fail(FU_IS_PROGRESS(progress)); + + /* subclassed */ + if (klass->set_progress == NULL) + return; + klass->set_progress(self, progress); +} + /** * fu_device_convert_instance_ids: * @self: a #FuDevice @@ -4217,6 +4130,7 @@ fu_device_setup(FuDevice *self, GError **error) /** * fu_device_activate: * @self: a #FuDevice + * @progress: a #FuProgress * @error: (nullable): optional return location for an error * * Activates up a device, which normally means the device switches to a new @@ -4227,16 +4141,17 @@ fu_device_setup(FuDevice *self, GError **error) * Since: 1.2.6 **/ gboolean -fu_device_activate(FuDevice *self, GError **error) +fu_device_activate(FuDevice *self, FuProgress *progress, GError **error) { FuDeviceClass *klass = FU_DEVICE_GET_CLASS(self); g_return_val_if_fail(FU_IS_DEVICE(self), FALSE); + g_return_val_if_fail(FU_IS_PROGRESS(progress), FALSE); g_return_val_if_fail(error == NULL || *error == NULL, FALSE); /* subclassed */ if (klass->activate != NULL) { - if (!klass->activate(self, error)) + if (!klass->activate(self, progress, error)) return FALSE; } @@ -4647,15 +4562,6 @@ fu_device_class_init(FuDeviceClass *klass) G_PARAM_READWRITE | G_PARAM_STATIC_NAME); g_object_class_install_property(object_class, PROP_BACKEND_ID, pspec); - pspec = g_param_spec_uint("progress", - NULL, - NULL, - 0, - 100, - 0, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME); - g_object_class_install_property(object_class, PROP_PROGRESS, pspec); - pspec = g_param_spec_uint("battery-level", NULL, NULL, diff --git a/libfwupdplugin/fu-device.h b/libfwupdplugin/fu-device.h index 699361f50..e244b3a6b 100644 --- a/libfwupdplugin/fu-device.h +++ b/libfwupdplugin/fu-device.h @@ -12,6 +12,7 @@ #include "fu-common-version.h" #include "fu-context.h" #include "fu-firmware.h" +#include "fu-progress.h" #include "fu-security-attrs.h" #define FU_TYPE_DEVICE (fu_device_get_type()) @@ -23,11 +24,18 @@ struct _FuDeviceClass { void (*to_string)(FuDevice *self, guint indent, GString *str); gboolean (*write_firmware)(FuDevice *self, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) G_GNUC_WARN_UNUSED_RESULT; - FuFirmware *(*read_firmware)(FuDevice *self, GError **error)G_GNUC_WARN_UNUSED_RESULT; - gboolean (*detach)(FuDevice *self, GError **error) G_GNUC_WARN_UNUSED_RESULT; - gboolean (*attach)(FuDevice *self, GError **error) G_GNUC_WARN_UNUSED_RESULT; + FuFirmware *(*read_firmware)(FuDevice *self, + FuProgress *progress, + GError **error)G_GNUC_WARN_UNUSED_RESULT; + gboolean (*detach)(FuDevice *self, + FuProgress *progress, + GError **error) G_GNUC_WARN_UNUSED_RESULT; + gboolean (*attach)(FuDevice *self, + FuProgress *progress, + GError **error) G_GNUC_WARN_UNUSED_RESULT; gboolean (*open)(FuDevice *self, GError **error) G_GNUC_WARN_UNUSED_RESULT; gboolean (*close)(FuDevice *self, GError **error) G_GNUC_WARN_UNUSED_RESULT; gboolean (*probe)(FuDevice *self, GError **error) G_GNUC_WARN_UNUSED_RESULT; @@ -43,7 +51,9 @@ struct _FuDeviceClass { gboolean (*setup)(FuDevice *self, GError **error) G_GNUC_WARN_UNUSED_RESULT; void (*incorporate)(FuDevice *self, FuDevice *donor); gboolean (*poll)(FuDevice *self, GError **error) G_GNUC_WARN_UNUSED_RESULT; - gboolean (*activate)(FuDevice *self, GError **error) G_GNUC_WARN_UNUSED_RESULT; + gboolean (*activate)(FuDevice *self, + FuProgress *progress, + GError **error) G_GNUC_WARN_UNUSED_RESULT; gboolean (*reload)(FuDevice *self, GError **error) G_GNUC_WARN_UNUSED_RESULT; gboolean (*prepare)(FuDevice *self, FwupdInstallFlags flags, @@ -58,7 +68,9 @@ struct _FuDeviceClass { const gchar *driver, GError **error) G_GNUC_WARN_UNUSED_RESULT; gboolean (*unbind_driver)(FuDevice *self, GError **error) G_GNUC_WARN_UNUSED_RESULT; - GBytes *(*dump_firmware)(FuDevice *self, GError **error)G_GNUC_WARN_UNUSED_RESULT; + GBytes *(*dump_firmware)(FuDevice *self, + FuProgress *progress, + GError **error)G_GNUC_WARN_UNUSED_RESULT; void (*add_security_attrs)(FuDevice *self, FuSecurityAttrs *attrs); gboolean (*ready)(FuDevice *self, GError **error) G_GNUC_WARN_UNUSED_RESULT; void (*child_added)(FuDevice *self, /* signal */ @@ -68,8 +80,9 @@ struct _FuDeviceClass { void (*request)(FuDevice *self, /* signal */ FwupdRequest *request); gboolean (*get_results)(FuDevice *self, GError **error) G_GNUC_WARN_UNUSED_RESULT; + void (*set_progress)(FuDevice *self, FuProgress *progress); /*< private >*/ - gpointer padding[5]; + gpointer padding[16]; #endif }; @@ -498,10 +511,6 @@ guint fu_device_get_remove_delay(FuDevice *self); void fu_device_set_remove_delay(FuDevice *self, guint remove_delay); -FwupdStatus -fu_device_get_status(FuDevice *self); -void -fu_device_set_status(FuDevice *self, FwupdStatus status); void fu_device_set_firmware_size(FuDevice *self, guint64 size); void @@ -513,10 +522,6 @@ fu_device_get_firmware_size_min(FuDevice *self); guint64 fu_device_get_firmware_size_max(FuDevice *self); guint -fu_device_get_progress(FuDevice *self); -void -fu_device_set_progress(FuDevice *self, guint progress); -guint fu_device_get_battery_level(FuDevice *self); void fu_device_set_battery_level(FuDevice *self, guint battery_level); @@ -525,10 +530,6 @@ fu_device_get_battery_threshold(FuDevice *self); void fu_device_set_battery_threshold(FuDevice *self, guint battery_threshold); void -fu_device_set_progress_full(FuDevice *self, gsize progress_done, gsize progress_total); -void -fu_device_sleep_with_progress(FuDevice *self, guint delay_secs); -void fu_device_set_update_state(FuDevice *self, FwupdUpdateState update_state); void fu_device_set_context(FuDevice *self, FuContext *ctx); @@ -547,19 +548,26 @@ fu_device_has_internal_flag(FuDevice *self, FuDeviceInternalFlags flag); gboolean fu_device_get_results(FuDevice *self, GError **error); gboolean -fu_device_write_firmware(FuDevice *self, GBytes *fw, FwupdInstallFlags flags, GError **error) - G_GNUC_WARN_UNUSED_RESULT; +fu_device_write_firmware(FuDevice *self, + GBytes *fw, + FuProgress *progress, + FwupdInstallFlags flags, + GError **error) G_GNUC_WARN_UNUSED_RESULT; FuFirmware * fu_device_prepare_firmware(FuDevice *self, GBytes *fw, FwupdInstallFlags flags, GError **error) G_GNUC_WARN_UNUSED_RESULT; FuFirmware * -fu_device_read_firmware(FuDevice *self, GError **error) G_GNUC_WARN_UNUSED_RESULT; +fu_device_read_firmware(FuDevice *self, + FuProgress *progress, + GError **error) G_GNUC_WARN_UNUSED_RESULT; GBytes * -fu_device_dump_firmware(FuDevice *self, GError **error) G_GNUC_WARN_UNUSED_RESULT; +fu_device_dump_firmware(FuDevice *self, + FuProgress *progress, + GError **error) G_GNUC_WARN_UNUSED_RESULT; gboolean -fu_device_attach(FuDevice *self, GError **error) G_GNUC_WARN_UNUSED_RESULT; +fu_device_attach(FuDevice *self, FuProgress *progress, GError **error) G_GNUC_WARN_UNUSED_RESULT; gboolean -fu_device_detach(FuDevice *self, GError **error) G_GNUC_WARN_UNUSED_RESULT; +fu_device_detach(FuDevice *self, FuProgress *progress, GError **error) G_GNUC_WARN_UNUSED_RESULT; gboolean fu_device_reload(FuDevice *self, GError **error) G_GNUC_WARN_UNUSED_RESULT; gboolean @@ -585,7 +593,7 @@ fu_device_setup(FuDevice *self, GError **error) G_GNUC_WARN_UNUSED_RESULT; gboolean fu_device_rescan(FuDevice *self, GError **error) G_GNUC_WARN_UNUSED_RESULT; gboolean -fu_device_activate(FuDevice *self, GError **error) G_GNUC_WARN_UNUSED_RESULT; +fu_device_activate(FuDevice *self, FuProgress *progress, GError **error) G_GNUC_WARN_UNUSED_RESULT; void fu_device_probe_invalidate(FuDevice *self); gboolean diff --git a/libfwupdplugin/fu-plugin-private.h b/libfwupdplugin/fu-plugin-private.h index 046a44d3a..6257cc117 100644 --- a/libfwupdplugin/fu-plugin-private.h +++ b/libfwupdplugin/fu-plugin-private.h @@ -57,9 +57,11 @@ fu_plugin_runner_composite_cleanup(FuPlugin *self, GPtrArray *devices, GError **error) G_GNUC_WARN_UNUSED_RESULT; gboolean -fu_plugin_runner_attach(FuPlugin *self, FuDevice *device, GError **error) G_GNUC_WARN_UNUSED_RESULT; +fu_plugin_runner_attach(FuPlugin *self, FuDevice *device, FuProgress *progress, GError **error) + G_GNUC_WARN_UNUSED_RESULT; gboolean -fu_plugin_runner_detach(FuPlugin *self, FuDevice *device, GError **error) G_GNUC_WARN_UNUSED_RESULT; +fu_plugin_runner_detach(FuPlugin *self, FuDevice *device, FuProgress *progress, GError **error) + G_GNUC_WARN_UNUSED_RESULT; gboolean fu_plugin_runner_reload(FuPlugin *self, FuDevice *device, GError **error) G_GNUC_WARN_UNUSED_RESULT; gboolean @@ -84,13 +86,17 @@ gboolean fu_plugin_runner_write_firmware(FuPlugin *self, FuDevice *device, GBytes *blob_fw, + FuProgress *progress, FwupdInstallFlags flags, GError **error) G_GNUC_WARN_UNUSED_RESULT; gboolean -fu_plugin_runner_verify(FuPlugin *self, FuDevice *device, FuPluginVerifyFlags flags, GError **error) - G_GNUC_WARN_UNUSED_RESULT; +fu_plugin_runner_verify(FuPlugin *self, + FuDevice *device, + FuProgress *progress, + FuPluginVerifyFlags flags, + GError **error) G_GNUC_WARN_UNUSED_RESULT; gboolean -fu_plugin_runner_activate(FuPlugin *self, FuDevice *device, GError **error); +fu_plugin_runner_activate(FuPlugin *self, FuDevice *device, FuProgress *progress, GError **error); gboolean fu_plugin_runner_unlock(FuPlugin *self, FuDevice *device, GError **error) G_GNUC_WARN_UNUSED_RESULT; gboolean diff --git a/libfwupdplugin/fu-plugin-vfuncs.h b/libfwupdplugin/fu-plugin-vfuncs.h index 40b075bed..a2a656e0e 100644 --- a/libfwupdplugin/fu-plugin-vfuncs.h +++ b/libfwupdplugin/fu-plugin-vfuncs.h @@ -98,6 +98,7 @@ fu_plugin_coldplug_cleanup(FuPlugin *plugin, GError **error); * @plugin: a plugin * @dev: a device * @blob_fw: a data blob + * @progress: a #FuProgress * @flags: install flags * @error: (nullable): optional return location for an error * @@ -109,6 +110,7 @@ gboolean fu_plugin_write_firmware(FuPlugin *plugin, FuDevice *dev, GBytes *blob_fw, + FuProgress *progress, FwupdInstallFlags flags, GError **error); /** @@ -150,7 +152,7 @@ fu_plugin_unlock(FuPlugin *plugin, FuDevice *dev, GError **error); * Since: 1.2.6 **/ gboolean -fu_plugin_activate(FuPlugin *plugin, FuDevice *dev, GError **error); +fu_plugin_activate(FuPlugin *plugin, FuDevice *dev, FuProgress *progress, GError **error); /** * fu_plugin_clear_results: * @plugin: a plugin @@ -186,7 +188,7 @@ fu_plugin_get_results(FuPlugin *plugin, FuDevice *dev, GError **error); * Since: 1.0.2 **/ gboolean -fu_plugin_attach(FuPlugin *plugin, FuDevice *dev, GError **error); +fu_plugin_attach(FuPlugin *plugin, FuDevice *dev, FuProgress *progress, GError **error); /** * fu_plugin_detach: * @plugin: a plugin @@ -198,7 +200,7 @@ fu_plugin_attach(FuPlugin *plugin, FuDevice *dev, GError **error); * Since: 1.7.0 **/ gboolean -fu_plugin_detach(FuPlugin *plugin, FuDevice *dev, GError **error); +fu_plugin_detach(FuPlugin *plugin, FuDevice *dev, FuProgress *progress, GError **error); /** * fu_plugin_prepare: * @plugin: a plugin diff --git a/libfwupdplugin/fu-plugin.c b/libfwupdplugin/fu-plugin.c index c0bc7e2cf..205362c51 100644 --- a/libfwupdplugin/fu-plugin.c +++ b/libfwupdplugin/fu-plugin.c @@ -68,6 +68,10 @@ typedef void (*FuPluginInitFunc)(FuPlugin *self); typedef gboolean (*FuPluginStartupFunc)(FuPlugin *self, GError **error); typedef void (*FuPluginDeviceRegisterFunc)(FuPlugin *self, FuDevice *device); typedef gboolean (*FuPluginDeviceFunc)(FuPlugin *self, FuDevice *device, GError **error); +typedef gboolean (*FuPluginDeviceProgressFunc)(FuPlugin *self, + FuDevice *device, + FuProgress *progress, + GError **error); typedef gboolean (*FuPluginFlaggedDeviceFunc)(FuPlugin *self, FuDevice *device, FwupdInstallFlags flags, @@ -80,6 +84,7 @@ typedef gboolean (*FuPluginVerifyFunc)(FuPlugin *self, typedef gboolean (*FuPluginUpdateFunc)(FuPlugin *self, FuDevice *device, GBytes *blob_fw, + FuProgress *progress, FwupdInstallFlags flags, GError **error); typedef void (*FuPluginSecurityAttrsFunc)(FuPlugin *self, FuSecurityAttrs *attrs); @@ -670,42 +675,43 @@ fu_plugin_get_context(FuPlugin *self) } static gboolean -fu_plugin_device_attach(FuPlugin *self, FuDevice *device, GError **error) +fu_plugin_device_attach(FuPlugin *self, FuDevice *device, FuProgress *progress, GError **error) { FuDevice *proxy = fu_device_get_proxy_with_fallback(device); g_autoptr(FuDeviceLocker) locker = NULL; locker = fu_device_locker_new(proxy, error); if (locker == NULL) return FALSE; - return fu_device_attach(device, error); + return fu_device_attach(device, progress, error); } static gboolean -fu_plugin_device_detach(FuPlugin *self, FuDevice *device, GError **error) +fu_plugin_device_detach(FuPlugin *self, FuDevice *device, FuProgress *progress, GError **error) { FuDevice *proxy = fu_device_get_proxy_with_fallback(device); g_autoptr(FuDeviceLocker) locker = NULL; locker = fu_device_locker_new(proxy, error); if (locker == NULL) return FALSE; - return fu_device_detach(device, error); + return fu_device_detach(device, progress, error); } static gboolean -fu_plugin_device_activate(FuPlugin *self, FuDevice *device, GError **error) +fu_plugin_device_activate(FuPlugin *self, FuDevice *device, FuProgress *progress, GError **error) { FuDevice *proxy = fu_device_get_proxy_with_fallback(device); g_autoptr(FuDeviceLocker) locker = NULL; locker = fu_device_locker_new(proxy, error); if (locker == NULL) return FALSE; - return fu_device_activate(device, error); + return fu_device_activate(device, progress, error); } static gboolean fu_plugin_device_write_firmware(FuPlugin *self, FuDevice *device, GBytes *fw, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -722,7 +728,7 @@ fu_plugin_device_write_firmware(FuPlugin *self, g_autofree gchar *fn = NULL; g_autofree gchar *localstatedir = NULL; - fw_old = fu_device_dump_firmware(device, error); + fw_old = fu_device_dump_firmware(device, progress, error); if (fw_old == NULL) { g_prefix_error(error, "failed to backup old firmware: "); return FALSE; @@ -740,7 +746,7 @@ fu_plugin_device_write_firmware(FuPlugin *self, return FALSE; } - return fu_device_write_firmware(device, fw, flags, error); + return fu_device_write_firmware(device, fw, progress, flags, error); } static gboolean @@ -761,7 +767,10 @@ fu_plugin_device_get_results(FuPlugin *self, FuDevice *device, GError **error) } static gboolean -fu_plugin_device_read_firmware(FuPlugin *self, FuDevice *device, GError **error) +fu_plugin_device_read_firmware(FuPlugin *self, + FuDevice *device, + FuProgress *progress, + GError **error) { FuDevice *proxy = fu_device_get_proxy_with_fallback(device); g_autoptr(FuDeviceLocker) locker = NULL; @@ -771,12 +780,12 @@ fu_plugin_device_read_firmware(FuPlugin *self, FuDevice *device, GError **error) locker = fu_device_locker_new(proxy, error); if (locker == NULL) return FALSE; - if (!fu_device_detach(device, error)) + if (!fu_device_detach(device, progress, error)) return FALSE; - firmware = fu_device_read_firmware(device, error); + firmware = fu_device_read_firmware(device, progress, error); if (firmware == NULL) { g_autoptr(GError) error_local = NULL; - if (!fu_device_attach(device, &error_local)) + if (!fu_device_attach(device, progress, &error_local)) g_debug("ignoring attach failure: %s", error_local->message); g_prefix_error(error, "failed to read firmware: "); return FALSE; @@ -784,7 +793,7 @@ fu_plugin_device_read_firmware(FuPlugin *self, FuDevice *device, GError **error) fw = fu_firmware_write(firmware, error); if (fw == NULL) { g_autoptr(GError) error_local = NULL; - if (!fu_device_attach(device, &error_local)) + if (!fu_device_attach(device, progress, &error_local)) g_debug("ignoring attach failure: %s", error_local->message); g_prefix_error(error, "failed to write firmware: "); return FALSE; @@ -794,7 +803,7 @@ fu_plugin_device_read_firmware(FuPlugin *self, FuDevice *device, GError **error) hash = g_compute_checksum_for_bytes(checksum_types[i], fw); fu_device_add_checksum(device, hash); } - return fu_device_attach(device, error); + return fu_device_attach(device, progress, error); } /** @@ -909,6 +918,58 @@ fu_plugin_runner_device_generic(FuPlugin *self, return TRUE; } +static gboolean +fu_plugin_runner_device_generic_progress(FuPlugin *self, + FuDevice *device, + FuProgress *progress, + const gchar *symbol_name, + FuPluginDeviceProgressFunc device_func, + GError **error) +{ + FuPluginPrivate *priv = GET_PRIVATE(self); + FuPluginDeviceProgressFunc func = NULL; + g_autoptr(GError) error_local = NULL; + + /* not enabled */ + if (fu_plugin_has_flag(self, FWUPD_PLUGIN_FLAG_DISABLED)) + return TRUE; + + /* no object loaded */ + if (priv->module == NULL) + return TRUE; + + /* optional */ + g_module_symbol(priv->module, symbol_name, (gpointer *)&func); + if (func == NULL) { + if (device_func != NULL) { + g_debug("running superclassed %s(%s)", + symbol_name + 10, + fu_plugin_get_name(self)); + return device_func(self, device, progress, error); + } + return TRUE; + } + g_debug("%s(%s)", symbol_name + 10, fu_plugin_get_name(self)); + if (!func(self, device, progress, &error_local)) { + if (error_local == NULL) { + g_critical("unset plugin error in %s(%s)", + fu_plugin_get_name(self), + symbol_name + 10); + g_set_error_literal(&error_local, + FWUPD_ERROR, + FWUPD_ERROR_INTERNAL, + "unspecified error"); + } + g_propagate_prefixed_error(error, + g_steal_pointer(&error_local), + "failed to %s using %s: ", + symbol_name + 10, + fu_plugin_get_name(self)); + return FALSE; + } + return TRUE; +} + static gboolean fu_plugin_runner_flagged_device_generic(FuPlugin *self, FuDevice *device, @@ -1238,6 +1299,7 @@ fu_plugin_runner_cleanup(FuPlugin *self, FuDevice *device, FwupdInstallFlags fla * fu_plugin_runner_attach: * @self: a #FuPlugin * @device: a device + * @progress: a #FuProgress * @error: (nullable): optional return location for an error * * Runs the update_attach routine for the plugin @@ -1247,19 +1309,21 @@ fu_plugin_runner_cleanup(FuPlugin *self, FuDevice *device, FwupdInstallFlags fla * Since: 1.7.0 **/ gboolean -fu_plugin_runner_attach(FuPlugin *self, FuDevice *device, GError **error) +fu_plugin_runner_attach(FuPlugin *self, FuDevice *device, FuProgress *progress, GError **error) { - return fu_plugin_runner_device_generic(self, - device, - "fu_plugin_attach", - fu_plugin_device_attach, - error); + return fu_plugin_runner_device_generic_progress(self, + device, + progress, + "fu_plugin_attach", + fu_plugin_device_attach, + error); } /** * fu_plugin_runner_detach: * @self: a #FuPlugin * @device: a device + * @progress: a #FuProgress * @error: (nullable): optional return location for an error * * Runs the update_detach routine for the plugin @@ -1269,13 +1333,14 @@ fu_plugin_runner_attach(FuPlugin *self, FuDevice *device, GError **error) * Since: 1.7.0 **/ gboolean -fu_plugin_runner_detach(FuPlugin *self, FuDevice *device, GError **error) +fu_plugin_runner_detach(FuPlugin *self, FuDevice *device, FuProgress *progress, GError **error) { - return fu_plugin_runner_device_generic(self, - device, - "fu_plugin_detach", - fu_plugin_device_detach, - error); + return fu_plugin_runner_device_generic_progress(self, + device, + progress, + "fu_plugin_detach", + fu_plugin_device_detach, + error); } /** @@ -1770,6 +1835,7 @@ fu_plugin_runner_device_created(FuPlugin *self, FuDevice *device, GError **error * fu_plugin_runner_verify: * @self: a #FuPlugin * @device: a device + * @progress: a #FuProgress * @flags: verify flags * @error: (nullable): optional return location for an error * @@ -1780,7 +1846,11 @@ fu_plugin_runner_device_created(FuPlugin *self, FuDevice *device, GError **error * Since: 0.8.0 **/ gboolean -fu_plugin_runner_verify(FuPlugin *self, FuDevice *device, FuPluginVerifyFlags flags, GError **error) +fu_plugin_runner_verify(FuPlugin *self, + FuDevice *device, + FuProgress *progress, + FuPluginVerifyFlags flags, + GError **error) { FuPluginPrivate *priv = GET_PRIVATE(self); FuPluginVerifyFunc func = NULL; @@ -1789,6 +1859,7 @@ fu_plugin_runner_verify(FuPlugin *self, FuDevice *device, FuPluginVerifyFlags fl g_return_val_if_fail(FU_IS_PLUGIN(self), FALSE); g_return_val_if_fail(FU_IS_DEVICE(device), FALSE); + g_return_val_if_fail(FU_IS_PROGRESS(progress), FALSE); g_return_val_if_fail(error == NULL || *error == NULL, FALSE); /* not enabled */ @@ -1810,7 +1881,7 @@ fu_plugin_runner_verify(FuPlugin *self, FuDevice *device, FuPluginVerifyFlags fl fu_device_get_id(device)); return FALSE; } - return fu_plugin_device_read_firmware(self, device, error); + return fu_plugin_device_read_firmware(self, device, progress, error); } /* clear any existing verification checksums */ @@ -1818,11 +1889,12 @@ fu_plugin_runner_verify(FuPlugin *self, FuDevice *device, FuPluginVerifyFlags fl g_ptr_array_set_size(checksums, 0); /* run additional detach */ - if (!fu_plugin_runner_device_generic(self, - device, - "fu_plugin_detach", - fu_plugin_device_detach, - error)) + if (!fu_plugin_runner_device_generic_progress(self, + device, + progress, + "fu_plugin_detach", + fu_plugin_device_detach, + error)) return FALSE; /* run vfunc */ @@ -1841,11 +1913,12 @@ fu_plugin_runner_verify(FuPlugin *self, FuDevice *device, FuPluginVerifyFlags fl "failed to verify using %s: ", fu_plugin_get_name(self)); /* make the device "work" again, but don't prefix the error */ - if (!fu_plugin_runner_device_generic(self, - device, - "fu_plugin_attach", - fu_plugin_device_attach, - &error_attach)) { + if (!fu_plugin_runner_device_generic_progress(self, + device, + progress, + "fu_plugin_attach", + fu_plugin_device_attach, + &error_attach)) { g_warning("failed to attach whilst aborting verify(): %s", error_attach->message); } @@ -1853,11 +1926,12 @@ fu_plugin_runner_verify(FuPlugin *self, FuDevice *device, FuPluginVerifyFlags fl } /* run optional attach */ - if (!fu_plugin_runner_device_generic(self, - device, - "fu_plugin_attach", - fu_plugin_device_attach, - error)) + if (!fu_plugin_runner_device_generic_progress(self, + device, + progress, + "fu_plugin_attach", + fu_plugin_device_attach, + error)) return FALSE; /* success */ @@ -1868,6 +1942,7 @@ fu_plugin_runner_verify(FuPlugin *self, FuDevice *device, FuPluginVerifyFlags fl * fu_plugin_runner_activate: * @self: a #FuPlugin * @device: a device + * @progress: a #FuProgress * @error: (nullable): optional return location for an error * * Call into the plugin's activate routine @@ -1877,12 +1952,13 @@ fu_plugin_runner_verify(FuPlugin *self, FuDevice *device, FuPluginVerifyFlags fl * Since: 1.2.6 **/ gboolean -fu_plugin_runner_activate(FuPlugin *self, FuDevice *device, GError **error) +fu_plugin_runner_activate(FuPlugin *self, FuDevice *device, FuProgress *progress, GError **error) { guint64 flags; g_return_val_if_fail(FU_IS_PLUGIN(self), FALSE); g_return_val_if_fail(FU_IS_DEVICE(device), FALSE); + g_return_val_if_fail(FU_IS_PROGRESS(progress), FALSE); g_return_val_if_fail(error == NULL || *error == NULL, FALSE); /* final check */ @@ -1897,11 +1973,12 @@ fu_plugin_runner_activate(FuPlugin *self, FuDevice *device, GError **error) } /* run vfunc */ - if (!fu_plugin_runner_device_generic(self, - device, - "fu_plugin_activate", - fu_plugin_device_activate, - error)) + if (!fu_plugin_runner_device_generic_progress(self, + device, + progress, + "fu_plugin_activate", + fu_plugin_device_activate, + error)) return FALSE; /* update with correct flags */ @@ -1957,6 +2034,7 @@ fu_plugin_runner_unlock(FuPlugin *self, FuDevice *device, GError **error) * @self: a #FuPlugin * @device: a device * @blob_fw: a data blob + * @progress: a #FuProgress * @flags: install flags * @error: (nullable): optional return location for an error * @@ -1970,6 +2048,7 @@ gboolean fu_plugin_runner_write_firmware(FuPlugin *self, FuDevice *device, GBytes *blob_fw, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -1979,6 +2058,7 @@ fu_plugin_runner_write_firmware(FuPlugin *self, g_return_val_if_fail(FU_IS_PLUGIN(self), FALSE); g_return_val_if_fail(FU_IS_DEVICE(device), FALSE); + g_return_val_if_fail(FU_IS_PROGRESS(progress), FALSE); g_return_val_if_fail(error == NULL || *error == NULL, FALSE); /* not enabled */ @@ -1997,11 +2077,16 @@ fu_plugin_runner_write_firmware(FuPlugin *self, g_module_symbol(priv->module, "fu_plugin_write_firmware", (gpointer *)&update_func); if (update_func == NULL) { g_debug("superclassed write_firmware(%s)", fu_plugin_get_name(self)); - return fu_plugin_device_write_firmware(self, device, blob_fw, flags, error); + return fu_plugin_device_write_firmware(self, + device, + blob_fw, + progress, + flags, + error); } /* online */ - if (!update_func(self, device, blob_fw, flags, &error_local)) { + if (!update_func(self, device, blob_fw, progress, flags, &error_local)) { if (error_local == NULL) { g_critical("unset plugin error in update(%s)", fu_plugin_get_name(self)); g_set_error_literal(&error_local, diff --git a/libfwupdplugin/fu-progress.c b/libfwupdplugin/fu-progress.c new file mode 100644 index 000000000..f27b280c1 --- /dev/null +++ b/libfwupdplugin/fu-progress.c @@ -0,0 +1,921 @@ +/* + * Copyright (C) 2021 Richard Hughes + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#define G_LOG_DOMAIN "FuProgress" + +#include "config.h" + +#include + +#include "fu-progress.h" + +/** + * FuProgress: + * + * Objects can use fu_progress_set_percentage() if the absolute percentage + * is known. Percentages should always go up, not down. + * + * Modules usually set the number of steps that are expected using + * fu_progress_set_steps() and then after each section is completed, + * the fu_progress_step_done() function should be called. This will automatically + * call fu_progress_set_percentage() with the correct values. + * + * #FuProgress allows sub-modules to be "chained up" to the parent module + * so that as the sub-module progresses, so does the parent. + * The child can be reused for each section, and chains can be deep. + * + * To get a child object, you should use fu_progress_get_child() and then + * use the result in any sub-process. You should ensure that the child + * is not re-used without calling fu_progress_step_done(). + * + * There are a few nice touches in this module, so that if a module only has + * one progress step, the child progress is used for parent updates. + * + * static void + * _do_something(FuProgress *self) + * { + * // setup correct number of steps + * fu_progress_set_steps(self, 2); + * + * // run a sub function + * _do_something_else1(fu_progress_get_child(self)); + * + * // this section done + * fu_progress_step_done(self); + * + * // run another sub function + * _do_something_else2(fu_progress_get_child(self)); + * + * // this progress done (all complete) + * fu_progress_step_done(self); + * } + * + * See also: [class@FuDevice] + */ + +typedef struct { + gchar *id; + FuProgressFlags flags; + guint percentage; + FwupdStatus status; + GPtrArray *steps; + gboolean profile; + GTimer *timer; + guint step_now; + guint step_max; + gulong percentage_child_id; + gulong status_child_id; + FuProgress *child; + FuProgress *parent; /* no-ref */ +} FuProgressPrivate; + +typedef struct { + FwupdStatus status; + guint value; + gdouble profile; +} FuProgressStep; + +enum { SIGNAL_PERCENTAGE_CHANGED, SIGNAL_STATUS_CHANGED, SIGNAL_LAST }; + +static guint signals[SIGNAL_LAST] = {0}; + +G_DEFINE_TYPE_WITH_PRIVATE(FuProgress, fu_progress, G_TYPE_OBJECT) +#define GET_PRIVATE(o) (fu_progress_get_instance_private(o)) + +/** + * fu_progress_get_id: + * @self: a #FuProgress + * + * Return the id of the progress, which is normally set by the caller. + * + * Returns: progress ID + * + * Since: 1.7.0 + **/ +const gchar * +fu_progress_get_id(FuProgress *self) +{ + FuProgressPrivate *priv = GET_PRIVATE(self); + g_return_val_if_fail(FU_IS_PROGRESS(self), NULL); + return priv->id; +} + +/** + * fu_progress_set_id: + * @self: a #FuProgress + * @id: progress ID, normally `G_STRLOC` + * + * Sets the id of the progress. + * + * Since: 1.7.0 + **/ +void +fu_progress_set_id(FuProgress *self, const gchar *id) +{ + FuProgressPrivate *priv = GET_PRIVATE(self); + g_return_if_fail(FU_IS_PROGRESS(self)); + g_return_if_fail(id != NULL); + + /* not changed */ + if (g_strcmp0(priv->id, id) == 0) + return; + + /* set id */ + g_free(priv->id); + priv->id = g_strdup(id); +} + +/** + * fu_progress_get_status: + * @self: a #FuProgress + * + * Return the status of the progress, which is normally indirectly by fu_progress_add_step(). + * + * Returns: status + * + * Since: 1.7.0 + **/ +FwupdStatus +fu_progress_get_status(FuProgress *self) +{ + FuProgressPrivate *priv = GET_PRIVATE(self); + g_return_val_if_fail(FU_IS_PROGRESS(self), FWUPD_STATUS_UNKNOWN); + return priv->status; +} + +/** + * fu_progress_flag_to_string: + * @flag: an internal progress flag, e.g. %FU_PROGRESS_FLAG_GUESSED + * + * Converts an progress flag to a string. + * + * Returns: identifier string + * + * Since: 1.7.0 + **/ +const gchar * +fu_progress_flag_to_string(FuProgressFlags flag) +{ + if (flag == FU_PROGRESS_FLAG_GUESSED) + return "guessed"; + if (flag == FU_PROGRESS_FLAG_NO_PROFILE) + return "no-profile"; + return NULL; +} + +/** + * fu_progress_flag_from_string: + * @flag: a string, e.g. `guessed` + * + * Converts a string to an progress flag. + * + * Returns: enumerated value + * + * Since: 1.7.0 + **/ +FuProgressFlags +fu_progress_flag_from_string(const gchar *flag) +{ + if (g_strcmp0(flag, "guessed") == 0) + return FU_PROGRESS_FLAG_GUESSED; + if (g_strcmp0(flag, "no-profile") == 0) + return FU_PROGRESS_FLAG_NO_PROFILE; + return FU_PROGRESS_FLAG_UNKNOWN; +} + +/** + * fu_progress_add_flag: + * @self: a #FuProgress + * @flag: an internal progress flag, e.g. %FU_PROGRESS_FLAG_GUESSED + * + * Adds a flag. + * + * Since: 1.7.0 + **/ +void +fu_progress_add_flag(FuProgress *self, FuProgressFlags flag) +{ + FuProgressPrivate *priv = GET_PRIVATE(self); + g_return_if_fail(FU_IS_PROGRESS(self)); + priv->flags |= flag; +} + +/** + * fu_progress_remove_flag: + * @self: a #FuProgress + * @flag: an internal progress flag, e.g. %FU_PROGRESS_FLAG_GUESSED + * + * Removes a flag. + * + * Since: 1.7.0 + **/ +void +fu_progress_remove_flag(FuProgress *self, FuProgressFlags flag) +{ + FuProgressPrivate *priv = GET_PRIVATE(self); + g_return_if_fail(FU_IS_PROGRESS(self)); + priv->flags &= ~flag; +} + +/** + * fu_progress_has_flag: + * @self: a #FuProgress + * @flag: an internal progress flag, e.g. %FU_PROGRESS_FLAG_GUESSED + * + * Tests for a flag. + * + * Since: 1.7.0 + **/ +gboolean +fu_progress_has_flag(FuProgress *self, FuProgressFlags flag) +{ + FuProgressPrivate *priv = GET_PRIVATE(self); + g_return_val_if_fail(FU_IS_PROGRESS(self), FALSE); + return (priv->flags & flag) > 0; +} + +/** + * fu_progress_set_status: + * @self: a #FuProgress + * @status: device status + * + * Sets the status of the progress. + * + * Since: 1.7.0 + **/ +void +fu_progress_set_status(FuProgress *self, FwupdStatus status) +{ + FuProgressPrivate *priv = GET_PRIVATE(self); + g_return_if_fail(FU_IS_PROGRESS(self)); + + /* not changed */ + if (priv->status == status) + return; + + /* save */ + priv->status = status; + g_signal_emit(self, signals[SIGNAL_STATUS_CHANGED], 0, status); +} + +/** + * fu_progress_get_percentage: + * @self: a #FuProgress + * + * Get the last set progress percentage. + * + * Return value: The percentage value, or %G_MAXUINT for error + * + * Since: 1.7.0 + **/ +guint +fu_progress_get_percentage(FuProgress *self) +{ + FuProgressPrivate *priv = GET_PRIVATE(self); + g_return_val_if_fail(FU_IS_PROGRESS(self), G_MAXUINT); + return priv->percentage; +} + +static void +fu_progress_build_parent_chain(FuProgress *self, GString *str, guint level) +{ + FuProgressPrivate *priv = GET_PRIVATE(self); + if (priv->parent != NULL) + fu_progress_build_parent_chain(priv->parent, str, level + 1); + g_string_append_printf(str, + "%u) %s (%u/%u)\n", + level, + priv->id, + priv->step_now, + priv->step_max); +} + +/** + * fu_progress_set_percentage: + * @self: a #FuProgress + * @percentage: value between 0% and 100% + * + * Sets the progress percentage complete. + * + * NOTE: this must be above what was previously set, or it will be rejected. + * + * Since: 1.7.0 + **/ +void +fu_progress_set_percentage(FuProgress *self, guint percentage) +{ + FuProgressPrivate *priv = GET_PRIVATE(self); + g_return_if_fail(FU_IS_PROGRESS(self)); + g_return_if_fail(percentage <= 100); + + /* is it the same */ + if (percentage == priv->percentage) + return; + + /* is it less */ + if (percentage < priv->percentage) { + if (priv->profile) { + g_autoptr(GString) str = g_string_new(NULL); + fu_progress_build_parent_chain(self, str, 0); + g_warning("percentage should not go down from %u to %u: %s", + priv->percentage, + percentage, + str->str); + } + return; + } + + /* save */ + priv->percentage = percentage; + g_signal_emit(self, signals[SIGNAL_PERCENTAGE_CHANGED], 0, percentage); +} + +/** + * fu_progress_set_percentage_full: + * @self: a #FuDevice + * @progress_done: the bytes already done + * @progress_total: the total number of bytes + * + * Sets the progress completion using the raw progress values. + * + * Since: 1.7.0 + **/ +void +fu_progress_set_percentage_full(FuProgress *self, gsize progress_done, gsize progress_total) +{ + gdouble percentage = 0.f; + g_return_if_fail(FU_IS_PROGRESS(self)); + g_return_if_fail(progress_done <= progress_total); + if (progress_total > 0) + percentage = (100.f * (gdouble)progress_done) / (gdouble)progress_total; + fu_progress_set_percentage(self, (guint)percentage); +} + +/** + * fu_progress_set_profile: + * @self: A #FuProgress + * @profile: if profiling should be enabled + * + * This enables profiling of FuProgress. This may be useful in development, + * but be warned; enabling profiling makes #FuProgress very slow. + * + * Since: 1.7.0 + **/ +void +fu_progress_set_profile(FuProgress *self, gboolean profile) +{ + FuProgressPrivate *priv = GET_PRIVATE(self); + g_return_if_fail(FU_IS_PROGRESS(self)); + priv->profile = profile; +} + +/** + * fu_progress_get_profile: + * @self: A #FuProgress + * @profile: + * + * Returns if the profile is enabled for this progress. + * + * Return value: if profiling should be enabled + * + * Since: 1.7.0 + **/ +static gboolean +fu_progress_get_profile(FuProgress *self) +{ + FuProgressPrivate *priv = GET_PRIVATE(self); + g_return_val_if_fail(FU_IS_PROGRESS(self), FALSE); + return priv->profile; +} + +/** + * fu_progress_reset: + * @self: A #FuProgress + * + * Resets the #FuProgress object to unset + * + * Since: 1.7.0 + **/ +void +fu_progress_reset(FuProgress *self) +{ + FuProgressPrivate *priv = GET_PRIVATE(self); + g_return_if_fail(FU_IS_PROGRESS(self)); + + /* reset values */ + priv->step_max = 0; + priv->step_now = 0; + priv->percentage = 0; + + /* only use the timer if profiling; it's expensive */ + if (priv->profile) + g_timer_start(priv->timer); + + /* disconnect client */ + if (priv->percentage_child_id != 0) { + g_signal_handler_disconnect(priv->child, priv->percentage_child_id); + priv->percentage_child_id = 0; + } + if (priv->status_child_id != 0) { + g_signal_handler_disconnect(priv->child, priv->status_child_id); + priv->status_child_id = 0; + } + g_clear_object(&priv->child); + + /* no more step data */ + g_ptr_array_set_size(priv->steps, 0); +} + +/** + * fu_progress_set_steps: + * @self: A #FuProgress + * @step_max: The number of sub-tasks in this progress, can be 0 + * + * Sets the number of sub-tasks, i.e. how many times the fu_progress_step_done() + * function will be called in the loop. + * + * The progress ID must be set fu_progress_set_id() before this method is used. + * + * Since: 1.7.0 + **/ +void +fu_progress_set_steps(FuProgress *self, guint step_max) +{ + FuProgressPrivate *priv = GET_PRIVATE(self); + g_return_if_fail(FU_IS_PROGRESS(self)); + g_return_if_fail(priv->id != NULL); + + /* only use the timer if profiling; it's expensive */ + if (priv->profile) + g_timer_start(priv->timer); + + /* set step_max */ + priv->step_max = step_max; +} + +/** + * fu_progress_get_steps: + * @self: A #FuProgress + * + * Gets the number of sub-tasks, i.e. how many times the fu_progress_step_done() + * function will be called in the loop. + * + * Return value: number of sub-tasks in this progress + * + * Since: 1.7.0 + **/ +guint +fu_progress_get_steps(FuProgress *self) +{ + FuProgressPrivate *priv = GET_PRIVATE(self); + g_return_val_if_fail(FU_IS_PROGRESS(self), G_MAXUINT); + return priv->step_max; +} + +/** + * fu_progress_add_step: + * @self: A #FuProgress + * @status: status value to use for this phase + * @value: A step weighting variable argument array + * + * This sets the step weighting, which you will want to do if one action + * will take a bigger chunk of time than another. + * + * The progress ID must be set fu_progress_set_id() before this method is used. + * + * Since: 1.7.0 + **/ +void +fu_progress_add_step(FuProgress *self, FwupdStatus status, guint value) +{ + FuProgressPrivate *priv = GET_PRIVATE(self); + FuProgressStep *step; + + g_return_if_fail(FU_IS_PROGRESS(self)); + g_return_if_fail(priv->id != NULL); + + /* current status */ + if (priv->steps->len == 0) + fu_progress_set_status(self, status); + + /* save data */ + step = g_new0(FuProgressStep, 1); + step->status = status; + step->value = value; + step->profile = .0; + g_ptr_array_add(priv->steps, step); + + /* in case anything is not using ->steps */ + fu_progress_set_steps(self, priv->steps->len); +} + +/** + * fu_progress_finished: + * @self: A #FuProgress + * + * Called when the step_now sub-task wants to finish early and still complete. + * + * Since: 1.7.0 + **/ +void +fu_progress_finished(FuProgress *self) +{ + FuProgressPrivate *priv = GET_PRIVATE(self); + + g_return_if_fail(FU_IS_PROGRESS(self)); + g_return_if_fail(priv->id != NULL); + + /* is already at 100%? */ + if (priv->step_now == priv->step_max) + return; + + /* all done */ + priv->step_now = priv->step_max; + fu_progress_set_percentage(self, 100); + fu_progress_set_status(self, FWUPD_STATUS_UNKNOWN); +} + +static gdouble +fu_progress_discrete_to_percent(guint discrete, guint step_max) +{ + /* check we are in range */ + if (discrete > step_max) + return 100; + if (step_max == 0) { + g_warning("step_max is 0!"); + return 0; + } + return ((gdouble)discrete * (100.0f / (gdouble)(step_max))); +} + +static gdouble +fu_progress_get_step_percentage(FuProgress *self, guint idx) +{ + FuProgressPrivate *priv = GET_PRIVATE(self); + guint current = 0; + guint total = 0; + + for (guint i = 0; i < priv->steps->len; i++) { + FuProgressStep *step = g_ptr_array_index(priv->steps, i); + if (i <= idx) + current += step->value; + total += step->value; + } + return ((gdouble)current * 100.f) / (gdouble)total; +} + +static void +fu_progress_child_status_changed_cb(FuProgress *child, FwupdStatus status, FuProgress *self) +{ + fu_progress_set_status(self, status); +} + +static void +fu_progress_child_percentage_changed_cb(FuProgress *child, guint percentage, FuProgress *self) +{ + FuProgressPrivate *priv = GET_PRIVATE(self); + gdouble offset; + gdouble range; + gdouble extra; + guint parent_percentage; + + /* propagate up the stack if FuProgress has only one step */ + if (priv->step_max == 1) { + fu_progress_set_percentage(self, percentage); + return; + } + + /* did we call done on a self that did not have a size set? */ + if (priv->step_max == 0) + return; + + /* already at >= 100% */ + if (priv->step_now >= priv->step_max) { + g_warning("already at %u/%u step_max", priv->step_now, priv->step_max); + return; + } + + /* we have to deal with non-linear step_max */ + if (priv->steps->len > 0) { + /* we don't store zero */ + if (priv->step_now == 0) { + gdouble pc = fu_progress_get_step_percentage(self, 0); + parent_percentage = percentage * pc / 100; + } else { + gdouble pc1 = fu_progress_get_step_percentage(self, priv->step_now - 1); + gdouble pc2 = fu_progress_get_step_percentage(self, priv->step_now); + /* bi-linearly interpolate */ + parent_percentage = (((100 - percentage) * pc1) + (percentage * pc2)) / 100; + } + goto out; + } + + /* get the offset */ + offset = fu_progress_discrete_to_percent(priv->step_now, priv->step_max); + + /* get the range between the parent step and the next parent step */ + range = fu_progress_discrete_to_percent(priv->step_now + 1, priv->step_max) - offset; + if (range < 0.01) + return; + + /* get the extra contributed by the child */ + extra = ((gdouble)percentage / 100.0f) * range; + + /* emit from the parent */ + parent_percentage = (guint)(offset + extra); +out: + fu_progress_set_percentage(self, parent_percentage); +} + +static void +fu_progress_set_parent(FuProgress *self, FuProgress *parent) +{ + FuProgressPrivate *priv = GET_PRIVATE(self); + g_return_if_fail(FU_IS_PROGRESS(self)); + priv->parent = parent; /* no ref! */ + priv->profile = fu_progress_get_profile(parent); +} + +/** + * fu_progress_get_child: + * @self: A #FuProgress + * + * Monitor a child and proxy back up to the parent with the correct percentage. + * + * Return value: (transfer none): A new %FuProgress or %NULL for failure + * + * Since: 1.7.0 + **/ +FuProgress * +fu_progress_get_child(FuProgress *self) +{ + FuProgressPrivate *priv = GET_PRIVATE(self); + + g_return_val_if_fail(FU_IS_PROGRESS(self), NULL); + g_return_val_if_fail(priv->id != NULL, NULL); + + /* already created child */ + if (priv->child != NULL) + return priv->child; + + /* connect up signals */ + priv->child = fu_progress_new(NULL); + priv->percentage_child_id = + g_signal_connect(priv->child, + "percentage-changed", + G_CALLBACK(fu_progress_child_percentage_changed_cb), + self); + priv->status_child_id = g_signal_connect(priv->child, + "status-changed", + G_CALLBACK(fu_progress_child_status_changed_cb), + self); + fu_progress_set_parent(priv->child, self); + return priv->child; +} + +static void +fu_progress_show_profile(FuProgress *self) +{ + FuProgressPrivate *priv = GET_PRIVATE(self); + gdouble division; + gdouble total_time = 0.0f; + gboolean close_enough = TRUE; + g_autoptr(GString) str = NULL; + + /* not accurate enough for a profile result */ + if (priv->flags & FU_PROGRESS_FLAG_NO_PROFILE) + return; + + /* get the total time so we can work out the divisor */ + str = g_string_new("raw timing data was { "); + for (guint i = 0; i < priv->step_max; i++) { + FuProgressStep *step = g_ptr_array_index(priv->steps, i); + g_string_append_printf(str, "%.3f, ", step->profile); + } + if (priv->step_max > 0) + g_string_set_size(str, str->len - 2); + g_string_append(str, " } -- "); + + /* get the total time so we can work out the divisor */ + for (guint i = 0; i < priv->step_max; i++) { + FuProgressStep *step = g_ptr_array_index(priv->steps, i); + total_time += step->profile; + } + if (total_time < 0.001) + return; + division = total_time / 100.0f; + + /* what we set */ + g_string_append(str, "steps were set as [ "); + for (guint i = 0; i < priv->step_max; i++) { + FuProgressStep *step = g_ptr_array_index(priv->steps, i); + g_string_append_printf(str, "%u ", step->value); + } + + /* what we _should_ have set */ + g_string_append_printf(str, "] but should have been [ "); + for (guint i = 0; i < priv->step_max; i++) { + FuProgressStep *step = g_ptr_array_index(priv->steps, i); + g_string_append_printf(str, "%.0f ", step->profile / division); + + /* this is sufficiently different to what we guessed */ + if (fabs((gdouble)step->value - step->profile / division) > 5) + close_enough = FALSE; + } + g_string_append(str, "]"); + if (priv->flags & FU_PROGRESS_FLAG_GUESSED) { +#ifdef SUPPORTED_BUILD + g_debug("%s at %s", str->str, priv->id); +#else + g_warning("%s at %s", str->str, priv->id); + g_warning("Please see " + "https://github.com/fwupd/fwupd/wiki/Daemon-Warning:-FuProgress-steps"); +#endif + } else if (!close_enough) { + g_debug("%s at %s", str->str, priv->id); + } +} + +/** + * fu_progress_step_done: + * @self: A #FuProgress + * + * Called when the step_now sub-task has finished. + * + * Since: 1.7.0 + **/ +void +fu_progress_step_done(FuProgress *self) +{ + FuProgressPrivate *priv = GET_PRIVATE(self); + gdouble percentage; + + g_return_if_fail(FU_IS_PROGRESS(self)); + g_return_if_fail(priv->id != NULL); + + /* did we call done on a self that did not have a size set? */ + if (priv->step_max == 0) { + g_autoptr(GString) str = g_string_new(NULL); + fu_progress_build_parent_chain(self, str, 0); + g_warning("progress done when no size set! [%s]: %s", priv->id, str->str); + return; + } + + /* save the duration in the array */ + if (priv->profile) { + if (priv->steps->len > 0) { + FuProgressStep *step = g_ptr_array_index(priv->steps, priv->step_now); + step->profile = g_timer_elapsed(priv->timer, NULL); + } + g_timer_start(priv->timer); + } + + /* is already at 100%? */ + if (priv->step_now >= priv->step_max) { + g_autoptr(GString) str = g_string_new(NULL); + fu_progress_build_parent_chain(self, str, 0); + g_warning("already at 100%% [%s]: %s", priv->id, str->str); + return; + } + + /* is child not at 100%? */ + if (priv->child != NULL) { + FuProgressPrivate *child_priv = GET_PRIVATE(priv->child); + if (child_priv->step_now != child_priv->step_max) { + g_autoptr(GString) str = g_string_new(NULL); + fu_progress_build_parent_chain(priv->child, str, 0); + g_warning("child is at %u/%u step_max and parent done [%s]\n%s", + child_priv->step_now, + child_priv->step_max, + priv->id, + str->str); + /* do not abort, as we want to clean this up */ + } + } + + /* another */ + priv->step_now++; + + /* update status */ + if (priv->steps->len > 0) { + if (priv->step_now == priv->step_max) { + fu_progress_set_status(self, FWUPD_STATUS_UNKNOWN); + } else { + FuProgressStep *step = g_ptr_array_index(priv->steps, priv->step_now); + fu_progress_set_status(self, step->status); + } + } + + /* find new percentage */ + if (priv->steps->len == 0) { + percentage = fu_progress_discrete_to_percent(priv->step_now, priv->step_max); + } else { + percentage = fu_progress_get_step_percentage(self, priv->step_now - 1); + } + fu_progress_set_percentage(self, (guint)percentage); + + /* show any profiling stats */ + if (priv->profile && priv->step_now == priv->step_max && priv->steps->len > 0) + fu_progress_show_profile(self); + + /* reset child if it exists */ + if (priv->child != NULL) + fu_progress_reset(priv->child); +} + +/** + * fu_progress_sleep: + * @self: a #FuProgress + * @delay_ms: the delay in milliseconds + * + * Sleeps, setting the device progress from 0..100% as time continues. + * + * Since: 1.7.0 + **/ +void +fu_progress_sleep(FuProgress *self, guint delay_ms) +{ + gulong delay_us_pc = (delay_ms * 1000) / 100; + + g_return_if_fail(FU_IS_PROGRESS(self)); + g_return_if_fail(delay_ms > 0); + + fu_progress_set_percentage(self, 0); + for (guint i = 0; i < 100; i++) { + g_usleep(delay_us_pc); + fu_progress_set_percentage(self, i + 1); + } +} + +static void +fu_progress_init(FuProgress *self) +{ + FuProgressPrivate *priv = GET_PRIVATE(self); + priv->timer = g_timer_new(); + priv->steps = g_ptr_array_new_with_free_func(g_free); +} + +static void +fu_progress_finalize(GObject *object) +{ + FuProgress *self = FU_PROGRESS(object); + FuProgressPrivate *priv = GET_PRIVATE(self); + + fu_progress_reset(self); + g_free(priv->id); + g_ptr_array_unref(priv->steps); + g_timer_destroy(priv->timer); + + G_OBJECT_CLASS(fu_progress_parent_class)->finalize(object); +} + +static void +fu_progress_class_init(FuProgressClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS(klass); + object_class->finalize = fu_progress_finalize; + + signals[SIGNAL_PERCENTAGE_CHANGED] = + g_signal_new("percentage-changed", + G_TYPE_FROM_CLASS(object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(FuProgressClass, percentage_changed), + NULL, + NULL, + g_cclosure_marshal_VOID__UINT, + G_TYPE_NONE, + 1, + G_TYPE_UINT); + signals[SIGNAL_STATUS_CHANGED] = + g_signal_new("status-changed", + G_TYPE_FROM_CLASS(object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(FuProgressClass, status_changed), + NULL, + NULL, + g_cclosure_marshal_VOID__UINT, + G_TYPE_NONE, + 1, + G_TYPE_UINT); +} + +/** + * fu_progress_new: + * @id: (nullable): progress ID, normally `G_STRLOC` + * + * Return value: A new #FuProgress instance. + * + * Since: 1.7.0 + **/ +FuProgress * +fu_progress_new(const gchar *id) +{ + FuProgress *self; + self = g_object_new(FU_TYPE_PROGRESS, NULL); + if (id != NULL) + fu_progress_set_id(self, id); + return FU_PROGRESS(self); +} diff --git a/libfwupdplugin/fu-progress.h b/libfwupdplugin/fu-progress.h new file mode 100644 index 000000000..3e8873c21 --- /dev/null +++ b/libfwupdplugin/fu-progress.h @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2021 Richard Hughes + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#pragma once + +#include +#include + +#define FU_TYPE_PROGRESS (fu_progress_get_type()) +G_DECLARE_DERIVABLE_TYPE(FuProgress, fu_progress, FU, PROGRESS, GObject) + +struct _FuProgressClass { + GObjectClass parent_class; + /* signals */ + void (*percentage_changed)(FuProgress *self, guint value); + void (*status_changed)(FuProgress *self, FwupdStatus status); + /*< private >*/ + gpointer padding[29]; +}; + +/** + * FuProgressFlags: + * + * The progress internal flags. + **/ +typedef guint64 FuProgressFlags; + +/** + * FU_PROGRESS_FLAG_NONE: + * + * No flags set. + * + * Since: 1.7.0 + */ +#define FU_PROGRESS_FLAG_NONE (0) + +/** + * FU_PROGRESS_FLAG_UNKNOWN: + * + * Unknown flag value. + * + * Since: 1.7.0 + */ +#define FU_PROGRESS_FLAG_UNKNOWN G_MAXUINT64 + +/** + * FU_PROGRESS_FLAG_GUESSED: + * + * The steps have not been measured on real hardware and have been guessed. + * + * Since: 1.7.0 + */ +#define FU_PROGRESS_FLAG_GUESSED (1ull << 0) + +/** + * FU_PROGRESS_FLAG_NO_PROFILE: + * + * The steps cannot be accurate enough for a profile result. + * + * Since: 1.7.0 + */ +#define FU_PROGRESS_FLAG_NO_PROFILE (1ull << 1) + +FuProgress * +fu_progress_new(const gchar *id); +const gchar * +fu_progress_get_id(FuProgress *self); +void +fu_progress_set_id(FuProgress *self, const gchar *id); +const gchar * +fu_progress_flag_to_string(FuProgressFlags flag); +FuProgressFlags +fu_progress_flag_from_string(const gchar *flag); +void +fu_progress_add_flag(FuProgress *self, FuProgressFlags flag); +void +fu_progress_remove_flag(FuProgress *self, FuProgressFlags flag); +gboolean +fu_progress_has_flag(FuProgress *self, FuProgressFlags flag); +FwupdStatus +fu_progress_get_status(FuProgress *self); +void +fu_progress_set_status(FuProgress *self, FwupdStatus status); +void +fu_progress_set_percentage(FuProgress *self, guint percentage); +void +fu_progress_set_percentage_full(FuProgress *self, gsize progress_done, gsize progress_total); +guint +fu_progress_get_percentage(FuProgress *self); +void +fu_progress_set_profile(FuProgress *self, gboolean profile); +void +fu_progress_reset(FuProgress *self); +void +fu_progress_set_steps(FuProgress *self, guint step_max); +guint +fu_progress_get_steps(FuProgress *self); +void +fu_progress_add_step(FuProgress *self, FwupdStatus status, guint value); +void +fu_progress_finished(FuProgress *self); +void +fu_progress_step_done(FuProgress *self); +FuProgress * +fu_progress_get_child(FuProgress *self); +void +fu_progress_sleep(FuProgress *self, guint delay_ms); diff --git a/libfwupdplugin/fu-self-test.c b/libfwupdplugin/fu-self-test.c index 3c2d9837c..ddb779fa0 100644 --- a/libfwupdplugin/fu-self-test.c +++ b/libfwupdplugin/fu-self-test.c @@ -3401,6 +3401,223 @@ fu_ifd_image_xml_func(void) g_assert_cmpstr(csum1, ==, csum2); } +typedef struct { + guint last_percentage; + guint updates; +} FuProgressHelper; + +static void +fu_progress_percentage_changed_cb(FuProgress *progress, guint percentage, gpointer data) +{ + FuProgressHelper *helper = (FuProgressHelper *)data; + helper->last_percentage = percentage; + helper->updates++; +} + +static void +fu_progress_func(void) +{ + FuProgressHelper helper = {0}; + g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC); + + g_signal_connect(progress, + "percentage-changed", + G_CALLBACK(fu_progress_percentage_changed_cb), + &helper); + + fu_progress_set_steps(progress, 5); + + fu_progress_step_done(progress); + g_assert_cmpint(helper.updates, ==, 1); + g_assert_cmpint(helper.last_percentage, ==, 20); + + for (guint i = 0; i < 4; i++) + fu_progress_step_done(progress); + g_assert_cmpint(helper.last_percentage, ==, 100); + g_assert_cmpint(helper.updates, ==, 5); +} + +static void +fu_progress_child_func(void) +{ + FuProgressHelper helper = {0}; + FuProgress *child; + g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC); + + /* reset */ + fu_progress_set_steps(progress, 2); + g_signal_connect(progress, + "percentage-changed", + G_CALLBACK(fu_progress_percentage_changed_cb), + &helper); + + /* parent: |-----------------------|-----------------------| + * step1: |-----------------------| + * child: |-------------|---------| + */ + + /* PARENT UPDATE */ + g_debug("parent update #1"); + fu_progress_step_done(progress); + g_assert_cmpint(helper.updates, ==, 1); + g_assert_cmpint(helper.last_percentage, ==, 50); + + /* now test with a child */ + child = fu_progress_get_child(progress); + fu_progress_set_id(child, G_STRLOC); + fu_progress_set_steps(child, 2); + + g_debug("child update #1"); + fu_progress_step_done(child); + g_assert_cmpint(helper.updates, ==, 2); + g_assert_cmpint(helper.last_percentage, ==, 75); + + /* child update */ + g_debug("child update #2"); + fu_progress_step_done(child); + g_assert_cmpint(helper.updates, ==, 3); + g_assert_cmpint(helper.last_percentage, ==, 100); + + /* parent update */ + g_debug("parent update #2"); + fu_progress_step_done(progress); + + /* ensure we ignored the duplicate */ + g_assert_cmpint(helper.updates, ==, 3); + g_assert_cmpint(helper.last_percentage, ==, 100); +} + +static void +fu_progress_parent_one_step_proxy_func(void) +{ + FuProgressHelper helper = {0}; + FuProgress *child; + g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC); + + /* one step */ + fu_progress_set_steps(progress, 1); + g_signal_connect(progress, + "percentage-changed", + G_CALLBACK(fu_progress_percentage_changed_cb), + &helper); + + /* now test with a child */ + child = fu_progress_get_child(progress); + fu_progress_set_id(child, G_STRLOC); + fu_progress_set_steps(child, 2); + + /* child set value */ + fu_progress_set_percentage(child, 33); + + /* ensure 1 updates for progress with one step and ensure using child value as parent */ + g_assert_cmpint(helper.updates, ==, 1); + g_assert_cmpint(helper.last_percentage, ==, 33); +} + +static void +fu_progress_non_equal_steps_func(void) +{ + g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC); + FuProgress *child; + FuProgress *grandchild; + + /* test non-equal steps */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_ERASE, 20); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 60); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_READ, 20); + g_assert_cmpint(fu_progress_get_percentage(progress), ==, 0); + g_assert_cmpint(fu_progress_get_status(progress), ==, FWUPD_STATUS_DEVICE_ERASE); + + /* child step should increment according to the custom steps */ + child = fu_progress_get_child(progress); + fu_progress_set_id(child, G_STRLOC); + fu_progress_set_steps(child, 2); + + /* start child */ + fu_progress_step_done(child); + + /* verify 10% */ + g_assert_cmpint(fu_progress_get_percentage(progress), ==, 10); + + /* finish child */ + fu_progress_step_done(child); + + fu_progress_step_done(progress); + g_assert_cmpint(fu_progress_get_status(progress), ==, FWUPD_STATUS_DEVICE_WRITE); + + /* verify 20% */ + g_assert_cmpint(fu_progress_get_percentage(progress), ==, 20); + + /* child step should increment according to the custom steps */ + child = fu_progress_get_child(progress); + fu_progress_set_id(child, G_STRLOC); + fu_progress_set_id(child, G_STRLOC); + fu_progress_add_step(child, FWUPD_STATUS_DEVICE_RESTART, 25); + fu_progress_add_step(child, FWUPD_STATUS_DEVICE_WRITE, 75); + g_assert_cmpint(fu_progress_get_status(progress), ==, FWUPD_STATUS_DEVICE_RESTART); + + /* start child */ + fu_progress_step_done(child); + g_assert_cmpint(fu_progress_get_status(progress), ==, FWUPD_STATUS_DEVICE_WRITE); + + /* verify bilinear interpolation is working */ + g_assert_cmpint(fu_progress_get_percentage(progress), ==, 35); + + /* + * 0 20 80 100 + * |---------||----------------------------||---------| + * | 35 | + * |-------||-------------------| (25%) + * | 75.5 | + * |---------------||--| (90%) + */ + grandchild = fu_progress_get_child(child); + fu_progress_set_id(grandchild, G_STRLOC); + fu_progress_add_step(grandchild, FWUPD_STATUS_DEVICE_ERASE, 90); + fu_progress_add_step(grandchild, FWUPD_STATUS_DEVICE_WRITE, 10); + + fu_progress_step_done(grandchild); + + /* verify bilinear interpolation (twice) is working for subpercentage */ + g_assert_cmpint(fu_progress_get_percentage(progress), ==, 75); + + fu_progress_step_done(grandchild); + + /* finish child */ + fu_progress_step_done(child); + + fu_progress_step_done(progress); + g_assert_cmpint(fu_progress_get_status(progress), ==, FWUPD_STATUS_DEVICE_READ); + + /* verify 80% */ + g_assert_cmpint(fu_progress_get_percentage(progress), ==, 80); + + fu_progress_step_done(progress); + + /* verify 100% */ + g_assert_cmpint(fu_progress_get_percentage(progress), ==, 100); + g_assert_cmpint(fu_progress_get_status(progress), ==, FWUPD_STATUS_UNKNOWN); +} + +static void +fu_progress_finish_func(void) +{ + FuProgress *child; + g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC); + + /* check straight finish */ + fu_progress_set_steps(progress, 3); + + child = fu_progress_get_child(progress); + fu_progress_set_id(child, G_STRLOC); + fu_progress_set_steps(child, 3); + fu_progress_finished(child); + + /* parent step done after child finish */ + fu_progress_step_done(progress); +} + int main(int argc, char **argv) { @@ -3416,6 +3633,11 @@ main(int argc, char **argv) g_setenv("FWUPD_OFFLINE_TRIGGER", "/tmp/fwupd-self-test/system-update", TRUE); g_setenv("FWUPD_LOCALSTATEDIR", "/tmp/fwupd-self-test/var", TRUE); + g_test_add_func("/fwupd/progress", fu_progress_func); + g_test_add_func("/fwupd/progress{child}", fu_progress_child_func); + g_test_add_func("/fwupd/progress{parent-1-step}", fu_progress_parent_one_step_proxy_func); + g_test_add_func("/fwupd/progress{no-equal}", fu_progress_non_equal_steps_func); + g_test_add_func("/fwupd/progress{finish}", fu_progress_finish_func); g_test_add_func("/fwupd/security-attrs{hsi}", fu_security_attrs_hsi_func); g_test_add_func("/fwupd/plugin{devices}", fu_plugin_devices_func); g_test_add_func("/fwupd/plugin{device-inhibit-children}", diff --git a/libfwupdplugin/fwupdplugin.h b/libfwupdplugin/fwupdplugin.h index 9db15c9fb..75c1d19a5 100644 --- a/libfwupdplugin/fwupdplugin.h +++ b/libfwupdplugin/fwupdplugin.h @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include diff --git a/libfwupdplugin/fwupdplugin.map b/libfwupdplugin/fwupdplugin.map index f8cd37519..a7b4ffad1 100644 --- a/libfwupdplugin/fwupdplugin.map +++ b/libfwupdplugin/fwupdplugin.map @@ -150,11 +150,6 @@ LIBFWUPDPLUGIN_1.0.3 { fu_common_read_uint32; fu_common_write_uint16; fu_common_write_uint32; - fu_device_get_progress; - fu_device_get_status; - fu_device_set_progress; - fu_device_set_progress_full; - fu_device_set_status; fu_usb_device_is_open; local: *; } LIBFWUPDPLUGIN_1.0.2; @@ -550,7 +545,6 @@ LIBFWUPDPLUGIN_1.5.0 { fu_device_dump_firmware; fu_device_report_metadata_post; fu_device_report_metadata_pre; - fu_device_sleep_with_progress; fu_device_unbind_driver; fu_efivar_get_data_bytes; fu_efivar_secure_boot_enabled_full; @@ -867,6 +861,7 @@ LIBFWUPDPLUGIN_1.6.2 { LIBFWUPDPLUGIN_1.7.0 { global: + fu_device_set_progress; fu_plugin_runner_attach; fu_plugin_runner_cleanup; fu_plugin_runner_detach; @@ -874,5 +869,28 @@ LIBFWUPDPLUGIN_1.7.0 { fu_plugin_runner_reload; fu_plugin_runner_write_firmware; fu_plugin_set_config_value; + fu_progress_add_flag; + fu_progress_add_step; + fu_progress_finished; + fu_progress_flag_from_string; + fu_progress_flag_to_string; + fu_progress_get_child; + fu_progress_get_id; + fu_progress_get_percentage; + fu_progress_get_status; + fu_progress_get_steps; + fu_progress_get_type; + fu_progress_has_flag; + fu_progress_new; + fu_progress_remove_flag; + fu_progress_reset; + fu_progress_set_id; + fu_progress_set_percentage; + fu_progress_set_percentage_full; + fu_progress_set_profile; + fu_progress_set_status; + fu_progress_set_steps; + fu_progress_sleep; + fu_progress_step_done; local: *; } LIBFWUPDPLUGIN_1.6.2; diff --git a/libfwupdplugin/meson.build b/libfwupdplugin/meson.build index bcf65e86d..0716e7d2a 100644 --- a/libfwupdplugin/meson.build +++ b/libfwupdplugin/meson.build @@ -28,6 +28,7 @@ fwupdplugin_src = [ 'fu-io-channel.c', # fuzzing 'fu-plugin.c', 'fu-quirks.c', # fuzzing + 'fu-progress.c', # fuzzing 'fu-security-attrs.c', 'fu-smbios.c', # fuzzing 'fu-srec-firmware.c', # fuzzing @@ -101,6 +102,7 @@ fwupdplugin_headers = [ 'fu-plugin.h', 'fu-quirks.h', 'fu-security-attrs.h', + 'fu-progress.h', 'fu-smbios.h', 'fu-srec-firmware.h', 'fu-efi-signature.h', diff --git a/plugins/altos/fu-altos-device.c b/plugins/altos/fu-altos-device.c index 9977582de..d6ba4a9e4 100644 --- a/plugins/altos/fu-altos-device.c +++ b/plugins/altos/fu-altos-device.c @@ -238,6 +238,7 @@ fu_altos_device_prepare_firmware(FuDevice *device, static gboolean fu_altos_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -258,6 +259,13 @@ fu_altos_device_write_firmware(FuDevice *device, return FALSE; } + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 5); /* open */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 90); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 5); /* attach */ + /* check sizes */ if (self->addr_base == 0x0 || self->addr_bound == 0x0) { g_set_error_literal(error, @@ -311,7 +319,8 @@ fu_altos_device_write_firmware(FuDevice *device, error); if (locker == NULL) return FALSE; - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); + fu_progress_step_done(progress); + for (guint i = 0; i < flash_len; i += 0x100) { g_autoptr(GString) str = NULL; guint8 buf_tmp[0x100]; @@ -360,23 +369,24 @@ fu_altos_device_write_firmware(FuDevice *device, } /* progress */ - fu_device_set_progress_full(device, i, flash_len); + fu_progress_set_percentage_full(fu_progress_get_child(progress), + i + 0x100, + flash_len); g_string_append_len(buf, str->str, str->len); } + fu_progress_step_done(progress); /* go to application mode */ if (!fu_altos_device_tty_write(self, "a\n", -1, error)) return FALSE; - - /* progress complete */ - fu_device_set_progress_full(device, flash_len, flash_len); + fu_progress_step_done(progress); /* success */ return TRUE; } static GBytes * -fu_altos_device_dump_firmware(FuDevice *device, GError **error) +fu_altos_device_dump_firmware(FuDevice *device, FuProgress *progress, GError **error) { FuAltosDevice *self = FU_ALTOS_DEVICE(device); guint flash_len; @@ -427,9 +437,9 @@ fu_altos_device_dump_firmware(FuDevice *device, GError **error) return NULL; /* progress */ - fu_device_set_progress_full(device, - i - self->addr_base, - self->addr_bound - self->addr_base); + fu_progress_set_percentage_full(progress, + i - self->addr_base, + self->addr_bound - self->addr_base); g_string_append_len(buf, str->str, str->len); } @@ -542,6 +552,17 @@ fu_altos_device_probe(FuDevice *device, GError **error) return TRUE; } +static void +fu_altos_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 98); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* reload */ +} + static void fu_altos_device_init(FuAltosDevice *self) { @@ -567,5 +588,6 @@ fu_altos_device_class_init(FuAltosDeviceClass *klass) klass_device->prepare_firmware = fu_altos_device_prepare_firmware; klass_device->write_firmware = fu_altos_device_write_firmware; klass_device->dump_firmware = fu_altos_device_dump_firmware; + klass_device->set_progress = fu_altos_device_set_progress; object_class->finalize = fu_altos_device_finalize; } diff --git a/plugins/analogix/fu-analogix-device.c b/plugins/analogix/fu-analogix-device.c index fcfcc5051..633dd9fcc 100644 --- a/plugins/analogix/fu-analogix-device.c +++ b/plugins/analogix/fu-analogix-device.c @@ -275,6 +275,7 @@ static gboolean fu_analogix_device_write_image(FuAnalogixDevice *self, FuFirmware *image, guint16 req_val, + FuProgress *progress, GError **error) { AnxUpdateStatus status = UPDATE_STATUS_INVALID; @@ -282,6 +283,12 @@ fu_analogix_device_write_image(FuAnalogixDevice *self, g_autoptr(GBytes) block_bytes = NULL; g_autoptr(GPtrArray) chunks = NULL; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 10); /* initialization */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 90); + /* offset into firmware */ block_bytes = fu_firmware_get_bytes(image, error); if (block_bytes == NULL) @@ -301,9 +308,9 @@ fu_analogix_device_write_image(FuAnalogixDevice *self, } if (!fu_analogix_device_get_update_status(self, &status, error)) return FALSE; + fu_progress_step_done(progress); /* write data */ - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_DEVICE_WRITE); chunks = fu_chunk_array_new_from_bytes(block_bytes, 0x00, 0x00, BILLBOARD_MAX_PACKET_SIZE); for (guint i = 0; i < chunks->len; i++) { FuChunk *chk = g_ptr_array_index(chunks, i); @@ -321,8 +328,11 @@ fu_analogix_device_write_image(FuAnalogixDevice *self, g_prefix_error(error, "failed status on chk %u: ", i); return FALSE; } - fu_device_set_progress_full(FU_DEVICE(self), i, chunks->len - 1); + fu_progress_set_percentage_full(fu_progress_get_child(progress), + i + 1, + chunks->len); } + fu_progress_step_done(progress); /* success */ return TRUE; @@ -331,6 +341,7 @@ fu_analogix_device_write_image(FuAnalogixDevice *self, static gboolean fu_analogix_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -340,44 +351,69 @@ fu_analogix_device_write_firmware(FuDevice *device, g_autoptr(FuFirmware) fw_srx = NULL; g_autoptr(FuFirmware) fw_stx = NULL; - /* OCM -> SECURE_TX -> SECURE_RX -> CUSTOM_DEF */ + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 25); /* cus */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 25); /* stx */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 25); /* srx */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 25); /* ocm */ + + /* CUSTOM_DEF */ fw_cus = fu_firmware_get_image_by_id(firmware, "custom", NULL); if (fw_cus != NULL) { if (!fu_analogix_device_write_image(self, fw_cus, ANX_BB_WVAL_UPDATE_CUSTOM_DEF, + fu_progress_get_child(progress), error)) { g_prefix_error(error, "program custom define failed: "); return FALSE; } } + fu_progress_step_done(progress); + + /* SECURE_TX */ fw_stx = fu_firmware_get_image_by_id(firmware, "stx", NULL); if (fw_stx != NULL) { if (!fu_analogix_device_write_image(self, fw_stx, ANX_BB_WVAL_UPDATE_SECURE_TX, + fu_progress_get_child(progress), error)) { g_prefix_error(error, "program secure TX failed: "); return FALSE; } } + fu_progress_step_done(progress); + + /* SECURE_RX */ fw_srx = fu_firmware_get_image_by_id(firmware, "srx", NULL); if (fw_srx != NULL) { if (!fu_analogix_device_write_image(self, fw_srx, ANX_BB_WVAL_UPDATE_SECURE_RX, + fu_progress_get_child(progress), error)) { g_prefix_error(error, "program secure RX failed: "); return FALSE; } } + fu_progress_step_done(progress); + + /* OCM */ fw_ocm = fu_firmware_get_image_by_id(firmware, "ocm", NULL); if (fw_ocm != NULL) { - if (!fu_analogix_device_write_image(self, fw_ocm, ANX_BB_WVAL_UPDATE_OCM, error)) { + if (!fu_analogix_device_write_image(self, + fw_ocm, + ANX_BB_WVAL_UPDATE_OCM, + fu_progress_get_child(progress), + error)) { g_prefix_error(error, "program OCM failed: "); return FALSE; } } + fu_progress_step_done(progress); /* success */ return TRUE; @@ -402,6 +438,17 @@ fu_analogix_device_close(FuDevice *device, GError **error) return FU_DEVICE_CLASS(fu_analogix_device_parent_class)->close(device, error); } +static void +fu_analogix_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 98); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* reload */ +} + static void fu_analogix_device_init(FuAnalogixDevice *self) { @@ -423,4 +470,5 @@ fu_analogix_device_class_init(FuAnalogixDeviceClass *klass) klass_device->probe = fu_analogix_device_probe; klass_device->prepare_firmware = fu_analogix_device_prepare_firmware; klass_device->close = fu_analogix_device_close; + klass_device->set_progress = fu_analogix_device_set_progress; } diff --git a/plugins/ata/fu-ata-device.c b/plugins/ata/fu-ata-device.c index 1d02f9fe2..f864bef5e 100644 --- a/plugins/ata/fu-ata-device.c +++ b/plugins/ata/fu-ata-device.c @@ -654,7 +654,7 @@ fu_ata_device_setup(FuDevice *device, GError **error) } static gboolean -fu_ata_device_activate(FuDevice *device, GError **error) +fu_ata_device_activate(FuDevice *device, FuProgress *progress, GError **error) { FuAtaDevice *self = FU_ATA_DEVICE(device); struct ata_tf tf = {0x0}; @@ -760,6 +760,7 @@ fu_ata_device_fw_download(FuAtaDevice *self, static gboolean fu_ata_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -797,7 +798,7 @@ fu_ata_device_write_firmware(FuDevice *device, } /* write each block */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_WRITE); chunks = fu_chunk_array_new_from_bytes(fw, 0x00, 0x00, chunksz); for (guint i = 0; i < chunks->len; i++) { FuChunk *chk = g_ptr_array_index(chunks, i); @@ -810,12 +811,11 @@ fu_ata_device_write_firmware(FuDevice *device, g_prefix_error(error, "failed to write chunk %u: ", i); return FALSE; } - fu_device_set_progress_full(device, (gsize)i, (gsize)chunks->len + 1); + fu_progress_set_percentage_full(progress, (gsize)i + 1, (gsize)chunks->len); } /* success! */ fu_device_add_flag(device, FWUPD_DEVICE_FLAG_NEEDS_ACTIVATION); - fu_device_set_progress(device, 100); return TRUE; } @@ -855,6 +855,17 @@ fu_ata_device_set_quirk_kv(FuDevice *device, const gchar *key, const gchar *valu return FALSE; } +static void +fu_ata_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 98); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* reload */ +} + static void fu_ata_device_init(FuAtaDevice *self) { @@ -890,6 +901,7 @@ fu_ata_device_class_init(FuAtaDeviceClass *klass) klass_device->activate = fu_ata_device_activate; klass_device->write_firmware = fu_ata_device_write_firmware; klass_device->probe = fu_ata_device_probe; + klass_device->set_progress = fu_ata_device_set_progress; } FuAtaDevice * diff --git a/plugins/bcm57xx/fu-bcm57xx-device.c b/plugins/bcm57xx/fu-bcm57xx-device.c index 925e96bae..6a587a26f 100644 --- a/plugins/bcm57xx/fu-bcm57xx-device.c +++ b/plugins/bcm57xx/fu-bcm57xx-device.c @@ -300,7 +300,7 @@ fu_bcm57xx_device_nvram_check(FuBcm57xxDevice *self, GError **error) } static gboolean -fu_bcm57xx_device_activate(FuDevice *device, GError **error) +fu_bcm57xx_device_activate(FuDevice *device, FuProgress *progress, GError **error) { FuBcm57xxDevice *self = FU_BCM57XX_DEVICE(device); g_autoptr(FuDeviceLocker) locker1 = NULL; @@ -320,7 +320,7 @@ fu_bcm57xx_device_activate(FuDevice *device, GError **error) return FALSE; /* activate, causing APE reset, then close, then attach */ - if (!fu_device_activate(FU_DEVICE(self->recovery), error)) + if (!fu_device_activate(FU_DEVICE(self->recovery), progress, error)) return FALSE; /* ensure we attach before we close */ @@ -328,20 +328,20 @@ fu_bcm57xx_device_activate(FuDevice *device, GError **error) return FALSE; /* wait for the device to restart before calling reload() */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_BUSY); - fu_device_sleep_with_progress(device, 5); /* seconds */ + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_BUSY); + fu_progress_sleep(progress, 5000); return TRUE; } static GBytes * -fu_bcm57xx_device_dump_firmware(FuDevice *device, GError **error) +fu_bcm57xx_device_dump_firmware(FuDevice *device, FuProgress *progress, GError **error) { FuBcm57xxDevice *self = FU_BCM57XX_DEVICE(device); const gsize bufsz = fu_device_get_firmware_size_max(FU_DEVICE(self)); g_autofree guint8 *buf = g_malloc0(bufsz); g_autoptr(GPtrArray) chunks = NULL; - fu_device_set_status(device, FWUPD_STATUS_DEVICE_READ); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_READ); chunks = fu_chunk_array_mutable_new(buf, bufsz, 0x0, 0x0, FU_BCM57XX_BLOCK_SZ); for (guint i = 0; i < chunks->len; i++) { FuChunk *chk = g_ptr_array_index(chunks, i); @@ -351,7 +351,7 @@ fu_bcm57xx_device_dump_firmware(FuDevice *device, GError **error) fu_chunk_get_data_sz(chk), error)) return NULL; - fu_device_set_progress_full(device, i, chunks->len - 1); + fu_progress_set_percentage_full(progress, i + 1, chunks->len - 1); } /* read from hardware */ @@ -359,13 +359,13 @@ fu_bcm57xx_device_dump_firmware(FuDevice *device, GError **error) } static FuFirmware * -fu_bcm57xx_device_read_firmware(FuDevice *device, GError **error) +fu_bcm57xx_device_read_firmware(FuDevice *device, FuProgress *progress, GError **error) { g_autoptr(FuFirmware) firmware = fu_bcm57xx_firmware_new(); g_autoptr(GBytes) fw = NULL; /* read from hardware */ - fw = fu_bcm57xx_device_dump_firmware(device, error); + fw = fu_bcm57xx_device_dump_firmware(device, progress, error); if (fw == NULL) return NULL; if (!fu_firmware_parse(firmware, fw, FWUPD_INSTALL_FLAG_NONE, error)) @@ -394,6 +394,7 @@ fu_bcm57xx_device_prepare_firmware(FuDevice *device, g_autoptr(FuFirmware) img_ape = NULL; g_autoptr(FuFirmware) img_stage1 = NULL; g_autoptr(FuFirmware) img_stage2 = NULL; + g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC); g_autoptr(GPtrArray) images = NULL; /* try to parse NVRAM, stage1 or APE */ @@ -423,7 +424,7 @@ fu_bcm57xx_device_prepare_firmware(FuDevice *device, } /* get the existing firmware from the device */ - fw_old = fu_bcm57xx_device_dump_firmware(device, error); + fw_old = fu_bcm57xx_device_dump_firmware(device, progress, error); if (fw_old == NULL) return NULL; if (!fu_firmware_parse(firmware, fw_old, flags, error)) { @@ -467,6 +468,7 @@ fu_bcm57xx_device_prepare_firmware(FuDevice *device, static gboolean fu_bcm57xx_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -475,14 +477,21 @@ fu_bcm57xx_device_write_firmware(FuDevice *device, g_autoptr(GBytes) blob_verify = NULL; g_autoptr(GPtrArray) chunks = NULL; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DECOMPRESSING, 1); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 80); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_VERIFY, 19); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); + /* build the images into one linear blob of the correct size */ - fu_device_set_status(device, FWUPD_STATUS_DECOMPRESSING); blob = fu_firmware_write(firmware, error); if (blob == NULL) return FALSE; + fu_progress_step_done(progress); /* hit hardware */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); chunks = fu_chunk_array_new_from_bytes(blob, 0x0, 0x0, FU_BCM57XX_BLOCK_SZ); for (guint i = 0; i < chunks->len; i++) { FuChunk *chk = g_ptr_array_index(chunks, i); @@ -492,19 +501,28 @@ fu_bcm57xx_device_write_firmware(FuDevice *device, fu_chunk_get_data_sz(chk), error)) return FALSE; - fu_device_set_progress_full(device, i, chunks->len - 1); + fu_progress_set_percentage_full(fu_progress_get_child(progress), + i + 1, + chunks->len - 1); } + fu_progress_step_done(progress); /* verify */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_VERIFY); - blob_verify = fu_bcm57xx_device_dump_firmware(device, error); + blob_verify = + fu_bcm57xx_device_dump_firmware(device, fu_progress_get_child(progress), error); if (blob_verify == NULL) return FALSE; if (!fu_common_bytes_compare(blob, blob_verify, error)) return FALSE; + fu_progress_step_done(progress); /* reset APE */ - return fu_device_activate(device, error); + if (!fu_device_activate(device, fu_progress_get_child(progress), error)) + return FALSE; + fu_progress_step_done(progress); + + /* success */ + return TRUE; } static gboolean @@ -616,6 +634,17 @@ fu_bcm57xx_device_close(FuDevice *device, GError **error) return g_close(self->ethtool_fd, error); } +static void +fu_bcm57xx_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 98); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* reload */ +} + static void fu_bcm57xx_device_init(FuBcm57xxDevice *self) { @@ -654,4 +683,5 @@ fu_bcm57xx_device_class_init(FuBcm57xxDeviceClass *klass) klass_device->dump_firmware = fu_bcm57xx_device_dump_firmware; klass_device->probe = fu_bcm57xx_device_probe; klass_device->to_string = fu_bcm57xx_device_to_string; + klass_device->set_progress = fu_bcm57xx_device_set_progress; } diff --git a/plugins/bcm57xx/fu-bcm57xx-recovery-device.c b/plugins/bcm57xx/fu-bcm57xx-recovery-device.c index 012427aba..d2da77948 100644 --- a/plugins/bcm57xx/fu-bcm57xx-recovery-device.c +++ b/plugins/bcm57xx/fu-bcm57xx-recovery-device.c @@ -341,6 +341,7 @@ fu_bcm57xx_recovery_device_nvram_read(FuBcm57xxRecoveryDevice *self, guint32 address, guint32 *buf, gsize bufsz, + FuProgress *progress, GError **error) { for (guint i = 0; i < bufsz; i++) { @@ -376,7 +377,7 @@ fu_bcm57xx_recovery_device_nvram_read(FuBcm57xxRecoveryDevice *self, return FALSE; buf[i] = GUINT32_FROM_BE(val32); address += sizeof(guint32); - fu_device_set_progress_full(FU_DEVICE(self), i, bufsz); + fu_progress_set_percentage_full(progress, i + 1, bufsz); } /* success */ @@ -388,6 +389,7 @@ fu_bcm57xx_recovery_device_nvram_write(FuBcm57xxRecoveryDevice *self, guint32 address, const guint32 *buf, gsize bufsz_dwrds, + FuProgress *progress, GError **error) { const guint32 page_size_dwrds = 64; @@ -434,7 +436,7 @@ fu_bcm57xx_recovery_device_nvram_write(FuBcm57xxRecoveryDevice *self, return FALSE; } address += sizeof(guint32); - fu_device_set_progress_full(FU_DEVICE(self), i, bufsz_dwrds); + fu_progress_set_percentage_full(progress, i + 1, bufsz_dwrds); } /* success */ @@ -442,14 +444,14 @@ fu_bcm57xx_recovery_device_nvram_write(FuBcm57xxRecoveryDevice *self, } static gboolean -fu_bcm57xx_recovery_device_detach(FuDevice *device, GError **error) +fu_bcm57xx_recovery_device_detach(FuDevice *device, FuProgress *progress, GError **error) { /* unbind tg3 */ return fu_device_unbind_driver(device, error); } static gboolean -fu_bcm57xx_recovery_device_attach(FuDevice *device, GError **error) +fu_bcm57xx_recovery_device_attach(FuDevice *device, FuProgress *progress, GError **error) { g_autoptr(GError) error_local = NULL; @@ -470,7 +472,7 @@ fu_bcm57xx_recovery_device_attach(FuDevice *device, GError **error) } static gboolean -fu_bcm57xx_recovery_device_activate(FuDevice *device, GError **error) +fu_bcm57xx_recovery_device_activate(FuDevice *device, FuProgress *progress, GError **error) { BcmRegAPEMode mode = {0}; FuBcm57xxRecoveryDevice *self = FU_BCM57XX_RECOVERY_DEVICE(device); @@ -497,7 +499,7 @@ fu_bcm57xx_recovery_device_activate(FuDevice *device, GError **error) } static GBytes * -fu_bcm57xx_recovery_device_dump_firmware(FuDevice *device, GError **error) +fu_bcm57xx_recovery_device_dump_firmware(FuDevice *device, FuProgress *progress, GError **error) { FuBcm57xxRecoveryDevice *self = FU_BCM57XX_RECOVERY_DEVICE(device); gsize bufsz_dwrds = fu_device_get_firmware_size_max(FU_DEVICE(self)) / sizeof(guint32); @@ -506,7 +508,7 @@ fu_bcm57xx_recovery_device_dump_firmware(FuDevice *device, GError **error) g_autoptr(FuDeviceLocker) locker2 = NULL; /* read from hardware */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_READ); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_READ); locker = fu_device_locker_new_full( self, (FuDeviceLockerFunc)fu_bcm57xx_recovery_device_nvram_acquire_lock, @@ -521,7 +523,12 @@ fu_bcm57xx_recovery_device_dump_firmware(FuDevice *device, GError **error) error); if (locker2 == NULL) return NULL; - if (!fu_bcm57xx_recovery_device_nvram_read(self, 0x0, buf_dwrds, bufsz_dwrds, error)) + if (!fu_bcm57xx_recovery_device_nvram_read(self, + 0x0, + buf_dwrds, + bufsz_dwrds, + progress, + error)) return NULL; if (!fu_device_locker_close(locker2, error)) return NULL; @@ -557,6 +564,7 @@ fu_bcm57xx_recovery_device_prepare_firmware(FuDevice *device, static gboolean fu_bcm57xx_recovery_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -569,11 +577,18 @@ fu_bcm57xx_recovery_device_write_firmware(FuDevice *device, g_autoptr(FuDeviceLocker) locker2 = NULL; g_autoptr(GBytes) blob = NULL; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DECOMPRESSING, 1); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 95); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 5); + /* build the images into one linear blob of the correct size */ - fu_device_set_status(device, FWUPD_STATUS_DECOMPRESSING); blob = fu_firmware_write(firmware, error); if (blob == NULL) return FALSE; + fu_progress_step_done(progress); /* align into uint32_t buffer */ buf = g_bytes_get_data(blob, &bufsz); @@ -590,7 +605,6 @@ fu_bcm57xx_recovery_device_write_firmware(FuDevice *device, return FALSE; /* hit hardware */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); locker = fu_device_locker_new_full( self, (FuDeviceLockerFunc)fu_bcm57xx_recovery_device_nvram_acquire_lock, @@ -605,15 +619,26 @@ fu_bcm57xx_recovery_device_write_firmware(FuDevice *device, error); if (locker2 == NULL) return FALSE; - if (!fu_bcm57xx_recovery_device_nvram_write(self, 0x0, buf_dwrds, bufsz_dwrds, error)) + if (!fu_bcm57xx_recovery_device_nvram_write(self, + 0x0, + buf_dwrds, + bufsz_dwrds, + fu_progress_get_child(progress), + error)) return FALSE; if (!fu_device_locker_close(locker2, error)) return FALSE; if (!fu_device_locker_close(locker, error)) return FALSE; + fu_progress_step_done(progress); /* reset APE */ - return fu_device_activate(device, error); + if (!fu_device_activate(device, fu_progress_get_child(progress), error)) + return FALSE; + fu_progress_step_done(progress); + + /* success */ + return TRUE; } static gboolean @@ -623,6 +648,15 @@ fu_bcm57xx_recovery_device_setup(FuDevice *device, GError **error) guint32 fwversion = 0; g_autoptr(FuDeviceLocker) locker = NULL; g_autoptr(FuDeviceLocker) locker2 = NULL; + g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC); + + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 10); /* enable */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 80); /* nvram */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 10); /* veraddr */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 10); /* version */ locker = fu_device_locker_new_full( self, @@ -638,14 +672,17 @@ fu_bcm57xx_recovery_device_setup(FuDevice *device, GError **error) error); if (locker2 == NULL) return FALSE; + fu_progress_step_done(progress); /* get NVRAM version */ if (!fu_bcm57xx_recovery_device_nvram_read(self, BCM_NVRAM_STAGE1_BASE + BCM_NVRAM_STAGE1_VERSION, &fwversion, 1, + fu_progress_get_child(progress), error)) return FALSE; + fu_progress_step_done(progress); if (fwversion != 0x0) { g_autofree gchar *fwversion_str = NULL; @@ -656,6 +693,8 @@ fu_bcm57xx_recovery_device_setup(FuDevice *device, GError **error) fu_device_set_version(device, fwversion_str); fu_device_set_version_raw(device, fwversion); fu_device_set_branch(device, BCM_FW_BRANCH_OSS_FIRMWARE); + fu_progress_step_done(progress); + fu_progress_step_done(progress); } else { guint32 bufver[4] = {0x0}; guint32 veraddr = 0; @@ -667,8 +706,10 @@ fu_bcm57xx_recovery_device_setup(FuDevice *device, GError **error) BCM_NVRAM_STAGE1_VERADDR, &veraddr, 1, + fu_progress_get_child(progress), error)) return FALSE; + fu_progress_step_done(progress); veraddr = GUINT32_FROM_BE(veraddr); if (veraddr > BCM_PHYS_ADDR_DEFAULT) veraddr -= BCM_PHYS_ADDR_DEFAULT; @@ -676,8 +717,10 @@ fu_bcm57xx_recovery_device_setup(FuDevice *device, GError **error) BCM_NVRAM_STAGE1_BASE + veraddr, bufver, 4, + fu_progress_get_child(progress), error)) return FALSE; + fu_progress_step_done(progress); veritem = fu_bcm57xx_veritem_new((guint8 *)bufver, sizeof(bufver)); if (veritem != NULL) { fu_device_set_version(device, veritem->version); @@ -796,6 +839,17 @@ fu_bcm57xx_recovery_device_close(FuDevice *device, GError **error) #endif } +static void +fu_bcm57xx_recovery_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 94); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* reload */ +} + static void fu_bcm57xx_recovery_device_init(FuBcm57xxRecoveryDevice *self) { @@ -842,6 +896,7 @@ fu_bcm57xx_recovery_device_class_init(FuBcm57xxRecoveryDeviceClass *klass) klass_device->attach = fu_bcm57xx_recovery_device_attach; klass_device->detach = fu_bcm57xx_recovery_device_detach; klass_device->probe = fu_bcm57xx_recovery_device_probe; + klass_device->set_progress = fu_bcm57xx_recovery_device_set_progress; } FuBcm57xxRecoveryDevice * diff --git a/plugins/ccgx/fu-ccgx-dmc-device.c b/plugins/ccgx/fu-ccgx-dmc-device.c index 9b95bb03a..1e793fead 100644 --- a/plugins/ccgx/fu-ccgx-dmc-device.c +++ b/plugins/ccgx/fu-ccgx-dmc-device.c @@ -354,11 +354,68 @@ fu_ccgx_dmc_get_image_write_status_cb(FuDevice *device, gpointer user_data, GErr return TRUE; } +static gboolean +fu_ccgx_dmc_write_firmware_record(FuCcgxDmcDevice *self, + FuCcgxDmcFirmwareSegmentRecord *seg_rcd, + gsize *fw_data_written, + FuProgress *progress, + GError **error) +{ + GPtrArray *data_records = NULL; + + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 1); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 99); + + /* write start row and number of rows to a device */ + if (!fu_ccgx_dmc_device_send_write_command(self, + seg_rcd->start_row, + seg_rcd->num_rows, + error)) + return FALSE; + fu_progress_step_done(progress); + + /* send data records */ + data_records = seg_rcd->data_records; + for (guint32 data_index = 0; data_index < data_records->len; data_index++) { + GBytes *data_rcd = g_ptr_array_index(data_records, data_index); + const guint8 *row_buffer = NULL; + gsize row_size = 0; + + /* write row data */ + row_buffer = g_bytes_get_data(data_rcd, &row_size); + if (!fu_ccgx_dmc_device_send_row_data(self, row_buffer, (guint16)row_size, error)) + return FALSE; + + /* increase fw written size */ + *fw_data_written += row_size; + + /* get status */ + if (!fu_device_retry(FU_DEVICE(self), + fu_ccgx_dmc_get_image_write_status_cb, + DMC_FW_WRITE_STATUS_RETRY_COUNT, + NULL, + error)) + return FALSE; + + /* done */ + fu_progress_set_percentage_full(fu_progress_get_child(progress), + data_index + 1, + data_records->len); + } + fu_progress_step_done(progress); + + /* success */ + return TRUE; +} + static gboolean fu_ccgx_dmc_write_firmware_image(FuDevice *device, FuCcgxDmcFirmwareRecord *img_rcd, gsize *fw_data_written, const gsize fw_data_size, + FuProgress *progress, GError **error) { FuCcgxDmcDevice *self = FU_CCGX_DMC_DEVICE(device); @@ -369,44 +426,17 @@ fu_ccgx_dmc_write_firmware_image(FuDevice *device, /* get segment records */ seg_records = img_rcd->seg_records; + fu_progress_set_id(progress, G_STRLOC); + fu_progress_set_steps(progress, seg_records->len); for (guint32 seg_index = 0; seg_index < seg_records->len; seg_index++) { - GPtrArray *data_records = NULL; FuCcgxDmcFirmwareSegmentRecord *seg_rcd = g_ptr_array_index(seg_records, seg_index); - - /* write start row and number of rows to a device */ - if (!fu_ccgx_dmc_device_send_write_command(self, - seg_rcd->start_row, - seg_rcd->num_rows, - error)) + if (!fu_ccgx_dmc_write_firmware_record(self, + seg_rcd, + fw_data_written, + fu_progress_get_child(progress), + error)) return FALSE; - - /* get data records */ - data_records = seg_rcd->data_records; - for (guint32 data_index = 0; data_index < data_records->len; data_index++) { - GBytes *data_rcd = g_ptr_array_index(data_records, data_index); - const guint8 *row_buffer = NULL; - gsize row_size = 0; - - /* write row data */ - row_buffer = g_bytes_get_data(data_rcd, &row_size); - if (!fu_ccgx_dmc_device_send_row_data(self, - row_buffer, - (guint16)row_size, - error)) - return FALSE; - - /* increase fw written size */ - *fw_data_written += row_size; - fu_device_set_progress_full(device, *fw_data_written, fw_data_size); - - /* get status */ - if (!fu_device_retry(FU_DEVICE(self), - fu_ccgx_dmc_get_image_write_status_cb, - DMC_FW_WRITE_STATUS_RETRY_COUNT, - NULL, - error)) - return FALSE; - } + fu_progress_step_done(progress); } return TRUE; } @@ -414,6 +444,7 @@ fu_ccgx_dmc_write_firmware_image(FuDevice *device, static gboolean fu_ccgx_dmc_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -431,6 +462,12 @@ fu_ccgx_dmc_write_firmware(FuDevice *device, gsize fw_data_written = 0; guint8 img_index = 0; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 1); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 1); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 98); + /* get fwct record */ fwct_blob = fu_ccgx_dmc_firmware_get_fwct_record(FU_CCGX_DMC_FIRMWARE(firmware)); fwct_buf = g_bytes_get_data(fwct_blob, &fwct_sz); @@ -449,9 +486,9 @@ fu_ccgx_dmc_write_firmware(FuDevice *device, custom_meta_data = g_bytes_get_data(custom_meta_blob, &custom_meta_bufsz); /* reset */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_BUSY); if (!fu_ccgx_dmc_device_send_reset_state_machine(self, error)) return FALSE; + fu_progress_step_done(progress); /* start fw upgrade with custom metadata */ if (!fu_ccgx_dmc_device_send_start_upgrade(self, @@ -463,11 +500,11 @@ fu_ccgx_dmc_write_firmware(FuDevice *device, /* send fwct data */ if (!fu_ccgx_dmc_device_send_fwct(self, fwct_buf, fwct_sz, error)) return FALSE; + fu_progress_step_done(progress); /* get total fw size */ image_records = fu_ccgx_dmc_firmware_get_image_records(FU_CCGX_DMC_FIRMWARE(firmware)); fw_data_size = fu_ccgx_dmc_firmware_get_fw_data_size(FU_CCGX_DMC_FIRMWARE(firmware)); - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); while (1) { /* get interrupt request */ if (!fu_ccgx_dmc_device_read_intr_req(self, &dmc_int_rqt, error)) @@ -494,10 +531,10 @@ fu_ccgx_dmc_write_firmware(FuDevice *device, img_rcd, &fw_data_written, fw_data_size, + fu_progress_get_child(progress), error)) return FALSE; } - if (dmc_int_rqt.opcode != DMC_INT_OPCODE_FW_UPGRADE_STATUS) { if (dmc_int_rqt.opcode == DMC_INT_OPCODE_FWCT_ANALYSIS_STATUS) { g_set_error(error, @@ -515,7 +552,6 @@ fu_ccgx_dmc_write_firmware(FuDevice *device, dmc_int_rqt.data[0]); return FALSE; } - if (dmc_int_rqt.data[0] == DMC_DEVICE_STATUS_UPDATE_PHASE_1_COMPLETE) { self->update_model = DMC_UPDATE_MODEL_DOWNLOAD_TRIGGER; } else if (dmc_int_rqt.data[0] == DMC_DEVICE_STATUS_FW_DOWNLOADED_UPDATE_PEND) { @@ -528,6 +564,9 @@ fu_ccgx_dmc_write_firmware(FuDevice *device, dmc_int_rqt.data[0]); return FALSE; } + fu_progress_step_done(progress); + + /* success */ return TRUE; } @@ -565,7 +604,7 @@ fu_ccgx_dmc_device_prepare_firmware(FuDevice *device, } static gboolean -fu_ccgx_dmc_device_attach(FuDevice *device, GError **error) +fu_ccgx_dmc_device_attach(FuDevice *device, FuProgress *progress, GError **error) { FuCcgxDmcDevice *self = FU_CCGX_DMC_DEVICE(device); gboolean manual_replug; @@ -603,7 +642,6 @@ fu_ccgx_dmc_device_attach(FuDevice *device, GError **error) if (manual_replug) return TRUE; - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG); return TRUE; } @@ -671,6 +709,17 @@ fu_ccgx_dmc_device_set_quirk_kv(FuDevice *device, return FALSE; } +static void +fu_ccgx_hid_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_NO_PROFILE); /* actually 0, 20, 0, 80! */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 75); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 25); /* reload */ +} + static void fu_ccgx_dmc_device_init(FuCcgxDmcDevice *self) { @@ -697,4 +746,5 @@ fu_ccgx_dmc_device_class_init(FuCcgxDmcDeviceClass *klass) klass_device->attach = fu_ccgx_dmc_device_attach; klass_device->setup = fu_ccgx_dmc_device_setup; klass_device->set_quirk_kv = fu_ccgx_dmc_device_set_quirk_kv; + klass_device->set_progress = fu_ccgx_hid_device_set_progress; } diff --git a/plugins/ccgx/fu-ccgx-hid-device.c b/plugins/ccgx/fu-ccgx-hid-device.c index b132b6bff..cca857a1b 100644 --- a/plugins/ccgx/fu-ccgx-hid-device.c +++ b/plugins/ccgx/fu-ccgx-hid-device.c @@ -24,7 +24,6 @@ fu_ccgx_hid_device_enable_hpi_mode_cb(FuDevice *device, gpointer user_data, GErr { guint8 buf[5] = {0xEE, 0xBC, 0xA6, 0xB9, 0xA8}; - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); if (!fu_hid_device_set_report(FU_HID_DEVICE(device), buf[0], buf, @@ -39,7 +38,7 @@ fu_ccgx_hid_device_enable_hpi_mode_cb(FuDevice *device, gpointer user_data, GErr } static gboolean -fu_ccgx_hid_device_detach(FuDevice *device, GError **error) +fu_ccgx_hid_device_detach(FuDevice *device, FuProgress *progress, GError **error) { if (!fu_device_retry(device, fu_ccgx_hid_device_enable_hpi_mode_cb, @@ -77,6 +76,17 @@ fu_ccgx_hid_device_setup(FuDevice *device, GError **error) return FALSE; } +static void +fu_ccgx_hid_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 98); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* reload */ +} + static void fu_ccgx_hid_device_init(FuCcgxHidDevice *self) { @@ -93,4 +103,5 @@ fu_ccgx_hid_device_class_init(FuCcgxHidDeviceClass *klass) FuDeviceClass *klass_device = FU_DEVICE_CLASS(klass); klass_device->detach = fu_ccgx_hid_device_detach; klass_device->setup = fu_ccgx_hid_device_setup; + klass_device->set_progress = fu_ccgx_hid_device_set_progress; } diff --git a/plugins/ccgx/fu-ccgx-hpi-device.c b/plugins/ccgx/fu-ccgx-hpi-device.c index 3f4bb6ef8..684d19e94 100644 --- a/plugins/ccgx/fu-ccgx-hpi-device.c +++ b/plugins/ccgx/fu-ccgx-hpi-device.c @@ -34,6 +34,15 @@ struct _FuCcgxHpiDevice { guint32 flash_size; }; +/** + * FU_CCGX_HPI_DEVICE_IS_IN_RESTART: + * + * Device is in restart and should not be closed manually. + * + * Since: 1.7.0 + */ +#define FU_CCGX_HPI_DEVICE_IS_IN_RESTART (1 << 0) + G_DEFINE_TYPE(FuCcgxHpiDevice, fu_ccgx_hpi_device, FU_TYPE_USB_DEVICE) #define HPI_CMD_REG_READ_WRITE_DELAY_US 10000 @@ -1027,7 +1036,7 @@ fu_ccgx_hpi_read_flash(FuCcgxHpiDevice *self, } static gboolean -fu_ccgx_hpi_device_detach(FuDevice *device, GError **error) +fu_ccgx_hpi_device_detach(FuDevice *device, FuProgress *progress, GError **error) { FuCcgxHpiDevice *self = FU_CCGX_HPI_DEVICE(device); guint8 buf[] = { @@ -1042,7 +1051,6 @@ fu_ccgx_hpi_device_detach(FuDevice *device, GError **error) /* jump to Alt FW */ if (!fu_ccgx_hpi_device_clear_all_events(self, HPI_CMD_COMMAND_CLEAR_EVENT_TIME_MS, error)) return FALSE; - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); if (!fu_ccgx_hpi_device_reg_write(self, CY_PD_JUMP_TO_BOOT_REG_ADDR, buf, @@ -1054,13 +1062,14 @@ fu_ccgx_hpi_device_detach(FuDevice *device, GError **error) /* sym not required */ fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG); + fu_device_add_private_flag(device, FU_CCGX_HPI_DEVICE_IS_IN_RESTART); /* success */ return TRUE; } static gboolean -fu_ccgx_hpi_device_attach(FuDevice *device, GError **error) +fu_ccgx_hpi_device_attach(FuDevice *device, FuProgress *progress, GError **error) { FuCcgxHpiDevice *self = FU_CCGX_HPI_DEVICE(device); guint8 buf[] = { @@ -1069,7 +1078,6 @@ fu_ccgx_hpi_device_attach(FuDevice *device, GError **error) }; if (!fu_ccgx_hpi_device_clear_all_events(self, HPI_CMD_COMMAND_CLEAR_EVENT_TIME_MS, error)) return FALSE; - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); if (!fu_ccgx_hpi_device_reg_write_no_resp(self, CY_PD_REG_RESET_ADDR, buf, @@ -1079,6 +1087,7 @@ fu_ccgx_hpi_device_attach(FuDevice *device, GError **error) return FALSE; } fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG); + fu_device_add_private_flag(device, FU_CCGX_HPI_DEVICE_IS_IN_RESTART); return TRUE; } @@ -1252,6 +1261,7 @@ fu_ccgx_hpi_save_metadata(FuCcgxHpiDevice *self, static gboolean fu_ccgx_hpi_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -1261,6 +1271,14 @@ fu_ccgx_hpi_write_firmware(FuDevice *device, FWMode fw_mode_alt = fu_ccgx_fw_mode_get_alternate(self->fw_mode); g_autoptr(FuDeviceLocker) locker = NULL; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 5); /* invalidate metadata */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 80); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_VERIFY, 10); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 5); /* leave-flash */ + /* enter flash mode */ locker = fu_device_locker_new_full(self, (FuDeviceLockerFunc)fu_ccgx_hpi_enter_flash_mode, @@ -1270,16 +1288,14 @@ fu_ccgx_hpi_write_firmware(FuDevice *device, return FALSE; /* invalidate metadata for alternate image */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_READ); if (!fu_ccgx_hpi_load_metadata(self, fw_mode_alt, &metadata, error)) return FALSE; - fu_device_set_status(device, FWUPD_STATUS_DEVICE_ERASE); metadata.metadata_valid = 0x00; if (!fu_ccgx_hpi_save_metadata(self, fw_mode_alt, &metadata, error)) return FALSE; + fu_progress_step_done(progress); /* write new image */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); for (guint i = 0; i < records->len; i++) { FuCcgxFirmwareRecord *rcd = g_ptr_array_index(records, i); @@ -1294,19 +1310,23 @@ fu_ccgx_hpi_write_firmware(FuDevice *device, } /* update progress */ - fu_device_set_progress_full(device, (gsize)i, (gsize)records->len - 1); + fu_progress_set_percentage_full(fu_progress_get_child(progress), + (gsize)i + 1, + (gsize)records->len); } + fu_progress_step_done(progress); /* validate fw */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_VERIFY); if (!fu_ccgx_hpi_validate_fw(self, fw_mode_alt, error)) { g_prefix_error(error, "fw validate error: "); return FALSE; } + fu_progress_step_done(progress); /* this is a good time to leave the flash mode *before* rebooting */ if (!fu_device_locker_close(locker, error)) return FALSE; + fu_progress_step_done(progress); /* success */ return TRUE; @@ -1586,7 +1606,7 @@ fu_ccgx_hpi_device_close(FuDevice *device, GError **error) g_autoptr(GError) error_local = NULL; /* do not close handle when device restarts */ - if (fu_device_get_status(device) == FWUPD_STATUS_DEVICE_RESTART) + if (fu_device_has_private_flag(device, FU_CCGX_HPI_DEVICE_IS_IN_RESTART)) return TRUE; if (!g_usb_device_release_interface(fu_usb_device_get_dev(FU_USB_DEVICE(device)), self->inf_num, @@ -1603,6 +1623,17 @@ fu_ccgx_hpi_device_close(FuDevice *device, GError **error) return FU_DEVICE_CLASS(fu_ccgx_hpi_device_parent_class)->close(device, error); } +static void +fu_ccgx_hpi_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 94); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* reload */ +} + static void fu_ccgx_hpi_device_init(FuCcgxHpiDevice *self) { @@ -1649,4 +1680,5 @@ fu_ccgx_hpi_device_class_init(FuCcgxHpiDeviceClass *klass) klass_device->set_quirk_kv = fu_ccgx_hpi_device_set_quirk_kv; klass_device->open = fu_ccgx_hpi_device_open; klass_device->close = fu_ccgx_hpi_device_close; + klass_device->set_progress = fu_ccgx_hpi_device_set_progress; } diff --git a/plugins/colorhug/fu-colorhug-device.c b/plugins/colorhug/fu-colorhug-device.c index c01c2a93e..e18cec70b 100644 --- a/plugins/colorhug/fu-colorhug-device.c +++ b/plugins/colorhug/fu-colorhug-device.c @@ -196,7 +196,7 @@ fu_colorhug_device_msg(FuColorhugDevice *self, } static gboolean -fu_colorhug_device_detach(FuDevice *device, GError **error) +fu_colorhug_device_detach(FuDevice *device, FuProgress *progress, GError **error) { FuColorhugDevice *self = FU_COLORHUG_DEVICE(device); g_autoptr(GError) error_local = NULL; @@ -206,8 +206,6 @@ fu_colorhug_device_detach(FuDevice *device, GError **error) g_debug("already in bootloader mode, skipping"); return TRUE; } - - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); if (!fu_colorhug_device_msg(self, CH_CMD_RESET, NULL, @@ -227,7 +225,7 @@ fu_colorhug_device_detach(FuDevice *device, GError **error) } static gboolean -fu_colorhug_device_attach(FuDevice *device, GError **error) +fu_colorhug_device_attach(FuDevice *device, FuProgress *progress, GError **error) { FuColorhugDevice *self = FU_COLORHUG_DEVICE(device); g_autoptr(GError) error_local = NULL; @@ -237,8 +235,6 @@ fu_colorhug_device_attach(FuDevice *device, GError **error) g_debug("already in runtime mode, skipping"); return TRUE; } - - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); if (!fu_colorhug_device_msg(self, CH_CMD_BOOT_FLASH, NULL, @@ -444,6 +440,7 @@ ch_colorhug_device_calculate_checksum(const guint8 *data, guint32 len) static gboolean fu_colorhug_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -451,27 +448,33 @@ fu_colorhug_device_write_firmware(FuDevice *device, g_autoptr(GBytes) fw = NULL; g_autoptr(GPtrArray) chunks = NULL; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 1); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_ERASE, 19); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 44); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_VERIFY, 35); + /* get default image */ fw = fu_firmware_get_bytes(firmware, error); if (fw == NULL) return FALSE; - /* build packets */ - chunks = fu_chunk_array_new_from_bytes(fw, - self->start_addr, - 0x00, /* page_sz */ - CH_FLASH_TRANSFER_BLOCK_SIZE); - /* don't auto-boot firmware */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); if (!fu_colorhug_device_set_flash_success(self, FALSE, error)) return FALSE; + fu_progress_step_done(progress); /* erase flash */ if (!fu_colorhug_device_erase(self, self->start_addr, g_bytes_get_size(fw), error)) return FALSE; + fu_progress_step_done(progress); /* write each block */ + chunks = fu_chunk_array_new_from_bytes(fw, + self->start_addr, + 0x00, /* page_sz */ + CH_FLASH_TRANSFER_BLOCK_SIZE); for (guint i = 0; i < chunks->len; i++) { FuChunk *chk = g_ptr_array_index(chunks, i); guint8 buf[CH_FLASH_TRANSFER_BLOCK_SIZE + 4]; @@ -507,11 +510,13 @@ fu_colorhug_device_write_firmware(FuDevice *device, } /* update progress */ - fu_device_set_progress_full(device, (gsize)i, (gsize)chunks->len * 2); + fu_progress_set_percentage_full(fu_progress_get_child(progress), + (gsize)i + 1, + (gsize)chunks->len); } + fu_progress_step_done(progress); /* verify each block */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_VERIFY); for (guint i = 0; i < chunks->len; i++) { FuChunk *chk = g_ptr_array_index(chunks, i); guint8 buf[3]; @@ -550,13 +555,26 @@ fu_colorhug_device_write_firmware(FuDevice *device, } /* update progress */ - fu_device_set_progress_full(device, (gsize)chunks->len + i, (gsize)chunks->len * 2); + fu_progress_set_percentage_full(fu_progress_get_child(progress), + (gsize)i + 1, + (gsize)chunks->len); } + fu_progress_step_done(progress); /* success! */ return TRUE; } +static void +fu_colorhug_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 57); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 43); /* reload */ +} + static void fu_colorhug_device_init(FuColorhugDevice *self) { @@ -582,4 +600,5 @@ fu_colorhug_device_class_init(FuColorhugDeviceClass *klass) klass_device->setup = fu_colorhug_device_setup; klass_device->open = fu_colorhug_device_open; klass_device->probe = fu_colorhug_device_probe; + klass_device->set_progress = fu_colorhug_device_set_progress; } diff --git a/plugins/cros-ec/fu-cros-ec-usb-device.c b/plugins/cros-ec/fu-cros-ec-usb-device.c index d7ad435ea..32068cd75 100644 --- a/plugins/cros-ec/fu-cros-ec-usb-device.c +++ b/plugins/cros-ec/fu-cros-ec-usb-device.c @@ -618,6 +618,7 @@ static gboolean fu_cros_ec_usb_device_transfer_section(FuDevice *device, FuFirmware *firmware, FuCrosEcFirmwareSection *section, + FuProgress *progress, GError **error) { FuCrosEcUsbDevice *self = FU_CROS_EC_USB_DEVICE(device); @@ -805,6 +806,7 @@ fu_cros_ec_usb_device_jump_to_rw(FuDevice *device) static gboolean fu_cros_ec_usb_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -880,7 +882,10 @@ fu_cros_ec_usb_device_write_firmware(FuDevice *device, return FALSE; } - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_set_steps(progress, sections->len); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_WRITE); for (guint i = 0; i < sections->len; i++) { FuCrosEcFirmwareSection *section = g_ptr_array_index(sections, i); @@ -890,6 +895,7 @@ fu_cros_ec_usb_device_write_firmware(FuDevice *device, if (!fu_cros_ec_usb_device_transfer_section(device, firmware, section, + fu_progress_get_child(progress), &error_local)) { if (g_error_matches(error_local, G_USB_DEVICE_ERROR, @@ -900,6 +906,7 @@ fu_cros_ec_usb_device_write_firmware(FuDevice *device, fu_device_add_flag( device, FWUPD_DEVICE_FLAG_ANOTHER_WRITE_REQUIRED); + fu_progress_finished(progress); return TRUE; } g_propagate_error(error, g_steal_pointer(&error_local)); @@ -914,6 +921,7 @@ fu_cros_ec_usb_device_write_firmware(FuDevice *device, section->version.triplet); } } + fu_progress_step_done(progress); } /* send done */ fu_cros_ec_usb_device_send_done(device); @@ -981,7 +989,7 @@ fu_cros_ec_usb_device_prepare_firmware(FuDevice *device, } static gboolean -fu_cros_ec_usb_device_attach(FuDevice *device, GError **error) +fu_cros_ec_usb_device_attach(FuDevice *device, FuProgress *progress, GError **error) { FuCrosEcUsbDevice *self = FU_CROS_EC_USB_DEVICE(device); @@ -996,7 +1004,6 @@ fu_cros_ec_usb_device_attach(FuDevice *device, GError **error) * ro -> rw. */ fu_device_remove_private_flag(device, FU_CROS_EC_USB_DEVICE_FLAG_SPECIAL); - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG); return TRUE; } @@ -1009,7 +1016,6 @@ fu_cros_ec_usb_device_attach(FuDevice *device, GError **error) } else { fu_cros_ec_usb_device_jump_to_rw(device); } - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG); /* success */ @@ -1017,7 +1023,7 @@ fu_cros_ec_usb_device_attach(FuDevice *device, GError **error) } static gboolean -fu_cros_ec_usb_device_detach(FuDevice *device, GError **error) +fu_cros_ec_usb_device_detach(FuDevice *device, FuProgress *progress, GError **error) { FuCrosEcUsbDevice *self = FU_CROS_EC_USB_DEVICE(device); @@ -1035,8 +1041,6 @@ fu_cros_ec_usb_device_detach(FuDevice *device, GError **error) fu_device_set_remove_delay(device, CROS_EC_REMOVE_DELAY_RE_ENUMERATE); if (!fu_cros_ec_usb_device_reset_to_ro(device, error)) return FALSE; - - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG); } @@ -1088,6 +1092,17 @@ fu_cros_ec_usb_device_to_string(FuDevice *device, guint idt, GString *str) fu_common_string_append_kx(str, idt, "WriteableOffset", self->writeable_offset); } +static void +fu_cros_ec_usb_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 94); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* reload */ +} + static void fu_cros_ec_usb_device_class_init(FuCrosEcUsbDeviceClass *klass) { @@ -1101,4 +1116,5 @@ fu_cros_ec_usb_device_class_init(FuCrosEcUsbDeviceClass *klass) klass_device->open = fu_cros_ec_usb_device_open; klass_device->probe = fu_cros_ec_usb_device_probe; klass_device->close = fu_cros_ec_usb_device_close; + klass_device->set_progress = fu_cros_ec_usb_device_set_progress; } diff --git a/plugins/dell-dock/fu-dell-dock-hub.c b/plugins/dell-dock/fu-dell-dock-hub.c index 703970b59..850ef487a 100644 --- a/plugins/dell-dock/fu-dell-dock-hub.c +++ b/plugins/dell-dock/fu-dell-dock-hub.c @@ -47,6 +47,7 @@ fu_dell_dock_hub_probe(FuDevice *device, GError **error) static gboolean fu_dell_dock_hub_write_fw(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -63,6 +64,12 @@ fu_dell_dock_hub_write_fw(FuDevice *device, g_return_val_if_fail(device != NULL, FALSE); g_return_val_if_fail(FU_IS_FIRMWARE(firmware), FALSE); + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_ERASE, 1); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 49); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_VERIFY, 50); + /* get default image */ fw = fu_firmware_get_bytes(firmware, error); if (fw == NULL) @@ -81,11 +88,12 @@ fu_dell_dock_hub_write_fw(FuDevice *device, if (!fu_dell_dock_hid_raise_mcu_clock(device, TRUE, error)) return FALSE; - fu_device_set_status(device, FWUPD_STATUS_DEVICE_ERASE); + /* erase */ if (!fu_dell_dock_hid_erase_bank(device, 1, error)) return FALSE; + fu_progress_step_done(progress); - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); + /* write */ do { /* last packet */ if (fw_size - nwritten < write_size) @@ -96,10 +104,11 @@ fu_dell_dock_hub_write_fw(FuDevice *device, nwritten += write_size; data += write_size; address += write_size; - fu_device_set_progress_full(device, nwritten, fw_size); + fu_progress_set_percentage_full(fu_progress_get_child(progress), nwritten, fw_size); } while (nwritten < fw_size); + fu_progress_step_done(progress); - fu_device_set_status(device, FWUPD_STATUS_DEVICE_BUSY); + /* verify */ if (!fu_dell_dock_hid_verify_update(device, &result, error)) return FALSE; if (!result) { @@ -109,9 +118,9 @@ fu_dell_dock_hub_write_fw(FuDevice *device, "Failed to verify the update"); return FALSE; } + fu_progress_step_done(progress); /* dock will reboot to re-read; this is to appease the daemon */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); fu_device_set_version_format(device, FWUPD_VERSION_FORMAT_PAIR); fu_device_set_version(device, dynamic_version); return TRUE; @@ -166,6 +175,16 @@ fu_dell_dock_hub_finalize(GObject *object) G_OBJECT_CLASS(fu_dell_dock_hub_parent_class)->finalize(object); } +static void +fu_dell_dock_hub_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 100); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 0); /* reload */ +} + static void fu_dell_dock_hub_init(FuDellDockHub *self) { @@ -185,6 +204,7 @@ fu_dell_dock_hub_class_init(FuDellDockHubClass *klass) klass_device->probe = fu_dell_dock_hub_probe; klass_device->write_firmware = fu_dell_dock_hub_write_fw; klass_device->set_quirk_kv = fu_dell_dock_hub_set_quirk_kv; + klass_device->set_progress = fu_dell_dock_hub_set_progress; } FuDellDockHub * diff --git a/plugins/dell-dock/fu-dell-dock-i2c-ec.c b/plugins/dell-dock/fu-dell-dock-i2c-ec.c index 5b07c2822..491818d7d 100644 --- a/plugins/dell-dock/fu-dell-dock-i2c-ec.c +++ b/plugins/dell-dock/fu-dell-dock-i2c-ec.c @@ -660,7 +660,7 @@ fu_dell_dock_ec_reset(FuDevice *device, GError **error) } static gboolean -fu_dell_dock_ec_activate(FuDevice *device, GError **error) +fu_dell_dock_ec_activate(FuDevice *device, FuProgress *progress, GError **error) { FuDellDockECFWUpdateStatus status; @@ -787,6 +787,7 @@ fu_dell_dock_ec_commit_package(FuDevice *device, GBytes *blob_fw, GError **error static gboolean fu_dell_dock_ec_write_fw(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -802,6 +803,11 @@ fu_dell_dock_ec_write_fw(FuDevice *device, g_return_val_if_fail(device != NULL, FALSE); g_return_val_if_fail(FU_IS_FIRMWARE(firmware), FALSE); + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_ERASE, 15); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 85); + /* get default image */ fw = fu_firmware_get_bytes(firmware, error); if (fw == NULL) @@ -832,11 +838,12 @@ fu_dell_dock_ec_write_fw(FuDevice *device, if (!fu_dell_dock_hid_raise_mcu_clock(fu_device_get_proxy(device), TRUE, error)) return FALSE; - fu_device_set_status(device, FWUPD_STATUS_DEVICE_ERASE); + /* erase */ if (!fu_dell_dock_hid_erase_bank(fu_device_get_proxy(device), 0xff, error)) return FALSE; + fu_progress_step_done(progress); - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); + /* write */ do { /* last packet */ if (fw_size - nwritten < write_size) @@ -850,11 +857,12 @@ fu_dell_dock_ec_write_fw(FuDevice *device, g_prefix_error(error, "write over HID failed: "); return FALSE; } - fu_device_set_progress_full(device, nwritten, fw_size); + fu_progress_set_percentage_full(fu_progress_get_child(progress), nwritten, fw_size); nwritten += write_size; data += write_size; address += write_size; } while (nwritten < fw_size); + fu_progress_step_done(progress); if (!fu_dell_dock_hid_raise_mcu_clock(fu_device_get_proxy(device), FALSE, error)) return FALSE; @@ -989,6 +997,17 @@ fu_dell_dock_ec_finalize(GObject *object) G_OBJECT_CLASS(fu_dell_dock_ec_parent_class)->finalize(object); } +static void +fu_dell_dock_ec_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 100); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 0); /* reload */ +} + static void fu_dell_dock_ec_init(FuDellDockEc *self) { @@ -1010,6 +1029,7 @@ fu_dell_dock_ec_class_init(FuDellDockEcClass *klass) klass_device->close = fu_dell_dock_ec_close; klass_device->write_firmware = fu_dell_dock_ec_write_fw; klass_device->set_quirk_kv = fu_dell_dock_ec_set_quirk_kv; + klass_device->set_progress = fu_dell_dock_ec_set_progress; } FuDellDockEc * diff --git a/plugins/dell-dock/fu-dell-dock-i2c-mst.c b/plugins/dell-dock/fu-dell-dock-i2c-mst.c index b0e2e3165..e521869c2 100644 --- a/plugins/dell-dock/fu-dell-dock-i2c-mst.c +++ b/plugins/dell-dock/fu-dell-dock-i2c-mst.c @@ -500,7 +500,11 @@ fu_dell_dock_mst_erase_bank(FuDevice *proxy, MSTBank bank, GError **error) } static gboolean -fu_dell_dock_write_flash_bank(FuDevice *device, GBytes *blob_fw, MSTBank bank, GError **error) +fu_dell_dock_write_flash_bank(FuDevice *device, + GBytes *blob_fw, + MSTBank bank, + FuProgress *progress, + GError **error) { const MSTBankAttributes *attribs = NULL; gsize write_size = 32; @@ -527,7 +531,7 @@ fu_dell_dock_write_flash_bank(FuDevice *device, GBytes *blob_fw, MSTBank bank, G i); return FALSE; } - fu_device_set_progress_full(device, i - attribs->start, end - attribs->start); + fu_progress_set_percentage_full(progress, i - attribs->start, end - attribs->start); } return TRUE; @@ -706,15 +710,67 @@ fu_dell_dock_mst_invalidate_bank(FuDevice *proxy, MSTBank bank_in_use, GError ** return TRUE; } +static gboolean +fu_dell_dock_mst_write_bank(FuDevice *device, + GBytes *fw, + guint8 bank, + FuProgress *progress, + GError **error) +{ + const guint retries = 2; + for (guint i = 0; i < retries; i++) { + gboolean checksum = FALSE; + + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_ERASE, 15); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 84); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_VERIFY, 1); + + if (!fu_dell_dock_mst_erase_bank(fu_device_get_proxy(device), bank, error)) + return FALSE; + fu_progress_step_done(progress); + + if (!fu_dell_dock_write_flash_bank(device, + fw, + bank, + fu_progress_get_child(progress), + error)) + return FALSE; + fu_progress_step_done(progress); + + if (!fu_dell_dock_mst_checksum_bank(fu_device_get_proxy(device), + fw, + bank, + &checksum, + error)) + return FALSE; + if (!checksum) { + g_debug("MST: Failed to verify checksum on bank %u", bank); + fu_progress_reset(progress); + continue; + } + fu_progress_step_done(progress); + + g_debug("MST: Bank %u successfully flashed", bank); + return TRUE; + } + + /* failed after all our retries */ + g_set_error(error, G_IO_ERROR, G_IO_ERROR_FAILED, "Failed to write to bank %u", bank); + return FALSE; +} + static gboolean fu_dell_dock_mst_write_fw(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { FuDellDockMst *self = FU_DELL_DOCK_MST(device); + FuProgress *progress_local; MSTBank bank_in_use = 0; - guint retries = 2; gboolean checksum = FALSE; guint8 order[2] = {ESM, Bank0}; guint16 chip_id; @@ -726,6 +782,11 @@ fu_dell_dock_mst_write_fw(FuDevice *device, g_return_val_if_fail(FU_IS_FIRMWARE(firmware), FALSE); g_return_val_if_fail(fu_device_get_proxy(device) != NULL, FALSE); + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 1); /* enable */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 99); + /* get default image */ fw = fu_firmware_get_bytes(firmware, error); if (fw == NULL) @@ -764,8 +825,12 @@ fu_dell_dock_mst_write_fw(FuDevice *device, /* ESM needs special handling during flash process*/ if (!fu_dell_dock_mst_stop_esm(fu_device_get_proxy(device), error)) return FALSE; + fu_progress_step_done(progress); /* Write each bank in order */ + progress_local = fu_progress_get_child(progress); + fu_progress_set_id(progress_local, G_STRLOC); + fu_progress_set_steps(progress_local, 2); for (guint phase = 0; phase < 2; phase++) { g_debug("MST: Checking bank %u", order[phase]); if (!fu_dell_dock_mst_checksum_bank(fu_device_get_proxy(device), @@ -776,51 +841,26 @@ fu_dell_dock_mst_write_fw(FuDevice *device, return FALSE; if (checksum) { g_debug("MST: bank %u is already up to date", order[phase]); + fu_progress_step_done(progress_local); continue; } g_debug("MST: bank %u needs to be updated", order[phase]); - for (guint i = 0; i < retries; i++) { - fu_device_set_progress_full(device, 0, 100); - fu_device_set_status(device, FWUPD_STATUS_DEVICE_ERASE); - if (!fu_dell_dock_mst_erase_bank(fu_device_get_proxy(device), - order[phase], - error)) - return FALSE; - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); - if (!fu_dell_dock_write_flash_bank(device, fw, order[phase], error)) - return FALSE; - if (!fu_dell_dock_mst_checksum_bank(fu_device_get_proxy(device), - fw, - order[phase], - &checksum, - error)) - return FALSE; - fu_device_set_status(device, FWUPD_STATUS_DEVICE_BUSY); - if (!checksum) { - g_debug("MST: Failed to verify checksum on bank %u", order[phase]); - continue; - } - g_debug("MST: Bank %u successfully flashed", order[phase]); - break; - } - /* failed after all our retries */ - if (!checksum) { - g_set_error(error, - G_IO_ERROR, - G_IO_ERROR_FAILED, - "Failed to write to bank %u", - order[phase]); + if (!fu_dell_dock_mst_write_bank(device, + fw, + order[phase], + fu_progress_get_child(progress_local), + error)) return FALSE; - } + fu_progress_step_done(progress_local); } /* invalidate the previous bank */ if (!fu_dell_dock_mst_invalidate_bank(fu_device_get_proxy(device), bank_in_use, error)) { g_prefix_error(error, "failed to invalidate bank %u: ", bank_in_use); return FALSE; } + fu_progress_step_done(progress); /* dock will reboot to re-read; this is to appease the daemon */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); fu_device_set_version_format(device, FWUPD_VERSION_FORMAT_TRIPLET); fu_device_set_version(device, dynamic_version); @@ -935,6 +975,16 @@ fu_dell_dock_mst_close(FuDevice *device, GError **error) return fu_device_close(fu_device_get_proxy(device), error); } +static void +fu_dell_dock_mst_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 100); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 0); /* reload */ +} + static void fu_dell_dock_mst_init(FuDellDockMst *self) { @@ -952,6 +1002,7 @@ fu_dell_dock_mst_class_init(FuDellDockMstClass *klass) klass_device->probe = fu_dell_dock_mst_probe; klass_device->write_firmware = fu_dell_dock_mst_write_fw; klass_device->set_quirk_kv = fu_dell_dock_mst_set_quirk_kv; + klass_device->set_progress = fu_dell_dock_mst_set_progress; } FuDellDockMst * diff --git a/plugins/dell-dock/fu-dell-dock-i2c-tbt.c b/plugins/dell-dock/fu-dell-dock-i2c-tbt.c index e39a81a02..6ad021e43 100644 --- a/plugins/dell-dock/fu-dell-dock-i2c-tbt.c +++ b/plugins/dell-dock/fu-dell-dock-i2c-tbt.c @@ -50,6 +50,7 @@ G_DEFINE_TYPE(FuDellDockTbt, fu_dell_dock_tbt, FU_TYPE_DEVICE) static gboolean fu_dell_dock_tbt_write_fw(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -106,7 +107,7 @@ fu_dell_dock_tbt_write_fw(FuDevice *device, return FALSE; g_usleep(2000000); - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_WRITE); for (guint i = 0; i < image_size; i += HIDI2C_MAX_WRITE, buffer += HIDI2C_MAX_WRITE) { guint8 write_size = (image_size - i) > HIDI2C_MAX_WRITE ? HIDI2C_MAX_WRITE : (image_size - i); @@ -119,11 +120,11 @@ fu_dell_dock_tbt_write_fw(FuDevice *device, error)) return FALSE; - fu_device_set_progress_full(device, i, image_size); + fu_progress_set_percentage_full(progress, i, image_size); } g_debug("writing took %f seconds", g_timer_elapsed(timer, NULL)); - fu_device_set_status(device, FWUPD_STATUS_DEVICE_BUSY); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_BUSY); if (fu_dell_dock_ec_tbt_passive(fu_device_get_parent(device))) { g_debug("using passive flow for Thunderbolt"); @@ -135,7 +136,6 @@ fu_dell_dock_tbt_write_fw(FuDevice *device, } /* dock will reboot to re-read; this is to appease the daemon */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); fu_device_set_version_format(device, FWUPD_VERSION_FORMAT_PAIR); fu_device_set_version(device, dynamic_version); diff --git a/plugins/dell-dock/fu-dell-dock-status.c b/plugins/dell-dock/fu-dell-dock-status.c index da9c170e6..9182cce3d 100644 --- a/plugins/dell-dock/fu-dell-dock-status.c +++ b/plugins/dell-dock/fu-dell-dock-status.c @@ -60,6 +60,7 @@ fu_dell_dock_status_setup(FuDevice *device, GError **error) static gboolean fu_dell_dock_status_write(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -96,7 +97,6 @@ fu_dell_dock_status_write(FuDevice *device, return FALSE; /* dock will reboot to re-read; this is to appease the daemon */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); fu_device_set_version_format(device, FWUPD_VERSION_FORMAT_QUAD); fu_device_set_version(device, dynamic_version); return TRUE; @@ -143,6 +143,16 @@ fu_dell_dock_status_finalize(GObject *object) G_OBJECT_CLASS(fu_dell_dock_status_parent_class)->finalize(object); } +static void +fu_dell_dock_status_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 13); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 72); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 9); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 7); /* reload */ +} + static void fu_dell_dock_status_init(FuDellDockStatus *self) { @@ -160,6 +170,7 @@ fu_dell_dock_status_class_init(FuDellDockStatusClass *klass) klass_device->open = fu_dell_dock_status_open; klass_device->close = fu_dell_dock_status_close; klass_device->set_quirk_kv = fu_dell_dock_status_set_quirk_kv; + klass_device->set_progress = fu_dell_dock_status_set_progress; } FuDellDockStatus * diff --git a/plugins/dell-dock/fu-dell-dock-usb-usb4.c b/plugins/dell-dock/fu-dell-dock-usb-usb4.c index 9caa1d187..0c9f5f1ec 100644 --- a/plugins/dell-dock/fu-dell-dock-usb-usb4.c +++ b/plugins/dell-dock/fu-dell-dock-usb-usb4.c @@ -357,6 +357,7 @@ fu_dell_dock_usb4_hub_nvm_write(FuDevice *device, const guint8 *buf, guint32 length, guint32 nvm_addr, + FuProgress *progress, GError **error) { guint8 metadata[4]; @@ -389,8 +390,8 @@ fu_dell_dock_usb4_hub_nvm_write(FuDevice *device, } /* 2 Write data in 64 byte blocks */ - fu_device_set_progress_full(device, bytes_done, bytes_total); - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); + fu_progress_set_percentage_full(progress, bytes_done, bytes_total); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_WRITE); while (length > 0) { /* write data to mbox data regs */ if (!fu_dell_dock_usb4_mbox_data_write(device, buf, 64, error)) { @@ -404,14 +405,14 @@ fu_dell_dock_usb4_hub_nvm_write(FuDevice *device, } buf += 64; length -= 64; - fu_device_set_progress_full(device, bytes_done += 64, bytes_total); + fu_progress_set_percentage_full(progress, bytes_done += 64, bytes_total); } - fu_device_set_status(device, FWUPD_STATUS_DEVICE_BUSY); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_BUSY); return TRUE; } static gboolean -fu_dell_dock_usb4_activate(FuDevice *device, GError **error) +fu_dell_dock_usb4_activate(FuDevice *device, FuProgress *progress, GError **error) { g_autoptr(FuDeviceLocker) locker = fu_device_locker_new(device, error); if (locker == NULL) @@ -429,6 +430,7 @@ fu_dell_dock_usb4_activate(FuDevice *device, GError **error) static gboolean fu_dell_dock_usb4_write_fw(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -522,7 +524,7 @@ fu_dell_dock_usb4_write_fw(FuDevice *device, /* firmware install */ fw_buf += fw_header_offset; fw_blob_size -= fw_header_offset; - if (!fu_dell_dock_usb4_hub_nvm_write(device, fw_buf, fw_blob_size, 0, error)) + if (!fu_dell_dock_usb4_hub_nvm_write(device, fw_buf, fw_blob_size, 0, progress, error)) return FALSE; fu_device_add_flag(device, FWUPD_DEVICE_FLAG_NEEDS_ACTIVATION); diff --git a/plugins/dell-dock/fu-plugin-dell-dock.c b/plugins/dell-dock/fu-plugin-dell-dock.c index 28af0f1d5..3c531bd82 100644 --- a/plugins/dell-dock/fu-plugin-dell-dock.c +++ b/plugins/dell-dock/fu-plugin-dell-dock.c @@ -311,7 +311,8 @@ fu_plugin_composite_cleanup(FuPlugin *plugin, GPtrArray *devices, GError **error return FALSE; if (needs_activation && dev != NULL) { - if (!fu_device_activate(dev, error)) + g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC); + if (!fu_device_activate(dev, progress, error)) return FALSE; } diff --git a/plugins/dell/fu-self-test.c b/plugins/dell/fu-self-test.c index 6dbad3b1c..21398096b 100644 --- a/plugins/dell/fu-self-test.c +++ b/plugins/dell/fu-self-test.c @@ -80,6 +80,7 @@ fu_plugin_dell_tpm_func(gconstpointer user_data) g_autoptr(GBytes) blob_fw = g_bytes_new_static(fw, sizeof(fw)); g_autoptr(GError) error = NULL; g_autoptr(GPtrArray) devices = NULL; + g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC); #ifdef HAVE_GETUID if (tpm_server_running == NULL && (getuid() != 0 || geteuid() != 0)) { @@ -234,6 +235,7 @@ fu_plugin_dell_tpm_func(gconstpointer user_data) ret = fu_plugin_runner_write_firmware(self->plugin_uefi_capsule, device_v20, blob_fw, + progress, FWUPD_INSTALL_FLAG_NONE, &error); g_assert_error(error, FWUPD_ERROR, FWUPD_ERROR_NOT_SUPPORTED); @@ -244,6 +246,7 @@ fu_plugin_dell_tpm_func(gconstpointer user_data) ret = fu_plugin_runner_write_firmware(self->plugin_uefi_capsule, device_v20, blob_fw, + progress, FWUPD_INSTALL_FLAG_FORCE, &error); g_assert_no_error(error); diff --git a/plugins/dfu-csr/fu-dfu-csr-device.c b/plugins/dfu-csr/fu-dfu-csr-device.c index 7deb1871d..ded200f89 100644 --- a/plugins/dfu-csr/fu-dfu-csr-device.c +++ b/plugins/dfu-csr/fu-dfu-csr-device.c @@ -58,7 +58,7 @@ fu_dfu_csr_device_to_string(FuDevice *device, guint idt, GString *str) } static gboolean -fu_dfu_csr_device_attach(FuDevice *device, GError **error) +fu_dfu_csr_device_attach(FuDevice *device, FuProgress *progress, GError **error) { guint8 buf[] = {FU_DFU_CSR_REPORT_ID_CONTROL, FU_DFU_CSR_CONTROL_RESET}; if (!fu_hid_device_set_report(FU_HID_DEVICE(device), @@ -180,7 +180,7 @@ fu_dfu_csr_device_upload_chunk(FuDfuCsrDevice *self, GError **error) } static GBytes * -fu_dfu_csr_device_upload(FuDevice *device, GError **error) +fu_dfu_csr_device_upload(FuDevice *device, FuProgress *progress, GError **error) { FuDfuCsrDevice *self = FU_DFU_CSR_DEVICE(device); g_autoptr(GPtrArray) chunks = NULL; @@ -188,7 +188,7 @@ fu_dfu_csr_device_upload(FuDevice *device, GError **error) gsize done_sz = 0; /* notify UI */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_READ); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_READ); chunks = g_ptr_array_new_with_free_func((GDestroyNotify)g_bytes_unref); for (guint32 i = 0; i < 0x3ffffff; i++) { @@ -253,7 +253,7 @@ fu_dfu_csr_device_upload(FuDevice *device, GError **error) /* add to chunk array */ done_sz += chunk_sz; g_ptr_array_add(chunks, g_steal_pointer(&chunk)); - fu_device_set_progress_full(device, done_sz, (gsize)total_sz); + fu_progress_set_percentage_full(progress, done_sz, (gsize)total_sz); /* we're done */ if (chunk_sz < 64 - FU_DFU_CSR_COMMAND_HEADER_SIZE) @@ -366,6 +366,7 @@ fu_dfu_csr_device_prepare_firmware(FuDevice *device, static gboolean fu_dfu_csr_device_download(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -381,7 +382,7 @@ fu_dfu_csr_device_download(FuDevice *device, return FALSE; /* notify UI */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_WRITE); /* create chunks */ chunks = fu_chunk_array_new_from_bytes(blob, @@ -400,7 +401,7 @@ fu_dfu_csr_device_download(FuDevice *device, return FALSE; /* update progress */ - fu_device_set_progress_full(device, (gsize)idx, (gsize)chunks->len); + fu_progress_set_percentage_full(progress, (gsize)idx + 1, (gsize)chunks->len); } /* all done */ @@ -438,6 +439,17 @@ fu_dfu_csr_device_setup(FuDevice *device, GError **error) return TRUE; } +static void +fu_dfu_csr_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 94); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* reload */ +} + static void fu_dfu_csr_device_init(FuDfuCsrDevice *self) { @@ -459,4 +471,5 @@ fu_dfu_csr_device_class_init(FuDfuCsrDeviceClass *klass) klass_device->attach = fu_dfu_csr_device_attach; klass_device->setup = fu_dfu_csr_device_setup; klass_device->probe = fu_dfu_csr_device_probe; + klass_device->set_progress = fu_dfu_csr_device_set_progress; } diff --git a/plugins/dfu/fu-dfu-device.c b/plugins/dfu/fu-dfu-device.c index 843ba9b7d..c26124504 100644 --- a/plugins/dfu/fu-dfu-device.c +++ b/plugins/dfu/fu-dfu-device.c @@ -906,7 +906,7 @@ fu_dfu_device_refresh(FuDfuDevice *self, GError **error) } static gboolean -fu_dfu_device_request_detach(FuDfuDevice *self, GError **error) +fu_dfu_device_request_detach(FuDfuDevice *self, FuProgress *progress, GError **error) { FuDfuDevicePrivate *priv = GET_PRIVATE(self); GUsbDevice *usb_device = fu_usb_device_get_dev(FU_USB_DEVICE(self)); @@ -954,7 +954,7 @@ fu_dfu_device_reload(FuDevice *device, GError **error) } static gboolean -fu_dfu_device_detach(FuDevice *device, GError **error) +fu_dfu_device_detach(FuDevice *device, FuProgress *progress, GError **error) { FuDfuDevice *self = FU_DFU_DEVICE(device); FuDfuDevicePrivate *priv = GET_PRIVATE(self); @@ -989,20 +989,18 @@ fu_dfu_device_detach(FuDevice *device, GError **error) return FALSE; /* inform UI there's going to be a detach:attach */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); - if (!fu_dfu_device_request_detach(self, error)) + if (!fu_dfu_device_request_detach(self, progress, error)) return FALSE; /* do a host reset */ if ((priv->attributes & FU_DFU_DEVICE_ATTR_WILL_DETACH) == 0) { g_debug("doing device reset as host will not self-reset"); - if (!fu_dfu_device_reset(self, error)) + if (!fu_dfu_device_reset(self, progress, error)) return FALSE; } /* success */ priv->force_version = 0x0; - fu_device_set_status(device, FWUPD_STATUS_IDLE); fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG); return TRUE; } @@ -1308,24 +1306,17 @@ fu_dfu_device_probe(FuDevice *device, GError **error) /* hardware from Jabra literally reboots if you try to retry a failed * write -- there's no way to avoid blocking the daemon like this... */ - if (fu_device_has_private_flag(FU_DEVICE(self), FU_DFU_DEVICE_FLAG_ATTACH_EXTRA_RESET)) - fu_device_sleep_with_progress(device, 10); /* seconds */ + if (fu_device_has_private_flag(FU_DEVICE(self), FU_DFU_DEVICE_FLAG_ATTACH_EXTRA_RESET)) { + g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC); + fu_progress_sleep(progress, 10000); + } /* success */ return TRUE; } -/** - * fu_dfu_device_reset: - * @self: a #FuDfuDevice - * @error: (nullable): optional return location for an error - * - * Resets the USB device. - * - * Returns: %TRUE for success - **/ gboolean -fu_dfu_device_reset(FuDfuDevice *self, GError **error) +fu_dfu_device_reset(FuDfuDevice *self, FuProgress *progress, GError **error) { GUsbDevice *usb_device = fu_usb_device_get_dev(FU_USB_DEVICE(self)); g_autoptr(GError) error_local = NULL; @@ -1358,7 +1349,7 @@ fu_dfu_device_reset(FuDfuDevice *self, GError **error) } static gboolean -fu_dfu_device_attach(FuDevice *device, GError **error) +fu_dfu_device_attach(FuDevice *device, FuProgress *progress, GError **error) { FuDfuDevice *self = FU_DFU_DEVICE(device); FuDfuDevicePrivate *priv = GET_PRIVATE(self); @@ -1373,14 +1364,10 @@ fu_dfu_device_attach(FuDevice *device, GError **error) if (!fu_device_has_flag(device, FWUPD_DEVICE_FLAG_IS_BOOTLOADER)) return TRUE; - /* inform UI there's going to be a re-attach */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); - /* handle weirdness */ if (fu_device_has_private_flag(FU_DEVICE(self), FU_DFU_DEVICE_FLAG_DETACH_FOR_ATTACH)) { - if (!fu_dfu_device_request_detach(self, error)) + if (!fu_dfu_device_request_detach(self, progress, error)) return FALSE; - fu_device_set_status(device, FWUPD_STATUS_IDLE); fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG); return TRUE; } @@ -1395,7 +1382,7 @@ fu_dfu_device_attach(FuDevice *device, GError **error) target_zero = fu_dfu_device_get_target_by_alt_setting(self, 0, error); if (target_zero == NULL) return FALSE; - chunk = fu_dfu_target_upload_chunk(target_zero, 0, 0, error); + chunk = fu_dfu_target_upload_chunk(target_zero, 0, 0, progress, error); if (chunk == NULL) return FALSE; } @@ -1409,28 +1396,15 @@ fu_dfu_device_attach(FuDevice *device, GError **error) if (fu_device_has_private_flag(FU_DEVICE(self), FU_DFU_DEVICE_FLAG_NO_BUS_RESET_ATTACH) && fu_dfu_device_has_attribute(self, FU_DFU_DEVICE_ATTR_WILL_DETACH)) g_debug("Bus reset is not required. Device will reboot to normal"); - else if (!fu_dfu_target_attach(target, error)) + else if (!fu_dfu_target_attach(target, progress, error)) return FALSE; /* success */ priv->force_version = 0x0; - fu_device_set_status(device, FWUPD_STATUS_IDLE); fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG); return TRUE; } -static void -fu_dfu_device_percentage_cb(FuDfuTarget *target, guint percentage, FuDfuDevice *self) -{ - fu_device_set_progress(FU_DEVICE(self), percentage); -} - -static void -fu_dfu_device_action_cb(FuDfuTarget *target, FwupdStatus action, FuDfuDevice *self) -{ - fu_device_set_status(FU_DEVICE(self), action); -} - /** * fu_dfu_device_upload: * @self: a #FuDfuDevice @@ -1442,7 +1416,10 @@ fu_dfu_device_action_cb(FuDfuTarget *target, FwupdStatus action, FuDfuDevice *se * Returns: (transfer full): the uploaded firmware, or %NULL for error **/ FuFirmware * -fu_dfu_device_upload(FuDfuDevice *self, FuDfuTargetTransferFlags flags, GError **error) +fu_dfu_device_upload(FuDfuDevice *self, + FuProgress *progress, + FuDfuTargetTransferFlags flags, + GError **error) { FuDfuDevicePrivate *priv = GET_PRIVATE(self); GUsbDevice *usb_device = fu_usb_device_get_dev(FU_USB_DEVICE(self)); @@ -1474,11 +1451,11 @@ fu_dfu_device_upload(FuDfuDevice *self, FuDfuTargetTransferFlags flags, GError * fu_dfu_firmware_set_release(FU_DFU_FIRMWARE(firmware), 0xffff); /* upload from each target */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_set_steps(progress, priv->targets->len); for (guint i = 0; i < priv->targets->len; i++) { FuDfuTarget *target; const gchar *alt_name; - gulong id1; - gulong id2; /* upload to target and proxy signals */ target = g_ptr_array_index(priv->targets, i); @@ -1489,26 +1466,19 @@ fu_dfu_device_upload(FuDfuDevice *self, FuDfuTargetTransferFlags flags, GError * g_debug("ignoring target %s", alt_name); continue; } - - id1 = g_signal_connect(target, - "percentage-changed", - G_CALLBACK(fu_dfu_device_percentage_cb), - self); - id2 = g_signal_connect(target, - "action-changed", - G_CALLBACK(fu_dfu_device_action_cb), - self); - if (!fu_dfu_target_upload(target, firmware, DFU_TARGET_TRANSFER_FLAG_NONE, error)) + if (!fu_dfu_target_upload(target, + firmware, + fu_progress_get_child(progress), + DFU_TARGET_TRANSFER_FLAG_NONE, + error)) return NULL; - g_signal_handler_disconnect(target, id1); - g_signal_handler_disconnect(target, id2); + fu_progress_step_done(progress); } /* do not do the dummy upload for quirked devices */ priv->done_upload_or_download = TRUE; /* success */ - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_IDLE); return g_object_ref(firmware); } @@ -1534,6 +1504,7 @@ fu_dfu_device_id_compatible(guint16 id_file, guint16 id_runtime, guint16 id_dev) static gboolean fu_dfu_device_download(FuDfuDevice *self, FuFirmware *firmware, + FuProgress *progress, FuDfuTargetTransferFlags flags, GError **error) { @@ -1625,13 +1596,13 @@ fu_dfu_device_download(FuDfuDevice *self, images = fu_firmware_get_images(firmware); if (images->len == 0) g_ptr_array_add(images, g_object_ref(firmware)); + fu_progress_set_id(progress, G_STRLOC); + fu_progress_set_steps(progress, images->len); for (guint i = 0; i < images->len; i++) { FuFirmware *image = g_ptr_array_index(images, i); FuDfuTargetTransferFlags flags_local = DFU_TARGET_TRANSFER_FLAG_NONE; const gchar *alt_name; guint8 alt; - gulong id1; - gulong id2; g_autoptr(FuDfuTarget) target_tmp = NULL; g_autoptr(GError) error_local = NULL; @@ -1658,26 +1629,20 @@ fu_dfu_device_download(FuDfuDevice *self, if (!FU_IS_DFU_FIRMWARE(firmware) || fu_dfu_firmware_get_version(FU_DFU_FIRMWARE(firmware)) == 0x0) flags_local |= DFU_TARGET_TRANSFER_FLAG_ADDR_HEURISTIC; - id1 = g_signal_connect(target_tmp, - "percentage-changed", - G_CALLBACK(fu_dfu_device_percentage_cb), - self); - id2 = g_signal_connect(target_tmp, - "action-changed", - G_CALLBACK(fu_dfu_device_action_cb), - self); - ret = fu_dfu_target_download(target_tmp, image, flags_local, error); - g_signal_handler_disconnect(target_tmp, id1); - g_signal_handler_disconnect(target_tmp, id2); + ret = fu_dfu_target_download(target_tmp, + image, + fu_progress_get_child(progress), + flags_local, + error); if (!ret) return FALSE; + fu_progress_step_done(progress); } /* do not do the dummy upload for quirked devices */ priv->done_upload_or_download = TRUE; /* success */ - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_IDLE); return TRUE; } @@ -1720,7 +1685,7 @@ fu_dfu_device_error_fixup(FuDfuDevice *self, GError **error) } static GBytes * -fu_dfu_device_dump_firmware(FuDevice *device, GError **error) +fu_dfu_device_dump_firmware(FuDevice *device, FuProgress *progress, GError **error) { FuDfuDevice *self = FU_DFU_DEVICE(device); g_autoptr(FuFirmware) firmware = NULL; @@ -1738,7 +1703,7 @@ fu_dfu_device_dump_firmware(FuDevice *device, GError **error) g_debug("uploading from device->host"); if (!fu_dfu_device_refresh_and_clear(self, error)) return NULL; - firmware = fu_dfu_device_upload(self, DFU_TARGET_TRANSFER_FLAG_NONE, error); + firmware = fu_dfu_device_upload(self, progress, DFU_TARGET_TRANSFER_FLAG_NONE, error); if (firmware == NULL) return NULL; @@ -1764,6 +1729,7 @@ fu_dfu_device_prepare_firmware(FuDevice *device, static gboolean fu_dfu_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -1779,7 +1745,7 @@ fu_dfu_device_write_firmware(FuDevice *device, } /* hit hardware */ - return fu_dfu_device_download(self, firmware, transfer_flags, error); + return fu_dfu_device_download(self, firmware, progress, transfer_flags, error); } static gboolean @@ -1869,6 +1835,16 @@ fu_dfu_device_get_attributes_as_string(FuDfuDevice *self) return g_string_free(str, FALSE); } +static void +fu_dfu_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 1); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 88); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 1); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 10); /* reload */ +} + static void fu_dfu_device_finalize(GObject *object) { @@ -1897,6 +1873,7 @@ fu_dfu_device_class_init(FuDfuDeviceClass *klass) klass_device->open = fu_dfu_device_open; klass_device->close = fu_dfu_device_close; klass_device->probe = fu_dfu_device_probe; + klass_device->set_progress = fu_dfu_device_set_progress; object_class->finalize = fu_dfu_device_finalize; } @@ -1971,7 +1948,4 @@ fu_dfu_device_init(FuDfuDevice *self) FU_DFU_DEVICE_FLAG_NO_BUS_RESET_ATTACH, "no-bus-reset-attach"); fu_device_register_private_flag(FU_DEVICE(self), FU_DFU_DEVICE_FLAG_GD32, "gd32"); - fu_device_register_private_flag(FU_DEVICE(self), - FU_DFU_DEVICE_FLAG_ALLOW_ZERO_POLLTIMEOUT, - "allow-zero-polltimeout"); } diff --git a/plugins/dfu/fu-dfu-device.h b/plugins/dfu/fu-dfu-device.h index 6a678f242..bfbb1774d 100644 --- a/plugins/dfu/fu-dfu-device.h +++ b/plugins/dfu/fu-dfu-device.h @@ -65,9 +65,12 @@ fu_dfu_device_get_runtime_pid(FuDfuDevice *self); guint16 fu_dfu_device_get_runtime_release(FuDfuDevice *self); gboolean -fu_dfu_device_reset(FuDfuDevice *self, GError **error); +fu_dfu_device_reset(FuDfuDevice *self, FuProgress *progress, GError **error); FuFirmware * -fu_dfu_device_upload(FuDfuDevice *self, FuDfuTargetTransferFlags flags, GError **error); +fu_dfu_device_upload(FuDfuDevice *self, + FuProgress *progress, + FuDfuTargetTransferFlags flags, + GError **error); gboolean fu_dfu_device_refresh(FuDfuDevice *self, GError **error); gboolean diff --git a/plugins/dfu/fu-dfu-target-avr.c b/plugins/dfu/fu-dfu-target-avr.c index 6048d884b..bc5f12c61 100644 --- a/plugins/dfu/fu-dfu-target-avr.c +++ b/plugins/dfu/fu-dfu-target-avr.c @@ -82,7 +82,7 @@ G_DEFINE_TYPE_WITH_PRIVATE(FuDfuTargetAvr, fu_dfu_target_avr, FU_TYPE_DFU_TARGET #define ATMEL_MANUFACTURER_CODE2 0x1e static gboolean -fu_dfu_target_avr_mass_erase(FuDfuTarget *target, GError **error) +fu_dfu_target_avr_mass_erase(FuDfuTarget *target, FuProgress *progress, GError **error) { g_autoptr(GBytes) data_in = NULL; guint8 buf[3]; @@ -95,18 +95,15 @@ fu_dfu_target_avr_mass_erase(FuDfuTarget *target, GError **error) buf[1] = DFU_AVR32_CMD_ERASE; buf[2] = 0xff; data_in = g_bytes_new_static(buf, sizeof(buf)); - g_debug("mass erasing"); - fu_dfu_target_set_action(target, FWUPD_STATUS_DEVICE_ERASE); - if (!fu_dfu_target_download_chunk(target, 0, data_in, error)) { + if (!fu_dfu_target_download_chunk(target, 0, data_in, progress, error)) { g_prefix_error(error, "cannot mass-erase: "); return FALSE; } - fu_dfu_target_set_action(target, FWUPD_STATUS_IDLE); return TRUE; } static gboolean -fu_dfu_target_avr_attach(FuDfuTarget *target, GError **error) +fu_dfu_target_avr_attach(FuDfuTarget *target, FuProgress *progress, GError **error) { guint8 buf[3]; g_autoptr(GBytes) data_empty = NULL; @@ -118,7 +115,7 @@ fu_dfu_target_avr_attach(FuDfuTarget *target, GError **error) buf[1] = DFU_AVR32_CMD_START_APPLI; buf[2] = DFU_AVR32_START_APPLI_RESET; data_in = g_bytes_new_static(buf, sizeof(buf)); - if (!fu_dfu_target_download_chunk(target, 0, data_in, &error_local)) { + if (!fu_dfu_target_download_chunk(target, 0, data_in, progress, &error_local)) { if (g_error_matches(error_local, FWUPD_ERROR, FWUPD_ERROR_NOT_SUPPORTED)) { g_debug("ignoring as device rebooting: %s", error_local->message); return TRUE; @@ -129,7 +126,7 @@ fu_dfu_target_avr_attach(FuDfuTarget *target, GError **error) /* do zero-sized download to initiate the reset */ data_empty = g_bytes_new(NULL, 0); - if (!fu_dfu_target_download_chunk(target, 0, data_empty, &error_local)) { + if (!fu_dfu_target_download_chunk(target, 0, data_empty, progress, &error_local)) { if (g_error_matches(error_local, FWUPD_ERROR, FWUPD_ERROR_NOT_SUPPORTED)) { g_debug("ignoring as device rebooting: %s", error_local->message); return TRUE; @@ -153,7 +150,10 @@ fu_dfu_target_avr_attach(FuDfuTarget *target, GError **error) * Returns: %TRUE for success **/ static gboolean -fu_dfu_target_avr_select_memory_unit(FuDfuTarget *target, guint8 memory_unit, GError **error) +fu_dfu_target_avr_select_memory_unit(FuDfuTarget *target, + guint8 memory_unit, + FuProgress *progress, + GError **error) { g_autoptr(GBytes) data_in = NULL; guint8 buf[4]; @@ -172,7 +172,7 @@ fu_dfu_target_avr_select_memory_unit(FuDfuTarget *target, guint8 memory_unit, GE buf[3] = memory_unit; data_in = g_bytes_new_static(buf, sizeof(buf)); g_debug("selecting memory unit 0x%02x", (guint)memory_unit); - if (!fu_dfu_target_download_chunk(target, 0, data_in, error)) { + if (!fu_dfu_target_download_chunk(target, 0, data_in, progress, error)) { g_prefix_error(error, "cannot select memory unit: "); return FALSE; } @@ -190,7 +190,10 @@ fu_dfu_target_avr_select_memory_unit(FuDfuTarget *target, guint8 memory_unit, GE * Returns: %TRUE for success **/ static gboolean -fu_dfu_target_avr_select_memory_page(FuDfuTarget *target, guint16 memory_page, GError **error) +fu_dfu_target_avr_select_memory_page(FuDfuTarget *target, + guint16 memory_page, + FuProgress *progress, + GError **error) { g_autoptr(GBytes) data_in = NULL; guint8 buf[4]; @@ -213,7 +216,7 @@ fu_dfu_target_avr_select_memory_page(FuDfuTarget *target, guint16 memory_page, G buf[3] = memory_page & 0xff; data_in = g_bytes_new_static(buf, sizeof(buf)); g_debug("selecting memory page 0x%01x", (guint)memory_page); - if (!fu_dfu_target_download_chunk(target, 0, data_in, error)) { + if (!fu_dfu_target_download_chunk(target, 0, data_in, progress, error)) { g_prefix_error(error, "cannot select memory page: "); return FALSE; } @@ -231,7 +234,10 @@ fu_dfu_target_avr_select_memory_page(FuDfuTarget *target, guint16 memory_page, G * Returns: %TRUE for success **/ static gboolean -fu_dfu_target_avr32_select_memory_page(FuDfuTarget *target, guint16 memory_page, GError **error) +fu_dfu_target_avr32_select_memory_page(FuDfuTarget *target, + guint16 memory_page, + FuProgress *progress, + GError **error) { g_autoptr(GBytes) data_in = NULL; guint8 buf[5]; @@ -243,7 +249,7 @@ fu_dfu_target_avr32_select_memory_page(FuDfuTarget *target, guint16 memory_page, fu_common_write_uint16(&buf[3], memory_page, G_BIG_ENDIAN); data_in = g_bytes_new_static(buf, sizeof(buf)); g_debug("selecting memory page 0x%02x", (guint)memory_page); - if (!fu_dfu_target_download_chunk(target, 0, data_in, error)) { + if (!fu_dfu_target_download_chunk(target, 0, data_in, progress, error)) { g_prefix_error(error, "cannot select memory page: "); return FALSE; } @@ -265,6 +271,7 @@ static gboolean fu_dfu_target_avr_read_memory(FuDfuTarget *target, guint16 addr_start, guint16 addr_end, + FuProgress *progress, GError **error) { g_autoptr(GBytes) data_in = NULL; @@ -277,7 +284,7 @@ fu_dfu_target_avr_read_memory(FuDfuTarget *target, fu_common_write_uint16(&buf[4], addr_end, G_BIG_ENDIAN); data_in = g_bytes_new_static(buf, sizeof(buf)); g_debug("reading memory from 0x%04x to 0x%04x", (guint)addr_start, (guint)addr_end); - if (!fu_dfu_target_download_chunk(target, 0, data_in, error)) { + if (!fu_dfu_target_download_chunk(target, 0, data_in, progress, error)) { g_prefix_error(error, "cannot read memory 0x%04x to 0x%04x: ", (guint)addr_start, @@ -298,7 +305,11 @@ fu_dfu_target_avr_read_memory(FuDfuTarget *target, * Returns: %TRUE for success **/ static gboolean -fu_dfu_target_avr_read_command(FuDfuTarget *target, guint8 page, guint8 addr, GError **error) +fu_dfu_target_avr_read_command(FuDfuTarget *target, + guint8 page, + guint8 addr, + FuProgress *progress, + GError **error) { g_autoptr(GBytes) data_in = NULL; guint8 buf[3]; @@ -309,7 +320,7 @@ fu_dfu_target_avr_read_command(FuDfuTarget *target, guint8 page, guint8 addr, GE buf[2] = addr; data_in = g_bytes_new_static(buf, sizeof(buf)); g_debug("read command page:0x%02x addr:0x%02x", (guint)page, (guint)addr); - if (!fu_dfu_target_download_chunk(target, 0, data_in, error)) { + if (!fu_dfu_target_download_chunk(target, 0, data_in, progress, error)) { g_prefix_error(error, "cannot read command page: "); return FALSE; } @@ -326,18 +337,21 @@ fu_dfu_target_avr_read_command(FuDfuTarget *target, guint8 page, guint8 addr, GE * Returns: a 4-byte %GBytes object for success, else %NULL **/ static GBytes * -fu_dfu_target_avr32_get_chip_signature(FuDfuTarget *target, GError **error) +fu_dfu_target_avr32_get_chip_signature(FuDfuTarget *target, FuProgress *progress, GError **error) { /* select unit, and request 4 bytes */ - if (!fu_dfu_target_avr_select_memory_unit(target, DFU_AVR32_MEMORY_UNIT_SIGNATURE, error)) + if (!fu_dfu_target_avr_select_memory_unit(target, + DFU_AVR32_MEMORY_UNIT_SIGNATURE, + progress, + error)) return NULL; - if (!fu_dfu_target_avr32_select_memory_page(target, 0x00, error)) + if (!fu_dfu_target_avr32_select_memory_page(target, 0x00, progress, error)) return NULL; - if (!fu_dfu_target_avr_read_memory(target, 0x00, 0x03, error)) + if (!fu_dfu_target_avr_read_memory(target, 0x00, 0x03, progress, error)) return NULL; /* get data back */ - return fu_dfu_target_upload_chunk(target, 0x00, 0, error); + return fu_dfu_target_upload_chunk(target, 0x00, 0, progress, error); } /** @@ -350,7 +364,7 @@ fu_dfu_target_avr32_get_chip_signature(FuDfuTarget *target, GError **error) * Returns: a 4-byte %GBytes object for success, else %NULL **/ static GBytes * -fu_dfu_target_avr_get_chip_signature(FuDfuTarget *target, GError **error) +fu_dfu_target_avr_get_chip_signature(FuDfuTarget *target, FuProgress *progress, GError **error) { struct { guint8 page; @@ -371,11 +385,12 @@ fu_dfu_target_avr_get_chip_signature(FuDfuTarget *target, GError **error) if (!fu_dfu_target_avr_read_command(target, signature_locations[i].page, signature_locations[i].addr, + progress, error)) return NULL; /* get data back */ - chunk_byte = fu_dfu_target_upload_chunk(target, 0x00, 0x01, error); + chunk_byte = fu_dfu_target_upload_chunk(target, 0x00, 0x01, progress, error); if (chunk_byte == NULL) return NULL; if (g_bytes_get_size(chunk_byte) != 1) { @@ -405,6 +420,7 @@ fu_dfu_target_avr_setup(FuDfuTarget *target, GError **error) gsize sz; guint32 device_id_be; g_autofree gchar *chip_id_guid = NULL; + g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC); g_autoptr(GBytes) chunk_sig = NULL; /* already done */ @@ -414,11 +430,11 @@ fu_dfu_target_avr_setup(FuDfuTarget *target, GError **error) /* different methods for AVR vs. AVR32 */ if (fu_device_has_private_flag(FU_DEVICE(fu_dfu_target_get_device(target)), FU_DFU_DEVICE_FLAG_LEGACY_PROTOCOL)) { - chunk_sig = fu_dfu_target_avr_get_chip_signature(target, error); + chunk_sig = fu_dfu_target_avr_get_chip_signature(target, progress, error); if (chunk_sig == NULL) return FALSE; } else { - chunk_sig = fu_dfu_target_avr32_get_chip_signature(target, error); + chunk_sig = fu_dfu_target_avr32_get_chip_signature(target, progress, error); if (chunk_sig == NULL) { g_prefix_error(error, "failed to get chip signature: "); return FALSE; @@ -477,6 +493,7 @@ fu_dfu_target_avr_setup(FuDfuTarget *target, GError **error) static gboolean fu_dfu_target_avr_download_element(FuDfuTarget *target, FuChunk *chk, + FuProgress *progress, FuDfuTargetTransferFlags flags, GError **error) { @@ -505,13 +522,21 @@ fu_dfu_target_avr_download_element(FuDfuTarget *target, 0xff, 0xff}; /* release */ + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_ERASE, 10); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 90); + /* select a memory and erase everything */ if (!fu_dfu_target_avr_select_memory_unit(target, fu_dfu_target_get_alt_setting(target), + progress, error)) return FALSE; - if (!fu_dfu_target_avr_mass_erase(target, error)) + if (!fu_dfu_target_avr_mass_erase(target, progress, error)) return FALSE; + fu_progress_step_done(progress); /* verify the element isn't larger than the target size */ blob = fu_chunk_get_bytes(chk); @@ -554,11 +579,8 @@ fu_dfu_target_avr_download_element(FuDfuTarget *target, fu_dfu_sector_get_address(sector), ATMEL_64KB_PAGE, ATMEL_MAX_TRANSFER_SIZE); - - /* update UI */ - fu_dfu_target_set_action(target, FWUPD_STATUS_DEVICE_WRITE); - - /* process each chunk */ + fu_progress_set_id(fu_progress_get_child(progress), G_STRLOC); + fu_progress_set_steps(fu_progress_get_child(progress), chunks->len); for (guint i = 0; i < chunks->len; i++) { FuChunk *chk2 = g_ptr_array_index(chunks, i); g_autofree guint8 *buf = NULL; @@ -570,11 +592,13 @@ fu_dfu_target_avr_download_element(FuDfuTarget *target, FU_DFU_DEVICE_FLAG_LEGACY_PROTOCOL)) { if (!fu_dfu_target_avr_select_memory_page(target, fu_chunk_get_page(chk2), + progress, error)) return FALSE; } else { if (!fu_dfu_target_avr32_select_memory_page(target, fu_chunk_get_page(chk2), + progress, error)) return FALSE; } @@ -598,16 +622,15 @@ fu_dfu_target_avr_download_element(FuDfuTarget *target, fu_chunk_get_data_sz(chk2) + header_sz + sizeof(footer)); g_debug("sending %" G_GSIZE_FORMAT " bytes to the hardware", g_bytes_get_size(chunk_tmp)); - if (!fu_dfu_target_download_chunk(target, i, chunk_tmp, error)) + if (!fu_dfu_target_download_chunk(target, i, chunk_tmp, progress, error)) return FALSE; /* update UI */ - fu_dfu_target_set_percentage(target, i + 1, chunks->len); + fu_progress_step_done(fu_progress_get_child(progress)); } + fu_progress_step_done(progress); /* done */ - fu_dfu_target_set_percentage_raw(target, 100); - fu_dfu_target_set_action(target, FWUPD_STATUS_IDLE); return TRUE; } @@ -616,6 +639,7 @@ fu_dfu_target_avr_upload_element(FuDfuTarget *target, guint32 address, gsize expected_size, gsize maximum_size, + FuProgress *progress, GError **error) { guint16 page_last = G_MAXUINT16; @@ -630,6 +654,7 @@ fu_dfu_target_avr_upload_element(FuDfuTarget *target, /* select unit */ if (!fu_dfu_target_avr_select_memory_unit(target, fu_dfu_target_get_alt_setting(target), + progress, error)) return NULL; @@ -661,7 +686,7 @@ fu_dfu_target_avr_upload_element(FuDfuTarget *target, ATMEL_MAX_TRANSFER_SIZE); /* update UI */ - fu_dfu_target_set_action(target, FWUPD_STATUS_DEVICE_READ); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_READ); /* process each chunk */ blobs = g_ptr_array_new_with_free_func((GDestroyNotify)g_bytes_unref); @@ -675,11 +700,13 @@ fu_dfu_target_avr_upload_element(FuDfuTarget *target, FU_DFU_DEVICE_FLAG_LEGACY_PROTOCOL)) { if (!fu_dfu_target_avr_select_memory_page(target, fu_chunk_get_page(chk), + progress, error)) return NULL; } else { if (!fu_dfu_target_avr32_select_memory_page(target, fu_chunk_get_page(chk), + progress, error)) return NULL; } @@ -691,6 +718,7 @@ fu_dfu_target_avr_upload_element(FuDfuTarget *target, fu_chunk_get_address(chk), fu_chunk_get_address(chk) + fu_chunk_get_data_sz(chk) - 1, + progress, error)) return NULL; @@ -698,7 +726,8 @@ fu_dfu_target_avr_upload_element(FuDfuTarget *target, g_debug("requesting %i bytes from the hardware for chunk 0x%x", ATMEL_MAX_TRANSFER_SIZE, i); - blob_tmp = fu_dfu_target_upload_chunk(target, i, ATMEL_MAX_TRANSFER_SIZE, error); + blob_tmp = + fu_dfu_target_upload_chunk(target, i, ATMEL_MAX_TRANSFER_SIZE, progress, error); if (blob_tmp == NULL) return NULL; g_ptr_array_add(blobs, blob_tmp); @@ -714,13 +743,9 @@ fu_dfu_target_avr_upload_element(FuDfuTarget *target, } /* update UI */ - fu_dfu_target_set_percentage(target, i + 1, chunks->len); + fu_progress_set_percentage_full(progress, i + 1, chunks->len); } - /* done */ - fu_dfu_target_set_percentage_raw(target, 100); - fu_dfu_target_set_action(target, FWUPD_STATUS_IDLE); - /* truncate the image if any sectors are empty, i.e. all 0xff */ if (chunk_valid == G_MAXUINT) { g_debug("all %u chunks are empty", blobs->len); diff --git a/plugins/dfu/fu-dfu-target-private.h b/plugins/dfu/fu-dfu-target-private.h index 7ecc746d6..55f6fb9c8 100644 --- a/plugins/dfu/fu-dfu-target-private.h +++ b/plugins/dfu/fu-dfu-target-private.h @@ -16,11 +16,19 @@ FuDfuTarget * fu_dfu_target_new(void); GBytes * -fu_dfu_target_upload_chunk(FuDfuTarget *self, guint16 index, gsize buf_sz, GError **error); +fu_dfu_target_upload_chunk(FuDfuTarget *self, + guint16 index, + gsize buf_sz, + FuProgress *progress, + GError **error); gboolean -fu_dfu_target_download_chunk(FuDfuTarget *self, guint16 index, GBytes *bytes, GError **error); +fu_dfu_target_download_chunk(FuDfuTarget *self, + guint16 index, + GBytes *bytes, + FuProgress *progress, + GError **error); gboolean -fu_dfu_target_attach(FuDfuTarget *self, GError **error); +fu_dfu_target_attach(FuDfuTarget *self, FuProgress *progress, GError **error); void fu_dfu_target_set_alt_idx(FuDfuTarget *self, guint8 alt_idx); void @@ -28,12 +36,6 @@ fu_dfu_target_set_alt_setting(FuDfuTarget *self, guint8 alt_setting); /* for the other implementations */ void -fu_dfu_target_set_action(FuDfuTarget *self, FwupdStatus action); -void -fu_dfu_target_set_percentage_raw(FuDfuTarget *self, guint percentage); -void -fu_dfu_target_set_percentage(FuDfuTarget *self, guint value, guint total); -void fu_dfu_target_set_alt_name(FuDfuTarget *self, const gchar *alt_name); void fu_dfu_target_set_device(FuDfuTarget *self, FuDfuDevice *device); diff --git a/plugins/dfu/fu-dfu-target-stm.c b/plugins/dfu/fu-dfu-target-stm.c index 76abc2816..c3eb23246 100644 --- a/plugins/dfu/fu-dfu-target-stm.c +++ b/plugins/dfu/fu-dfu-target-stm.c @@ -27,16 +27,16 @@ G_DEFINE_TYPE(FuDfuTargetStm, fu_dfu_target_stm, FU_TYPE_DFU_TARGET) #define DFU_STM_CMD_READ_UNPROTECT 0x92 static gboolean -fu_dfu_target_stm_attach(FuDfuTarget *target, GError **error) +fu_dfu_target_stm_attach(FuDfuTarget *target, FuProgress *progress, GError **error) { /* downloading empty payload will cause a dfu to leave, * the returned status will be dfuMANIFEST and expect the device to disconnect */ g_autoptr(GBytes) bytes_tmp = g_bytes_new(NULL, 0); - return fu_dfu_target_download_chunk(target, 2, bytes_tmp, error); + return fu_dfu_target_download_chunk(target, 2, bytes_tmp, progress, error); } static gboolean -fu_dfu_target_stm_mass_erase(FuDfuTarget *target, GError **error) +fu_dfu_target_stm_mass_erase(FuDfuTarget *target, FuProgress *progress, GError **error) { GBytes *data_in; guint8 buf[1]; @@ -44,7 +44,7 @@ fu_dfu_target_stm_mass_erase(FuDfuTarget *target, GError **error) /* format buffer */ buf[0] = DFU_STM_CMD_ERASE; data_in = g_bytes_new_static(buf, sizeof(buf)); - if (!fu_dfu_target_download_chunk(target, 0, data_in, error)) { + if (!fu_dfu_target_download_chunk(target, 0, data_in, progress, error)) { g_prefix_error(error, "cannot mass-erase: "); return FALSE; } @@ -53,18 +53,12 @@ fu_dfu_target_stm_mass_erase(FuDfuTarget *target, GError **error) return fu_dfu_target_check_status(target, error); } -/** - * fu_dfu_target_stm_set_address: - * @target: a #FuDfuTarget - * @address: memory address - * @error: (nullable): optional return location for an error - * - * Sets the address used for the next download or upload request. - * - * Returns: %TRUE for success - **/ +/* sets the address used for the next download or upload request */ static gboolean -fu_dfu_target_stm_set_address(FuDfuTarget *target, guint32 address, GError **error) +fu_dfu_target_stm_set_address(FuDfuTarget *target, + guint32 address, + FuProgress *progress, + GError **error) { GBytes *data_in; guint8 buf[5]; @@ -73,7 +67,7 @@ fu_dfu_target_stm_set_address(FuDfuTarget *target, guint32 address, GError **err buf[0] = DFU_STM_CMD_SET_ADDRESS_POINTER; memcpy(buf + 1, &address, 4); data_in = g_bytes_new_static(buf, sizeof(buf)); - if (!fu_dfu_target_download_chunk(target, 0, data_in, error)) { + if (!fu_dfu_target_download_chunk(target, 0, data_in, progress, error)) { g_prefix_error(error, "cannot set address 0x%x: ", address); return FALSE; } @@ -88,6 +82,7 @@ fu_dfu_target_stm_upload_element(FuDfuTarget *target, guint32 address, gsize expected_size, gsize maximum_size, + FuProgress *progress, GError **error) { FuDfuDevice *device = fu_dfu_target_get_device(target); @@ -123,11 +118,11 @@ fu_dfu_target_stm_upload_element(FuDfuTarget *target, } /* update UI */ - fu_dfu_target_set_action(target, FWUPD_STATUS_DEVICE_READ); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_READ); /* manually set the sector address */ g_debug("setting DfuSe address to 0x%04x", (guint)offset); - if (!fu_dfu_target_stm_set_address(target, offset, error)) + if (!fu_dfu_target_stm_set_address(target, offset, progress, error)) return NULL; /* abort back to IDLE */ @@ -144,6 +139,7 @@ fu_dfu_target_stm_upload_element(FuDfuTarget *target, chunk_tmp = fu_dfu_target_upload_chunk(target, idx + 2, 0, /* device transfer size */ + progress, error); if (chunk_tmp == NULL) return NULL; @@ -160,7 +156,7 @@ fu_dfu_target_stm_upload_element(FuDfuTarget *target, /* update UI */ if (chunk_size > 0) - fu_dfu_target_set_percentage(target, total_size, percentage_size); + fu_progress_set_percentage_full(progress, total_size, percentage_size); /* detect short write as EOF */ if (chunk_size < transfer_size) @@ -189,10 +185,6 @@ fu_dfu_target_stm_upload_element(FuDfuTarget *target, } } - /* done */ - fu_dfu_target_set_percentage_raw(target, 100); - fu_dfu_target_set_action(target, FWUPD_STATUS_IDLE); - /* create new image */ contents = fu_dfu_utils_bytes_join_array(chunks); if (expected_size > 0) { @@ -218,7 +210,10 @@ fu_dfu_target_stm_upload_element(FuDfuTarget *target, * Returns: %TRUE for success **/ static gboolean -fu_dfu_target_stm_erase_address(FuDfuTarget *target, guint32 address, GError **error) +fu_dfu_target_stm_erase_address(FuDfuTarget *target, + guint32 address, + FuProgress *progress, + GError **error) { GBytes *data_in; guint8 buf[5]; @@ -227,7 +222,7 @@ fu_dfu_target_stm_erase_address(FuDfuTarget *target, guint32 address, GError **e buf[0] = DFU_STM_CMD_ERASE; memcpy(buf + 1, &address, 4); data_in = g_bytes_new_static(buf, sizeof(buf)); - if (!fu_dfu_target_download_chunk(target, 0, data_in, error)) { + if (!fu_dfu_target_download_chunk(target, 0, data_in, progress, error)) { g_prefix_error(error, "cannot erase address 0x%x: ", address); return FALSE; } @@ -240,11 +235,13 @@ fu_dfu_target_stm_erase_address(FuDfuTarget *target, guint32 address, GError **e static gboolean fu_dfu_target_stm_download_element(FuDfuTarget *target, FuChunk *chk, + FuProgress *progress, FuDfuTargetTransferFlags flags, GError **error) { FuDfuDevice *device = fu_dfu_target_get_device(target); FuDfuSector *sector; + FuProgress *progress_local; guint nr_chunks; guint zone_last = G_MAXUINT; guint16 transfer_size = fu_dfu_device_get_transfer_size(device); @@ -263,6 +260,13 @@ fu_dfu_target_stm_download_element(FuDfuTarget *target, return FALSE; } + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 1); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_ERASE, 10); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 89); + /* 1st pass: work out which sectors need erasing */ sectors_array = g_ptr_array_new(); sectors_hash = g_hash_table_new(g_direct_hash, g_direct_equal); @@ -306,23 +310,28 @@ fu_dfu_target_stm_download_element(FuDfuTarget *target, offset_dev += fu_dfu_sector_get_size(sector); } } + fu_progress_step_done(progress); /* 2nd pass: actually erase sectors */ - fu_dfu_target_set_action(target, FWUPD_STATUS_DEVICE_ERASE); + progress_local = fu_progress_get_child(progress); + fu_progress_set_id(progress_local, G_STRLOC); + fu_progress_set_steps(progress_local, sectors_array->len); for (guint i = 0; i < sectors_array->len; i++) { sector = g_ptr_array_index(sectors_array, i); g_debug("erasing sector at 0x%04x", fu_dfu_sector_get_address(sector)); if (!fu_dfu_target_stm_erase_address(target, fu_dfu_sector_get_address(sector), + fu_progress_get_child(progress_local), error)) return FALSE; - fu_dfu_target_set_percentage(target, i + 1, sectors_array->len); + fu_progress_step_done(progress_local); } - fu_dfu_target_set_percentage_raw(target, 100); - fu_dfu_target_set_action(target, FWUPD_STATUS_IDLE); + fu_progress_step_done(progress); /* 3rd pass: write data */ - fu_dfu_target_set_action(target, FWUPD_STATUS_DEVICE_WRITE); + progress_local = fu_progress_get_child(progress); + fu_progress_set_id(progress_local, G_STRLOC); + fu_progress_set_steps(progress_local, nr_chunks); for (guint i = 0; i < nr_chunks; i++) { gsize length; guint32 offset; @@ -340,7 +349,10 @@ fu_dfu_target_stm_download_element(FuDfuTarget *target, /* manually set the sector address */ if (fu_dfu_sector_get_zone(sector) != zone_last) { g_debug("setting address to 0x%04x", (guint)offset_dev); - if (!fu_dfu_target_stm_set_address(target, (guint32)offset_dev, error)) + if (!fu_dfu_target_stm_set_address(target, + (guint32)offset_dev, + fu_progress_get_child(progress_local), + error)) return FALSE; zone_last = fu_dfu_sector_get_zone(sector); } @@ -356,7 +368,11 @@ fu_dfu_target_stm_download_element(FuDfuTarget *target, offset_dev, g_bytes_get_size(bytes_tmp)); /* ST uses wBlockNum=0 for DfuSe commands and wBlockNum=1 is reserved */ - if (!fu_dfu_target_download_chunk(target, (i + 2), bytes_tmp, error)) + if (!fu_dfu_target_download_chunk(target, + (i + 2), + bytes_tmp, + fu_progress_get_child(progress_local), + error)) return FALSE; /* getting the status moves the state machine to DNLOAD-IDLE */ @@ -364,12 +380,9 @@ fu_dfu_target_stm_download_element(FuDfuTarget *target, return FALSE; /* update UI */ - fu_dfu_target_set_percentage(target, offset, g_bytes_get_size(bytes)); + fu_progress_step_done(progress_local); } - - /* done */ - fu_dfu_target_set_percentage_raw(target, 100); - fu_dfu_target_set_action(target, FWUPD_STATUS_IDLE); + fu_progress_step_done(progress); /* success */ return TRUE; diff --git a/plugins/dfu/fu-dfu-target.c b/plugins/dfu/fu-dfu-target.c index 415fa832e..8a26b65ff 100644 --- a/plugins/dfu/fu-dfu-target.c +++ b/plugins/dfu/fu-dfu-target.c @@ -45,10 +45,6 @@ typedef struct { FwupdStatus old_action; } FuDfuTargetPrivate; -enum { SIGNAL_PERCENTAGE_CHANGED, SIGNAL_ACTION_CHANGED, SIGNAL_LAST }; - -static guint signals[SIGNAL_LAST] = {0}; - G_DEFINE_TYPE_WITH_PRIVATE(FuDfuTarget, fu_dfu_target, G_TYPE_OBJECT) #define GET_PRIVATE(o) (fu_dfu_target_get_instance_private(o)) @@ -56,45 +52,6 @@ static void fu_dfu_target_class_init(FuDfuTargetClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS(klass); - - /** - * FuDfuTarget::percentage-changed: - * @device: the #FuDfuTarget instance that emitted the signal - * @percentage: the new percentage - * - * The ::percentage-changed signal is emitted when the percentage changes. - **/ - signals[SIGNAL_PERCENTAGE_CHANGED] = - g_signal_new("percentage-changed", - G_TYPE_FROM_CLASS(object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET(FuDfuTargetClass, percentage_changed), - NULL, - NULL, - g_cclosure_marshal_VOID__UINT, - G_TYPE_NONE, - 1, - G_TYPE_UINT); - - /** - * FuDfuTarget::action-changed: - * @device: the #FuDfuTarget instance that emitted the signal - * @action: the new FwupdStatus - * - * The ::action-changed signal is emitted when the high level action changes. - **/ - signals[SIGNAL_ACTION_CHANGED] = - g_signal_new("action-changed", - G_TYPE_FROM_CLASS(object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET(FuDfuTargetClass, action_changed), - NULL, - NULL, - g_cclosure_marshal_VOID__UINT, - G_TYPE_NONE, - 1, - G_TYPE_UINT); - object_class->finalize = fu_dfu_target_finalize; } @@ -750,7 +707,7 @@ fu_dfu_target_setup(FuDfuTarget *self, GError **error) * Returns: %TRUE for success **/ gboolean -fu_dfu_target_mass_erase(FuDfuTarget *self, GError **error) +fu_dfu_target_mass_erase(FuDfuTarget *self, FuProgress *progress, GError **error) { FuDfuTargetClass *klass = FU_DFU_TARGET_GET_CLASS(self); if (!fu_dfu_target_setup(self, error)) @@ -762,11 +719,15 @@ fu_dfu_target_mass_erase(FuDfuTarget *self, GError **error) "mass erase not supported"); return FALSE; } - return klass->mass_erase(self, error); + return klass->mass_erase(self, progress, error); } gboolean -fu_dfu_target_download_chunk(FuDfuTarget *self, guint16 index, GBytes *bytes, GError **error) +fu_dfu_target_download_chunk(FuDfuTarget *self, + guint16 index, + GBytes *bytes, + FuProgress *progress, + GError **error) { FuDfuTargetPrivate *priv = GET_PRIVATE(self); GUsbDevice *usb_device = fu_usb_device_get_dev(FU_USB_DEVICE(priv->device)); @@ -807,10 +768,8 @@ fu_dfu_target_download_chunk(FuDfuTarget *self, guint16 index, GBytes *bytes, GE } /* wait for the device to write contents to the EEPROM */ - if (g_bytes_get_size(bytes) == 0 && fu_dfu_device_get_download_timeout(priv->device) > 0) { - fu_dfu_target_set_action(self, FWUPD_STATUS_IDLE); - fu_dfu_target_set_action(self, FWUPD_STATUS_DEVICE_BUSY); - } + if (g_bytes_get_size(bytes) == 0 && fu_dfu_device_get_download_timeout(priv->device) > 0) + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_BUSY); if (fu_dfu_device_get_download_timeout(priv->device) > 0) { g_debug("sleeping for %ums…", fu_dfu_device_get_download_timeout(priv->device)); g_usleep(fu_dfu_device_get_download_timeout(priv->device) * 1000); @@ -825,7 +784,11 @@ fu_dfu_target_download_chunk(FuDfuTarget *self, guint16 index, GBytes *bytes, GE } GBytes * -fu_dfu_target_upload_chunk(FuDfuTarget *self, guint16 index, gsize buf_sz, GError **error) +fu_dfu_target_upload_chunk(FuDfuTarget *self, + guint16 index, + gsize buf_sz, + FuProgress *progress, + GError **error) { FuDfuTargetPrivate *priv = GET_PRIVATE(self); GUsbDevice *usb_device = fu_usb_device_get_dev(FU_USB_DEVICE(priv->device)); @@ -882,25 +845,6 @@ fu_dfu_target_set_alt_setting(FuDfuTarget *self, guint8 alt_setting) priv->alt_setting = alt_setting; } -void -fu_dfu_target_set_action(FuDfuTarget *self, FwupdStatus action) -{ - FuDfuTargetPrivate *priv = GET_PRIVATE(self); - - /* unchanged */ - if (priv->old_action == action) - return; - if (priv->old_action != FWUPD_STATUS_IDLE && action != FWUPD_STATUS_IDLE) { - g_debug("ignoring action %s as %s already set and not idle", - fwupd_status_to_string(action), - fwupd_status_to_string(priv->old_action)); - return; - } - g_debug("setting action %s", fwupd_status_to_string(action)); - g_signal_emit(self, signals[SIGNAL_ACTION_CHANGED], 0, action); - priv->old_action = action; -} - FuDfuDevice * fu_dfu_target_get_device(FuDfuTarget *self) { @@ -908,34 +852,8 @@ fu_dfu_target_get_device(FuDfuTarget *self) return priv->device; } -void -fu_dfu_target_set_percentage_raw(FuDfuTarget *self, guint percentage) -{ - FuDfuTargetPrivate *priv = GET_PRIVATE(self); - if (percentage == priv->old_percentage) - return; - g_debug("setting percentage %u%% of %s", - percentage, - fwupd_status_to_string(priv->old_action)); - g_signal_emit(self, signals[SIGNAL_PERCENTAGE_CHANGED], 0, percentage); - priv->old_percentage = percentage; -} - -void -fu_dfu_target_set_percentage(FuDfuTarget *self, guint value, guint total) -{ - guint percentage; - - g_return_if_fail(total > 0); - - percentage = (value * 100) / total; - if (percentage >= 100) - return; - fu_dfu_target_set_percentage_raw(self, percentage); -} - gboolean -fu_dfu_target_attach(FuDfuTarget *self, GError **error) +fu_dfu_target_attach(FuDfuTarget *self, FuProgress *progress, GError **error) { FuDfuTargetPrivate *priv = GET_PRIVATE(self); FuDfuTargetClass *klass = FU_DFU_TARGET_GET_CLASS(self); @@ -946,10 +864,10 @@ fu_dfu_target_attach(FuDfuTarget *self, GError **error) /* implemented as part of a superclass */ if (klass->attach != NULL) - return klass->attach(self, error); + return klass->attach(self, progress, error); /* normal DFU mode just needs a bus reset */ - return fu_dfu_device_reset(priv->device, error); + return fu_dfu_device_reset(priv->device, progress, error); } static FuChunk * @@ -957,6 +875,7 @@ fu_dfu_target_upload_element_dfu(FuDfuTarget *self, guint32 address, gsize expected_size, gsize maximum_size, + FuProgress *progress, GError **error) { FuDfuTargetPrivate *priv = GET_PRIVATE(self); @@ -969,7 +888,7 @@ fu_dfu_target_upload_element_dfu(FuDfuTarget *self, g_autoptr(GPtrArray) chunks = NULL; /* update UI */ - fu_dfu_target_set_action(self, FWUPD_STATUS_DEVICE_READ); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_READ); /* get all the chunks from the hardware */ chunks = g_ptr_array_new_with_free_func((GDestroyNotify)g_bytes_unref); @@ -980,6 +899,7 @@ fu_dfu_target_upload_element_dfu(FuDfuTarget *self, chunk_tmp = fu_dfu_target_upload_chunk(self, idx, 0, /* device transfer size */ + progress, error); if (chunk_tmp == NULL) return NULL; @@ -995,7 +915,7 @@ fu_dfu_target_upload_element_dfu(FuDfuTarget *self, /* update UI */ if (chunk_size > 0) - fu_dfu_target_set_percentage(self, total_size, percentage_size); + fu_progress_set_percentage_full(progress, total_size, percentage_size); /* detect short write as EOF */ if (chunk_size < transfer_size) @@ -1017,8 +937,7 @@ fu_dfu_target_upload_element_dfu(FuDfuTarget *self, } /* done */ - fu_dfu_target_set_percentage_raw(self, 100); - fu_dfu_target_set_action(self, FWUPD_STATUS_IDLE); + fu_progress_set_percentage(progress, 100); /* create new image */ contents = fu_dfu_utils_bytes_join_array(chunks); @@ -1030,15 +949,22 @@ fu_dfu_target_upload_element(FuDfuTarget *self, guint32 address, gsize expected_size, gsize maximum_size, + FuProgress *progress, GError **error) { FuDfuTargetClass *klass = FU_DFU_TARGET_GET_CLASS(self); /* implemented as part of a superclass */ if (klass->upload_element != NULL) { - return klass->upload_element(self, address, expected_size, maximum_size, error); + return klass + ->upload_element(self, address, expected_size, maximum_size, progress, error); } - return fu_dfu_target_upload_element_dfu(self, address, expected_size, maximum_size, error); + return fu_dfu_target_upload_element_dfu(self, + address, + expected_size, + maximum_size, + progress, + error); } static guint32 @@ -1059,6 +985,7 @@ fu_dfu_target_get_size_of_zone(FuDfuTarget *self, guint16 zone) gboolean fu_dfu_target_upload(FuDfuTarget *self, FuFirmware *firmware, + FuProgress *progress, FuDfuTargetTransferFlags flags, GError **error) { @@ -1104,6 +1031,8 @@ fu_dfu_target_upload(FuDfuTarget *self, fu_firmware_set_idx(image, priv->alt_setting); /* get all the sectors for the device */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_set_steps(progress, priv->sectors->len); for (guint i = 0; i < priv->sectors->len; i++) { g_autoptr(FuChunk) chk = NULL; @@ -1125,12 +1054,14 @@ fu_dfu_target_upload(FuDfuTarget *self, fu_dfu_sector_get_address(sector), 0, /* expected */ zone_size, /* maximum */ + fu_progress_get_child(progress), error); if (chk == NULL) return FALSE; /* this chunk was uploaded okay */ fu_firmware_add_chunk(image, chk); + fu_progress_step_done(progress); } /* success */ @@ -1172,6 +1103,7 @@ _g_bytes_compare_verbose(GBytes *bytes1, GBytes *bytes2) static gboolean fu_dfu_target_download_element_dfu(FuDfuTarget *self, FuChunk *chk, + FuProgress *progress, FuDfuTargetTransferFlags flags, GError **error) { @@ -1190,7 +1122,7 @@ fu_dfu_target_download_element_dfu(FuDfuTarget *self, "zero-length firmware"); return FALSE; } - fu_dfu_target_set_action(self, FWUPD_STATUS_DEVICE_WRITE); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_WRITE); for (guint32 i = 0; i < nr_chunks + 1; i++) { gsize length; guint32 offset; @@ -1213,17 +1145,13 @@ fu_dfu_target_download_element_dfu(FuDfuTarget *self, g_debug("writing #%04x chunk of size %" G_GSIZE_FORMAT, i, g_bytes_get_size(bytes_tmp)); - if (!fu_dfu_target_download_chunk(self, i, bytes_tmp, error)) + if (!fu_dfu_target_download_chunk(self, i, bytes_tmp, progress, error)) return FALSE; /* update UI */ - fu_dfu_target_set_percentage(self, offset, g_bytes_get_size(bytes)); + fu_progress_set_percentage_full(progress, i + 1, nr_chunks + 1); } - /* done */ - fu_dfu_target_set_percentage_raw(self, 100); - fu_dfu_target_set_action(self, FWUPD_STATUS_IDLE); - /* success */ return TRUE; } @@ -1231,20 +1159,41 @@ fu_dfu_target_download_element_dfu(FuDfuTarget *self, static gboolean fu_dfu_target_download_element(FuDfuTarget *self, FuChunk *chk, + FuProgress *progress, FuDfuTargetTransferFlags flags, GError **error) { FuDfuTargetPrivate *priv = GET_PRIVATE(self); FuDfuTargetClass *klass = FU_DFU_TARGET_GET_CLASS(self); + /* progress */ + if (flags & DFU_TARGET_TRANSFER_FLAG_VERIFY && + fu_dfu_device_has_attribute(priv->device, FU_DFU_DEVICE_ATTR_CAN_UPLOAD)) { + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 96); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_VERIFY, 4); + } else { + fu_progress_set_id(progress, G_STRLOC); + fu_progress_set_steps(progress, 1); + } + /* implemented as part of a superclass */ if (klass->download_element != NULL) { - if (!klass->download_element(self, chk, flags, error)) + if (!klass->download_element(self, + chk, + fu_progress_get_child(progress), + flags, + error)) return FALSE; } else { - if (!fu_dfu_target_download_element_dfu(self, chk, flags, error)) + if (!fu_dfu_target_download_element_dfu(self, + chk, + fu_progress_get_child(progress), + flags, + error)) return FALSE; } + fu_progress_step_done(progress); /* verify */ if (flags & DFU_TARGET_TRANSFER_FLAG_VERIFY && @@ -1252,12 +1201,12 @@ fu_dfu_target_download_element(FuDfuTarget *self, g_autoptr(GBytes) bytes = NULL; g_autoptr(GBytes) bytes_tmp = NULL; g_autoptr(FuChunk) chunk_tmp = NULL; - fu_dfu_target_set_action(self, FWUPD_STATUS_DEVICE_VERIFY); bytes = fu_chunk_get_bytes(chk); chunk_tmp = fu_dfu_target_upload_element(self, fu_chunk_get_address(chk), g_bytes_get_size(bytes), g_bytes_get_size(bytes), + fu_progress_get_child(progress), error); if (chunk_tmp == NULL) return FALSE; @@ -1272,7 +1221,7 @@ fu_dfu_target_download_element(FuDfuTarget *self, bytes_cmp_str); return FALSE; } - fu_dfu_target_set_action(self, FWUPD_STATUS_IDLE); + fu_progress_step_done(progress); } return TRUE; @@ -1293,6 +1242,7 @@ fu_dfu_target_download_element(FuDfuTarget *self, gboolean fu_dfu_target_download(FuDfuTarget *self, FuFirmware *image, + FuProgress *progress, FuDfuTargetTransferFlags flags, GError **error) { @@ -1348,7 +1298,7 @@ fu_dfu_target_download(FuDfuTarget *self, } /* download to device */ - if (!fu_dfu_target_download_element(self, chk, flags, error)) + if (!fu_dfu_target_download_element(self, chk, progress, flags, error)) return FALSE; } diff --git a/plugins/dfu/fu-dfu-target.h b/plugins/dfu/fu-dfu-target.h index b6c682c73..75b464ccc 100644 --- a/plugins/dfu/fu-dfu-target.h +++ b/plugins/dfu/fu-dfu-target.h @@ -40,19 +40,20 @@ typedef enum { struct _FuDfuTargetClass { GUsbDeviceClass parent_class; - void (*percentage_changed)(FuDfuTarget *self, guint percentage); void (*action_changed)(FuDfuTarget *self, FwupdStatus action); gboolean (*setup)(FuDfuTarget *self, GError **error); - gboolean (*attach)(FuDfuTarget *self, GError **error); - gboolean (*detach)(FuDfuTarget *self, GError **error); - gboolean (*mass_erase)(FuDfuTarget *self, GError **error); + gboolean (*attach)(FuDfuTarget *self, FuProgress *progress, GError **error); + gboolean (*detach)(FuDfuTarget *self, FuProgress *progress, GError **error); + gboolean (*mass_erase)(FuDfuTarget *self, FuProgress *progress, GError **error); FuChunk *(*upload_element)(FuDfuTarget *self, guint32 address, gsize expected_size, gsize maximum_size, + FuProgress *progress, GError **error); gboolean (*download_element)(FuDfuTarget *self, FuChunk *chk, + FuProgress *progress, FuDfuTargetTransferFlags flags, GError **error); }; @@ -70,6 +71,7 @@ fu_dfu_target_get_alt_name_for_display(FuDfuTarget *self, GError **error); gboolean fu_dfu_target_upload(FuDfuTarget *self, FuFirmware *firmware, + FuProgress *progress, FuDfuTargetTransferFlags flags, GError **error); gboolean @@ -77,9 +79,10 @@ fu_dfu_target_setup(FuDfuTarget *self, GError **error); gboolean fu_dfu_target_download(FuDfuTarget *self, FuFirmware *image, + FuProgress *progress, FuDfuTargetTransferFlags flags, GError **error); gboolean -fu_dfu_target_mass_erase(FuDfuTarget *self, GError **error); +fu_dfu_target_mass_erase(FuDfuTarget *self, FuProgress *progress, GError **error); void fu_dfu_target_to_string(FuDfuTarget *self, guint idt, GString *str); diff --git a/plugins/dfu/fu-dfu-tool.c b/plugins/dfu/fu-dfu-tool.c index e18d696e8..d0727c306 100644 --- a/plugins/dfu/fu-dfu-tool.c +++ b/plugins/dfu/fu-dfu-tool.c @@ -259,7 +259,6 @@ fu_dfu_device_wait_for_replug(FuDfuTool *self, FuDfuDevice *device, guint timeou return FALSE; /* re-open with new device set */ - fu_device_set_status(FU_DEVICE(device), FWUPD_STATUS_IDLE); fu_usb_device_set_dev(FU_USB_DEVICE(device), usb_device2); if (!fu_device_open(FU_DEVICE(device), error)) return FALSE; @@ -444,11 +443,11 @@ fu_dfu_tool_replace_data(FuDfuTool *self, gchar **values, GError **error) } static void -fu_tool_action_changed_cb(FuDevice *device, GParamSpec *pspec, FuDfuTool *self) +fu_tool_action_changed_cb(FuProgress *progress, gpointer dummy, FuDfuTool *self) { g_print("%s:\t%u%%\n", - fwupd_status_to_string(fu_device_get_status(device)), - fu_device_get_progress(device)); + fwupd_status_to_string(fu_progress_get_status(progress)), + fu_progress_get_percentage(progress)); } static gboolean @@ -461,6 +460,7 @@ fu_dfu_tool_read_alt(FuDfuTool *self, gchar **values, GError **error) g_autoptr(FuDfuTarget) target = NULL; g_autoptr(FuDeviceLocker) locker = NULL; g_autoptr(GFile) file = NULL; + g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC); /* check args */ if (g_strv_length(values) < 2) { @@ -485,13 +485,16 @@ fu_dfu_tool_read_alt(FuDfuTool *self, gchar **values, GError **error) return FALSE; /* set up progress */ - g_signal_connect(device, "notify::status", G_CALLBACK(fu_tool_action_changed_cb), self); - g_signal_connect(device, "notify::progress", G_CALLBACK(fu_tool_action_changed_cb), self); + g_signal_connect(progress, "status-changed", G_CALLBACK(fu_tool_action_changed_cb), self); + g_signal_connect(progress, + "percentage-changed", + G_CALLBACK(fu_tool_action_changed_cb), + self); /* APP -> DFU */ if (!fu_device_has_flag(FU_DEVICE(device), FWUPD_DEVICE_FLAG_IS_BOOTLOADER)) { g_debug("detaching"); - if (!fu_device_detach(FU_DEVICE(device), error)) + if (!fu_device_detach(FU_DEVICE(device), progress, error)) return FALSE; if (!fu_dfu_device_wait_for_replug(self, device, @@ -522,11 +525,11 @@ fu_dfu_tool_read_alt(FuDfuTool *self, gchar **values, GError **error) firmware = fu_dfuse_firmware_new(); fu_dfu_firmware_set_vid(FU_DFU_FIRMWARE(firmware), fu_dfu_device_get_runtime_vid(device)); fu_dfu_firmware_set_pid(FU_DFU_FIRMWARE(firmware), fu_dfu_device_get_runtime_pid(device)); - if (!fu_dfu_target_upload(target, firmware, flags, error)) + if (!fu_dfu_target_upload(target, firmware, progress, flags, error)) return FALSE; /* do host reset */ - if (!fu_device_attach(FU_DEVICE(device), error)) + if (!fu_device_attach(FU_DEVICE(device), progress, error)) return FALSE; if (!fu_dfu_device_wait_for_replug(self, device, @@ -557,6 +560,7 @@ fu_dfu_tool_read(FuDfuTool *self, gchar **values, GError **error) g_autoptr(FuFirmware) firmware = NULL; g_autoptr(FuDeviceLocker) locker = NULL; g_autoptr(GFile) file = NULL; + g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC); /* check args */ if (g_strv_length(values) != 1) { @@ -579,7 +583,7 @@ fu_dfu_tool_read(FuDfuTool *self, gchar **values, GError **error) /* APP -> DFU */ if (!fu_device_has_flag(FU_DEVICE(device), FWUPD_DEVICE_FLAG_IS_BOOTLOADER)) { - if (!fu_device_detach(FU_DEVICE(device), error)) + if (!fu_device_detach(FU_DEVICE(device), progress, error)) return FALSE; if (!fu_dfu_device_wait_for_replug(self, device, @@ -590,14 +594,14 @@ fu_dfu_tool_read(FuDfuTool *self, gchar **values, GError **error) } /* transfer */ - g_signal_connect(device, "notify::status", G_CALLBACK(fu_tool_action_changed_cb), self); - g_signal_connect(device, "notify::progress", G_CALLBACK(fu_tool_action_changed_cb), self); - firmware = fu_dfu_device_upload(device, flags, error); + g_signal_connect(device, "status-changed", G_CALLBACK(fu_tool_action_changed_cb), self); + g_signal_connect(device, "percentage-changed", G_CALLBACK(fu_tool_action_changed_cb), self); + firmware = fu_dfu_device_upload(device, progress, flags, error); if (firmware == NULL) return FALSE; /* do host reset */ - if (!fu_device_attach(FU_DEVICE(device), error)) + if (!fu_device_attach(FU_DEVICE(device), progress, error)) return FALSE; if (!fu_dfu_device_wait_for_replug(self, device, @@ -630,6 +634,7 @@ fu_dfu_tool_write_alt(FuDfuTool *self, gchar **values, GError **error) g_autoptr(FuDfuTarget) target = NULL; g_autoptr(FuDeviceLocker) locker = NULL; g_autoptr(GFile) file = NULL; + g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC); /* check args */ if (g_strv_length(values) < 2) { @@ -661,13 +666,13 @@ fu_dfu_tool_write_alt(FuDfuTool *self, gchar **values, GError **error) return FALSE; /* set up progress */ - g_signal_connect(device, "notify::status", G_CALLBACK(fu_tool_action_changed_cb), self); - g_signal_connect(device, "notify::progress", G_CALLBACK(fu_tool_action_changed_cb), self); + g_signal_connect(device, "status-changed", G_CALLBACK(fu_tool_action_changed_cb), self); + g_signal_connect(device, "percentage-changed", G_CALLBACK(fu_tool_action_changed_cb), self); /* APP -> DFU */ if (!fu_device_has_flag(FU_DEVICE(device), FWUPD_DEVICE_FLAG_IS_BOOTLOADER)) { g_debug("detaching"); - if (!fu_device_detach(FU_DEVICE(device), error)) + if (!fu_device_detach(FU_DEVICE(device), progress, error)) return FALSE; if (!fu_dfu_device_wait_for_replug(self, device, 5000, error)) return FALSE; @@ -721,11 +726,11 @@ fu_dfu_tool_write_alt(FuDfuTool *self, gchar **values, GError **error) } /* transfer */ - if (!fu_dfu_target_download(target, image, flags, error)) + if (!fu_dfu_target_download(target, image, progress, flags, error)) return FALSE; /* do host reset */ - if (!fu_device_attach(FU_DEVICE(device), error)) + if (!fu_device_attach(FU_DEVICE(device), progress, error)) return FALSE; if (!fu_dfu_device_wait_for_replug(self, device, @@ -745,6 +750,7 @@ fu_dfu_tool_write(FuDfuTool *self, gchar **values, GError **error) g_autoptr(FuDfuDevice) device = NULL; g_autoptr(GBytes) fw = NULL; g_autoptr(FuDeviceLocker) locker = NULL; + g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC); /* check args */ if (g_strv_length(values) < 1) { @@ -772,7 +778,7 @@ fu_dfu_tool_write(FuDfuTool *self, gchar **values, GError **error) /* APP -> DFU */ if (!fu_device_has_flag(FU_DEVICE(device), FWUPD_DEVICE_FLAG_IS_BOOTLOADER)) { - if (!fu_device_detach(FU_DEVICE(device), error)) + if (!fu_device_detach(FU_DEVICE(device), progress, error)) return FALSE; if (!fu_dfu_device_wait_for_replug(self, device, @@ -788,13 +794,13 @@ fu_dfu_tool_write(FuDfuTool *self, gchar **values, GError **error) } /* transfer */ - g_signal_connect(device, "notify::status", G_CALLBACK(fu_tool_action_changed_cb), self); - g_signal_connect(device, "notify::progress", G_CALLBACK(fu_tool_action_changed_cb), self); - if (!fu_device_write_firmware(FU_DEVICE(device), fw, flags, error)) + g_signal_connect(device, "status-changed", G_CALLBACK(fu_tool_action_changed_cb), self); + g_signal_connect(device, "percentage-changed", G_CALLBACK(fu_tool_action_changed_cb), self); + if (!fu_device_write_firmware(FU_DEVICE(device), fw, progress, flags, error)) return FALSE; /* do host reset */ - if (!fu_device_attach(FU_DEVICE(device), error)) + if (!fu_device_attach(FU_DEVICE(device), progress, error)) return FALSE; if (fu_dfu_device_has_attribute(device, FU_DFU_DEVICE_ATTR_MANIFEST_TOL)) { diff --git a/plugins/ebitdo/fu-ebitdo-device.c b/plugins/ebitdo/fu-ebitdo-device.c index a1e0656e3..64a2e14a2 100644 --- a/plugins/ebitdo/fu-ebitdo-device.c +++ b/plugins/ebitdo/fu-ebitdo-device.c @@ -374,7 +374,7 @@ fu_ebitdo_device_setup(FuDevice *device, GError **error) } static gboolean -fu_ebitdo_device_detach(FuDevice *device, GError **error) +fu_ebitdo_device_detach(FuDevice *device, FuProgress *progress, GError **error) { g_autoptr(FwupdRequest) request = fwupd_request_new(); @@ -437,7 +437,6 @@ fu_ebitdo_device_detach(FuDevice *device, GError **error) } /* wait */ - fu_device_set_progress(device, 0); fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG); /* emit request */ @@ -452,6 +451,7 @@ fu_ebitdo_device_detach(FuDevice *device, GError **error) static gboolean fu_ebitdo_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -489,6 +489,12 @@ fu_ebitdo_device_write_firmware(FuDevice *device, return FALSE; } + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 1); /* header */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 97); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_VERIFY, 2); + /* get header and payload */ fw_hdr = fu_firmware_get_image_by_id_bytes(firmware, FU_FIRMWARE_ID_HEADER, error); if (fw_hdr == NULL) @@ -498,7 +504,6 @@ fu_ebitdo_device_write_firmware(FuDevice *device, return FALSE; /* set up the firmware header */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); buf = g_bytes_get_data(fw_hdr, &bufsz); if (!fu_ebitdo_device_send(self, FU_EBITDO_PKT_TYPE_USER_CMD, @@ -514,6 +519,7 @@ fu_ebitdo_device_write_firmware(FuDevice *device, g_prefix_error(error, "failed to get ACK for fw update header: "); return FALSE; } + fu_progress_step_done(progress); /* flash the firmware in 32 byte blocks */ chunks = fu_chunk_array_new_from_bytes(fw_payload, 0x0, 0x0, 32); @@ -543,8 +549,11 @@ fu_ebitdo_device_write_firmware(FuDevice *device, fu_chunk_get_address(chk)); return FALSE; } - fu_device_set_progress_full(device, fu_chunk_get_idx(chk), chunks->len); + fu_progress_set_percentage_full(fu_progress_get_child(progress), + i + 1, + chunks->len); } + fu_progress_step_done(progress); /* set the "encode id" which is likely a checksum, bluetooth pairing * or maybe just security-through-obscurity -- also note: @@ -584,20 +593,20 @@ fu_ebitdo_device_write_firmware(FuDevice *device, g_propagate_error(error, g_steal_pointer(&error_local)); return FALSE; } + fu_progress_step_done(progress); /* success! */ return TRUE; } static gboolean -fu_ebitdo_device_attach(FuDevice *device, GError **error) +fu_ebitdo_device_attach(FuDevice *device, FuProgress *progress, GError **error) { GUsbDevice *usb_device = fu_usb_device_get_dev(FU_USB_DEVICE(device)); g_autoptr(GError) error_local = NULL; /* when doing a soft-reboot the device does not re-enumerate properly * so manually reboot the GUsbDevice */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); if (!g_usb_device_reset(usb_device, &error_local)) { g_prefix_error(&error_local, "failed to force-reset device: "); if (fu_device_has_flag(device, FWUPD_DEVICE_FLAG_WILL_DISAPPEAR)) { @@ -659,6 +668,17 @@ fu_ebitdo_device_prepare_firmware(FuDevice *device, return g_steal_pointer(&firmware); } +static void +fu_ebitdo_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_NO_PROFILE); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 97); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 0); /* reload */ +} + static void fu_ebitdo_device_init(FuEbitdoDevice *self) { @@ -678,4 +698,5 @@ fu_ebitdo_device_class_init(FuEbitdoDeviceClass *klass) klass_device->open = fu_ebitdo_device_open; klass_device->probe = fu_ebitdo_device_probe; klass_device->prepare_firmware = fu_ebitdo_device_prepare_firmware; + klass_device->set_progress = fu_ebitdo_set_progress; } diff --git a/plugins/elantp/fu-elantp-hid-device.c b/plugins/elantp/fu-elantp-hid-device.c index 720d9ba49..894f5f1b8 100644 --- a/plugins/elantp/fu-elantp-hid-device.c +++ b/plugins/elantp/fu-elantp-hid-device.c @@ -29,7 +29,7 @@ struct _FuElantpHidDevice { G_DEFINE_TYPE(FuElantpHidDevice, fu_elantp_hid_device, FU_TYPE_UDEV_DEVICE) static gboolean -fu_elantp_hid_device_detach(FuDevice *device, GError **error); +fu_elantp_hid_device_detach(FuDevice *device, FuProgress *progress, GError **error); static void fu_elantp_hid_device_to_string(FuDevice *device, guint idt, GString *str) @@ -300,6 +300,7 @@ fu_elantp_hid_device_prepare_firmware(FuDevice *device, static gboolean fu_elantp_hid_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -314,17 +315,25 @@ fu_elantp_hid_device_write_firmware(FuDevice *device, g_autoptr(GBytes) fw = NULL; g_autoptr(GPtrArray) chunks = NULL; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 10); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 50); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_VERIFY, 30); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 10); /* reset */ + /* simple image */ fw = fu_firmware_get_bytes(firmware, error); if (fw == NULL) return FALSE; /* detach */ - if (!fu_elantp_hid_device_detach(device, error)) + if (!fu_elantp_hid_device_detach(device, fu_progress_get_child(progress), error)) return FALSE; + fu_progress_step_done(progress); /* write each block */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); buf = g_bytes_get_data(fw, &bufsz); iap_addr = fu_elantp_firmware_get_iap_addr(firmware_elantp); chunks = fu_chunk_array_new(buf + iap_addr, bufsz - iap_addr, 0x0, 0x0, self->fw_page_size); @@ -368,11 +377,13 @@ fu_elantp_hid_device_write_firmware(FuDevice *device, /* update progress */ checksum += csum_tmp; - fu_device_set_progress_full(device, (gsize)i, (gsize)chunks->len); + fu_progress_set_percentage_full(fu_progress_get_child(progress), + (gsize)i + 1, + (gsize)chunks->len); } + fu_progress_step_done(progress); /* verify the written checksum */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_VERIFY); if (!fu_elantp_hid_device_read_cmd(self, ETP_CMD_I2C_IAP_CHECKSUM, csum_buf, @@ -395,16 +406,16 @@ fu_elantp_hid_device_write_firmware(FuDevice *device, checksum_device); return FALSE; } + fu_progress_step_done(progress); /* wait for a reset */ - fu_device_set_progress(device, 0); - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); - g_usleep(ELANTP_DELAY_COMPLETE * 1000); + fu_progress_sleep(fu_progress_get_child(progress), ELANTP_DELAY_COMPLETE); + fu_progress_step_done(progress); return TRUE; } static gboolean -fu_elantp_hid_device_detach(FuDevice *device, GError **error) +fu_elantp_hid_device_detach(FuDevice *device, FuProgress *progress, GError **error) { FuElantpHidDevice *self = FU_ELANTP_HID_DEVICE(device); guint16 iap_ver; @@ -415,7 +426,6 @@ fu_elantp_hid_device_detach(FuDevice *device, GError **error) /* sanity check */ if (fu_device_has_flag(device, FWUPD_DEVICE_FLAG_IS_BOOTLOADER)) { g_debug("in bootloader mode, reset IC"); - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); if (!fu_elantp_hid_device_write_cmd(self, ETP_CMD_I2C_IAP_RESET, ETP_I2C_IAP_RESET, @@ -513,7 +523,7 @@ fu_elantp_hid_device_detach(FuDevice *device, GError **error) } static gboolean -fu_elantp_hid_device_attach(FuDevice *device, GError **error) +fu_elantp_hid_device_attach(FuDevice *device, FuProgress *progress, GError **error) { FuElantpHidDevice *self = FU_ELANTP_HID_DEVICE(device); @@ -524,7 +534,6 @@ fu_elantp_hid_device_attach(FuDevice *device, GError **error) } /* reset back to runtime */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); if (!fu_elantp_hid_device_write_cmd(self, ETP_CMD_I2C_IAP_RESET, ETP_I2C_IAP_RESET, error)) return FALSE; g_usleep(ELANTP_DELAY_RESET * 1000); @@ -583,6 +592,17 @@ fu_elantp_hid_device_set_quirk_kv(FuDevice *device, return FALSE; } +static void +fu_elantp_hid_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 94); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* reload */ +} + static void fu_elantp_hid_device_init(FuElantpHidDevice *self) { @@ -618,4 +638,5 @@ fu_elantp_hid_device_class_init(FuElantpHidDeviceClass *klass) klass_device->write_firmware = fu_elantp_hid_device_write_firmware; klass_device->prepare_firmware = fu_elantp_hid_device_prepare_firmware; klass_device->probe = fu_elantp_hid_device_probe; + klass_device->set_progress = fu_elantp_hid_device_set_progress; } diff --git a/plugins/elantp/fu-elantp-i2c-device.c b/plugins/elantp/fu-elantp-i2c-device.c index fa564997a..2921da22e 100644 --- a/plugins/elantp/fu-elantp-i2c-device.c +++ b/plugins/elantp/fu-elantp-i2c-device.c @@ -29,7 +29,7 @@ struct _FuElantpI2cDevice { G_DEFINE_TYPE(FuElantpI2cDevice, fu_elantp_i2c_device, FU_TYPE_UDEV_DEVICE) static gboolean -fu_elantp_i2c_device_detach(FuDevice *device, GError **error); +fu_elantp_i2c_device_detach(FuDevice *device, FuProgress *progress, GError **error); static void fu_elantp_i2c_device_to_string(FuDevice *device, guint idt, GString *str) @@ -372,6 +372,7 @@ fu_elantp_i2c_device_prepare_firmware(FuDevice *device, static gboolean fu_elantp_i2c_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -386,17 +387,25 @@ fu_elantp_i2c_device_write_firmware(FuDevice *device, g_autoptr(GBytes) fw = NULL; g_autoptr(GPtrArray) chunks = NULL; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 90); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_VERIFY, 10); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 1); + /* simple image */ fw = fu_firmware_get_bytes(firmware, error); if (fw == NULL) return FALSE; /* detach */ - if (!fu_elantp_i2c_device_detach(device, error)) + if (!fu_elantp_i2c_device_detach(device, fu_progress_get_child(progress), error)) return FALSE; + fu_progress_step_done(progress); /* write each block */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); buf = g_bytes_get_data(fw, &bufsz); iap_addr = fu_elantp_firmware_get_iap_addr(firmware_elantp); chunks = fu_chunk_array_new(buf + iap_addr, bufsz - iap_addr, 0x0, 0x0, self->fw_page_size); @@ -442,11 +451,13 @@ fu_elantp_i2c_device_write_firmware(FuDevice *device, /* update progress */ checksum += csum_tmp; - fu_device_set_progress_full(device, (gsize)i, (gsize)chunks->len); + fu_progress_set_percentage_full(fu_progress_get_child(progress), + (gsize)i + 1, + (gsize)chunks->len); } + fu_progress_step_done(progress); /* verify the written checksum */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_VERIFY); if (!fu_elantp_i2c_device_read_cmd(self, ETP_CMD_I2C_IAP_CHECKSUM, csum_buf, @@ -469,16 +480,16 @@ fu_elantp_i2c_device_write_firmware(FuDevice *device, checksum_device); return FALSE; } + fu_progress_step_done(progress); /* wait for a reset */ - fu_device_set_progress(device, 0); - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); - g_usleep(ELANTP_DELAY_COMPLETE * 1000); + fu_progress_sleep(fu_progress_get_child(progress), ELANTP_DELAY_COMPLETE); + fu_progress_step_done(progress); return TRUE; } static gboolean -fu_elantp_i2c_device_detach(FuDevice *device, GError **error) +fu_elantp_i2c_device_detach(FuDevice *device, FuProgress *progress, GError **error) { guint16 iap_ver; guint16 ic_type; @@ -489,7 +500,6 @@ fu_elantp_i2c_device_detach(FuDevice *device, GError **error) /* sanity check */ if (fu_device_has_flag(device, FWUPD_DEVICE_FLAG_IS_BOOTLOADER)) { g_debug("in bootloader mode, reset IC"); - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); if (!fu_elantp_i2c_device_write_cmd(self, ETP_CMD_I2C_IAP_RESET, ETP_I2C_IAP_RESET, @@ -607,7 +617,7 @@ fu_elantp_i2c_device_detach(FuDevice *device, GError **error) } static gboolean -fu_elantp_i2c_device_attach(FuDevice *device, GError **error) +fu_elantp_i2c_device_attach(FuDevice *device, FuProgress *progress, GError **error) { FuElantpI2cDevice *self = FU_ELANTP_I2C_DEVICE(device); @@ -618,7 +628,6 @@ fu_elantp_i2c_device_attach(FuDevice *device, GError **error) } /* reset back to runtime */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); if (!fu_elantp_i2c_device_write_cmd(self, ETP_CMD_I2C_IAP_RESET, ETP_I2C_IAP_RESET, error)) return FALSE; g_usleep(ELANTP_DELAY_RESET * 1000); @@ -690,6 +699,17 @@ fu_elantp_i2c_device_set_quirk_kv(FuDevice *device, return FALSE; } +static void +fu_elantp_i2c_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 94); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* reload */ +} + static void fu_elantp_i2c_device_init(FuElantpI2cDevice *self) { @@ -725,4 +745,5 @@ fu_elantp_i2c_device_class_init(FuElantpI2cDeviceClass *klass) klass_device->prepare_firmware = fu_elantp_i2c_device_prepare_firmware; klass_device->probe = fu_elantp_i2c_device_probe; klass_device->open = fu_elantp_i2c_device_open; + klass_device->set_progress = fu_elantp_i2c_device_set_progress; } diff --git a/plugins/emmc/fu-emmc-device.c b/plugins/emmc/fu-emmc-device.c index 6d92a4dce..df31c9445 100644 --- a/plugins/emmc/fu-emmc-device.c +++ b/plugins/emmc/fu-emmc-device.c @@ -343,6 +343,7 @@ fu_emmc_device_prepare_firmware(FuDevice *device, static gboolean fu_emmc_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -357,6 +358,13 @@ fu_emmc_device_write_firmware(FuDevice *device, g_autoptr(GBytes) fw = NULL; g_autoptr(GPtrArray) chunks = NULL; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 5); /* ffu */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 50); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_VERIFY, 45); + if (!fu_emmc_read_extcsd(FU_EMMC_DEVICE(device), ext_csd, sizeof(ext_csd), error)) return FALSE; @@ -394,6 +402,7 @@ fu_emmc_device_write_firmware(FuDevice *device, (EXT_CSD_NORMAL_MODE << 8) | EXT_CSD_CMD_SET_NORMAL; multi_cmd->cmds[2].flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; multi_cmd->cmds[2].write_flag = 1; + fu_progress_step_done(progress); /* build packets */ chunks = fu_chunk_array_new_from_bytes(fw, @@ -446,9 +455,12 @@ fu_emmc_device_write_firmware(FuDevice *device, } /* update progress */ - fu_device_set_progress_full(device, (gsize)i, (gsize)chunks->len - 1); + fu_progress_set_percentage_full(fu_progress_get_child(progress), + (gsize)i + 1, + (gsize)chunks->len); } } + fu_progress_step_done(progress); /* sanity check */ total_done = (gsize)sect_done * (gsize)self->sect_size; @@ -511,10 +523,22 @@ fu_emmc_device_write_firmware(FuDevice *device, return FALSE; } } + fu_progress_step_done(progress); return TRUE; } +static void +fu_emmc_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 98); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* reload */ +} + static void fu_emmc_device_init(FuEmmcDevice *self) { @@ -539,4 +563,5 @@ fu_emmc_device_class_init(FuEmmcDeviceClass *klass) klass_device->prepare_firmware = fu_emmc_device_prepare_firmware; klass_device->probe = fu_emmc_device_probe; klass_device->write_firmware = fu_emmc_device_write_firmware; + klass_device->set_progress = fu_emmc_device_set_progress; } diff --git a/plugins/ep963x/fu-ep963x-device.c b/plugins/ep963x/fu-ep963x-device.c index 88769f939..b1d2c1a68 100644 --- a/plugins/ep963x/fu-ep963x-device.c +++ b/plugins/ep963x/fu-ep963x-device.c @@ -108,7 +108,7 @@ fu_ep963x_device_write_icp(FuEp963xDevice *self, } static gboolean -fu_ep963x_device_detach(FuDevice *device, GError **error) +fu_ep963x_device_detach(FuDevice *device, FuProgress *progress, GError **error) { FuEp963xDevice *self = FU_EP963X_DEVICE(device); const guint8 buf[] = {'E', 'P', '9', '6', '3'}; @@ -135,13 +135,12 @@ fu_ep963x_device_detach(FuDevice *device, GError **error) return FALSE; } - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG); return TRUE; } static gboolean -fu_ep963x_device_attach(FuDevice *device, GError **error) +fu_ep963x_device_attach(FuDevice *device, FuProgress *progress, GError **error) { FuEp963xDevice *self = FU_EP963X_DEVICE(device); g_autoptr(GError) error_local = NULL; @@ -151,8 +150,6 @@ fu_ep963x_device_attach(FuDevice *device, GError **error) g_debug("already in runtime mode, skipping"); return TRUE; } - - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); if (!fu_ep963x_device_write(self, FU_EP963_USB_CONTROL_ID, FU_EP963_OPCODE_SUBMCU_PROGRAM_FINISHED, @@ -244,6 +241,7 @@ fu_ep963x_device_wait_cb(FuDevice *device, gpointer user_data, GError **error) static gboolean fu_ep963x_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -252,13 +250,18 @@ fu_ep963x_device_write_firmware(FuDevice *device, g_autoptr(GError) error_local = NULL; g_autoptr(GPtrArray) blocks = NULL; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 5); /* ICP */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 95); + /* get default image */ fw = fu_firmware_get_bytes(firmware, error); if (fw == NULL) return FALSE; /* reset the block index */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); if (!fu_ep963x_device_write(self, FU_EP963_USB_CONTROL_ID, FU_EP963_OPCODE_SUBMCU_ENTER_ICP, @@ -272,6 +275,7 @@ fu_ep963x_device_write_firmware(FuDevice *device, error_local->message); return FALSE; } + fu_progress_step_done(progress); /* write each block */ blocks = fu_chunk_array_new_from_bytes(fw, 0x00, 0x00, FU_EP963_TRANSFER_BLOCK_SIZE); @@ -343,13 +347,27 @@ fu_ep963x_device_write_firmware(FuDevice *device, return FALSE; /* update progress */ - fu_device_set_progress_full(device, (gsize)i, (gsize)chunks->len); + fu_progress_set_percentage_full(fu_progress_get_child(progress), + (gsize)i + 1, + (gsize)chunks->len); } + fu_progress_step_done(progress); /* success! */ return TRUE; } +static void +fu_ep963x_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 94); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* reload */ +} + static void fu_ep963x_device_init(FuEp963xDevice *self) { @@ -370,4 +388,5 @@ fu_ep963x_device_class_init(FuEp963xDeviceClass *klass) klass_device->attach = fu_ep963x_device_attach; klass_device->detach = fu_ep963x_device_detach; klass_device->setup = fu_ep963x_device_setup; + klass_device->set_progress = fu_ep963x_device_set_progress; } diff --git a/plugins/fastboot/fu-fastboot-device.c b/plugins/fastboot/fu-fastboot-device.c index f00357517..6a8ccb45d 100644 --- a/plugins/fastboot/fu-fastboot-device.c +++ b/plugins/fastboot/fu-fastboot-device.c @@ -149,6 +149,7 @@ typedef enum { static gboolean fu_fastboot_device_read(FuDevice *device, gchar **str, + FuProgress *progress, FuFastbootDeviceReadFlags flags, GError **error) { @@ -201,9 +202,9 @@ fu_fastboot_device_read(FuDevice *device, tmp = g_strndup((const gchar *)buf + 4, self->blocksz - 4); if (memcmp(buf, "INFO", 4) == 0) { if (g_strcmp0(tmp, "erasing flash") == 0) - fu_device_set_status(device, FWUPD_STATUS_DEVICE_ERASE); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_ERASE); else if (g_strcmp0(tmp, "writing flash") == 0) - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_WRITE); else g_debug("INFO returned unknown: %s", tmp); continue; @@ -245,7 +246,7 @@ fu_fastboot_device_getvar(FuDevice *device, const gchar *key, gchar **str, GErro g_autofree gchar *tmp = g_strdup_printf("getvar:%s", key); if (!fu_fastboot_device_writestr(device, tmp, error)) return FALSE; - if (!fu_fastboot_device_read(device, str, FU_FASTBOOT_DEVICE_READ_FLAG_NONE, error)) { + if (!fu_fastboot_device_read(device, str, NULL, FU_FASTBOOT_DEVICE_READ_FLAG_NONE, error)) { g_prefix_error(error, "failed to getvar %s: ", key); return FALSE; } @@ -255,25 +256,33 @@ fu_fastboot_device_getvar(FuDevice *device, const gchar *key, gchar **str, GErro static gboolean fu_fastboot_device_cmd(FuDevice *device, const gchar *cmd, + FuProgress *progress, FuFastbootDeviceReadFlags flags, GError **error) { if (!fu_fastboot_device_writestr(device, cmd, error)) return FALSE; - if (!fu_fastboot_device_read(device, NULL, flags, error)) + if (!fu_fastboot_device_read(device, NULL, progress, flags, error)) return FALSE; return TRUE; } static gboolean -fu_fastboot_device_flash(FuDevice *device, const gchar *partition, GError **error) +fu_fastboot_device_flash(FuDevice *device, + const gchar *partition, + FuProgress *progress, + GError **error) { g_autofree gchar *tmp = g_strdup_printf("flash:%s", partition); - return fu_fastboot_device_cmd(device, tmp, FU_FASTBOOT_DEVICE_READ_FLAG_STATUS_POLL, error); + return fu_fastboot_device_cmd(device, + tmp, + progress, + FU_FASTBOOT_DEVICE_READ_FLAG_STATUS_POLL, + error); } static gboolean -fu_fastboot_device_download(FuDevice *device, GBytes *fw, GError **error) +fu_fastboot_device_download(FuDevice *device, GBytes *fw, FuProgress *progress, GError **error) { FuFastbootDevice *self = FU_FASTBOOT_DEVICE(device); gsize sz = g_bytes_get_size(fw); @@ -281,11 +290,15 @@ fu_fastboot_device_download(FuDevice *device, GBytes *fw, GError **error) g_autoptr(GPtrArray) chunks = NULL; /* tell the client the size of data to expect */ - if (!fu_fastboot_device_cmd(device, tmp, FU_FASTBOOT_DEVICE_READ_FLAG_STATUS_POLL, error)) + if (!fu_fastboot_device_cmd(device, + tmp, + progress, + FU_FASTBOOT_DEVICE_READ_FLAG_STATUS_POLL, + error)) return FALSE; /* send the data in chunks */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_WRITE); chunks = fu_chunk_array_new_from_bytes(fw, 0x00, /* start addr */ 0x00, /* page_sz */ @@ -297,9 +310,13 @@ fu_fastboot_device_download(FuDevice *device, GBytes *fw, GError **error) fu_chunk_get_data_sz(chk), error)) return FALSE; - fu_device_set_progress_full(device, (gsize)i, (gsize)chunks->len * 2); + fu_progress_set_percentage_full(progress, (gsize)i + 1, (gsize)chunks->len); } - if (!fu_fastboot_device_read(device, NULL, FU_FASTBOOT_DEVICE_READ_FLAG_STATUS_POLL, error)) + if (!fu_fastboot_device_read(device, + NULL, + progress, + FU_FASTBOOT_DEVICE_READ_FLAG_STATUS_POLL, + error)) return FALSE; return TRUE; } @@ -360,6 +377,7 @@ static gboolean fu_fastboot_device_write_qfil_part(FuDevice *device, FuArchive *archive, XbNode *part, + FuProgress *progress, GError **error) { GBytes *data; @@ -384,15 +402,16 @@ fu_fastboot_device_write_qfil_part(FuDevice *device, partition += 2; /* flash the partition */ - if (!fu_fastboot_device_download(device, data, error)) + if (!fu_fastboot_device_download(device, data, progress, error)) return FALSE; - return fu_fastboot_device_flash(device, partition, error); + return fu_fastboot_device_flash(device, partition, progress, error); } static gboolean fu_fastboot_device_write_motorola_part(FuDevice *device, FuArchive *archive, XbNode *part, + FuProgress *progress, GError **error) { const gchar *op = xb_node_get_attr(part, "operation"); @@ -456,6 +475,7 @@ fu_fastboot_device_write_motorola_part(FuDevice *device, /* erase the partition */ return fu_fastboot_device_cmd(device, cmd, + progress, FU_FASTBOOT_DEVICE_READ_FLAG_NONE, error); } @@ -512,16 +532,20 @@ fu_fastboot_device_write_motorola_part(FuDevice *device, } /* flash the partition */ - if (!fu_fastboot_device_download(device, data, error)) + if (!fu_fastboot_device_download(device, data, progress, error)) return FALSE; - return fu_fastboot_device_flash(device, partition, error); + return fu_fastboot_device_flash(device, partition, progress, error); } /* dumb operation that doesn't expect a response */ if (g_strcmp0(op, "boot") == 0 || g_strcmp0(op, "continue") == 0 || g_strcmp0(op, "reboot") == 0 || g_strcmp0(op, "reboot-bootloader") == 0 || g_strcmp0(op, "powerdown") == 0) { - return fu_fastboot_device_cmd(device, op, FU_FASTBOOT_DEVICE_READ_FLAG_NONE, error); + return fu_fastboot_device_cmd(device, + op, + progress, + FU_FASTBOOT_DEVICE_READ_FLAG_NONE, + error); } /* unknown */ @@ -530,7 +554,10 @@ fu_fastboot_device_write_motorola_part(FuDevice *device, } static gboolean -fu_fastboot_device_write_motorola(FuDevice *device, FuArchive *archive, GError **error) +fu_fastboot_device_write_motorola(FuDevice *device, + FuArchive *archive, + FuProgress *progress, + GError **error) { GBytes *data; g_autoptr(GPtrArray) parts = NULL; @@ -553,10 +580,17 @@ fu_fastboot_device_write_motorola(FuDevice *device, FuArchive *archive, GError * parts = xb_silo_query(silo, "parts/part", 0, error); if (parts == NULL) return FALSE; + fu_progress_set_id(progress, G_STRLOC); + fu_progress_set_steps(progress, parts->len); for (guint i = 0; i < parts->len; i++) { XbNode *part = g_ptr_array_index(parts, i); - if (!fu_fastboot_device_write_motorola_part(device, archive, part, error)) + if (!fu_fastboot_device_write_motorola_part(device, + archive, + part, + fu_progress_get_child(progress), + error)) return FALSE; + fu_progress_step_done(progress); } /* success */ @@ -564,7 +598,10 @@ fu_fastboot_device_write_motorola(FuDevice *device, FuArchive *archive, GError * } static gboolean -fu_fastboot_device_write_qfil(FuDevice *device, FuArchive *archive, GError **error) +fu_fastboot_device_write_qfil(FuDevice *device, + FuArchive *archive, + FuProgress *progress, + GError **error) { GBytes *data; g_autoptr(GPtrArray) parts = NULL; @@ -587,10 +624,17 @@ fu_fastboot_device_write_qfil(FuDevice *device, FuArchive *archive, GError **err parts = xb_silo_query(silo, "nandboot/partitions/partition", 0, error); if (parts == NULL) return FALSE; + fu_progress_set_id(progress, G_STRLOC); + fu_progress_set_steps(progress, parts->len); for (guint i = 0; i < parts->len; i++) { XbNode *part = g_ptr_array_index(parts, i); - if (!fu_fastboot_device_write_qfil_part(device, archive, part, error)) + if (!fu_fastboot_device_write_qfil_part(device, + archive, + part, + fu_progress_get_child(progress), + error)) return FALSE; + fu_progress_step_done(progress); } /* success */ @@ -600,6 +644,7 @@ fu_fastboot_device_write_qfil(FuDevice *device, FuArchive *archive, GError **err static gboolean fu_fastboot_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -618,9 +663,9 @@ fu_fastboot_device_write_firmware(FuDevice *device, /* load the manifest of operations */ if (fu_archive_lookup_by_fn(archive, "partition_nand.xml", NULL) != NULL) - return fu_fastboot_device_write_qfil(device, archive, error); + return fu_fastboot_device_write_qfil(device, archive, progress, error); if (fu_archive_lookup_by_fn(archive, "flashfile.xml", NULL) != NULL) { - return fu_fastboot_device_write_motorola(device, archive, error); + return fu_fastboot_device_write_motorola(device, archive, progress, error); } /* not supported */ @@ -675,15 +720,29 @@ fu_fastboot_device_set_quirk_kv(FuDevice *device, } static gboolean -fu_fastboot_device_attach(FuDevice *device, GError **error) +fu_fastboot_device_attach(FuDevice *device, FuProgress *progress, GError **error) { - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); - if (!fu_fastboot_device_cmd(device, "reboot", FU_FASTBOOT_DEVICE_READ_FLAG_NONE, error)) + if (!fu_fastboot_device_cmd(device, + "reboot", + progress, + FU_FASTBOOT_DEVICE_READ_FLAG_NONE, + error)) return FALSE; fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG); return TRUE; } +static void +fu_fastboot_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 94); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* reload */ +} + static void fu_fastboot_device_init(FuFastbootDevice *self) { @@ -709,4 +768,5 @@ fu_fastboot_device_class_init(FuFastbootDeviceClass *klass) klass_device->set_quirk_kv = fu_fastboot_device_set_quirk_kv; klass_device->open = fu_fastboot_device_open; klass_device->close = fu_fastboot_device_close; + klass_device->set_progress = fu_fastboot_device_set_progress; } diff --git a/plugins/flashrom/fu-flashrom-device.c b/plugins/flashrom/fu-flashrom-device.c index 1e2dfd345..cf17a910b 100644 --- a/plugins/flashrom/fu-flashrom-device.c +++ b/plugins/flashrom/fu-flashrom-device.c @@ -193,6 +193,17 @@ fu_flashrom_device_close(FuDevice *device, GError **error) return TRUE; } +static void +fu_flashrom_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 100); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 0); /* reload */ +} + static void fu_flashrom_device_class_init(FuFlashromDeviceClass *klass) { @@ -203,4 +214,5 @@ fu_flashrom_device_class_init(FuFlashromDeviceClass *klass) klass_device->probe = fu_flashrom_device_probe; klass_device->open = fu_flashrom_device_open; klass_device->close = fu_flashrom_device_close; + klass_device->set_progress = fu_flashrom_device_set_progress; } diff --git a/plugins/flashrom/fu-flashrom-internal-device.c b/plugins/flashrom/fu-flashrom-internal-device.c index 41c416e4c..2f9935dbf 100644 --- a/plugins/flashrom/fu-flashrom-internal-device.c +++ b/plugins/flashrom/fu-flashrom-internal-device.c @@ -49,6 +49,7 @@ fu_flashrom_internal_device_prepare(FuDevice *device, FwupdInstallFlags flags, G g_autofree gchar *firmware_orig = NULL; g_autofree gchar *localstatedir = NULL; g_autofree gchar *basename = NULL; + g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC); /* if the original firmware doesn't exist, grab it now */ basename = g_strdup_printf("flashrom-%s.bin", fu_device_get_id(device)); @@ -63,7 +64,6 @@ fu_flashrom_internal_device_prepare(FuDevice *device, FwupdInstallFlags flags, G struct flashrom_layout *layout; g_autofree guint8 *newcontents = g_malloc0(flash_size); g_autoptr(GBytes) buf = NULL; - fu_device_set_status(device, FWUPD_STATUS_DEVICE_READ); if (flashrom_layout_read_from_ifd(&layout, flashctx, NULL, 0)) { g_set_error_literal(error, @@ -85,6 +85,7 @@ fu_flashrom_internal_device_prepare(FuDevice *device, FwupdInstallFlags flags, G /* read region */ flashrom_layout_set(flashctx, layout); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_READ); if (flashrom_image_read(flashctx, newcontents, flash_size)) { g_set_error_literal(error, FWUPD_ERROR, @@ -103,6 +104,7 @@ fu_flashrom_internal_device_prepare(FuDevice *device, FwupdInstallFlags flags, G static gboolean fu_flashrom_internal_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -117,6 +119,12 @@ fu_flashrom_internal_device_write_firmware(FuDevice *device, if (blob_fw == NULL) return FALSE; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 90); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_VERIFY, 10); + /* Check if CMOS needs a reset */ if (fu_device_has_private_flag(device, FU_FLASHROM_DEVICE_FLAG_RESET_CMOS)) { g_debug("Attempting CMOS Reset"); @@ -156,9 +164,6 @@ fu_flashrom_internal_device_write_firmware(FuDevice *device, (guint)flash_size); return FALSE; } - - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); - fu_device_set_progress(device, 0); /* urgh */ rc = flashrom_image_write(flashctx, (void *)buf, sz, NULL /* refbuffer */); if (rc != 0) { g_set_error(error, @@ -168,12 +173,13 @@ fu_flashrom_internal_device_write_firmware(FuDevice *device, rc); return FALSE; } + fu_progress_step_done(progress); - fu_device_set_status(device, FWUPD_STATUS_DEVICE_VERIFY); if (flashrom_image_verify(flashctx, (void *)buf, sz)) { g_set_error(error, FWUPD_ERROR, FWUPD_ERROR_WRITE, "image verify failed"); return FALSE; } + fu_progress_step_done(progress); flashrom_layout_release(layout); /* success */ diff --git a/plugins/fresco-pd/fu-fresco-pd-device.c b/plugins/fresco-pd/fu-fresco-pd-device.c index c6b6e542b..5cd61dd9c 100644 --- a/plugins/fresco-pd/fu-fresco-pd-device.c +++ b/plugins/fresco-pd/fu-fresco-pd-device.c @@ -226,7 +226,6 @@ fu_fresco_pd_device_panther_reset_device(FuFrescoPdDevice *self, GError **error) g_autoptr(GError) error_local = NULL; g_debug("resetting target device"); - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_DEVICE_RESTART); fu_device_add_flag(FU_DEVICE(self), FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG); /* ignore when the device reset before completing the transaction */ @@ -246,6 +245,7 @@ fu_fresco_pd_device_panther_reset_device(FuFrescoPdDevice *self, GError **error) static gboolean fu_fresco_pd_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -257,6 +257,15 @@ fu_fresco_pd_device_write_firmware(FuDevice *device, guint8 start_symbols[2] = {0x0}; g_autoptr(GBytes) fw = NULL; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* enable mtp write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 50); /* copy-mmio */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_VERIFY, 46); /* customize */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* boot */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); + /* get default blob, which we know is already bigger than FirmwareMin */ fw = fu_firmware_get_bytes(firmware, error); if (fw == NULL) @@ -277,7 +286,6 @@ fu_fresco_pd_device_write_firmware(FuDevice *device, /* 0xA001 = b'0 * 0x6C00 = b'0 * 0x6C04 = 0x08 */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_BUSY); g_debug("disable MCU, and enable mtp write"); if (!fu_fresco_pd_device_and_byte(self, 0xa001, ~(1 << 2), error)) { g_prefix_error(error, "failed to disable MCU bit 2: "); @@ -293,7 +301,6 @@ fu_fresco_pd_device_write_firmware(FuDevice *device, } /* fill safe code in the boot code */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); for (guint16 i = 0; i < 0x400; i += 3) { for (guint j = 0; j < 3; j++) { if (!fu_fresco_pd_device_read_byte(self, @@ -328,6 +335,7 @@ fu_fresco_pd_device_write_firmware(FuDevice *device, } else if (config[0] == 0x00 && config[1] == 0x00 && config[2] != 0x00) break; } + fu_progress_step_done(progress); /* copy buf offset [0 - 0x3FFFF] to mmio address [0x2000 - 0x5FFF] */ g_debug("fill firmware body"); @@ -337,8 +345,11 @@ fu_fresco_pd_device_write_firmware(FuDevice *device, buf[byte_index], error)) return FALSE; - fu_device_set_progress_full(device, (gsize)byte_index, 0x4000); + fu_progress_set_percentage_full(fu_progress_get_child(progress), + (gsize)byte_index + 1, + 0x4000); } + fu_progress_step_done(progress); /* write file buf 0x4200 ~ 0x4205, 6 bytes to internal address 0x6600 ~ 0x6605 * write file buf 0x4210 ~ 0x4215, 6 bytes to internal address 0x6610 ~ 0x6615 @@ -364,6 +375,7 @@ fu_fresco_pd_device_write_firmware(FuDevice *device, } if (!fu_fresco_pd_device_set_byte(self, 0x6630, buf[0x4230], error)) return FALSE; + fu_progress_step_done(progress); /* overwrite firmware file's boot code area (0x4020 ~ 0x41ff) to the area on the device * marked by begin_addr example: if the begin_addr = 0x6420, then copy file buf [0x4020 ~ @@ -386,9 +398,26 @@ fu_fresco_pd_device_write_firmware(FuDevice *device, error)) return FALSE; } + fu_progress_step_done(progress); /* reset the device */ - return fu_fresco_pd_device_panther_reset_device(self, error); + if (!fu_fresco_pd_device_panther_reset_device(self, error)) + return FALSE; + fu_progress_step_done(progress); + + /* success */ + return TRUE; +} + +static void +fu_fresco_pd_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 100); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 0); /* reload */ } static void @@ -412,4 +441,5 @@ fu_fresco_pd_device_class_init(FuFrescoPdDeviceClass *klass) klass_device->setup = fu_fresco_pd_device_setup; klass_device->write_firmware = fu_fresco_pd_device_write_firmware; klass_device->prepare_firmware = fu_fresco_pd_device_prepare_firmware; + klass_device->set_progress = fu_fresco_pd_device_set_progress; } diff --git a/plugins/goodix-moc/fu-goodixmoc-device.c b/plugins/goodix-moc/fu-goodixmoc-device.c index 44f5f7d46..9c60e38a0 100644 --- a/plugins/goodix-moc/fu-goodixmoc-device.c +++ b/plugins/goodix-moc/fu-goodixmoc-device.c @@ -286,14 +286,13 @@ fu_goodixmoc_device_update_init(FuGoodixMocDevice *self, GError **error) } static gboolean -fu_goodixmoc_device_attach(FuDevice *device, GError **error) +fu_goodixmoc_device_attach(FuDevice *device, FuProgress *progress, GError **error) { FuGoodixMocDevice *self = FU_GOODIXMOC_DEVICE(device); GxfpCmdResp rsp = {0}; g_autoptr(GByteArray) req = g_byte_array_new(); /* reset device */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); if (!fu_goodixmoc_device_cmd_xfer(self, GX_CMD_RESET, 0x03, @@ -356,6 +355,7 @@ fu_goodixmoc_device_setup(FuDevice *device, GError **error) static gboolean fu_goodixmoc_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -367,6 +367,12 @@ fu_goodixmoc_device_write_firmware(FuDevice *device, g_autoptr(GError) error_local = NULL; g_autoptr(GPtrArray) chunks = NULL; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 1); /* init */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 99); + /* get default image */ fw = fu_firmware_get_bytes(firmware, error); if (fw == NULL) @@ -379,7 +385,6 @@ fu_goodixmoc_device_write_firmware(FuDevice *device, GX_FLASH_TRANSFER_BLOCK_SIZE); /* don't auto-boot firmware */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); if (!fu_goodixmoc_device_update_init(self, &error_local)) { g_set_error(error, FWUPD_ERROR, @@ -388,6 +393,7 @@ fu_goodixmoc_device_write_firmware(FuDevice *device, error_local->message); return FALSE; } + fu_progress_step_done(progress); /* write each block */ for (guint i = 0; i < chunks->len; i++) { @@ -429,13 +435,27 @@ fu_goodixmoc_device_write_firmware(FuDevice *device, } /* update progress */ - fu_device_set_progress_full(device, (gsize)i, (gsize)chunks->len); + fu_progress_set_percentage_full(fu_progress_get_child(progress), + (gsize)i + 1, + (gsize)chunks->len); } + fu_progress_step_done(progress); /* success! */ return TRUE; } +static void +fu_goodixmoc_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 94); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* reload */ +} + static void fu_goodixmoc_device_init(FuGoodixMocDevice *self) { @@ -461,4 +481,5 @@ fu_goodixmoc_device_class_init(FuGoodixMocDeviceClass *klass) klass_device->setup = fu_goodixmoc_device_setup; klass_device->attach = fu_goodixmoc_device_attach; klass_device->open = fu_goodixmoc_device_open; + klass_device->set_progress = fu_goodixmoc_device_set_progress; } diff --git a/plugins/hailuck/fu-hailuck-bl-device.c b/plugins/hailuck/fu-hailuck-bl-device.c index edd3f9d39..9effdf7c5 100644 --- a/plugins/hailuck/fu-hailuck-bl-device.c +++ b/plugins/hailuck/fu-hailuck-bl-device.c @@ -19,13 +19,12 @@ struct _FuHailuckBlDevice { G_DEFINE_TYPE(FuHailuckBlDevice, fu_hailuck_bl_device, FU_TYPE_HID_DEVICE) static gboolean -fu_hailuck_bl_device_attach(FuDevice *device, GError **error) +fu_hailuck_bl_device_attach(FuDevice *device, FuProgress *progress, GError **error) { guint8 buf[6] = { FU_HAILUCK_REPORT_ID_SHORT, FU_HAILUCK_CMD_ATTACH, }; - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); if (!fu_hid_device_set_report(FU_HID_DEVICE(device), buf[0], buf, @@ -111,7 +110,7 @@ fu_hailuck_bl_device_read_block(FuHailuckBlDevice *self, } static GBytes * -fu_hailuck_bl_device_dump_firmware(FuDevice *device, GError **error) +fu_hailuck_bl_device_dump_firmware(FuDevice *device, FuProgress *progress, GError **error) { FuHailuckBlDevice *self = FU_HAILUCK_BL_DEVICE(device); gsize fwsz = fu_device_get_firmware_size_max(device); @@ -119,7 +118,7 @@ fu_hailuck_bl_device_dump_firmware(FuDevice *device, GError **error) g_autoptr(GPtrArray) chunks = NULL; /* tell device amount of data to send */ - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_DEVICE_READ); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_READ); if (!fu_hailuck_bl_device_read_block_start(self, fwsz, error)) return NULL; @@ -133,7 +132,7 @@ fu_hailuck_bl_device_dump_firmware(FuDevice *device, GError **error) fu_chunk_get_data_sz(chk), error)) return NULL; - fu_device_set_progress_full(device, i, chunks->len - 1); + fu_progress_set_percentage_full(progress, i + 1, chunks->len); } /* success */ @@ -141,7 +140,7 @@ fu_hailuck_bl_device_dump_firmware(FuDevice *device, GError **error) } static gboolean -fu_hailuck_bl_device_erase(FuHailuckBlDevice *self, GError **error) +fu_hailuck_bl_device_erase(FuHailuckBlDevice *self, FuProgress *progress, GError **error) { guint8 buf[6] = { FU_HAILUCK_REPORT_ID_SHORT, @@ -155,7 +154,7 @@ fu_hailuck_bl_device_erase(FuHailuckBlDevice *self, GError **error) FU_HID_DEVICE_FLAG_IS_FEATURE, error)) return FALSE; - fu_device_sleep_with_progress(FU_DEVICE(self), 2); + fu_progress_sleep(progress, 2000); return TRUE; } @@ -225,6 +224,7 @@ fu_hailuck_bl_device_prepare_firmware(FuDevice *device, static gboolean fu_hailuck_bl_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -235,18 +235,25 @@ fu_hailuck_bl_device_write_firmware(FuDevice *device, g_autoptr(GPtrArray) chunks = NULL; g_autofree guint8 *chk0_data = NULL; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_ERASE, 10); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 80); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 1); /* block 0 */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_VERIFY, 9); + /* get default image */ fw = fu_firmware_get_bytes(firmware, error); if (fw == NULL) return FALSE; /* erase all contents */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_ERASE); - if (!fu_hailuck_bl_device_erase(self, error)) + if (!fu_hailuck_bl_device_erase(self, fu_progress_get_child(progress), error)) return FALSE; + fu_progress_step_done(progress); /* tell device amount of data to expect */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); if (!fu_hailuck_bl_device_write_block_start(self, g_bytes_get_size(fw), error)) return FALSE; @@ -270,8 +277,11 @@ fu_hailuck_bl_device_write_firmware(FuDevice *device, fu_chunk_get_data_sz(chk), error)) return FALSE; - fu_device_set_progress_full(device, i, chunks->len); + fu_progress_set_percentage_full(fu_progress_get_child(progress), + i + 1, + chunks->len); } + fu_progress_step_done(progress); /* retry write of first block */ if (!fu_hailuck_bl_device_write_block_start(self, g_bytes_get_size(fw), error)) @@ -281,10 +291,11 @@ fu_hailuck_bl_device_write_firmware(FuDevice *device, fu_chunk_get_data_sz(chk0), error)) return FALSE; - fu_device_set_progress_full(device, chunks->len, chunks->len); + fu_progress_step_done(progress); /* verify */ - fw_new = fu_hailuck_bl_device_dump_firmware(device, error); + fw_new = fu_hailuck_bl_device_dump_firmware(device, fu_progress_get_child(progress), error); + fu_progress_step_done(progress); return fu_common_bytes_compare(fw, fw_new, error); } diff --git a/plugins/hailuck/fu-hailuck-kbd-device.c b/plugins/hailuck/fu-hailuck-kbd-device.c index 7d4b4c284..66fb3bd15 100644 --- a/plugins/hailuck/fu-hailuck-kbd-device.c +++ b/plugins/hailuck/fu-hailuck-kbd-device.c @@ -17,10 +17,9 @@ struct _FuHailuckKbdDevice { G_DEFINE_TYPE(FuHailuckKbdDevice, fu_hailuck_kbd_device, FU_TYPE_HID_DEVICE) static gboolean -fu_hailuck_kbd_device_detach(FuDevice *device, GError **error) +fu_hailuck_kbd_device_detach(FuDevice *device, FuProgress *progress, GError **error) { guint8 buf[6] = {FU_HAILUCK_REPORT_ID_SHORT, FU_HAILUCK_CMD_DETACH}; - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); if (!fu_hid_device_set_report(FU_HID_DEVICE(device), buf[0], buf, @@ -62,6 +61,17 @@ fu_hailuck_kbd_device_probe(FuDevice *device, GError **error) return TRUE; } +static void +fu_hailuck_kbd_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 94); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* reload */ +} + static void fu_hailuck_kbd_device_init(FuHailuckKbdDevice *self) { @@ -81,4 +91,5 @@ fu_hailuck_kbd_device_class_init(FuHailuckKbdDeviceClass *klass) FuDeviceClass *klass_device = FU_DEVICE_CLASS(klass); klass_device->detach = fu_hailuck_kbd_device_detach; klass_device->probe = fu_hailuck_kbd_device_probe; + klass_device->set_progress = fu_hailuck_kbd_device_set_progress; } diff --git a/plugins/hailuck/fu-hailuck-tp-device.c b/plugins/hailuck/fu-hailuck-tp-device.c index 4a53611f3..f188161cb 100644 --- a/plugins/hailuck/fu-hailuck-tp-device.c +++ b/plugins/hailuck/fu-hailuck-tp-device.c @@ -89,6 +89,7 @@ fu_hailuck_tp_device_cmd_cb(FuDevice *device, gpointer user_data, GError **error static gboolean fu_hailuck_tp_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -101,22 +102,30 @@ fu_hailuck_tp_device_write_firmware(FuDevice *device, .success = 0xff, }; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_ERASE, 10); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 85); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 1); /* end-program */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_VERIFY, 3); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 1); /* pass */ + /* get default image */ fw = fu_firmware_get_bytes(firmware, error); if (fw == NULL) return FALSE; /* erase */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_ERASE); req.type = FU_HAILUCK_CMD_I2C_ERASE; if (!fu_device_retry(device, fu_hailuck_tp_device_cmd_cb, 100, &req, error)) { g_prefix_error(error, "failed to erase: "); return FALSE; } g_usleep(10000); + fu_progress_step_done(progress); /* write */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); chunks = fu_chunk_array_new_from_bytes(fw, 0x0, 0x0, block_size); for (guint i = 0; i < chunks->len; i++) { FuChunk *chk = g_ptr_array_index(chunks, i); @@ -163,9 +172,12 @@ fu_hailuck_tp_device_write_firmware(FuDevice *device, } /* update progress */ - fu_device_set_progress_full(device, i, chunks->len - 1); + fu_progress_set_percentage_full(fu_progress_get_child(progress), + i + 1, + chunks->len); } g_usleep(50 * 1000); + fu_progress_step_done(progress); /* end-program */ req.type = FU_HAILUCK_CMD_I2C_END_PROGRAM; @@ -174,6 +186,7 @@ fu_hailuck_tp_device_write_firmware(FuDevice *device, return FALSE; } g_usleep(50 * 1000); + fu_progress_step_done(progress); /* verify checksum */ req.type = FU_HAILUCK_CMD_I2C_VERIFY_CHECKSUM; @@ -182,6 +195,7 @@ fu_hailuck_tp_device_write_firmware(FuDevice *device, return FALSE; } g_usleep(50 * 1000); + fu_progress_step_done(progress); /* signal that programming has completed */ req.type = FU_HAILUCK_CMD_I2C_PROGRAMPASS; @@ -190,11 +204,23 @@ fu_hailuck_tp_device_write_firmware(FuDevice *device, g_prefix_error(error, "failed to program: "); return FALSE; } + fu_progress_step_done(progress); /* success! */ return TRUE; } +static void +fu_hailuck_tp_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 94); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* reload */ +} + static void fu_hailuck_tp_device_init(FuHailuckTpDevice *self) { @@ -216,6 +242,7 @@ fu_hailuck_tp_device_class_init(FuHailuckTpDeviceClass *klass) FuDeviceClass *klass_device = FU_DEVICE_CLASS(klass); klass_device->write_firmware = fu_hailuck_tp_device_write_firmware; klass_device->probe = fu_hailuck_tp_device_probe; + klass_device->set_progress = fu_hailuck_tp_device_set_progress; } FuHailuckTpDevice * diff --git a/plugins/intel-spi/fu-ifd-device.c b/plugins/intel-spi/fu-ifd-device.c index 2ff9f62e1..b1e5d7f0d 100644 --- a/plugins/intel-spi/fu-ifd-device.c +++ b/plugins/intel-spi/fu-ifd-device.c @@ -78,7 +78,7 @@ fu_ifd_device_to_string(FuDevice *device, guint idt, GString *str) } static GBytes * -fu_ifd_device_dump_firmware(FuDevice *device, GError **error) +fu_ifd_device_dump_firmware(FuDevice *device, FuProgress *progress, GError **error) { FuIfdDevice *self = FU_IFD_DEVICE(device); FuIfdDevicePrivate *priv = GET_PRIVATE(self); @@ -88,18 +88,19 @@ fu_ifd_device_dump_firmware(FuDevice *device, GError **error) device, priv->offset, total_size, + progress, error); } static FuFirmware * -fu_ifd_device_read_firmware(FuDevice *device, GError **error) +fu_ifd_device_read_firmware(FuDevice *device, FuProgress *progress, GError **error) { FuIfdDevice *self = FU_IFD_DEVICE(device); FuIfdDevicePrivate *priv = GET_PRIVATE(self); g_autoptr(FuFirmware) firmware = fu_ifd_image_new(); g_autoptr(GBytes) blob = NULL; - blob = fu_ifd_device_dump_firmware(device, error); + blob = fu_ifd_device_dump_firmware(device, progress, error); if (blob == NULL) return NULL; if (priv->region == FU_IFD_REGION_BIOS) diff --git a/plugins/intel-spi/fu-intel-spi-device.c b/plugins/intel-spi/fu-intel-spi-device.c index 9b3900752..b01173f86 100644 --- a/plugins/intel-spi/fu-intel-spi-device.c +++ b/plugins/intel-spi/fu-intel-spi-device.c @@ -391,13 +391,14 @@ fu_intel_spi_device_dump(FuIntelSpiDevice *self, FuDevice *device, guint32 offset, guint32 length, + FuProgress *progress, GError **error) { guint8 block_len = 0x40; g_autoptr(GByteArray) buf = g_byte_array_sized_new(length); /* set FDONE, FCERR, AEL */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_READ); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_READ); fu_mmio_write16(self->spibar, ICH9_REG_HSFS, fu_mmio_read16(self->spibar, ICH9_REG_HSFS)); for (guint32 addr = offset; addr < offset + length; addr += block_len) { guint16 hsfc; @@ -426,7 +427,7 @@ fu_intel_spi_device_dump(FuIntelSpiDevice *self, } /* progress */ - fu_device_set_progress_full(device, addr - offset + block_len, length); + fu_progress_set_percentage_full(progress, addr - offset + block_len, length); } /* success */ @@ -434,20 +435,26 @@ fu_intel_spi_device_dump(FuIntelSpiDevice *self, } static GBytes * -fu_intel_spi_device_dump_firmware(FuDevice *device, GError **error) +fu_intel_spi_device_dump_firmware2(FuDevice *device, FuProgress *progress, GError **error) { FuIntelSpiDevice *self = FU_INTEL_SPI_DEVICE(device); guint64 total_size = fu_device_get_firmware_size_max(device); - return fu_intel_spi_device_dump(self, device, 0x0, total_size, error); + return fu_intel_spi_device_dump(self, device, 0x0, total_size, progress, error); +} + +static GBytes * +fu_intel_spi_device_dump_firmware(FuDevice *device, FuProgress *progress, GError **error) +{ + return fu_intel_spi_device_dump_firmware2(device, progress, error); } static FuFirmware * -fu_intel_spi_device_read_firmware(FuDevice *device, GError **error) +fu_intel_spi_device_read_firmware(FuDevice *device, FuProgress *progress, GError **error) { g_autoptr(FuFirmware) firmware = fu_ifd_firmware_new(); g_autoptr(GBytes) blob = NULL; - blob = fu_intel_spi_device_dump_firmware(device, error); + blob = fu_intel_spi_device_dump_firmware2(device, progress, error); if (blob == NULL) return NULL; if (!fu_firmware_parse(firmware, blob, FWUPD_INSTALL_FLAG_NONE, error)) diff --git a/plugins/intel-spi/fu-intel-spi-device.h b/plugins/intel-spi/fu-intel-spi-device.h index 5e97da490..d7fb7f845 100644 --- a/plugins/intel-spi/fu-intel-spi-device.h +++ b/plugins/intel-spi/fu-intel-spi-device.h @@ -16,4 +16,5 @@ fu_intel_spi_device_dump(FuIntelSpiDevice *self, FuDevice *device, guint32 offset, guint32 length, + FuProgress *progress, GError **error); diff --git a/plugins/jabra/fu-jabra-device.c b/plugins/jabra/fu-jabra-device.c index 9fc2cebed..e6412054c 100644 --- a/plugins/jabra/fu-jabra-device.c +++ b/plugins/jabra/fu-jabra-device.c @@ -53,6 +53,7 @@ fu_jabra_device_prepare(FuDevice *device, FwupdInstallFlags flags, GError **erro guint8 rep = 0x00; guint8 iface_hid; guint8 buf[33] = {0x00}; + g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC); g_autoptr(GError) error_local = NULL; /* parse string and create magic packet */ @@ -110,7 +111,7 @@ fu_jabra_device_prepare(FuDevice *device, FwupdInstallFlags flags, GError **erro } /* wait for device to re-appear and be added to the dfu plugin */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_RESTART); fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG); return TRUE; } diff --git a/plugins/jabra/fu-plugin-jabra.c b/plugins/jabra/fu-plugin-jabra.c index a31504858..d4ed1ee1f 100644 --- a/plugins/jabra/fu-plugin-jabra.c +++ b/plugins/jabra/fu-plugin-jabra.c @@ -26,6 +26,7 @@ fu_plugin_cleanup(FuPlugin *plugin, FuDevice *device, FwupdInstallFlags flags, G { GUsbDevice *usb_device; g_autoptr(FuDeviceLocker) locker = NULL; + g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC); g_autoptr(GError) error_local = NULL; /* check for a property on the *dfu* FuDevice, which is also why we @@ -35,7 +36,7 @@ fu_plugin_cleanup(FuPlugin *plugin, FuDevice *device, FwupdInstallFlags flags, G locker = fu_device_locker_new(device, error); if (locker == NULL) return FALSE; - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_RESTART); usb_device = fu_usb_device_get_dev(FU_USB_DEVICE(device)); if (!g_usb_device_reset(usb_device, &error_local)) { g_set_error(error, diff --git a/plugins/logitech-bulkcontroller/fu-logitech-bulkcontroller-device.c b/plugins/logitech-bulkcontroller/fu-logitech-bulkcontroller-device.c index b4fc61c1a..82b38b092 100644 --- a/plugins/logitech-bulkcontroller/fu-logitech-bulkcontroller-device.c +++ b/plugins/logitech-bulkcontroller/fu-logitech-bulkcontroller-device.c @@ -418,6 +418,7 @@ fu_logitech_bulkcontroller_device_compute_hash(GBytes *data) static gboolean fu_logitech_bulkcontroller_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -428,6 +429,13 @@ fu_logitech_bulkcontroller_device_write_firmware(FuDevice *device, g_autoptr(GBytes) fw = NULL; g_autoptr(GPtrArray) chunks = NULL; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 5); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 90); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 5); + /* get default image */ fw = fu_firmware_get_bytes(firmware, error); if (fw == NULL) @@ -440,7 +448,6 @@ fu_logitech_bulkcontroller_device_write_firmware(FuDevice *device, } /* transfer sent */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); fu_byte_array_append_uint64(start_pkt, g_bytes_get_size(fw), G_LITTLE_ENDIAN); if (!fu_logitech_bulkcontroller_device_send_upd_cmd(self, CMD_START_TRANSFER, @@ -449,6 +456,7 @@ fu_logitech_bulkcontroller_device_write_firmware(FuDevice *device, g_prefix_error(error, "error in writing start transfer packet: "); return FALSE; } + fu_progress_step_done(progress); /* each block */ chunks = fu_chunk_array_new_from_bytes(fw, 0x0, 0x0, PAYLOAD_SIZE); @@ -463,8 +471,11 @@ fu_logitech_bulkcontroller_device_write_firmware(FuDevice *device, g_prefix_error(error, "failed to send data packet 0x%x: ", i); return FALSE; } - fu_device_set_progress_full(FU_DEVICE(self), i + 1, chunks->len); + fu_progress_set_percentage_full(fu_progress_get_child(progress), + i + 1, + chunks->len); } + fu_progress_step_done(progress); /* sending end transfer */ base64hash = fu_logitech_bulkcontroller_device_compute_hash(fw); @@ -485,6 +496,7 @@ fu_logitech_bulkcontroller_device_write_firmware(FuDevice *device, g_prefix_error(error, "error in writing finish transfer packet: "); return FALSE; } + fu_progress_step_done(progress); /* success! */ return TRUE; @@ -683,6 +695,17 @@ fu_logitech_bulkcontroller_device_setup(FuDevice *device, GError **error) return TRUE; } +static void +fu_logitech_bulkcontroller_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 98); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* reload */ +} + static void fu_logitech_bulkcontroller_device_init(FuLogitechBulkcontrollerDevice *self) { @@ -701,4 +724,5 @@ fu_logitech_bulkcontroller_device_class_init(FuLogitechBulkcontrollerDeviceClass klass_device->setup = fu_logitech_bulkcontroller_device_setup; klass_device->open = fu_logitech_bulkcontroller_device_open; klass_device->close = fu_logitech_bulkcontroller_device_close; + klass_device->set_progress = fu_logitech_bulkcontroller_device_set_progress; } diff --git a/plugins/logitech-hidpp/fu-logitech-hidpp-bootloader-nordic.c b/plugins/logitech-hidpp/fu-logitech-hidpp-bootloader-nordic.c index ef825c1ae..1271b78d0 100644 --- a/plugins/logitech-hidpp/fu-logitech-hidpp-bootloader-nordic.c +++ b/plugins/logitech-hidpp/fu-logitech-hidpp-bootloader-nordic.c @@ -217,6 +217,7 @@ fu_logitech_hidpp_bootloader_nordic_erase(FuLogitechHidPpBootloader *self, static gboolean fu_logitech_hidpp_bootloader_nordic_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -226,25 +227,40 @@ fu_logitech_hidpp_bootloader_nordic_write_firmware(FuDevice *device, g_autoptr(GBytes) fw = NULL; g_autoptr(GPtrArray) reqs = NULL; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + if (fu_device_has_private_flag(device, FU_LOGITECH_HIDPP_BOOTLOADER_FLAG_IS_SIGNED)) { + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_ERASE, 4); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 13); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 1); /* block 0 */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 82); /* reset vector */ + } else { + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_ERASE, 22); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 72); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 1); /* block 0 */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 6); /* reset vector */ + } + /* get default image */ fw = fu_firmware_get_bytes(firmware, error); if (fw == NULL) return FALSE; /* erase firmware pages up to the bootloader */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_ERASE); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_ERASE); for (addr = fu_logitech_hidpp_bootloader_get_addr_lo(self); addr < fu_logitech_hidpp_bootloader_get_addr_hi(self); addr += fu_logitech_hidpp_bootloader_get_blocksize(self)) { if (!fu_logitech_hidpp_bootloader_nordic_erase(self, addr, error)) return FALSE; } + fu_progress_step_done(progress); /* transfer payload */ reqs = fu_logitech_hidpp_bootloader_parse_requests(self, fw, error); if (reqs == NULL) return FALSE; - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_WRITE); for (guint i = 1; i < reqs->len; i++) { gboolean res; payload = g_ptr_array_index(reqs, i); @@ -265,8 +281,9 @@ fu_logitech_hidpp_bootloader_nordic_write_firmware(FuDevice *device, if (!res) return FALSE; - fu_device_set_progress_full(device, i * 32, reqs->len * 32); + fu_progress_set_percentage_full(fu_progress_get_child(progress), i + 1, reqs->len); } + fu_progress_step_done(progress); /* send the first managed packet last, excluding the reset vector */ payload = g_ptr_array_index(reqs, 0); @@ -276,12 +293,12 @@ fu_logitech_hidpp_bootloader_nordic_write_firmware(FuDevice *device, payload->data + 1, error)) return FALSE; + fu_progress_step_done(progress); + /* reset vector */ if (!fu_logitech_hidpp_bootloader_nordic_write(self, 0x0000, 0x01, payload->data, error)) return FALSE; - - /* mark as complete */ - fu_device_set_progress_full(device, reqs->len * 32, reqs->len * 32); + fu_progress_step_done(progress); /* success! */ return TRUE; diff --git a/plugins/logitech-hidpp/fu-logitech-hidpp-bootloader-texas.c b/plugins/logitech-hidpp/fu-logitech-hidpp-bootloader-texas.c index cc201d1e7..7affc3976 100644 --- a/plugins/logitech-hidpp/fu-logitech-hidpp-bootloader-texas.c +++ b/plugins/logitech-hidpp/fu-logitech-hidpp-bootloader-texas.c @@ -115,6 +115,7 @@ fu_logitech_hidpp_bootloader_texas_clear_ram_buffer(FuLogitechHidPpBootloader *s static gboolean fu_logitech_hidpp_bootloader_texas_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -125,6 +126,20 @@ fu_logitech_hidpp_bootloader_texas_write_firmware(FuDevice *device, g_autoptr(FuLogitechHidPpBootloaderRequest) req = fu_logitech_hidpp_bootloader_request_new(); + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + if (fu_device_has_private_flag(device, FU_LOGITECH_HIDPP_BOOTLOADER_FLAG_IS_SIGNED)) { + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_ERASE, 3); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_ERASE, 1); /* clear */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 18); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_VERIFY, 79); + } else { + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_ERASE, 11); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_ERASE, 1); /* clear */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 75); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_VERIFY, 12); + } + /* get default image */ fw = fu_firmware_get_bytes(firmware, error); if (fw == NULL) @@ -136,16 +151,16 @@ fu_logitech_hidpp_bootloader_texas_write_firmware(FuDevice *device, return FALSE; /* erase all flash pages */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_ERASE); if (!fu_logitech_hidpp_bootloader_texas_erase_all(self, error)) return FALSE; + fu_progress_step_done(progress); /* set existing RAM buffer to 0xff's */ if (!fu_logitech_hidpp_bootloader_texas_clear_ram_buffer(self, error)) return FALSE; + fu_progress_step_done(progress); /* write to RAM buffer */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); for (guint i = 0; i < reqs->len; i++) { payload = g_ptr_array_index(reqs, i); @@ -213,15 +228,14 @@ fu_logitech_hidpp_bootloader_texas_write_firmware(FuDevice *device, } /* update progress */ - fu_device_set_progress_full(device, i * 32, reqs->len * 32); + fu_progress_set_percentage_full(fu_progress_get_child(progress), i + 1, reqs->len); } + fu_progress_step_done(progress); /* check CRC */ if (!fu_logitech_hidpp_bootloader_texas_compute_and_test_crc(self, error)) return FALSE; - - /* mark as complete */ - fu_device_set_progress_full(device, reqs->len * 32, reqs->len * 32); + fu_progress_step_done(progress); /* success! */ return TRUE; diff --git a/plugins/logitech-hidpp/fu-logitech-hidpp-bootloader.c b/plugins/logitech-hidpp/fu-logitech-hidpp-bootloader.c index db960c6ff..70e50c112 100644 --- a/plugins/logitech-hidpp/fu-logitech-hidpp-bootloader.c +++ b/plugins/logitech-hidpp/fu-logitech-hidpp-bootloader.c @@ -208,7 +208,7 @@ fu_logitech_hidpp_bootloader_get_blocksize(FuLogitechHidPpBootloader *self) } static gboolean -fu_logitech_hidpp_bootloader_attach(FuDevice *device, GError **error) +fu_logitech_hidpp_bootloader_attach(FuDevice *device, FuProgress *progress, GError **error) { FuLogitechHidPpBootloader *self = FU_UNIFYING_BOOTLOADER(device); g_autoptr(FuLogitechHidPpBootloaderRequest) req = @@ -252,10 +252,13 @@ fu_logitech_hidpp_bootloader_set_bl_version(FuLogitechHidPpBootloader *self, GEr } fu_device_set_version_bootloader(FU_DEVICE(self), version); - if ((major == 0x01 && minor >= 0x04) || (major == 0x03 && minor >= 0x02)) + if ((major == 0x01 && minor >= 0x04) || (major == 0x03 && minor >= 0x02)) { + fu_device_add_private_flag(FU_DEVICE(self), + FU_LOGITECH_HIDPP_BOOTLOADER_FLAG_IS_SIGNED); fu_device_add_protocol(FU_DEVICE(self), "com.logitech.unifyingsigned"); - else + } else { fu_device_add_protocol(FU_DEVICE(self), "com.logitech.unifying"); + } return TRUE; } @@ -471,6 +474,9 @@ fu_logitech_hidpp_bootloader_init(FuLogitechHidPpBootloader *self) fu_device_set_name(FU_DEVICE(self), "Unifying Receiver"); fu_device_set_summary(FU_DEVICE(self), "Miniaturised USB wireless receiver (bootloader)"); fu_device_set_remove_delay(FU_DEVICE(self), FU_UNIFYING_DEVICE_TIMEOUT_MS); + fu_device_register_private_flag(FU_DEVICE(self), + FU_LOGITECH_HIDPP_BOOTLOADER_FLAG_IS_SIGNED, + "is-signed"); } static void diff --git a/plugins/logitech-hidpp/fu-logitech-hidpp-bootloader.h b/plugins/logitech-hidpp/fu-logitech-hidpp-bootloader.h index 4a2b1595a..497adcc7d 100644 --- a/plugins/logitech-hidpp/fu-logitech-hidpp-bootloader.h +++ b/plugins/logitech-hidpp/fu-logitech-hidpp-bootloader.h @@ -19,6 +19,15 @@ struct _FuLogitechHidPpBootloaderClass { FuHidDeviceClass parent_class; }; +/** + * FU_LOGITECH_HIDPP_BOOTLOADER_FLAG_IS_SIGNED: + * + * Device requires signed firmware. + * + * Since: 1.7.0 + */ +#define FU_LOGITECH_HIDPP_BOOTLOADER_FLAG_IS_SIGNED (1 << 0) + typedef enum { FU_UNIFYING_BOOTLOADER_CMD_GENERAL_ERROR = 0x01, FU_UNIFYING_BOOTLOADER_CMD_READ = 0x10, diff --git a/plugins/logitech-hidpp/fu-logitech-hidpp-device.c b/plugins/logitech-hidpp/fu-logitech-hidpp-device.c index 643d8e4fa..2056a8966 100644 --- a/plugins/logitech-hidpp/fu-logitech-hidpp-device.c +++ b/plugins/logitech-hidpp/fu-logitech-hidpp-device.c @@ -852,7 +852,7 @@ fu_logitech_hidpp_device_setup(FuDevice *device, GError **error) } static gboolean -fu_logitech_hidpp_device_detach(FuDevice *device, GError **error) +fu_logitech_hidpp_device_detach(FuDevice *device, FuProgress *progress, GError **error) { FuLogitechHidPpDevice *self = FU_HIDPP_DEVICE(device); FuLogitechHidPpDevicePrivate *priv = GET_PRIVATE(self); @@ -887,7 +887,6 @@ fu_logitech_hidpp_device_detach(FuDevice *device, GError **error) msg->hidpp_version = priv->hidpp_version; msg->flags = FU_UNIFYING_HIDPP_MSG_FLAG_IGNORE_SUB_ID | FU_UNIFYING_HIDPP_MSG_FLAG_LONGER_TIMEOUT; - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); if (!fu_logitech_hidpp_transfer(priv->io_channel, msg, &error_local)) { if (fu_device_has_private_flag( device, @@ -1139,6 +1138,7 @@ fu_logitech_hidpp_device_write_firmware_pkt(FuLogitechHidPpDevice *self, static gboolean fu_logitech_hidpp_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -1168,7 +1168,7 @@ fu_logitech_hidpp_device_write_firmware(FuDevice *device, g_warning("updating cached entity 0x%x with 0x%x", priv->cached_fw_entity, data[0]); priv->cached_fw_entity = data[0]; } - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_WRITE); for (gsize i = 0; i < sz / 16; i++) { /* send packet and wait for reply */ if (g_getenv("FWUPD_LOGITECH_HIDPP") != NULL) @@ -1186,7 +1186,7 @@ fu_logitech_hidpp_device_write_firmware(FuDevice *device, cmd = (cmd + 1) % 4; /* update progress-bar */ - fu_device_set_progress_full(device, i * 16, sz); + fu_progress_set_percentage_full(progress, (i + 1) * 16, sz); } return TRUE; @@ -1199,7 +1199,10 @@ fu_logitech_hidpp_device_reprobe_cb(FuDevice *device, gpointer user_data, GError } gboolean -fu_logitech_hidpp_device_attach(FuLogitechHidPpDevice *self, guint8 entity, GError **error) +fu_logitech_hidpp_device_attach(FuLogitechHidPpDevice *self, + guint8 entity, + FuProgress *progress, + GError **error) { FuLogitechHidPpDevicePrivate *priv = GET_PRIVATE(self); FuDevice *device = FU_DEVICE(self); @@ -1248,7 +1251,7 @@ fu_logitech_hidpp_device_attach(FuLogitechHidPpDevice *self, guint8 entity, GErr * Possible race condition: after the device is reset, Linux might enumerate it as * a different hidraw device depending on timing. */ - fu_device_sleep_with_progress(device, 1); /* second */ + fu_progress_sleep(progress, 1000); /* ms */ } else { /* device file hasn't been unbound/re-bound, just probe again */ if (!fu_device_retry(device, fu_logitech_hidpp_device_reprobe_cb, 10, NULL, error)) @@ -1260,14 +1263,14 @@ fu_logitech_hidpp_device_attach(FuLogitechHidPpDevice *self, guint8 entity, GErr } static gboolean -fu_logitech_hidpp_device_attach_cached(FuDevice *device, GError **error) +fu_logitech_hidpp_device_attach_cached(FuDevice *device, FuProgress *progress, GError **error) { FuLogitechHidPpDevice *self = FU_HIDPP_DEVICE(device); FuLogitechHidPpDevicePrivate *priv = GET_PRIVATE(self); - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); + if (fu_device_has_private_flag(device, FU_LOGITECH_HIDPP_DEVICE_FLAG_REBIND_ATTACH)) fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG); - return fu_logitech_hidpp_device_attach(self, priv->cached_fw_entity, error); + return fu_logitech_hidpp_device_attach(self, priv->cached_fw_entity, progress, error); } static gboolean @@ -1286,6 +1289,17 @@ fu_logitech_hidpp_device_set_quirk_kv(FuDevice *device, return FALSE; } +static void +fu_logitech_hidpp_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 94); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* reload */ +} + static void fu_logitech_hidpp_device_finalize(GObject *object) { @@ -1327,6 +1341,7 @@ fu_logitech_hidpp_device_class_init(FuLogitechHidPpDeviceClass *klass) klass_device->probe = fu_logitech_hidpp_device_probe; klass_device->set_quirk_kv = fu_logitech_hidpp_device_set_quirk_kv; klass_device->cleanup = fu_logitech_hidpp_device_cleanup; + klass_device->set_progress = fu_logitech_hidpp_device_set_progress; } static void diff --git a/plugins/logitech-hidpp/fu-logitech-hidpp-device.h b/plugins/logitech-hidpp/fu-logitech-hidpp-device.h index 4b1fd62f3..4eb3e4071 100644 --- a/plugins/logitech-hidpp/fu-logitech-hidpp-device.h +++ b/plugins/logitech-hidpp/fu-logitech-hidpp-device.h @@ -84,6 +84,9 @@ fu_logitech_hidpp_device_set_hidpp_pid(FuLogitechHidPpDevice *self, guint16 hidp const gchar * fu_logitech_hidpp_device_get_model_id(FuLogitechHidPpDevice *self); gboolean -fu_logitech_hidpp_device_attach(FuLogitechHidPpDevice *self, guint8 entity, GError **error); +fu_logitech_hidpp_device_attach(FuLogitechHidPpDevice *self, + guint8 entity, + FuProgress *progress, + GError **error); FuLogitechHidPpDevice * fu_logitech_hidpp_device_new(FuUdevDevice *parent); diff --git a/plugins/logitech-hidpp/fu-logitech-hidpp-radio.c b/plugins/logitech-hidpp/fu-logitech-hidpp-radio.c index f2223094e..c37575927 100644 --- a/plugins/logitech-hidpp/fu-logitech-hidpp-radio.c +++ b/plugins/logitech-hidpp/fu-logitech-hidpp-radio.c @@ -24,7 +24,7 @@ fu_logitech_hidpp_radio_to_string(FuDevice *device, guint idt, GString *str) } static gboolean -fu_logitech_hidpp_radio_attach(FuDevice *device, GError **error) +fu_logitech_hidpp_radio_attach(FuDevice *device, FuProgress *progress, GError **error) { FuLogitechHidPpRadio *self = FU_HIDPP_RADIO(device); FuDevice *parent = fu_device_get_parent(device); @@ -35,13 +35,15 @@ fu_logitech_hidpp_radio_attach(FuDevice *device, GError **error) if (locker == NULL) return FALSE; - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG); - return fu_logitech_hidpp_device_attach(FU_HIDPP_DEVICE(parent), self->entity, error); + return fu_logitech_hidpp_device_attach(FU_HIDPP_DEVICE(parent), + self->entity, + progress, + error); } static gboolean -fu_logitech_hidpp_radio_detach(FuDevice *device, GError **error) +fu_logitech_hidpp_radio_detach(FuDevice *device, FuProgress *progress, GError **error) { FuDevice *parent = fu_device_get_parent(device); g_autoptr(FuDeviceLocker) locker = NULL; @@ -51,16 +53,15 @@ fu_logitech_hidpp_radio_detach(FuDevice *device, GError **error) if (locker == NULL) return FALSE; - if (!fu_device_has_flag(parent, FWUPD_DEVICE_FLAG_IS_BOOTLOADER)) { - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); + if (!fu_device_has_flag(parent, FWUPD_DEVICE_FLAG_IS_BOOTLOADER)) fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG); - } - return fu_device_detach(parent, error); + return fu_device_detach(parent, progress, error); } static gboolean fu_logitech_hidpp_radio_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -76,9 +77,7 @@ fu_logitech_hidpp_radio_write_firmware(FuDevice *device, locker = fu_device_locker_new(parent, error); if (locker == NULL) return FALSE; - - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); - return fu_device_write_firmware(parent, fw, flags, error); + return fu_device_write_firmware(parent, fw, progress, flags, error); } static void diff --git a/plugins/logitech-hidpp/fu-logitech-hidpp-runtime-bolt.c b/plugins/logitech-hidpp/fu-logitech-hidpp-runtime-bolt.c index cf788138d..dc12108ba 100644 --- a/plugins/logitech-hidpp/fu-logitech-hidpp-runtime-bolt.c +++ b/plugins/logitech-hidpp/fu-logitech-hidpp-runtime-bolt.c @@ -20,7 +20,7 @@ struct _FuLogitechHidPpRuntimeBolt { G_DEFINE_TYPE(FuLogitechHidPpRuntimeBolt, fu_logitech_hidpp_runtime_bolt, FU_TYPE_HIDPP_RUNTIME) static gboolean -fu_logitech_hidpp_runtime_bolt_detach(FuDevice *device, GError **error) +fu_logitech_hidpp_runtime_bolt_detach(FuDevice *device, FuProgress *progress, GError **error) { FuLogitechHidPpRuntime *self = FU_HIDPP_RUNTIME(device); g_autoptr(FuLogitechHidPpHidppMsg) msg = fu_logitech_hidpp_msg_new(); diff --git a/plugins/logitech-hidpp/fu-logitech-hidpp-runtime-unifying.c b/plugins/logitech-hidpp/fu-logitech-hidpp-runtime-unifying.c index a525e3576..83602e63e 100644 --- a/plugins/logitech-hidpp/fu-logitech-hidpp-runtime-unifying.c +++ b/plugins/logitech-hidpp/fu-logitech-hidpp-runtime-unifying.c @@ -20,7 +20,7 @@ G_DEFINE_TYPE(FuLogitechHidPpRuntimeUnifying, #define GET_PRIVATE(o) (fu_logitech_hidpp_runtime_unifying_get_instance_private(o)) static gboolean -fu_logitech_hidpp_runtime_unifying_detach(FuDevice *device, GError **error) +fu_logitech_hidpp_runtime_unifying_detach(FuDevice *device, FuProgress *progress, GError **error) { FuLogitechHidPpRuntime *self = FU_HIDPP_RUNTIME(device); g_autoptr(FuLogitechHidPpHidppMsg) msg = fu_logitech_hidpp_msg_new(); @@ -151,6 +151,16 @@ fu_logitech_hidpp_runtime_unifying_setup(FuDevice *device, GError **error) return FALSE; } +static void +fu_logitech_hidpp_runtime_unifying_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 70); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 4); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 27); /* reload */ +} + static void fu_logitech_hidpp_runtime_unifying_class_init(FuLogitechHidPpRuntimeUnifyingClass *klass) { @@ -158,6 +168,7 @@ fu_logitech_hidpp_runtime_unifying_class_init(FuLogitechHidPpRuntimeUnifyingClas klass_device->detach = fu_logitech_hidpp_runtime_unifying_detach; klass_device->setup = fu_logitech_hidpp_runtime_unifying_setup; + klass_device->set_progress = fu_logitech_hidpp_runtime_unifying_set_progress; } static void diff --git a/plugins/modem-manager/fu-firehose-updater.c b/plugins/modem-manager/fu-firehose-updater.c index 1858ba1e2..69bd3c6b8 100644 --- a/plugins/modem-manager/fu-firehose-updater.c +++ b/plugins/modem-manager/fu-firehose-updater.c @@ -49,10 +49,6 @@ #define CONFIGURE_ZLP_AWARE_HOST 1 #define CONFIGURE_SKIP_STORAGE_INIT 0 -enum { SIGNAL_WRITE_PERCENTAGE, SIGNAL_LAST }; - -static guint signals[SIGNAL_LAST] = {0}; - struct _FuFirehoseUpdater { GObject parent_instance; gchar *port; @@ -755,6 +751,7 @@ fu_firehose_updater_run_actions(FuFirehoseUpdater *self, XbSilo *silo, GPtrArray *action_nodes, guint max_payload_size, + FuProgress *progress, GError **error) { gsize sent_bytes = 0; @@ -777,10 +774,7 @@ fu_firehose_updater_run_actions(FuFirehoseUpdater *self, error)) return FALSE; - g_signal_emit(self, - signals[SIGNAL_WRITE_PERCENTAGE], - 0, - (guint)((100.0 * (gdouble)sent_bytes) / (gdouble)total_bytes)); + fu_progress_set_percentage_full(progress, sent_bytes, total_bytes); } return TRUE; @@ -790,14 +784,13 @@ gboolean fu_firehose_updater_write(FuFirehoseUpdater *self, XbSilo *silo, GPtrArray *action_nodes, + FuProgress *progress, GError **error) { guint max_payload_size; gboolean result; g_autoptr(GError) error_local = NULL; - g_signal_emit(self, signals[SIGNAL_WRITE_PERCENTAGE], 0, 0); - if (!fu_firehose_updater_initialize(self, error)) return FALSE; @@ -805,7 +798,12 @@ fu_firehose_updater_write(FuFirehoseUpdater *self, if (max_payload_size == 0) return FALSE; - result = fu_firehose_updater_run_actions(self, silo, action_nodes, max_payload_size, error); + result = fu_firehose_updater_run_actions(self, + silo, + action_nodes, + max_payload_size, + progress, + error); if (!fu_firehose_updater_reset(self, &error_local)) { if (result) @@ -813,8 +811,6 @@ fu_firehose_updater_write(FuFirehoseUpdater *self, return FALSE; } - g_signal_emit(self, signals[SIGNAL_WRITE_PERCENTAGE], 0, 100); - return result; } @@ -837,17 +833,6 @@ fu_firehose_updater_class_init(FuFirehoseUpdaterClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS(klass); object_class->finalize = fu_firehose_updater_finalize; - - signals[SIGNAL_WRITE_PERCENTAGE] = g_signal_new("write-percentage", - G_TYPE_FROM_CLASS(object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, - NULL, - g_cclosure_marshal_VOID__UINT, - G_TYPE_NONE, - 1, - G_TYPE_UINT); } FuFirehoseUpdater * diff --git a/plugins/modem-manager/fu-firehose-updater.h b/plugins/modem-manager/fu-firehose-updater.h index ab11c345a..6b91ce320 100644 --- a/plugins/modem-manager/fu-firehose-updater.h +++ b/plugins/modem-manager/fu-firehose-updater.h @@ -23,6 +23,7 @@ gboolean fu_firehose_updater_write(FuFirehoseUpdater *self, XbSilo *silo, GPtrArray *action_nodes, + FuProgress *progress, GError **error); gboolean fu_firehose_updater_close(FuFirehoseUpdater *self, GError **error); diff --git a/plugins/modem-manager/fu-mbim-qdu-updater.c b/plugins/modem-manager/fu-mbim-qdu-updater.c index 4f81b4d6a..5756ce815 100644 --- a/plugins/modem-manager/fu-mbim-qdu-updater.c +++ b/plugins/modem-manager/fu-mbim-qdu-updater.c @@ -267,6 +267,7 @@ typedef struct { GPtrArray *chunks; guint chunk_sent; FuDevice *device; + FuProgress *progress; } WriteContext; static gboolean @@ -302,10 +303,10 @@ fu_mbim_qdu_updater_file_write_ready(MbimDevice *device, GAsyncResult *res, gpoi return; } - fu_device_set_progress_full(FU_DEVICE(ctx->device), - (gsize)ctx->chunk_sent, - (gsize)ctx->chunks->len); ctx->chunk_sent++; + fu_progress_set_percentage_full(ctx->progress, + (gsize)ctx->chunk_sent, + (gsize)ctx->chunks->len); if (ctx->chunk_sent < ctx->chunks->len) { FuChunk *chk = g_ptr_array_index(ctx->chunks, ctx->chunk_sent); g_autoptr(MbimMessage) request = @@ -321,8 +322,7 @@ fu_mbim_qdu_updater_file_write_ready(MbimDevice *device, GAsyncResult *res, gpoi return; } - fu_device_set_progress(FU_DEVICE(ctx->device), 100); - fu_device_set_status(FU_DEVICE(ctx->device), FWUPD_STATUS_DEVICE_RESTART); + fu_progress_set_status(ctx->progress, FWUPD_STATUS_DEVICE_RESTART); /* device will auto reboot right after update finish */ g_timeout_add_seconds(10, fu_mbim_qdu_updater_reboot_timeout, ctx); } @@ -462,6 +462,7 @@ fu_mbim_qdu_updater_write(FuMbimQduUpdater *self, const gchar *filename, GBytes *blob, FuDevice *device, + FuProgress *progress, GError **error) { g_autoptr(GMainLoop) mainloop = g_main_loop_new(NULL, FALSE); @@ -476,6 +477,7 @@ fu_mbim_qdu_updater_write(FuMbimQduUpdater *self, .chunks = chunks, .chunk_sent = 0, .device = device, + .progress = progress, }; fu_mbim_qdu_updater_set_update_session(self->mbim_device, &ctx); diff --git a/plugins/modem-manager/fu-mbim-qdu-updater.h b/plugins/modem-manager/fu-mbim-qdu-updater.h index 6aa36f73a..1f334b7bb 100644 --- a/plugins/modem-manager/fu-mbim-qdu-updater.h +++ b/plugins/modem-manager/fu-mbim-qdu-updater.h @@ -23,6 +23,7 @@ fu_mbim_qdu_updater_write(FuMbimQduUpdater *self, const gchar *filename, GBytes *blob, FuDevice *device, + FuProgress *progress, GError **error); gchar * fu_mbim_qdu_updater_check_ready(FuMbimQduUpdater *self, GError **error); diff --git a/plugins/modem-manager/fu-mm-device.c b/plugins/modem-manager/fu-mm-device.c index 745ce8ec8..6367443da 100644 --- a/plugins/modem-manager/fu-mm-device.c +++ b/plugins/modem-manager/fu-mm-device.c @@ -763,7 +763,7 @@ fu_mm_device_qcdm_switch_to_edl(FuDevice *device, GError **error) #endif /* MM_CHECK_VERSION(1,17,2) */ static gboolean -fu_mm_device_detach(FuDevice *device, GError **error) +fu_mm_device_detach(FuDevice *device, FuProgress *progress, GError **error) { FuMmDevice *self = FU_MM_DEVICE(device); g_autoptr(FuDeviceLocker) locker = NULL; @@ -1094,7 +1094,10 @@ fu_mm_device_writeln(const gchar *fn, const gchar *buf, GError **error) } static gboolean -fu_mm_device_write_firmware_mbim_qdu(FuDevice *device, GBytes *fw, GError **error) +fu_mm_device_write_firmware_mbim_qdu(FuDevice *device, + GBytes *fw, + FuProgress *progress, + GError **error) { GBytes *data; XbNode *part = NULL; @@ -1162,12 +1165,12 @@ fu_mm_device_write_firmware_mbim_qdu(FuDevice *device, GBytes *fw, GError **erro if (!fu_mm_device_writeln(autosuspend_delay_filename, "10000", error)) return FALSE; - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); - fu_mbim_qdu_updater_write(self->mbim_qdu_updater, filename, data, device, error); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_WRITE); + fu_mbim_qdu_updater_write(self->mbim_qdu_updater, filename, data, device, progress, error); if (!fu_device_locker_close(locker, error)) return FALSE; - fu_device_set_status(device, FWUPD_STATUS_DEVICE_READ); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_READ); fu_device_set_remove_delay(device, MAX_WAIT_TIME_SECS * 1000); fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG); version = fu_mm_device_get_firmware_version_mbim(device, error); @@ -1200,32 +1203,21 @@ static gboolean fu_mm_device_firehose_write(FuMmDevice *self, XbSilo *rawprogram_silo, GPtrArray *rawprogram_actions, + FuProgress *progress, GError **error) { g_autoptr(FuDeviceLocker) locker = NULL; - guint progress_signal_id; - gboolean write_result; - locker = fu_device_locker_new_full(self, (FuDeviceLockerFunc)fu_mm_device_firehose_open, (FuDeviceLockerFunc)fu_mm_device_firehose_close, error); if (locker == NULL) return FALSE; - - progress_signal_id = g_signal_connect_swapped(self->firehose_updater, - "write-percentage", - G_CALLBACK(fu_device_set_progress), - self); - - write_result = fu_firehose_updater_write(self->firehose_updater, - rawprogram_silo, - rawprogram_actions, - error); - - g_signal_handler_disconnect(self->firehose_updater, progress_signal_id); - - return write_result; + return fu_firehose_updater_write(self->firehose_updater, + rawprogram_silo, + rawprogram_actions, + progress, + error); } static gboolean @@ -1297,20 +1289,30 @@ fu_mm_restore_firmware_search_path(FuMmDevice *self, GError **error) } static gboolean -fu_mm_device_write_firmware_firehose(FuDevice *device, GBytes *fw, GError **error) +fu_mm_device_write_firmware_firehose(FuDevice *device, + GBytes *fw, + FuProgress *progress, + GError **error) { FuMmDevice *self = FU_MM_DEVICE(device); - GBytes *firehose_rawprogram; g_autoptr(FuDeviceLocker) locker = NULL; g_autoptr(FuArchive) archive = NULL; g_autoptr(XbSilo) firehose_rawprogram_silo = NULL; g_autoptr(GPtrArray) firehose_rawprogram_actions = NULL; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DECOMPRESSING, 1); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 10); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 90); + /* decompress entire archive ahead of time */ archive = fu_archive_new(fw, FU_ARCHIVE_FLAG_IGNORE_PATH, error); if (archive == NULL) return FALSE; + fu_progress_step_done(progress); /* modify firmware search path and restore it before function returns */ locker = fu_device_locker_new_full(self, @@ -1325,9 +1327,6 @@ fu_mm_device_write_firmware_firehose(FuDevice *device, GBytes *fw, GError **erro if (!fu_mm_copy_firehose_prog(self, archive, error)) return FALSE; - /* flag as restart because the QCDM and MHI/BHI operations switch the - * device into FP execution environment */ - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_DEVICE_RESTART); /* switch to embedded downloader (EDL) execution environment */ if (!fu_mm_device_qcdm_switch_to_edl(FU_DEVICE(self), error)) return FALSE; @@ -1344,20 +1343,19 @@ fu_mm_device_write_firmware_firehose(FuDevice *device, GBytes *fw, GError **erro g_prefix_error(error, "Invalid firehose rawprogram manifest: "); return FALSE; } - - /* flag as write */ - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_DEVICE_WRITE); + fu_progress_step_done(progress); /* download all files in the firehose-rawprogram manifest via Firehose */ if (!fu_mm_device_firehose_write(self, firehose_rawprogram_silo, firehose_rawprogram_actions, + fu_progress_get_child(progress), error)) return FALSE; + fu_progress_step_done(progress); /* flag as restart again, the module is switching to modem mode */ - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_DEVICE_RESTART); - + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_RESTART); return TRUE; } @@ -1366,6 +1364,7 @@ fu_mm_device_write_firmware_firehose(FuDevice *device, GBytes *fw, GError **erro static gboolean fu_mm_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -1393,13 +1392,13 @@ fu_mm_device_write_firmware(FuDevice *device, #if MM_CHECK_VERSION(1, 17, 1) && MBIM_CHECK_VERSION(1, 25, 3) /* mbim qdu write operation */ if (self->update_methods & MM_MODEM_FIRMWARE_UPDATE_METHOD_MBIM_QDU) - return fu_mm_device_write_firmware_mbim_qdu(device, fw, error); + return fu_mm_device_write_firmware_mbim_qdu(device, fw, progress, error); #endif /* MM_CHECK_VERSION(1,17,1) && MBIM_CHECK_VERSION(1,25,3) */ #if MM_CHECK_VERSION(1, 17, 2) /* firehose operation */ if (self->update_methods & MM_MODEM_FIRMWARE_UPDATE_METHOD_FIREHOSE) - return fu_mm_device_write_firmware_firehose(device, fw, error); + return fu_mm_device_write_firmware_firehose(device, fw, progress, error); #endif g_set_error(error, FWUPD_ERROR, FWUPD_ERROR_NOT_SUPPORTED, "unsupported update method"); @@ -1455,7 +1454,7 @@ fu_mm_device_attach_qmi_pdc_idle(gpointer user_data) } static gboolean -fu_mm_device_attach(FuDevice *device, GError **error) +fu_mm_device_attach(FuDevice *device, FuProgress *progress, GError **error) { FuMmDevice *self = FU_MM_DEVICE(device); g_autoptr(FuDeviceLocker) locker = NULL; @@ -1478,6 +1477,17 @@ fu_mm_device_attach(FuDevice *device, GError **error) return TRUE; } +static void +fu_mm_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 94); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* reload */ +} + static void fu_mm_device_init(FuMmDevice *self) { @@ -1522,6 +1532,7 @@ fu_mm_device_class_init(FuMmDeviceClass *klass) klass_device->detach = fu_mm_device_detach; klass_device->write_firmware = fu_mm_device_write_firmware; klass_device->attach = fu_mm_device_attach; + klass_device->set_progress = fu_mm_device_set_progress; signals[SIGNAL_ATTACH_FINISHED] = g_signal_new("attach-finished", G_TYPE_FROM_CLASS(object_class), diff --git a/plugins/modem-manager/fu-plugin-modem-manager.c b/plugins/modem-manager/fu-plugin-modem-manager.c index c49f88980..2ac97189c 100644 --- a/plugins/modem-manager/fu-plugin-modem-manager.c +++ b/plugins/modem-manager/fu-plugin-modem-manager.c @@ -1,3 +1,4 @@ + /* * Copyright (C) 2018 Richard Hughes * @@ -370,7 +371,7 @@ fu_plugin_destroy(FuPlugin *plugin) } gboolean -fu_plugin_detach(FuPlugin *plugin, FuDevice *device, GError **error) +fu_plugin_detach(FuPlugin *plugin, FuDevice *device, FuProgress *progress, GError **error) { FuPluginData *priv = fu_plugin_get_data(plugin); g_autoptr(FuDeviceLocker) locker = NULL; @@ -397,7 +398,7 @@ fu_plugin_detach(FuPlugin *plugin, FuDevice *device, GError **error) } /* reset */ - if (!fu_device_detach(device, error)) { + if (!fu_device_detach(device, progress, error)) { fu_plugin_mm_uninhibit_device(plugin); return FALSE; } @@ -414,7 +415,7 @@ fu_plugin_mm_device_attach_finished(gpointer user_data) } gboolean -fu_plugin_attach(FuPlugin *plugin, FuDevice *device, GError **error) +fu_plugin_attach(FuPlugin *plugin, FuDevice *device, FuProgress *progress, GError **error) { g_autoptr(FuDeviceLocker) locker = NULL; @@ -434,7 +435,7 @@ fu_plugin_attach(FuPlugin *plugin, FuDevice *device, GError **error) * so that engine can setup the device "waiting" logic before the actual * attach procedure happens (which will reset the module if it worked * properly) */ - if (!fu_device_attach(device, error)) + if (!fu_device_attach(device, progress, error)) return FALSE; /* this signal will always be emitted asynchronously */ diff --git a/plugins/nvme/fu-nvme-device.c b/plugins/nvme/fu-nvme-device.c index b9549849d..f195de2f2 100644 --- a/plugins/nvme/fu-nvme-device.c +++ b/plugins/nvme/fu-nvme-device.c @@ -318,6 +318,7 @@ fu_nvme_device_setup(FuDevice *device, GError **error) static gboolean fu_nvme_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -327,6 +328,12 @@ fu_nvme_device_write_firmware(FuDevice *device, g_autoptr(GPtrArray) chunks = NULL; guint64 block_size = self->write_block_size > 0 ? self->write_block_size : 0x1000; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 90); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_VERIFY, 10); /* commit */ + /* get default image */ fw = fu_firmware_get_bytes(firmware, error); if (fw == NULL) @@ -340,14 +347,11 @@ fu_nvme_device_write_firmware(FuDevice *device, fw2 = g_bytes_ref(fw); } - /* build packets */ + /* write each block */ chunks = fu_chunk_array_new_from_bytes(fw2, 0x00, /* start_addr */ 0x00, /* page_sz */ block_size); /* block size */ - - /* write each block */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); for (guint i = 0; i < chunks->len; i++) { FuChunk *chk = g_ptr_array_index(chunks, i); if (!fu_nvme_device_fw_download(self, @@ -358,8 +362,11 @@ fu_nvme_device_write_firmware(FuDevice *device, g_prefix_error(error, "failed to write chunk %u: ", i); return FALSE; } - fu_device_set_progress_full(device, (gsize)i, (gsize)chunks->len + 1); + fu_progress_set_percentage_full(fu_progress_get_child(progress), + (gsize)i + 1, + (gsize)chunks->len); } + fu_progress_step_done(progress); /* commit */ if (!fu_nvme_device_fw_commit(self, @@ -370,9 +377,9 @@ fu_nvme_device_write_firmware(FuDevice *device, g_prefix_error(error, "failed to commit to auto slot: "); return FALSE; } + fu_progress_step_done(progress); /* success! */ - fu_device_set_progress(device, 100); return TRUE; } @@ -389,6 +396,16 @@ fu_nvme_device_set_quirk_kv(FuDevice *device, const gchar *key, const gchar *val return FALSE; } +static void +fu_nvme_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 100); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 0); /* reload */ +} + static void fu_nvme_device_init(FuNvmeDevice *self) { @@ -423,6 +440,7 @@ fu_nvme_device_class_init(FuNvmeDeviceClass *klass) klass_device->setup = fu_nvme_device_setup; klass_device->write_firmware = fu_nvme_device_write_firmware; klass_device->probe = fu_nvme_device_probe; + klass_device->set_progress = fu_nvme_device_set_progress; } FuNvmeDevice * diff --git a/plugins/optionrom/fu-optionrom-device.c b/plugins/optionrom/fu-optionrom-device.c index abaead947..3fe8e3141 100644 --- a/plugins/optionrom/fu-optionrom-device.c +++ b/plugins/optionrom/fu-optionrom-device.c @@ -38,7 +38,7 @@ fu_optionrom_device_probe(FuDevice *device, GError **error) } static GBytes * -fu_optionrom_device_dump_firmware(FuDevice *device, GError **error) +fu_optionrom_device_dump_firmware(FuDevice *device, FuProgress *progress, GError **error) { FuUdevDevice *udev_device = FU_UDEV_DEVICE(device); guint number_reads = 0; diff --git a/plugins/parade-lspcon/fu-parade-lspcon-device.c b/plugins/parade-lspcon/fu-parade-lspcon-device.c index d43c3693d..d108d2021 100644 --- a/plugins/parade-lspcon/fu-parade-lspcon-device.c +++ b/plugins/parade-lspcon/fu-parade-lspcon-device.c @@ -287,9 +287,9 @@ fu_parade_lspcon_flash_read(FuParadeLspconDevice *self, guint32 base_address, guint8 *data, const gsize len, + FuProgress *progress, GError **error) { - FuDevice *device = FU_DEVICE(self); FuI2cDevice *i2c_device = FU_I2C_DEVICE(self); gsize offset = 0; @@ -322,7 +322,7 @@ fu_parade_lspcon_flash_read(FuParadeLspconDevice *self, base_address += page_data_take; offset += page_data_take; - fu_device_set_progress_full(device, offset, len); + fu_progress_set_percentage_full(progress, offset, len); } return TRUE; @@ -417,9 +417,9 @@ static gboolean fu_parade_lspcon_flash_write(FuParadeLspconDevice *self, guint32 base_address, GBytes *data, + FuProgress *progress, GError **error) { - FuDevice *device = FU_DEVICE(self); FuI2cDevice *i2c_device = FU_I2C_DEVICE(self); const guint8 unlock_writes[] = {0xaa, 0x55, 0x50, 0x41, 0x52, 0x44}; gsize data_len = g_bytes_get_size(data); @@ -477,7 +477,7 @@ fu_parade_lspcon_flash_write(FuParadeLspconDevice *self, if (!fu_i2c_device_write_full(i2c_device, write_data, chunk_size + 1, error)) return FALSE; - fu_device_set_progress_full(device, address - base_address, data_len); + fu_progress_set_percentage_full(progress, address - base_address, data_len); } /* re-lock map writes */ @@ -631,6 +631,7 @@ fu_parade_lspcon_device_reload(FuDevice *device, GError **error) static gboolean fu_parade_lspcon_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -652,6 +653,15 @@ fu_parade_lspcon_device_write_firmware(FuDevice *device, g_autoptr(GBytes) blob_fw = NULL; g_autoptr(GBytes) flag_data_bytes = NULL; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_ERASE, 5); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 70); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_VERIFY, 25); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 3); /* boot */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_VERIFY, 2); /* boot */ + blob_fw = fu_firmware_get_bytes(firmware, error); if (blob_fw == NULL) return FALSE; @@ -688,45 +698,62 @@ fu_parade_lspcon_device_write_firmware(FuDevice *device, return FALSE; /* erase entire target partition (one flash block) */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_ERASE); if (!fu_parade_lspcon_flash_erase_block(self, target_address, bufsz, error)) { g_prefix_error(error, "failed to erase flash partition %d: ", target_partition); return FALSE; } + fu_progress_step_done(progress); /* write image */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); - if (!fu_parade_lspcon_flash_write(self, target_address, blob_fw, error)) { + if (!fu_parade_lspcon_flash_write(self, + target_address, + blob_fw, + fu_progress_get_child(progress), + error)) { g_prefix_error(error, "failed to write firmware to partition %d: ", target_partition); return FALSE; } + fu_progress_step_done(progress); /* read back written image to verify */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_VERIFY); readback_buf = g_malloc0(bufsz); - if (!fu_parade_lspcon_flash_read(self, target_address, readback_buf, bufsz, error)) + if (!fu_parade_lspcon_flash_read(self, + target_address, + readback_buf, + bufsz, + fu_progress_get_child(progress), + error)) return FALSE; if (!fu_common_bytes_compare_raw(buf, bufsz, readback_buf, bufsz, error)) { g_prefix_error(error, "flash contents do not match: "); return FALSE; } + fu_progress_step_done(progress); /* erase flag partition */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_ERASE); if (!fu_parade_lspcon_flash_erase_block(self, 0, FLASH_BLOCK_SIZE, error)) return FALSE; /* write flag indicating device should boot the target partition */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_WRITE); flag_data_bytes = g_bytes_new_static(flag_data, sizeof(flag_data)); - if (!fu_parade_lspcon_flash_write(self, 0, flag_data_bytes, error)) + if (!fu_parade_lspcon_flash_write(self, + 0, + flag_data_bytes, + fu_progress_get_child(progress), + error)) return FALSE; + fu_progress_step_done(progress); /* verify flag partition */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_VERIFY); - if (!fu_parade_lspcon_flash_read(self, 0, readback_buf, sizeof(flag_data), error)) + if (!fu_parade_lspcon_flash_read(self, + 0, + readback_buf, + sizeof(flag_data), + fu_progress_get_child(progress), + error)) return FALSE; if (!fu_common_bytes_compare_raw(flag_data, sizeof(flag_data), @@ -748,6 +775,7 @@ fu_parade_lspcon_device_write_firmware(FuDevice *device, sizeof(write_sr_enable_bp), error)) return FALSE; + fu_progress_step_done(progress); /* reassert /WP to flash */ return fu_parade_lspcon_write_register(self, REG_ADDR_WR_PROTECT, 0, error); @@ -765,21 +793,21 @@ fu_parade_lspcon_set_mpu_running(FuParadeLspconDevice *self, gboolean running, G } static gboolean -fu_parade_lspcon_device_detach(FuDevice *device, GError **error) +fu_parade_lspcon_device_detach(FuDevice *device, FuProgress *progress, GError **error) { FuParadeLspconDevice *self = FU_PARADE_LSPCON_DEVICE(device); return fu_parade_lspcon_set_mpu_running(self, FALSE, error); } static gboolean -fu_parade_lspcon_device_attach(FuDevice *device, GError **error) +fu_parade_lspcon_device_attach(FuDevice *device, FuProgress *progress, GError **error) { FuParadeLspconDevice *self = FU_PARADE_LSPCON_DEVICE(device); return fu_parade_lspcon_set_mpu_running(self, TRUE, error); } static GBytes * -fu_parade_lspcon_device_dump_firmware(FuDevice *device, GError **error) +fu_parade_lspcon_device_dump_firmware(FuDevice *device, FuProgress *progress, GError **error) { FuParadeLspconDevice *self = FU_PARADE_LSPCON_DEVICE(device); g_autofree guint8 *data = g_malloc0(FLASH_BLOCK_SIZE); @@ -788,11 +816,23 @@ fu_parade_lspcon_device_dump_firmware(FuDevice *device, GError **error) self->active_partition * FLASH_BLOCK_SIZE, data, FLASH_BLOCK_SIZE, + progress, error)) return NULL; return g_bytes_new_take(g_steal_pointer(&data), FLASH_BLOCK_SIZE); } +static void +fu_parade_lspcon_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 94); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* reload */ +} + static void fu_parade_lspcon_device_class_init(FuParadeLspconDeviceClass *klass) { @@ -809,4 +849,5 @@ fu_parade_lspcon_device_class_init(FuParadeLspconDeviceClass *klass) klass_device->write_firmware = fu_parade_lspcon_device_write_firmware; klass_device->attach = fu_parade_lspcon_device_attach; klass_device->dump_firmware = fu_parade_lspcon_device_dump_firmware; + klass_device->set_progress = fu_parade_lspcon_device_set_progress; } diff --git a/plugins/pixart-rf/fu-pxi-ble-device.c b/plugins/pixart-rf/fu-pxi-ble-device.c index ae48cd994..35d80cc21 100644 --- a/plugins/pixart-rf/fu-pxi-ble-device.c +++ b/plugins/pixart-rf/fu-pxi-ble-device.c @@ -284,7 +284,10 @@ fu_pxi_ble_device_fw_ota_check_retransmit(FuPxiBleDevice *self, GError **error) } static gboolean -fu_pxi_ble_device_check_support_resume(FuPxiBleDevice *self, FuFirmware *firmware, GError **error) +fu_pxi_ble_device_check_support_resume(FuPxiBleDevice *self, + FuFirmware *firmware, + FuProgress *progress, + GError **error) { g_autoptr(GBytes) fw = NULL; g_autoptr(GPtrArray) chunks = NULL; @@ -507,7 +510,6 @@ fu_pxi_ble_device_reset(FuPxiBleDevice *self, GError **error) fu_byte_array_append_uint8(req, PXI_HID_DEV_OTA_FEATURE_REPORT_ID); fu_byte_array_append_uint8(req, FU_PXI_DEVICE_CMD_FW_MCU_RESET); /* OTA reset command */ fu_byte_array_append_uint8(req, OTA_RESET); /* OTA reset reason */ - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_DEVICE_RESTART); if (!fu_pxi_ble_device_set_feature(self, req, error)) { g_prefix_error(error, "failed to reset: "); @@ -572,7 +574,10 @@ fu_pxi_ble_device_fw_ota_init_new(FuPxiBleDevice *self, gsize bufsz, GError **er } static gboolean -fu_pxi_ble_device_fw_upgrade(FuPxiBleDevice *self, FuFirmware *firmware, GError **error) +fu_pxi_ble_device_fw_upgrade(FuPxiBleDevice *self, + FuFirmware *firmware, + FuProgress *progress, + GError **error) { const gchar *version; const guint8 *buf; @@ -605,7 +610,6 @@ fu_pxi_ble_device_fw_upgrade(FuPxiBleDevice *self, FuFirmware *firmware, GError g_byte_array_append(req, fw_version, sizeof(fw_version)); /* send fw upgrade command */ - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_DEVICE_VERIFY); if (!fu_pxi_ble_device_set_feature(self, req, error)) return FALSE; @@ -637,6 +641,7 @@ fu_pxi_ble_device_fw_upgrade(FuPxiBleDevice *self, FuFirmware *firmware, GError static gboolean fu_pxi_ble_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -645,13 +650,21 @@ fu_pxi_ble_device_write_firmware(FuDevice *device, g_autoptr(GPtrArray) chunks = NULL; g_autoptr(GError) error_local = NULL; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 9); /* ota-init */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 1); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 90); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_VERIFY, 1); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 1); + /* get the default image */ fw = fu_firmware_get_bytes(firmware, error); if (fw == NULL) return FALSE; /* send fw ota retransmit command to reset status */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_BUSY); if (!fu_pxi_ble_device_fw_ota_check_retransmit(self, error)) { g_prefix_error(error, "failed to OTA check retransmit: "); return FALSE; @@ -661,30 +674,43 @@ fu_pxi_ble_device_write_firmware(FuDevice *device, return FALSE; if (!fu_pxi_ble_device_fw_ota_init_new(self, g_bytes_get_size(fw), error)) return FALSE; + fu_progress_step_done(progress); /* prepare write fw into device */ chunks = fu_chunk_array_new_from_bytes(fw, 0x0, 0x0, FU_PXI_DEVICE_OBJECT_SIZE_MAX); - if (!fu_pxi_ble_device_check_support_resume(self, firmware, &error_local)) { + if (!fu_pxi_ble_device_check_support_resume(self, + firmware, + fu_progress_get_child(progress), + &error_local)) { g_debug("do not resume: %s", error_local->message); self->fwstate.offset = 0; self->fwstate.checksum = 0; } + fu_progress_step_done(progress); /* write fw into device */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); for (guint i = self->fwstate.offset; i < chunks->len; i++) { FuChunk *chk = g_ptr_array_index(chunks, i); if (!fu_pxi_ble_device_write_chunk(self, chk, error)) return FALSE; - fu_device_set_progress_full(device, (gsize)i, (gsize)chunks->len); + fu_progress_set_percentage_full(fu_progress_get_child(progress), + (gsize)self->fwstate.offset + 1, + (gsize)chunks->len); } + fu_progress_step_done(progress); /* fw upgrade command */ - if (!fu_pxi_ble_device_fw_upgrade(self, firmware, error)) + if (!fu_pxi_ble_device_fw_upgrade(self, firmware, fu_progress_get_child(progress), error)) return FALSE; + fu_progress_step_done(progress); /* send device reset command */ - return fu_pxi_ble_device_reset(self, error); + if (!fu_pxi_ble_device_reset(self, error)) + return FALSE; + fu_progress_step_done(progress); + + /* success */ + return TRUE; } static gboolean @@ -855,6 +881,17 @@ fu_pxi_ble_device_setup(FuDevice *device, GError **error) return TRUE; } +static void +fu_pxi_ble_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 98); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* reload */ +} + static void fu_pxi_ble_device_init(FuPxiBleDevice *self) { @@ -884,4 +921,5 @@ fu_pxi_ble_device_class_init(FuPxiBleDeviceClass *klass) klass_device->to_string = fu_pxi_ble_device_to_string; klass_device->write_firmware = fu_pxi_ble_device_write_firmware; klass_device->prepare_firmware = fu_pxi_ble_device_prepare_firmware; + klass_device->set_progress = fu_pxi_ble_device_set_progress; } diff --git a/plugins/pixart-rf/fu-pxi-receiver-device.c b/plugins/pixart-rf/fu-pxi-receiver-device.c index aee790ccd..3a136d567 100644 --- a/plugins/pixart-rf/fu-pxi-receiver-device.c +++ b/plugins/pixart-rf/fu-pxi-receiver-device.c @@ -407,7 +407,10 @@ fu_pxi_receiver_device_write_chunk(FuDevice *device, FuChunk *chk, GError **erro } static gboolean -fu_pxi_receiver_device_fw_upgrade(FuDevice *device, FuFirmware *firmware, GError **error) +fu_pxi_receiver_device_fw_upgrade(FuDevice *device, + FuFirmware *firmware, + FuProgress *progress, + GError **error) { FuPxiReceiverDevice *self = FU_PXI_RECEIVER_DEVICE(device); const gchar *version; @@ -421,6 +424,12 @@ fu_pxi_receiver_device_fw_upgrade(FuDevice *device, FuFirmware *firmware, GError g_autoptr(GByteArray) receiver_device_cmd = g_byte_array_new(); g_autoptr(GBytes) fw = NULL; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 5); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_VERIFY, 95); + fw = fu_firmware_get_bytes(firmware, error); if (fw == NULL) return FALSE; @@ -464,9 +473,8 @@ fu_pxi_receiver_device_fw_upgrade(FuDevice *device, FuFirmware *firmware, GError ota_cmd, error)) return FALSE; + fu_progress_step_done(progress); - /* update device status */ - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_DEVICE_VERIFY); /* send ota fw upgrade command */ if (!fu_pxi_receiver_device_set_feature(self, receiver_device_cmd->data, @@ -491,6 +499,7 @@ fu_pxi_receiver_device_fw_upgrade(FuDevice *device, FuFirmware *firmware, GError result); return FALSE; } + fu_progress_step_done(progress); /* success */ return TRUE; @@ -520,9 +529,6 @@ fu_pxi_receiver_device_reset(FuDevice *device, GError **error) error)) return FALSE; - /* update device status */ - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_DEVICE_RESTART); - /* send ota mcu reset command */ return fu_pxi_receiver_device_set_feature(self, receiver_device_cmd->data, @@ -545,6 +551,7 @@ fu_pxi_receiver_device_prepare_firmware(FuDevice *device, static gboolean fu_pxi_receiver_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -552,6 +559,13 @@ fu_pxi_receiver_device_write_firmware(FuDevice *device, g_autoptr(GBytes) fw = NULL; g_autoptr(GPtrArray) chunks = NULL; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 9); /* ota-init */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 90); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_VERIFY, 1); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 1); + /* get the default image */ fw = fu_firmware_get_bytes(firmware, error); if (fw == NULL) @@ -563,6 +577,7 @@ fu_pxi_receiver_device_write_firmware(FuDevice *device, if (!fu_pxi_receiver_device_fw_ota_ini_new_check(self, error)) return FALSE; + fu_progress_step_done(progress); chunks = fu_chunk_array_new_from_bytes(fw, 0x0, 0x0, FU_PXI_DEVICE_OBJECT_SIZE_MAX); /* prepare write fw into device */ @@ -570,23 +585,34 @@ fu_pxi_receiver_device_write_firmware(FuDevice *device, self->fwstate.checksum = 0; /* write fw into device */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); for (guint i = self->fwstate.offset; i < chunks->len; i++) { FuChunk *chk = g_ptr_array_index(chunks, i); if (!fu_pxi_receiver_device_write_chunk(device, chk, error)) return FALSE; - fu_device_set_progress_full(device, (gsize)i, (gsize)chunks->len); + fu_progress_set_percentage_full(fu_progress_get_child(progress), + (gsize)i + self->fwstate.offset + 1, + (gsize)chunks->len); } + fu_progress_step_done(progress); /* fw upgrade command */ - if (!fu_pxi_receiver_device_fw_upgrade(device, firmware, error)) + if (!fu_pxi_receiver_device_fw_upgrade(device, + firmware, + fu_progress_get_child(progress), + error)) return FALSE; + fu_progress_step_done(progress); /* delay for wireless module device read command */ g_usleep(5 * 1000); /* send device reset command */ - return fu_pxi_receiver_device_reset(device, error); + if (!fu_pxi_receiver_device_reset(device, error)) + return FALSE; + fu_progress_step_done(progress); + + /* success */ + return TRUE; } static gboolean @@ -836,6 +862,17 @@ fu_pxi_receiver_device_probe(FuDevice *device, GError **error) return fu_udev_device_set_physical_id(FU_UDEV_DEVICE(device), "hid", error); } +static void +fu_pxi_receiver_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 98); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* reload */ +} + static void fu_pxi_receiver_device_init(FuPxiReceiverDevice *self) { @@ -854,4 +891,5 @@ fu_pxi_receiver_device_class_init(FuPxiReceiverDeviceClass *klass) klass_device->probe = fu_pxi_receiver_device_probe; klass_device->write_firmware = fu_pxi_receiver_device_write_firmware; klass_device->prepare_firmware = fu_pxi_receiver_device_prepare_firmware; + klass_device->set_progress = fu_pxi_receiver_device_set_progress; } diff --git a/plugins/pixart-rf/fu-pxi-wireless-device.c b/plugins/pixart-rf/fu-pxi-wireless-device.c index 0f163f791..66d5c179b 100644 --- a/plugins/pixart-rf/fu-pxi-wireless-device.c +++ b/plugins/pixart-rf/fu-pxi-wireless-device.c @@ -453,7 +453,10 @@ fu_pxi_wireless_device_fw_ota_ini_new_check(FuDevice *device, GError **error) } static gboolean -fu_pxi_wireless_device_fw_upgrade(FuDevice *device, FuFirmware *firmware, GError **error) +fu_pxi_wireless_device_fw_upgrade(FuDevice *device, + FuFirmware *firmware, + FuProgress *progress, + GError **error) { FuPxiReceiverDevice *parent; FuPxiWirelessDevice *self = FU_PXI_WIRELESS_DEVICE(device); @@ -466,6 +469,12 @@ fu_pxi_wireless_device_fw_upgrade(FuDevice *device, FuFirmware *firmware, GError g_autoptr(GByteArray) receiver_cmd = g_byte_array_new(); g_autoptr(GBytes) fw = NULL; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 5); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_VERIFY, 95); + /* proxy */ parent = fu_pxi_wireless_device_get_parent(device, error); if (parent == NULL) @@ -512,14 +521,16 @@ fu_pxi_wireless_device_fw_upgrade(FuDevice *device, FuFirmware *firmware, GError ota_cmd, error)) return FALSE; - /* update device status */ - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_DEVICE_VERIFY); + fu_progress_step_done(progress); /* send ota fw upgrade command */ - return fu_pxi_wireless_device_set_feature(FU_DEVICE(parent), - receiver_cmd->data, - receiver_cmd->len, - error); + if (!fu_pxi_wireless_device_set_feature(FU_DEVICE(parent), + receiver_cmd->data, + receiver_cmd->len, + error)) + return FALSE; + fu_progress_step_done(progress); + return TRUE; } static gboolean @@ -553,7 +564,6 @@ fu_pxi_wireless_device_reset(FuDevice *device, GError **error) return FALSE; /* send ota mcu reset command */ - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_DEVICE_RESTART); return fu_pxi_wireless_device_set_feature(FU_DEVICE(parent), receiver_cmd->data, receiver_cmd->len, @@ -575,6 +585,7 @@ fu_pxi_wireless_device_prepare_firmware(FuDevice *device, static gboolean fu_pxi_wireless_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -582,6 +593,13 @@ fu_pxi_wireless_device_write_firmware(FuDevice *device, g_autoptr(GBytes) fw = NULL; g_autoptr(GPtrArray) chunks = NULL; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 9); /* ota-init */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 90); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_VERIFY, 1); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 1); + /* get the default image */ fw = fu_firmware_get_bytes(firmware, error); if (fw == NULL) @@ -592,6 +610,7 @@ fu_pxi_wireless_device_write_firmware(FuDevice *device, return FALSE; if (!fu_pxi_wireless_device_fw_ota_ini_new_check(device, error)) return FALSE; + fu_progress_step_done(progress); chunks = fu_chunk_array_new_from_bytes(fw, 0x0, 0x0, FU_PXI_DEVICE_OBJECT_SIZE_MAX); /* prepare write fw into device */ @@ -599,21 +618,43 @@ fu_pxi_wireless_device_write_firmware(FuDevice *device, self->fwstate.checksum = 0; /* write fw into device */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); for (guint i = self->fwstate.offset; i < chunks->len; i++) { FuChunk *chk = g_ptr_array_index(chunks, i); if (!fu_pxi_wireless_device_write_chunk(device, chk, error)) return FALSE; - fu_device_set_progress_full(device, (gsize)i, (gsize)chunks->len); + fu_progress_set_percentage_full(fu_progress_get_child(progress), + (gsize)i + self->fwstate.offset + 1, + (gsize)chunks->len); } + fu_progress_step_done(progress); /* fw upgrade command */ - if (!fu_pxi_wireless_device_fw_upgrade(device, firmware, error)) + if (!fu_pxi_wireless_device_fw_upgrade(device, + firmware, + fu_progress_get_child(progress), + error)) return FALSE; + fu_progress_step_done(progress); /* send device reset command */ g_usleep(FU_PXI_WIRELESS_DEV_DELAY_US); - return fu_pxi_wireless_device_reset(device, error); + if (!fu_pxi_wireless_device_reset(device, error)) + return FALSE; + fu_progress_step_done(progress); + + /* success */ + return TRUE; +} + +static void +fu_pxi_wireless_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 98); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* reload */ } static void @@ -633,6 +674,7 @@ fu_pxi_wireless_device_class_init(FuPxiWirelessDeviceClass *klass) klass_device->write_firmware = fu_pxi_wireless_device_write_firmware; klass_device->prepare_firmware = fu_pxi_wireless_device_prepare_firmware; klass_device->to_string = fu_pxi_wireless_device_to_string; + klass_device->set_progress = fu_pxi_wireless_device_set_progress; } FuPxiWirelessDevice * diff --git a/plugins/realtek-mst/fu-realtek-mst-device.c b/plugins/realtek-mst/fu-realtek-mst-device.c index dd961d37f..6c78214c8 100644 --- a/plugins/realtek-mst/fu-realtek-mst-device.c +++ b/plugins/realtek-mst/fu-realtek-mst-device.c @@ -550,6 +550,7 @@ flash_iface_read(FuRealtekMstDevice *self, guint32 address, guint8 *buf, const gsize buf_size, + FuProgress *progress, GError **error) { gsize bytes_read = 0; @@ -591,7 +592,7 @@ flash_iface_read(FuRealtekMstDevice *self, return FALSE; bytes_read += read_len; - fu_device_set_progress_full(FU_DEVICE(self), bytes_read, buf_size); + fu_progress_set_percentage_full(progress, bytes_read, buf_size); } return TRUE; } @@ -648,7 +649,11 @@ flash_iface_erase_block(FuRealtekMstDevice *self, guint32 address, GError **erro } static gboolean -flash_iface_write(FuRealtekMstDevice *self, guint32 address, GBytes *data, GError **error) +flash_iface_write(FuRealtekMstDevice *self, + guint32 address, + GBytes *data, + FuProgress *progress, + GError **error) { gsize bytes_written = 0; gsize total_size = g_bytes_get_size(data); @@ -704,14 +709,14 @@ flash_iface_write(FuRealtekMstDevice *self, guint32 address, GBytes *data, GErro } bytes_written += chunk_size; - fu_device_set_progress_full(FU_DEVICE(self), bytes_written, total_size); + fu_progress_set_percentage_full(progress, i + 1, chunks->len); } return TRUE; } static gboolean -fu_realtek_mst_device_detach(FuDevice *device, GError **error) +fu_realtek_mst_device_detach(FuDevice *device, FuProgress *progress, GError **error) { FuRealtekMstDevice *self = FU_REALTEK_MST_DEVICE(device); @@ -719,7 +724,6 @@ fu_realtek_mst_device_detach(FuDevice *device, GError **error) return FALSE; /* Switch to programming mode (stops regular operation) */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); if (!mst_write_register(self, REG_MCU_MODE, MCU_MODE_ISP, error)) return FALSE; g_debug("wait for ISP mode ready"); @@ -733,7 +737,6 @@ fu_realtek_mst_device_detach(FuDevice *device, GError **error) return FALSE; fu_device_add_flag(device, FWUPD_DEVICE_FLAG_IS_BOOTLOADER); - fu_device_set_status(device, FWUPD_STATUS_IDLE); /* Disable hardware write protect, assuming Flash ~WP is connected to * device pin 88, a GPIO. */ @@ -743,6 +746,7 @@ fu_realtek_mst_device_detach(FuDevice *device, GError **error) static gboolean fu_realtek_mst_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -759,26 +763,45 @@ fu_realtek_mst_device_write_firmware(FuDevice *device, g_return_val_if_fail(g_bytes_get_size(firmware_bytes) == FLASH_USER_SIZE, FALSE); + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_ERASE, 20); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 70); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_VERIFY, 9); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 1); /* flag */ + if (!mst_ensure_device_address(self, I2C_ADDR_ISP, error)) return FALSE; /* erase old image */ g_debug("erase old image from %#x", base_addr); - fu_device_set_status(device, FWUPD_STATUS_DEVICE_ERASE); for (guint32 offset = 0; offset < FLASH_USER_SIZE; offset += FLASH_BLOCK_SIZE) { - fu_device_set_progress_full(device, offset, FLASH_USER_SIZE); if (!flash_iface_erase_block(self, base_addr + offset, error)) return FALSE; + fu_progress_set_percentage_full(fu_progress_get_child(progress), + offset + FLASH_BLOCK_SIZE, + FLASH_USER_SIZE); } + fu_progress_step_done(progress); /* write new image */ g_debug("write new image to %#x", base_addr); - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); - if (!flash_iface_write(self, base_addr, firmware_bytes, error)) + if (!flash_iface_write(self, + base_addr, + firmware_bytes, + fu_progress_get_child(progress), + error)) return FALSE; + fu_progress_step_done(progress); - fu_device_set_status(device, FWUPD_STATUS_DEVICE_VERIFY); - if (!flash_iface_read(self, base_addr, readback_buf, FLASH_USER_SIZE, error)) + /* verify */ + if (!flash_iface_read(self, + base_addr, + readback_buf, + FLASH_USER_SIZE, + fu_progress_get_child(progress), + error)) return FALSE; if (memcmp(g_bytes_get_data(firmware_bytes, NULL), readback_buf, FLASH_USER_SIZE) != 0) { g_set_error(error, @@ -787,22 +810,27 @@ fu_realtek_mst_device_write_firmware(FuDevice *device, "flash contents after write do not match firmware image"); return FALSE; } + fu_progress_step_done(progress); /* Erase old flag and write new one. The MST appears to modify the * flag value once booted, so we always write the same value here and * it picks up what we've updated. */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_ERASE); if (!flash_iface_erase_sector(self, flag_addr & ~(FLASH_SECTOR_SIZE - 1), error)) return FALSE; - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); - return flash_iface_write(self, - flag_addr, - g_bytes_new_static(flag_data, sizeof(flag_data)), - error); + if (!flash_iface_write(self, + flag_addr, + g_bytes_new_static(flag_data, sizeof(flag_data)), + fu_progress_get_child(progress), + error)) + return FALSE; + fu_progress_step_done(progress); + + /* success */ + return TRUE; } static FuFirmware * -fu_realtek_mst_device_read_firmware(FuDevice *device, GError **error) +fu_realtek_mst_device_read_firmware(FuDevice *device, FuProgress *progress, GError **error) { FuRealtekMstDevice *self = FU_REALTEK_MST_DEVICE(device); guint32 bank_address; @@ -824,30 +852,30 @@ fu_realtek_mst_device_read_firmware(FuDevice *device, GError **error) image_bytes = g_malloc0(FLASH_USER_SIZE); if (!mst_ensure_device_address(self, I2C_ADDR_ISP, error)) return NULL; - if (!flash_iface_read(self, bank_address, image_bytes, FLASH_USER_SIZE, error)) + if (!flash_iface_read(self, bank_address, image_bytes, FLASH_USER_SIZE, progress, error)) return NULL; return fu_firmware_new_from_bytes( g_bytes_new_take(g_steal_pointer(&image_bytes), FLASH_USER_SIZE)); } static GBytes * -fu_realtek_mst_device_dump_firmware(FuDevice *device, GError **error) +fu_realtek_mst_device_dump_firmware(FuDevice *device, FuProgress *progress, GError **error) { FuRealtekMstDevice *self = FU_REALTEK_MST_DEVICE(device); g_autofree guint8 *flash_contents = g_malloc0(FLASH_SIZE); if (!mst_ensure_device_address(self, I2C_ADDR_ISP, error)) return NULL; - fu_device_set_status(device, FWUPD_STATUS_DEVICE_READ); - if (!flash_iface_read(self, 0, flash_contents, FLASH_SIZE, error)) + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_READ); + if (!flash_iface_read(self, 0, flash_contents, FLASH_SIZE, progress, error)) return NULL; - fu_device_set_status(device, FWUPD_STATUS_IDLE); + fu_progress_set_status(progress, FWUPD_STATUS_IDLE); return g_bytes_new_take(g_steal_pointer(&flash_contents), FLASH_SIZE); } static gboolean -fu_realtek_mst_device_attach(FuDevice *device, GError **error) +fu_realtek_mst_device_attach(FuDevice *device, FuProgress *progress, GError **error) { FuRealtekMstDevice *self = FU_REALTEK_MST_DEVICE(device); guint8 value; @@ -865,7 +893,6 @@ fu_realtek_mst_device_attach(FuDevice *device, GError **error) g_autoptr(GError) error_local = NULL; g_debug("resetting device to exit ISP mode"); - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); /* Set register EE bit 2 to request reset. This write can fail * spuriously, so we ignore the write result and verify the device is @@ -895,10 +922,20 @@ fu_realtek_mst_device_attach(FuDevice *device, GError **error) } fu_device_remove_flag(device, FWUPD_DEVICE_FLAG_IS_BOOTLOADER); - fu_device_set_status(device, FWUPD_STATUS_IDLE); return TRUE; } +static void +fu_realtek_mst_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 94); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* reload */ +} + static void fu_realtek_mst_device_init(FuRealtekMstDevice *self) { @@ -942,4 +979,5 @@ fu_realtek_mst_device_class_init(FuRealtekMstDeviceClass *klass) klass_device->read_firmware = fu_realtek_mst_device_read_firmware; /* dump whole flash */ klass_device->dump_firmware = fu_realtek_mst_device_dump_firmware; + klass_device->set_progress = fu_realtek_mst_device_set_progress; } diff --git a/plugins/redfish/fu-redfish-device.c b/plugins/redfish/fu-redfish-device.c index d9456eec1..d0499a6dc 100644 --- a/plugins/redfish/fu-redfish-device.c +++ b/plugins/redfish/fu-redfish-device.c @@ -515,6 +515,7 @@ typedef struct { gchar *location; gboolean completed; GHashTable *messages_seen; + FuProgress *progress; } FuRedfishDevicePollCtx; static void @@ -560,43 +561,43 @@ fu_redfish_device_poll_set_message_id(FuRedfishDevice *self, /* set status */ if (g_strcmp0(message_id, "Update.1.1.TargetDetermined") == 0) { - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_LOADING); + fu_progress_set_status(ctx->progress, FWUPD_STATUS_LOADING); return; } if (g_strcmp0(message_id, "LenovoFirmwareUpdateRegistry.1.0.UpdateAssignment") == 0) { - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_LOADING); + fu_progress_set_status(ctx->progress, FWUPD_STATUS_LOADING); return; } if (g_strcmp0(message_id, "LenovoFirmwareUpdateRegistry.1.0.PayloadApplyInProgress") == 0) { - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_DEVICE_WRITE); + fu_progress_set_status(ctx->progress, FWUPD_STATUS_DEVICE_WRITE); return; } if (g_strcmp0(message_id, "LenovoFirmwareUpdateRegistry.1.0.PayloadApplyCompleted") == 0) { - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_IDLE); + fu_progress_set_status(ctx->progress, FWUPD_STATUS_IDLE); return; } if (g_strcmp0(message_id, "LenovoFirmwareUpdateRegistry.1.0.UpdateVerifyInProgress") == 0) { - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_DEVICE_VERIFY); + fu_progress_set_status(ctx->progress, FWUPD_STATUS_DEVICE_VERIFY); return; } if (g_strcmp0(message_id, "Update.1.1.TransferringToComponent") == 0) { - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_LOADING); + fu_progress_set_status(ctx->progress, FWUPD_STATUS_LOADING); return; } if (g_strcmp0(message_id, "Update.1.1.VerifyingAtComponent") == 0) { - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_DEVICE_VERIFY); + fu_progress_set_status(ctx->progress, FWUPD_STATUS_DEVICE_VERIFY); return; } if (g_strcmp0(message_id, "Update.1.1.UpdateInProgress") == 0) { - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_DEVICE_WRITE); + fu_progress_set_status(ctx->progress, FWUPD_STATUS_DEVICE_WRITE); return; } if (g_strcmp0(message_id, "Update.1.1.UpdateSuccessful") == 0) { - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_IDLE); + fu_progress_set_status(ctx->progress, FWUPD_STATUS_IDLE); return; } if (g_strcmp0(message_id, "Update.1.1.InstallingOnComponent") == 0) { - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_DEVICE_WRITE); + fu_progress_set_status(ctx->progress, FWUPD_STATUS_DEVICE_WRITE); return; } } @@ -622,7 +623,7 @@ fu_redfish_device_poll_task_once(FuRedfishDevice *self, FuRedfishDevicePollCtx * if (json_object_has_member(json_obj, "PercentComplete")) { gint64 pc = json_object_get_int_member(json_obj, "PercentComplete"); if (pc >= 0 && pc <= 100) - fu_device_set_progress(FU_DEVICE(self), (guint)pc); + fu_progress_set_percentage(ctx->progress, (guint)pc); } /* print all messages we've not seen yet */ @@ -685,12 +686,13 @@ fu_redfish_device_poll_task_once(FuRedfishDevice *self, FuRedfishDevicePollCtx * } static FuRedfishDevicePollCtx * -fu_redfish_device_poll_ctx_new(const gchar *location) +fu_redfish_device_poll_ctx_new(FuProgress *progress, const gchar *location) { FuRedfishDevicePollCtx *ctx = g_new0(FuRedfishDevicePollCtx, 1); ctx->messages_seen = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); ctx->location = g_strdup(location); ctx->error_code = FWUPD_ERROR_INTERNAL; + ctx->progress = g_object_ref(progress); return ctx; } @@ -698,6 +700,7 @@ static void fu_redfish_device_poll_ctx_free(FuRedfishDevicePollCtx *ctx) { g_hash_table_unref(ctx->messages_seen); + g_object_unref(ctx->progress); g_free(ctx->location); g_free(ctx); } @@ -708,11 +711,14 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(FuRedfishDevicePollCtx, fu_redfish_device_poll_ctx #pragma clang diagnostic pop gboolean -fu_redfish_device_poll_task(FuRedfishDevice *self, const gchar *location, GError **error) +fu_redfish_device_poll_task(FuRedfishDevice *self, + const gchar *location, + FuProgress *progress, + GError **error) { const guint timeout = 2400; g_autoptr(GTimer) timer = g_timer_new(); - g_autoptr(FuRedfishDevicePollCtx) ctx = fu_redfish_device_poll_ctx_new(location); + g_autoptr(FuRedfishDevicePollCtx) ctx = fu_redfish_device_poll_ctx_new(progress, location); /* sleep and then reprobe hardware */ do { diff --git a/plugins/redfish/fu-redfish-device.h b/plugins/redfish/fu-redfish-device.h index f49ca3839..c2cc68db6 100644 --- a/plugins/redfish/fu-redfish-device.h +++ b/plugins/redfish/fu-redfish-device.h @@ -45,4 +45,7 @@ struct _FuRedfishDeviceClass { FuRedfishBackend * fu_redfish_device_get_backend(FuRedfishDevice *self); gboolean -fu_redfish_device_poll_task(FuRedfishDevice *self, const gchar *location, GError **error); +fu_redfish_device_poll_task(FuRedfishDevice *self, + const gchar *location, + FuProgress *progress, + GError **error); diff --git a/plugins/redfish/fu-redfish-legacy-device.c b/plugins/redfish/fu-redfish-legacy-device.c index 65e43aee2..19eea55ab 100644 --- a/plugins/redfish/fu-redfish-legacy-device.c +++ b/plugins/redfish/fu-redfish-legacy-device.c @@ -18,7 +18,7 @@ struct _FuRedfishLegacyDevice { G_DEFINE_TYPE(FuRedfishLegacyDevice, fu_redfish_legacy_device, FU_TYPE_REDFISH_DEVICE) static gboolean -fu_redfish_legacy_device_detach(FuDevice *dev, GError **error) +fu_redfish_legacy_device_detach(FuDevice *dev, FuProgress *progress, GError **error) { FuRedfishLegacyDevice *self = FU_REDFISH_LEGACY_DEVICE(dev); FuRedfishBackend *backend = fu_redfish_device_get_backend(FU_REDFISH_DEVICE(self)); @@ -44,7 +44,7 @@ fu_redfish_legacy_device_detach(FuDevice *dev, GError **error) } static gboolean -fu_redfish_legacy_device_attach(FuDevice *dev, GError **error) +fu_redfish_legacy_device_attach(FuDevice *dev, FuProgress *progress, GError **error) { FuRedfishLegacyDevice *self = FU_REDFISH_LEGACY_DEVICE(dev); FuRedfishBackend *backend = fu_redfish_device_get_backend(FU_REDFISH_DEVICE(self)); @@ -71,6 +71,7 @@ fu_redfish_legacy_device_attach(FuDevice *dev, GError **error) static gboolean fu_redfish_legacy_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -93,7 +94,7 @@ fu_redfish_legacy_device_write_firmware(FuDevice *device, curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST"); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, g_bytes_get_data(fw, NULL)); curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)g_bytes_get_size(fw)); - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_DEVICE_WRITE); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_WRITE); if (!fu_redfish_request_perform(request, fu_redfish_backend_get_push_uri_path(backend), FU_REDFISH_REQUEST_PERFORM_FLAG_LOAD_JSON, @@ -111,7 +112,17 @@ fu_redfish_legacy_device_write_firmware(FuDevice *device, return FALSE; } location = json_object_get_string_member(json_obj, "@odata.id"); - return fu_redfish_device_poll_task(FU_REDFISH_DEVICE(self), location, error); + return fu_redfish_device_poll_task(FU_REDFISH_DEVICE(self), location, progress, error); +} + +static void +fu_redfish_legacy_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 1); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 98); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 1); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 0); /* reload */ } static void @@ -127,4 +138,5 @@ fu_redfish_legacy_device_class_init(FuRedfishLegacyDeviceClass *klass) klass_device->attach = fu_redfish_legacy_device_attach; klass_device->detach = fu_redfish_legacy_device_detach; klass_device->write_firmware = fu_redfish_legacy_device_write_firmware; + klass_device->set_progress = fu_redfish_legacy_device_set_progress; } diff --git a/plugins/redfish/fu-redfish-multipart-device.c b/plugins/redfish/fu-redfish-multipart-device.c index c2dd4fb3a..80049acb9 100644 --- a/plugins/redfish/fu-redfish-multipart-device.c +++ b/plugins/redfish/fu-redfish-multipart-device.c @@ -51,6 +51,7 @@ fu_redfish_multipart_device_get_parameters(FuRedfishMultipartDevice *self) static gboolean fu_redfish_multipart_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -94,7 +95,7 @@ fu_redfish_multipart_device_write_firmware(FuDevice *device, curl_mime_filedata(part, filename); curl_mime_data(part, g_bytes_get_data(fw, NULL), g_bytes_get_size(fw)); - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_DEVICE_WRITE); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_WRITE); if (!fu_redfish_request_perform(request, fu_redfish_backend_get_push_uri_path(backend), FU_REDFISH_REQUEST_PERFORM_FLAG_LOAD_JSON, @@ -127,7 +128,17 @@ fu_redfish_multipart_device_write_firmware(FuDevice *device, return FALSE; } location = json_object_get_string_member(json_obj, "@odata.id"); - return fu_redfish_device_poll_task(FU_REDFISH_DEVICE(self), location, error); + return fu_redfish_device_poll_task(FU_REDFISH_DEVICE(self), location, progress, error); +} + +static void +fu_redfish_multipart_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 100); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 0); /* reload */ } static void @@ -141,4 +152,5 @@ fu_redfish_multipart_device_class_init(FuRedfishMultipartDeviceClass *klass) { FuDeviceClass *klass_device = FU_DEVICE_CLASS(klass); klass_device->write_firmware = fu_redfish_multipart_device_write_firmware; + klass_device->set_progress = fu_redfish_multipart_device_set_progress; } diff --git a/plugins/redfish/fu-self-test.c b/plugins/redfish/fu-self-test.c index 665e7f660..bb5d82247 100644 --- a/plugins/redfish/fu-self-test.c +++ b/plugins/redfish/fu-self-test.c @@ -296,6 +296,7 @@ fu_test_redfish_update_func(gconstpointer user_data) gboolean ret; g_autoptr(GError) error = NULL; g_autoptr(GBytes) blob_fw = NULL; + g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC); devices = fu_plugin_get_devices(self->plugin); g_assert_nonnull(devices); @@ -311,6 +312,7 @@ fu_test_redfish_update_func(gconstpointer user_data) ret = fu_plugin_runner_write_firmware(self->plugin, dev, blob_fw, + progress, FWUPD_INSTALL_FLAG_NONE, &error); g_assert_no_error(error); @@ -321,6 +323,7 @@ fu_test_redfish_update_func(gconstpointer user_data) ret = fu_plugin_runner_write_firmware(self->plugin, dev, blob_fw, + progress, FWUPD_INSTALL_FLAG_NONE, &error); g_assert_error(error, FWUPD_ERROR, FWUPD_ERROR_WRITE); diff --git a/plugins/rts54hid/fu-rts54hid-device.c b/plugins/rts54hid/fu-rts54hid-device.c index 3a196b0cb..a53354238 100644 --- a/plugins/rts54hid/fu-rts54hid-device.c +++ b/plugins/rts54hid/fu-rts54hid-device.c @@ -126,7 +126,7 @@ fu_rts54hid_device_write_flash(FuRts54HidDevice *self, } static gboolean -fu_rts54hid_device_verify_update_fw(FuRts54HidDevice *self, GError **error) +fu_rts54hid_device_verify_update_fw(FuRts54HidDevice *self, FuProgress *progress, GError **error) { const FuRts54HidCmdBuffer cmd_buffer = { .cmd = FU_RTS54HID_CMD_WRITE_DATA, @@ -150,7 +150,7 @@ fu_rts54hid_device_verify_update_fw(FuRts54HidDevice *self, GError **error) FU_HID_DEVICE_FLAG_NONE, error)) return FALSE; - fu_device_sleep_with_progress(FU_DEVICE(self), 4); /* seconds */ + fu_progress_sleep(progress, 4000); if (!fu_hid_device_get_report(FU_HID_DEVICE(self), 0x0, buf, @@ -285,6 +285,7 @@ fu_rts54hid_device_close(FuDevice *device, GError **error) static gboolean fu_rts54hid_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -292,6 +293,13 @@ fu_rts54hid_device_write_firmware(FuDevice *device, g_autoptr(GBytes) fw = NULL; g_autoptr(GPtrArray) chunks = NULL; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_ERASE, 1); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 46); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_VERIFY, 52); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 1); /* reset */ + /* get default image */ fw = fu_firmware_get_bytes(firmware, error); if (fw == NULL) @@ -302,18 +310,15 @@ fu_rts54hid_device_write_firmware(FuDevice *device, return FALSE; /* erase spare flash bank only if it is not empty */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_ERASE); if (!fu_rts54hid_device_erase_spare_bank(self, error)) return FALSE; + fu_progress_step_done(progress); - /* build packets */ + /* write each block */ chunks = fu_chunk_array_new_from_bytes(fw, 0x00, /* start addr */ 0x00, /* page_sz */ FU_RTS54HID_TRANSFER_BLOCK_SIZE); - - /* write each block */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); for (guint i = 0; i < chunks->len; i++) { FuChunk *chk = g_ptr_array_index(chunks, i); /* write chunk */ @@ -325,21 +330,37 @@ fu_rts54hid_device_write_firmware(FuDevice *device, return FALSE; /* update progress */ - fu_device_set_progress_full(device, (gsize)i, (gsize)chunks->len * 2); + fu_progress_set_percentage_full(fu_progress_get_child(progress), + (gsize)i + 1, + (gsize)chunks->len); } + fu_progress_step_done(progress); /* get device to authenticate the firmware */ - if (!fu_rts54hid_device_verify_update_fw(self, error)) + if (!fu_rts54hid_device_verify_update_fw(self, fu_progress_get_child(progress), error)) return FALSE; + fu_progress_step_done(progress); /* send software reset to run available flash code */ if (!fu_rts54hid_device_reset_to_flash(self, error)) return FALSE; + fu_progress_step_done(progress); /* success! */ return TRUE; } +static void +fu_rts54hid_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 62); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 38); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 0); /* reload */ +} + static void fu_rts54hid_device_init(FuRts54HidDevice *self) { @@ -355,4 +376,5 @@ fu_rts54hid_device_class_init(FuRts54HidDeviceClass *klass) klass_device->to_string = fu_rts54hid_device_to_string; klass_device->setup = fu_rts54hid_device_setup; klass_device->close = fu_rts54hid_device_close; + klass_device->set_progress = fu_rts54hid_device_set_progress; } diff --git a/plugins/rts54hid/fu-rts54hid-module.c b/plugins/rts54hid/fu-rts54hid-module.c index 23b3e8e00..f31f645f7 100644 --- a/plugins/rts54hid/fu-rts54hid-module.c +++ b/plugins/rts54hid/fu-rts54hid-module.c @@ -209,6 +209,7 @@ fu_rts54hid_module_set_quirk_kv(FuDevice *device, static gboolean fu_rts54hid_module_write_firmware(FuDevice *module, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -235,7 +236,7 @@ fu_rts54hid_module_write_firmware(FuDevice *module, } /* write each block */ - fu_device_set_status(module, FWUPD_STATUS_DEVICE_WRITE); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_WRITE); for (guint i = 0; i < chunks->len; i++) { FuChunk *chk = g_ptr_array_index(chunks, i); @@ -247,7 +248,7 @@ fu_rts54hid_module_write_firmware(FuDevice *module, return FALSE; /* update progress */ - fu_device_set_progress_full(module, (gsize)i, (gsize)chunks->len * 2); + fu_progress_set_percentage_full(progress, (gsize)i + 1, (gsize)chunks->len); } /* success! */ diff --git a/plugins/rts54hub/fu-rts54hub-device.c b/plugins/rts54hub/fu-rts54hub-device.c index c0d27f47a..5606f01d5 100644 --- a/plugins/rts54hub/fu-rts54hub-device.c +++ b/plugins/rts54hub/fu-rts54hub-device.c @@ -427,6 +427,7 @@ fu_rts54hub_device_close(FuDevice *device, GError **error) static gboolean fu_rts54hub_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -434,6 +435,13 @@ fu_rts54hub_device_write_firmware(FuDevice *device, g_autoptr(GBytes) fw = NULL; g_autoptr(GPtrArray) chunks = NULL; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_ERASE, 1); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 46); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_VERIFY, 52); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 1); + /* get default image */ fw = fu_firmware_get_bytes(firmware, error); if (fw == NULL) @@ -449,9 +457,9 @@ fu_rts54hub_device_write_firmware(FuDevice *device, } /* erase spare flash bank only if it is not empty */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_ERASE); if (!fu_rts54hub_device_erase_flash(self, 1, error)) return FALSE; + fu_progress_step_done(progress); /* set MCU clock to high clock mode */ if (!fu_rts54hub_device_highclockmode(self, 0x0001, error)) { @@ -465,14 +473,11 @@ fu_rts54hub_device_write_firmware(FuDevice *device, return FALSE; } - /* build packets */ + /* write each block */ chunks = fu_chunk_array_new_from_bytes(fw, 0x00, /* start addr */ 0x00, /* page_sz */ FU_RTS54HUB_DEVICE_BLOCK_SIZE); - - /* write each block */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); for (guint i = 0; i < chunks->len; i++) { FuChunk *chk = g_ptr_array_index(chunks, i); @@ -485,18 +490,21 @@ fu_rts54hub_device_write_firmware(FuDevice *device, return FALSE; /* update progress */ - fu_device_set_progress_full(device, (gsize)i, (gsize)chunks->len - 1); + fu_progress_set_percentage_full(fu_progress_get_child(progress), + (gsize)i + 1, + (gsize)chunks->len); } + fu_progress_step_done(progress); /* get device to authenticate the firmware */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_VERIFY); if (!fu_rts54hub_device_flash_authentication(self, error)) return FALSE; + fu_progress_step_done(progress); /* send software reset to run available flash code */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); if (!fu_rts54hub_device_reset_flash(self, error)) return FALSE; + fu_progress_step_done(progress); /* don't reset the vendor command enable, the device will be rebooted */ self->vendor_cmd = FU_RTS54HUB_VENDOR_CMD_NONE; @@ -528,6 +536,16 @@ fu_rts54hub_device_prepare_firmware(FuDevice *device, return fu_firmware_new_from_bytes(fw); } +static void +fu_rts54hub_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 62); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 38); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 0); /* reload */ +} + static void fu_rts54hub_device_init(FuRts54HubDevice *self) { @@ -544,4 +562,5 @@ fu_rts54hub_device_class_init(FuRts54HubDeviceClass *klass) klass_device->to_string = fu_rts54hub_device_to_string; klass_device->prepare_firmware = fu_rts54hub_device_prepare_firmware; klass_device->close = fu_rts54hub_device_close; + klass_device->set_progress = fu_rts54hub_device_set_progress; } diff --git a/plugins/rts54hub/fu-rts54hub-rtd21xx-background.c b/plugins/rts54hub/fu-rts54hub-rtd21xx-background.c index 553a776e8..46c3edaf0 100644 --- a/plugins/rts54hub/fu-rts54hub-rtd21xx-background.c +++ b/plugins/rts54hub/fu-rts54hub-rtd21xx-background.c @@ -114,7 +114,7 @@ fu_rts54hub_rtd21xx_background_detach_cb(FuDevice *device, gpointer user_data, G } static gboolean -fu_rts54hub_rtd21xx_background_detach(FuDevice *device, GError **error) +fu_rts54hub_rtd21xx_background_detach(FuDevice *device, FuProgress *progress, GError **error) { FuRts54HubDevice *parent = FU_RTS54HUB_DEVICE(fu_device_get_parent(device)); g_autoptr(FuDeviceLocker) locker = NULL; @@ -127,7 +127,7 @@ fu_rts54hub_rtd21xx_background_detach(FuDevice *device, GError **error) } static gboolean -fu_rts54hub_rtd21xx_background_attach(FuDevice *device, GError **error) +fu_rts54hub_rtd21xx_background_attach(FuDevice *device, FuProgress *progress, GError **error) { FuRts54HubDevice *parent = FU_RTS54HUB_DEVICE(fu_device_get_parent(device)); FuRts54hubRtd21xxDevice *self = FU_RTS54HUB_RTD21XX_DEVICE(device); @@ -147,7 +147,7 @@ fu_rts54hub_rtd21xx_background_attach(FuDevice *device, GError **error) g_prefix_error(error, "failed to attach: "); return FALSE; } - fu_device_sleep_with_progress(device, 1); + fu_progress_sleep(progress, 1000); /* success */ fu_device_remove_flag(device, FWUPD_DEVICE_FLAG_IS_BOOTLOADER); @@ -190,6 +190,7 @@ fu_rts54hub_rtd21xx_background_reload(FuDevice *device, GError **error) static gboolean fu_rts54hub_rtd21xx_background_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -204,6 +205,13 @@ fu_rts54hub_rtd21xx_background_write_firmware(FuDevice *device, g_autoptr(GBytes) fw = NULL; g_autoptr(GPtrArray) chunks = NULL; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 5); /* setup */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 90); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 5); /* exit */ + /* open device */ locker = fu_device_locker_new(self, error); if (locker == NULL) @@ -217,7 +225,6 @@ fu_rts54hub_rtd21xx_background_write_firmware(FuDevice *device, /* get project ID address */ write_buf[0] = ISP_CMD_GET_PROJECT_ID_ADDR; - fu_device_set_status(device, FWUPD_STATUS_DEVICE_READ); if (!fu_rts54hub_rtd21xx_device_i2c_write(FU_RTS54HUB_RTD21XX_DEVICE(self), UC_ISP_SLAVE_ADDR, UC_BACKGROUND_OPCODE, @@ -263,7 +270,6 @@ fu_rts54hub_rtd21xx_background_write_firmware(FuDevice *device, g_prefix_error(error, "failed to write project ID from 0x%04x: ", project_addr); return FALSE; } - fu_device_set_status(device, FWUPD_STATUS_DEVICE_BUSY); if (!fu_rts54hub_rtd21xx_device_i2c_write(FU_RTS54HUB_RTD21XX_DEVICE(self), UC_ISP_SLAVE_ADDR, UC_BACKGROUND_OPCODE, @@ -288,9 +294,9 @@ fu_rts54hub_rtd21xx_background_write_firmware(FuDevice *device, g_prefix_error(error, "failed to send fw update start cmd: "); return FALSE; } + fu_progress_step_done(progress); /* send data */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); chunks = fu_chunk_array_new_from_bytes(fw, 0x00, /* start addr */ 0x00, /* page_sz */ @@ -314,11 +320,13 @@ fu_rts54hub_rtd21xx_background_write_firmware(FuDevice *device, } /* update progress */ - fu_device_set_progress_full(device, (gsize)i, (gsize)chunks->len); + fu_progress_set_percentage_full(fu_progress_get_child(progress), + (gsize)i + 1, + (gsize)chunks->len); } + fu_progress_step_done(progress); /* update finish command */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_BUSY); if (!fu_rts54hub_rtd21xx_device_read_status(FU_RTS54HUB_RTD21XX_DEVICE(self), NULL, error)) return FALSE; write_buf[0] = ISP_CMD_FW_UPDATE_ISP_DONE; @@ -333,10 +341,9 @@ fu_rts54hub_rtd21xx_background_write_firmware(FuDevice *device, } /* exit fw mode */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); - fu_device_set_progress(device, 0); if (!fu_rts54hub_rtd21xx_device_read_status(FU_RTS54HUB_RTD21XX_DEVICE(self), NULL, error)) return FALSE; + fu_progress_step_done(progress); /* success */ return TRUE; diff --git a/plugins/rts54hub/fu-rts54hub-rtd21xx-foreground.c b/plugins/rts54hub/fu-rts54hub-rtd21xx-foreground.c index e4dbc3123..2a6677454 100644 --- a/plugins/rts54hub/fu-rts54hub-rtd21xx-foreground.c +++ b/plugins/rts54hub/fu-rts54hub-rtd21xx-foreground.c @@ -113,7 +113,7 @@ fu_rts54hub_rtd21xx_foreground_detach_cb(FuDevice *device, gpointer user_data, G } static gboolean -fu_rts54hub_rtd21xx_foreground_detach(FuDevice *device, GError **error) +fu_rts54hub_rtd21xx_foreground_detach(FuDevice *device, FuProgress *progress, GError **error) { FuRts54HubDevice *parent = FU_RTS54HUB_DEVICE(fu_device_get_parent(device)); g_autoptr(FuDeviceLocker) locker = NULL; @@ -126,7 +126,7 @@ fu_rts54hub_rtd21xx_foreground_detach(FuDevice *device, GError **error) } static gboolean -fu_rts54hub_rtd21xx_foreground_attach(FuDevice *device, GError **error) +fu_rts54hub_rtd21xx_foreground_attach(FuDevice *device, FuProgress *progress, GError **error) { FuRts54HubDevice *parent = FU_RTS54HUB_DEVICE(fu_device_get_parent(device)); FuRts54hubRtd21xxForeground *self = FU_RTS54HUB_RTD21XX_FOREGROUND(device); @@ -139,8 +139,6 @@ fu_rts54hub_rtd21xx_foreground_attach(FuDevice *device, GError **error) return FALSE; /* exit fw mode */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); - fu_device_set_progress(device, 0); if (!fu_rts54hub_rtd21xx_device_read_status(FU_RTS54HUB_RTD21XX_DEVICE(self), NULL, error)) return FALSE; if (!fu_rts54hub_rtd21xx_device_i2c_write(FU_RTS54HUB_RTD21XX_DEVICE(self), @@ -155,7 +153,7 @@ fu_rts54hub_rtd21xx_foreground_attach(FuDevice *device, GError **error) /* the device needs some time to restart with the new firmware before * it can be queried again */ - fu_device_sleep_with_progress(device, 60); + fu_progress_sleep(progress, 60000); /* success */ return TRUE; @@ -224,6 +222,7 @@ fu_rts54hub_rtd21xx_foreground_reload(FuDevice *device, GError **error) static gboolean fu_rts54hub_rtd21xx_foreground_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -238,6 +237,13 @@ fu_rts54hub_rtd21xx_foreground_write_firmware(FuDevice *device, g_autoptr(GBytes) fw = NULL; g_autoptr(GPtrArray) chunks = NULL; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 5); /* setup */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 90); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 5); /* finish */ + /* open device */ locker = fu_device_locker_new(self, error); if (locker == NULL) @@ -252,7 +258,6 @@ fu_rts54hub_rtd21xx_foreground_write_firmware(FuDevice *device, /* enable ISP high priority */ write_buf[0] = ISP_CMD_ENTER_FW_UPDATE; write_buf[1] = 0x01; - fu_device_set_status(device, FWUPD_STATUS_DEVICE_BUSY); if (!fu_rts54hub_rtd21xx_device_i2c_write(FU_RTS54HUB_RTD21XX_DEVICE(self), UC_ISP_SLAVE_ADDR, UC_FOREGROUND_OPCODE, @@ -267,7 +272,6 @@ fu_rts54hub_rtd21xx_foreground_write_firmware(FuDevice *device, /* get project ID address */ write_buf[0] = ISP_CMD_GET_PROJECT_ID_ADDR; - fu_device_set_status(device, FWUPD_STATUS_DEVICE_READ); if (!fu_rts54hub_rtd21xx_device_i2c_write(FU_RTS54HUB_RTD21XX_DEVICE(self), UC_ISP_SLAVE_ADDR, UC_FOREGROUND_OPCODE, @@ -313,7 +317,6 @@ fu_rts54hub_rtd21xx_foreground_write_firmware(FuDevice *device, g_prefix_error(error, "failed to write project ID from 0x%04x: ", project_addr); return FALSE; } - fu_device_set_status(device, FWUPD_STATUS_DEVICE_BUSY); if (!fu_rts54hub_rtd21xx_device_i2c_write(FU_RTS54HUB_RTD21XX_DEVICE(self), UC_ISP_SLAVE_ADDR, UC_FOREGROUND_OPCODE, @@ -338,9 +341,9 @@ fu_rts54hub_rtd21xx_foreground_write_firmware(FuDevice *device, g_prefix_error(error, "failed to send fw update start cmd: "); return FALSE; } + fu_progress_step_done(progress); /* send data */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); chunks = fu_chunk_array_new_from_bytes(fw, 0x00, /* start addr */ 0x00, /* page_sz */ @@ -364,11 +367,13 @@ fu_rts54hub_rtd21xx_foreground_write_firmware(FuDevice *device, } /* update progress */ - fu_device_set_progress_full(device, (gsize)i, (gsize)chunks->len); + fu_progress_set_percentage_full(fu_progress_get_child(progress), + (gsize)i + 1, + (gsize)chunks->len); } + fu_progress_step_done(progress); /* update finish command */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_BUSY); if (!fu_rts54hub_rtd21xx_device_read_status(FU_RTS54HUB_RTD21XX_DEVICE(self), NULL, error)) return FALSE; write_buf[0] = ISP_CMD_FW_UPDATE_ISP_DONE; @@ -381,6 +386,7 @@ fu_rts54hub_rtd21xx_foreground_write_firmware(FuDevice *device, g_prefix_error(error, "failed update finish cmd: "); return FALSE; } + fu_progress_step_done(progress); /* success */ return TRUE; diff --git a/plugins/solokey/fu-solokey-device.c b/plugins/solokey/fu-solokey-device.c index 95b62d9d2..f51336634 100644 --- a/plugins/solokey/fu-solokey-device.c +++ b/plugins/solokey/fu-solokey-device.c @@ -423,7 +423,6 @@ fu_solokey_device_verify(FuSolokeyDevice *self, GBytes *fw_sig, GError **error) g_autoptr(GByteArray) res = NULL; g_autoptr(GByteArray) sig = g_byte_array_new(); - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_DEVICE_VERIFY); fu_byte_array_append_bytes(sig, fw_sig); fu_solokey_device_exchange(req, SOLO_BOOTLOADER_DONE, 0x00, sig); res = fu_solokey_device_packet(self, SOLO_BOOTLOADER_HID_CMD_BOOT, req, error); @@ -447,6 +446,7 @@ fu_solokey_device_prepare_firmware(FuDevice *device, static gboolean fu_solokey_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -455,6 +455,12 @@ fu_solokey_device_write_firmware(FuDevice *device, g_autoptr(GBytes) fw_sig = NULL; g_autoptr(GPtrArray) chunks = NULL; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 90); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_VERIFY, 10); + /* build packets */ fw = fu_firmware_get_bytes(firmware, error); if (fw == NULL) @@ -465,7 +471,6 @@ fu_solokey_device_write_firmware(FuDevice *device, 2048); /* write each block */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); for (guint i = 0; i < chunks->len; i++) { FuChunk *chk = g_ptr_array_index(chunks, i); g_autoptr(GByteArray) buf = g_byte_array_new(); @@ -490,14 +495,33 @@ fu_solokey_device_write_firmware(FuDevice *device, } /* update progress */ - fu_device_set_progress_full(device, (gsize)i, (gsize)chunks->len); + fu_progress_set_percentage_full(fu_progress_get_child(progress), + (gsize)i + 1, + (gsize)chunks->len); } + fu_progress_step_done(progress); /* verify the signature and reboot back to runtime */ fw_sig = fu_firmware_get_image_by_id_bytes(firmware, FU_FIRMWARE_ID_SIGNATURE, error); if (fw_sig == NULL) return FALSE; - return fu_solokey_device_verify(self, fw_sig, error); + if (!fu_solokey_device_verify(self, fw_sig, error)) + return FALSE; + fu_progress_step_done(progress); + + /* success */ + return TRUE; +} + +static void +fu_solokey_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 98); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* reload */ } static void @@ -522,4 +546,5 @@ fu_solokey_device_class_init(FuSolokeyDeviceClass *klass) klass_device->setup = fu_solokey_device_setup; klass_device->open = fu_solokey_device_open; klass_device->close = fu_solokey_device_close; + klass_device->set_progress = fu_solokey_device_set_progress; } diff --git a/plugins/superio/fu-superio-device.c b/plugins/superio/fu-superio-device.c index d7277de79..880b3d51a 100644 --- a/plugins/superio/fu-superio-device.c +++ b/plugins/superio/fu-superio-device.c @@ -472,6 +472,17 @@ fu_superio_device_set_quirk_kv(FuDevice *device, return FALSE; } +static void +fu_superio_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 98); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* reload */ +} + static void fu_superio_device_init(FuSuperioDevice *self) { @@ -517,4 +528,5 @@ fu_superio_device_class_init(FuSuperioDeviceClass *klass) klass_device->probe = fu_superio_device_probe; klass_device->setup = fu_superio_device_setup; klass_device->prepare_firmware = fu_superio_device_prepare_firmware; + klass_device->set_progress = fu_superio_device_set_progress; } diff --git a/plugins/superio/fu-superio-it55-device.c b/plugins/superio/fu-superio-it55-device.c index 0c0e88730..90f5c8b5e 100644 --- a/plugins/superio/fu-superio-it55-device.c +++ b/plugins/superio/fu-superio-it55-device.c @@ -174,13 +174,6 @@ fu_superio_it55_device_setup(FuDevice *device, GError **error) return TRUE; } -static void -fu_superio_it55_device_progress_cb(goffset current, goffset total, gpointer user_data) -{ - FuDevice *device = FU_DEVICE(user_data); - fu_device_set_progress_full(device, (gsize)current, (gsize)total); -} - static GBytes * fu_plugin_superio_patch_autoload(FuDevice *device, GBytes *fw, GError **error) { @@ -234,9 +227,7 @@ fu_plugin_superio_patch_autoload(FuDevice *device, GBytes *fw, GError **error) /* progress callback is optional to not affect device progress during writing * firmware */ static GBytes * -fu_superio_it55_device_get_firmware(FuDevice *device, - GFileProgressCallback progress_cb, - GError **error) +fu_superio_it55_device_get_firmware(FuDevice *device, FuProgress *progress, GError **error) { FuSuperioDevice *self = FU_SUPERIO_DEVICE(device); guint64 fwsize = fu_device_get_firmware_size_min(device); @@ -254,8 +245,7 @@ fu_superio_it55_device_get_firmware(FuDevice *device, if (!fu_superio_device_ec_read_data(self, &buf[offset], error)) return NULL; - if (progress_cb != NULL) - progress_cb(offset, (goffset)fwsize, self); + fu_progress_set_percentage_full(progress, (gsize)i + 1, (gsize)block_count); } } @@ -263,7 +253,7 @@ fu_superio_it55_device_get_firmware(FuDevice *device, } static GBytes * -fu_superio_it55_device_dump_firmware(FuDevice *device, GError **error) +fu_superio_it55_device_dump_firmware(FuDevice *device, FuProgress *progress, GError **error) { g_autoptr(FuDeviceLocker) locker = NULL; @@ -275,14 +265,12 @@ fu_superio_it55_device_dump_firmware(FuDevice *device, GError **error) if (locker == NULL) return NULL; - fu_device_set_status(device, FWUPD_STATUS_DEVICE_READ); - return fu_superio_it55_device_get_firmware(device, - fu_superio_it55_device_progress_cb, - error); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_READ); + return fu_superio_it55_device_get_firmware(device, progress, error); } static gboolean -fu_superio_it55_device_attach(FuDevice *device, GError **error) +fu_superio_it55_device_attach(FuDevice *device, FuProgress *progress, GError **error) { FuSuperioDevice *self = FU_SUPERIO_DEVICE(device); @@ -299,7 +287,7 @@ fu_superio_it55_device_attach(FuDevice *device, GError **error) } static gboolean -fu_superio_it55_device_detach(FuDevice *device, GError **error) +fu_superio_it55_device_detach(FuDevice *device, FuProgress *progress, GError **error) { FuSuperioDevice *self = FU_SUPERIO_DEVICE(device); @@ -338,20 +326,30 @@ fu_superio_it55_device_erase(FuDevice *device, GError **error) } static gboolean -fu_superio_it55_device_write_attempt(FuDevice *device, GBytes *firmware, GError **error) +fu_superio_it55_device_write_attempt(FuDevice *device, + GBytes *firmware, + FuProgress *progress, + GError **error) { FuSuperioDevice *self = FU_SUPERIO_DEVICE(device); - gsize fwsize = g_bytes_get_size(firmware); - guint64 total = (fwsize + CHUNK_SIZE - 1) / CHUNK_SIZE; const guint8 *fw_data = NULL; g_autoptr(GBytes) erased_fw = NULL; g_autoptr(GBytes) written_fw = NULL; g_autoptr(GPtrArray) blocks = NULL; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_ERASE, 10); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 80); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 1); /* block 0 */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_VERIFY, 9); + if (!fu_superio_it55_device_erase(device, error)) return FALSE; - erased_fw = fu_superio_it55_device_get_firmware(device, NULL, error); + erased_fw = + fu_superio_it55_device_get_firmware(device, fu_progress_get_child(progress), error); if (erased_fw == NULL) { g_prefix_error(error, "failed to read erased firmware"); return FALSE; @@ -363,6 +361,7 @@ fu_superio_it55_device_write_attempt(FuDevice *device, GBytes *firmware, GError "firmware was not erased"); return FALSE; } + fu_progress_step_done(progress); /* write everything but the first kilobyte */ blocks = fu_chunk_array_new_from_bytes(firmware, 0x00, 0x00, BLOCK_SIZE); @@ -381,12 +380,9 @@ fu_superio_it55_device_write_attempt(FuDevice *device, GBytes *firmware, GError return FALSE; for (guint j = 0; j < CHUNKS_IN_BLOCK; ++j) { - gsize progress = i * CHUNKS_IN_BLOCK + j; - if (first && j < CHUNKS_IN_KBYTE) { offset += CHUNK_SIZE; bytes_left -= CHUNK_SIZE; - fu_device_set_progress_full(device, progress, (gsize)total); continue; } @@ -403,10 +399,12 @@ fu_superio_it55_device_write_attempt(FuDevice *device, GBytes *firmware, GError ++offset; --bytes_left; } - - fu_device_set_progress_full(device, progress, (gsize)total); } + fu_progress_set_percentage_full(fu_progress_get_child(progress), + (gsize)i + 1, + (gsize)blocks->len); } + fu_progress_step_done(progress); /* now write the first kilobyte */ if (!fu_superio_device_ec_write_cmd(self, SIO_CMD_EC_WRITE_1ST_KBYTE, error)) @@ -415,27 +413,30 @@ fu_superio_it55_device_write_attempt(FuDevice *device, GBytes *firmware, GError for (guint i = 0; i < CHUNK_SIZE * CHUNKS_IN_KBYTE; ++i) if (!fu_superio_device_ec_write_data(self, fw_data[i], error)) return FALSE; + fu_progress_step_done(progress); g_usleep(1000); - written_fw = fu_superio_it55_device_get_firmware(device, NULL, error); + written_fw = + fu_superio_it55_device_get_firmware(device, fu_progress_get_child(progress), error); if (written_fw == NULL) { - g_prefix_error(error, "failed to read erased firmware"); + g_prefix_error(error, "failed to read firmware"); return FALSE; } if (!fu_common_bytes_compare(written_fw, firmware, error)) { g_prefix_error(error, "firmware verification"); return FALSE; } + fu_progress_step_done(progress); /* success */ - fu_device_set_progress(device, 100); return TRUE; } static gboolean fu_superio_it55_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -444,6 +445,11 @@ fu_superio_it55_device_write_firmware(FuDevice *device, g_autoptr(GBytes) fw_patched = NULL; g_autoptr(FuDeviceLocker) locker = NULL; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 10); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 90); + /* require detach -> attach */ locker = fu_device_locker_new_full(device, (FuDeviceLockerFunc)fu_device_detach, @@ -466,14 +472,16 @@ fu_superio_it55_device_write_firmware(FuDevice *device, fw_patched = fu_plugin_superio_patch_autoload(device, fw, error); if (fw_patched == NULL) return FALSE; - - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); + fu_progress_step_done(progress); /* try this many times; the failure-to-flash case leaves you without a * keyboard and future boot may completely fail */ for (guint i = 1;; ++i) { g_autoptr(GError) error_chk = NULL; - if (fu_superio_it55_device_write_attempt(device, fw_patched, &error_chk)) + if (fu_superio_it55_device_write_attempt(device, + fw_patched, + fu_progress_get_child(progress), + &error_chk)) break; if (i == MAX_FLASHING_ATTEMPTS) { @@ -483,6 +491,7 @@ fu_superio_it55_device_write_firmware(FuDevice *device, g_warning("failure %u: %s", i, error_chk->message); } + fu_progress_step_done(progress); /* success */ return TRUE; diff --git a/plugins/superio/fu-superio-it89-device.c b/plugins/superio/fu-superio-it89-device.c index e6701d352..4793676f2 100644 --- a/plugins/superio/fu-superio-it89-device.c +++ b/plugins/superio/fu-superio-it89-device.c @@ -223,7 +223,7 @@ static GBytes * fu_superio_it89_device_read_addr(FuSuperioDevice *self, guint32 addr, guint size, - GFileProgressCallback progress_cb, + FuProgress *progress, GError **error) { g_autofree guint8 *buf = NULL; @@ -261,8 +261,7 @@ fu_superio_it89_device_read_addr(FuSuperioDevice *self, return NULL; /* update progress */ - if (progress_cb != NULL) - progress_cb((goffset)i, (goffset)size, self); + fu_progress_set_percentage_full(progress, (goffset)i, (goffset)size); } /* check again... */ @@ -273,13 +272,6 @@ fu_superio_it89_device_read_addr(FuSuperioDevice *self, return g_bytes_new_take(g_steal_pointer(&buf), size); } -static void -fu_superio_it89_device_progress_cb(goffset current, goffset total, gpointer user_data) -{ - FuDevice *device = FU_DEVICE(user_data); - fu_device_set_progress_full(device, (gsize)current, (gsize)total); -} - static gboolean fu_superio_it89_device_write_addr(FuSuperioDevice *self, guint addr, GBytes *fw, GError **error) { @@ -409,7 +401,7 @@ fu_plugin_superio_fix_signature(FuSuperioDevice *self, GBytes *fw, GError **erro } static GBytes * -fu_superio_it89_device_dump_firmware(FuDevice *device, GError **error) +fu_superio_it89_device_dump_firmware(FuDevice *device, FuProgress *progress, GError **error) { FuSuperioDevice *self = FU_SUPERIO_DEVICE(device); guint64 fwsize = fu_device_get_firmware_size_min(device); @@ -423,28 +415,24 @@ fu_superio_it89_device_dump_firmware(FuDevice *device, GError **error) if (locker == NULL) return NULL; - fu_device_set_status(device, FWUPD_STATUS_DEVICE_READ); - return fu_superio_it89_device_read_addr(self, - 0x0, - fwsize, - fu_superio_it89_device_progress_cb, - error); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_READ); + return fu_superio_it89_device_read_addr(self, 0x0, fwsize, progress, error); } static FuFirmware * -fu_superio_it89_device_read_firmware(FuDevice *device, GError **error) +fu_superio_it89_device_read_firmware(FuDevice *device, FuProgress *progress, GError **error) { FuSuperioDevice *self = FU_SUPERIO_DEVICE(device); g_autoptr(GBytes) blob = NULL; g_autoptr(GBytes) fw = NULL; - blob = fu_superio_it89_device_dump_firmware(device, error); + blob = fu_superio_it89_device_dump_firmware(device, progress, error); fw = fu_plugin_superio_fix_signature(self, blob, error); return fu_firmware_new_from_bytes(fw); } static gboolean -fu_superio_it89_device_attach(FuDevice *device, GError **error) +fu_superio_it89_device_attach(FuDevice *device, FuProgress *progress, GError **error) { FuSuperioDevice *self = FU_SUPERIO_DEVICE(device); @@ -458,7 +446,7 @@ fu_superio_it89_device_attach(FuDevice *device, GError **error) } static gboolean -fu_superio_it89_device_detach(FuDevice *device, GError **error) +fu_superio_it89_device_detach(FuDevice *device, FuProgress *progress, GError **error) { FuSuperioDevice *self = FU_SUPERIO_DEVICE(device); guint8 tmp = 0x00; @@ -483,14 +471,14 @@ fu_superio_it89_device_detach(FuDevice *device, GError **error) } static gboolean -fu_superio_it89_device_check_eflash(FuSuperioDevice *self, GError **error) +fu_superio_it89_device_check_eflash(FuSuperioDevice *self, FuProgress *progress, GError **error) { g_autoptr(GBytes) fw = NULL; const guint64 fwsize = fu_device_get_firmware_size_min(FU_DEVICE(self)); const guint sigsz = 16; /* last 16 bytes of eeprom */ - fw = fu_superio_it89_device_read_addr(self, fwsize - sigsz, sigsz, NULL, error); + fw = fu_superio_it89_device_read_addr(self, fwsize - sigsz, sigsz, progress, error); if (fw == NULL) { g_prefix_error(error, "failed to read signature bytes: "); return FALSE; @@ -518,12 +506,22 @@ fu_superio_it89_device_check_eflash(FuSuperioDevice *self, GError **error) } static gboolean -fu_superio_it89_device_write_chunk(FuSuperioDevice *self, FuChunk *chk, GError **error) +fu_superio_it89_device_write_chunk(FuSuperioDevice *self, + FuChunk *chk, + FuProgress *progress, + GError **error) { g_autoptr(GBytes) fw1 = NULL; g_autoptr(GBytes) fw2 = NULL; g_autoptr(GBytes) fw3 = NULL; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_ERASE, 1); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_ERASE, 21); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 59); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_VERIFY, 20); + /* erase page */ if (!fu_superio_it89_device_erase_addr(self, fu_chunk_get_address(chk), error)) { g_prefix_error(error, @@ -531,12 +529,13 @@ fu_superio_it89_device_write_chunk(FuSuperioDevice *self, FuChunk *chk, GError * (guint)fu_chunk_get_address(chk)); return FALSE; } + fu_progress_step_done(progress); /* check erased */ fw1 = fu_superio_it89_device_read_addr(self, fu_chunk_get_address(chk), fu_chunk_get_data_sz(chk), - NULL, + fu_progress_get_child(progress), error); if (fw1 == NULL) { g_prefix_error(error, @@ -548,11 +547,14 @@ fu_superio_it89_device_write_chunk(FuSuperioDevice *self, FuChunk *chk, GError * g_set_error_literal(error, FWUPD_ERROR, FWUPD_ERROR_READ, "sector was not erased"); return FALSE; } + fu_progress_step_done(progress); /* skip empty page */ fw2 = g_bytes_new_static(fu_chunk_get_data(chk), fu_chunk_get_data_sz(chk)); - if (fu_common_bytes_is_empty(fw2)) + if (fu_common_bytes_is_empty(fw2)) { + fu_progress_finished(progress); return TRUE; + } /* write page */ if (!fu_superio_it89_device_write_addr(self, fu_chunk_get_address(chk), fw2, error)) { @@ -561,12 +563,13 @@ fu_superio_it89_device_write_chunk(FuSuperioDevice *self, FuChunk *chk, GError * (guint)fu_chunk_get_address(chk)); return FALSE; } + fu_progress_step_done(progress); /* verify page */ fw3 = fu_superio_it89_device_read_addr(self, fu_chunk_get_address(chk), fu_chunk_get_data_sz(chk), - NULL, + fu_progress_get_child(progress), error); if (fw3 == NULL) { g_prefix_error(error, @@ -581,6 +584,7 @@ fu_superio_it89_device_write_chunk(FuSuperioDevice *self, FuChunk *chk, GError * (guint)fu_chunk_get_address(chk)); return FALSE; } + fu_progress_step_done(progress); /* success */ return TRUE; @@ -609,9 +613,47 @@ fu_superio_it89_device_get_jedec_id(FuSuperioDevice *self, guint8 *id, GError ** return fu_superio_device_ec_write_cmd(self, SIO_EC_PMC_PM1DISCI, error); } +static gboolean +fu_superio_it89_device_write_chunks(FuSuperioDevice *self, + GPtrArray *chunks, + FuProgress *progress, + GError **error) +{ + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_set_steps(progress, chunks->len - 1); + for (guint i = 0; i < chunks->len - 1; i++) { + FuChunk *chk = g_ptr_array_index(chunks, i); + + /* try this many times; the failure-to-flash case leaves you + * without a keyboard and future boot may completely fail */ + for (guint j = 0;; j++) { + g_autoptr(GError) error_chk = NULL; + if (fu_superio_it89_device_write_chunk(self, + chk, + fu_progress_get_child(progress), + &error_chk)) + break; + if (j > 5) { + g_propagate_error(error, g_steal_pointer(&error_chk)); + return FALSE; + } + g_warning("failure %u: %s", j, error_chk->message); + fu_progress_reset(fu_progress_get_child(progress)); + } + + /* set progress */ + fu_progress_step_done(progress); + } + + /* success */ + return TRUE; +} + static gboolean fu_superio_it89_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -621,6 +663,12 @@ fu_superio_it89_device_write_firmware(FuDevice *device, g_autoptr(GBytes) fw = NULL; g_autoptr(GPtrArray) chunks = NULL; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 5); /* check e-flash */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 95); + /* check JEDEC ID */ if (!fu_superio_it89_device_get_jedec_id(self, id, error)) { g_prefix_error(error, "failed to get JEDEC ID: "); @@ -639,8 +687,9 @@ fu_superio_it89_device_write_firmware(FuDevice *device, } /* check eflash is writable */ - if (!fu_superio_it89_device_check_eflash(self, error)) + if (!fu_superio_it89_device_check_eflash(self, fu_progress_get_child(progress), error)) return FALSE; + fu_progress_step_done(progress); /* get default image */ fw = fu_firmware_get_bytes(firmware, error); @@ -658,29 +707,14 @@ fu_superio_it89_device_write_firmware(FuDevice *device, /* chunks of 1kB, skipping the final chunk */ chunks = fu_chunk_array_new_from_bytes(fw_fixed, 0x00, 0x00, 0x400); - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); - for (guint i = 0; i < chunks->len - 1; i++) { - FuChunk *chk = g_ptr_array_index(chunks, i); - - /* try this many times; the failure-to-flash case leaves you - * without a keyboard and future boot may completely fail */ - for (guint j = 0;; j++) { - g_autoptr(GError) error_chk = NULL; - if (fu_superio_it89_device_write_chunk(self, chk, &error_chk)) - break; - if (j > 5) { - g_propagate_error(error, g_steal_pointer(&error_chk)); - return FALSE; - } - g_warning("failure %u: %s", j, error_chk->message); - } - - /* set progress */ - fu_device_set_progress_full(device, (gsize)i, (gsize)chunks->len); - } + if (!fu_superio_it89_device_write_chunks(self, + chunks, + fu_progress_get_child(progress), + error)) + return FALSE; + fu_progress_step_done(progress); /* success */ - fu_device_set_progress(device, 100); return TRUE; } diff --git a/plugins/synaptics-cxaudio/fu-synaptics-cxaudio-device.c b/plugins/synaptics-cxaudio/fu-synaptics-cxaudio-device.c index 0a843af06..7f04c4d56 100644 --- a/plugins/synaptics-cxaudio/fu-synaptics-cxaudio-device.c +++ b/plugins/synaptics-cxaudio/fu-synaptics-cxaudio-device.c @@ -612,6 +612,7 @@ fu_synaptics_cxaudio_device_prepare_firmware(FuDevice *device, static gboolean fu_synaptics_cxaudio_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -619,6 +620,14 @@ fu_synaptics_cxaudio_device_write_firmware(FuDevice *device, GPtrArray *records = fu_srec_firmware_get_records(FU_SREC_FIRMWARE(firmware)); FuSynapticsCxaudioFileKind file_kind; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 3); /* park */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 1); /* init */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 94); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 1); /* invalidate */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 1); /* unpark */ + /* check if a patch file fits completely into the EEPROM */ for (guint i = 0; i < records->len; i++) { FuSrecFirmwareRecord *rcd = g_ptr_array_index(records, i); @@ -645,6 +654,7 @@ fu_synaptics_cxaudio_device_write_firmware(FuDevice *device, error)) return FALSE; g_usleep(10 * 1000); + fu_progress_step_done(progress); /* initialize layout signature and version to 0 if transitioning from * EEPROM layout version 1 => 0 */ @@ -681,9 +691,9 @@ fu_synaptics_cxaudio_device_write_firmware(FuDevice *device, } g_debug("initialized layout signature"); } + fu_progress_step_done(progress); /* perform the actual write */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); for (guint i = 0; i < records->len; i++) { FuSrecFirmwareRecord *rcd = g_ptr_array_index(records, i); if (rcd->kind != FU_FIRMWARE_SREC_RECORD_KIND_S3_DATA_32) @@ -704,8 +714,11 @@ fu_synaptics_cxaudio_device_write_firmware(FuDevice *device, rcd->buf->len); return FALSE; } - fu_device_set_progress_full(device, (gsize)i, (gsize)records->len); + fu_progress_set_percentage_full(fu_progress_get_child(progress), + (gsize)i + 1, + (gsize)records->len); } + fu_progress_step_done(progress); /* in case of a full FW upgrade invalidate the old FW patch (if any) * as it may have not been done by the S37 file */ @@ -740,6 +753,7 @@ fu_synaptics_cxaudio_device_write_firmware(FuDevice *device, g_debug("invalidated old FW patch for CX2070x (RAM) device"); } } + fu_progress_step_done(progress); /* unpark the FW */ if (!fu_synaptics_cxaudio_device_register_clear_bit( @@ -748,13 +762,14 @@ fu_synaptics_cxaudio_device_write_firmware(FuDevice *device, 7, error)) return FALSE; + fu_progress_step_done(progress); /* success */ return TRUE; } static gboolean -fu_synaptics_cxaudio_device_attach(FuDevice *device, GError **error) +fu_synaptics_cxaudio_device_attach(FuDevice *device, FuProgress *progress, GError **error) { FuSynapticsCxaudioDevice *self = FU_SYNAPTICS_CXAUDIO_DEVICE(device); guint8 tmp = 1 << 6; @@ -765,7 +780,6 @@ fu_synaptics_cxaudio_device_attach(FuDevice *device, GError **error) return TRUE; /* wait for re-enumeration */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG); /* this fails on success */ @@ -816,6 +830,17 @@ fu_synaptics_cxaudio_device_set_quirk_kv(FuDevice *device, return FALSE; } +static void +fu_synaptics_cxaudio_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 94); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* reload */ +} + static void fu_synaptics_cxaudio_device_init(FuSynapticsCxaudioDevice *self) { @@ -839,4 +864,5 @@ fu_synaptics_cxaudio_device_class_init(FuSynapticsCxaudioDeviceClass *klass) klass_device->write_firmware = fu_synaptics_cxaudio_device_write_firmware; klass_device->attach = fu_synaptics_cxaudio_device_attach; klass_device->prepare_firmware = fu_synaptics_cxaudio_device_prepare_firmware; + klass_device->set_progress = fu_synaptics_cxaudio_device_set_progress; } diff --git a/plugins/synaptics-mst/fu-plugin-synaptics-mst.c b/plugins/synaptics-mst/fu-plugin-synaptics-mst.c index 1f34e61c1..296c605e0 100644 --- a/plugins/synaptics-mst/fu-plugin-synaptics-mst.c +++ b/plugins/synaptics-mst/fu-plugin-synaptics-mst.c @@ -119,13 +119,14 @@ gboolean fu_plugin_write_firmware(FuPlugin *plugin, FuDevice *device, GBytes *blob_fw, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { g_autoptr(FuDeviceLocker) locker = fu_device_locker_new(device, error); if (locker == NULL) return FALSE; - if (!fu_device_write_firmware(device, blob_fw, flags, error)) + if (!fu_device_write_firmware(device, blob_fw, progress, flags, error)) return FALSE; if (!fu_device_has_flag(device, FWUPD_DEVICE_FLAG_SKIPS_RESTART)) fu_plugin_device_remove(plugin, device); diff --git a/plugins/synaptics-mst/fu-synaptics-mst-device.c b/plugins/synaptics-mst/fu-synaptics-mst-device.c index 33bd36376..ca3c41fa4 100644 --- a/plugins/synaptics-mst/fu-synaptics-mst-device.c +++ b/plugins/synaptics-mst/fu-synaptics-mst-device.c @@ -295,6 +295,7 @@ fu_synaptics_mst_device_set_flash_sector_erase(FuSynapticsMstDevice *self, static gboolean fu_synaptics_mst_device_update_esm(FuSynapticsMstDevice *self, const guint8 *payload_data, + FuProgress *progress, GError **error) { guint32 checksum = 0; @@ -360,9 +361,9 @@ fu_synaptics_mst_device_update_esm(FuSynapticsMstDevice *self, } write_offset += unit_sz; write_idx += unit_sz; - fu_device_set_progress_full(FU_DEVICE(self), - (goffset)i * 100, - (goffset)(write_loops - 1) * 100); + fu_progress_set_percentage_full(progress, + (goffset)i + 1, + (goffset)write_loops); } /* check ESM checksum */ @@ -404,6 +405,7 @@ static gboolean fu_synaptics_mst_device_update_tesla_leaf_firmware(FuSynapticsMstDevice *self, guint32 payload_len, const guint8 *payload_data, + FuProgress *progress, GError **error) { g_autoptr(FuSynapticsMstConnection) connection = NULL; @@ -460,9 +462,9 @@ fu_synaptics_mst_device_update_tesla_leaf_firmware(FuSynapticsMstDevice *self, } offset += length; data_to_write -= length; - fu_device_set_progress_full(FU_DEVICE(self), - (goffset)i * 100, - (goffset)(write_loops - 1) * 100); + fu_progress_set_percentage_full(progress, + (goffset)i + 1, + (goffset)write_loops); } /* check data just written */ @@ -526,6 +528,7 @@ static gboolean fu_synaptics_mst_device_update_panamera_firmware(FuSynapticsMstDevice *self, guint32 payload_len, const guint8 *payload_data, + FuProgress *progress, GError **error) { guint16 crc_tmp = 0; @@ -613,9 +616,9 @@ fu_synaptics_mst_device_update_panamera_firmware(FuSynapticsMstDevice *self, write_offset += unit_sz; write_idx += unit_sz; - fu_device_set_progress_full(FU_DEVICE(self), - (goffset)i * 100, - (goffset)(write_loops - 1) * 100); + fu_progress_set_percentage_full(progress, + (goffset)i + 1, + (goffset)write_loops); } /* verify CRC */ @@ -853,6 +856,7 @@ static gboolean fu_synaptics_mst_device_update_cayenne_firmware(FuSynapticsMstDevice *self, guint32 payload_len, const guint8 *payload_data, + FuProgress *progress, GError **error) { g_autoptr(FuSynapticsMstConnection) connection = NULL; @@ -910,9 +914,9 @@ fu_synaptics_mst_device_update_cayenne_firmware(FuSynapticsMstDevice *self, } offset += length; data_to_write -= length; - fu_device_set_progress_full(FU_DEVICE(self), - (goffset)i * 100, - (goffset)(write_loops - 1) * 100); + fu_progress_set_percentage_full(progress, + (goffset)i * 100, + (goffset)(write_loops - 1) * 100); } /* verify CRC */ @@ -1031,6 +1035,7 @@ fu_synaptics_mst_device_prepare_firmware(FuDevice *device, static gboolean fu_synaptics_mst_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -1040,13 +1045,18 @@ fu_synaptics_mst_device_write_firmware(FuDevice *device, gsize payload_len; g_autoptr(FuDeviceLocker) locker = NULL; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 90); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 10); + fw = fu_firmware_get_bytes(firmware, error); if (fw == NULL) return FALSE; payload_data = g_bytes_get_data(fw, &payload_len); /* enable remote control and disable on exit */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); if (!fu_device_has_flag(device, FWUPD_DEVICE_FLAG_SKIPS_RESTART)) { locker = fu_device_locker_new_full(self, @@ -1072,6 +1082,7 @@ fu_synaptics_mst_device_write_firmware(FuDevice *device, if (!fu_synaptics_mst_device_update_tesla_leaf_firmware(self, payload_len, payload_data, + progress, error)) { g_prefix_error(error, "Firmware update failed: "); return FALSE; @@ -1082,13 +1093,14 @@ fu_synaptics_mst_device_write_firmware(FuDevice *device, g_prefix_error(error, "Failed to prepare for write: "); return FALSE; } - if (!fu_synaptics_mst_device_update_esm(self, payload_data, error)) { + if (!fu_synaptics_mst_device_update_esm(self, payload_data, progress, error)) { g_prefix_error(error, "ESM update failed: "); return FALSE; } if (!fu_synaptics_mst_device_update_panamera_firmware(self, payload_len, payload_data, + progress, error)) { g_prefix_error(error, "Firmware update failed: "); return FALSE; @@ -1099,6 +1111,7 @@ fu_synaptics_mst_device_write_firmware(FuDevice *device, if (!fu_synaptics_mst_device_update_cayenne_firmware(self, payload_len, payload_data, + progress, error)) { g_prefix_error(error, "Firmware update failed: "); return FALSE; @@ -1111,10 +1124,11 @@ fu_synaptics_mst_device_write_firmware(FuDevice *device, "Unsupported chip family"); return FALSE; } + fu_progress_step_done(progress); /* wait for flash clear to settle */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); - fu_device_sleep_with_progress(device, 2); + fu_progress_sleep(fu_progress_get_child(progress), 2000); + fu_progress_step_done(progress); return TRUE; } @@ -1465,6 +1479,17 @@ fu_synaptics_mst_device_set_quirk_kv(FuDevice *device, return FALSE; } +static void +fu_synaptics_mst_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 98); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* reload */ +} + static void fu_synaptics_mst_device_class_init(FuSynapticsMstDeviceClass *klass) { @@ -1477,4 +1502,5 @@ fu_synaptics_mst_device_class_init(FuSynapticsMstDeviceClass *klass) klass_device->write_firmware = fu_synaptics_mst_device_write_firmware; klass_device->prepare_firmware = fu_synaptics_mst_device_prepare_firmware; klass_device->probe = fu_synaptics_mst_device_probe; + klass_device->set_progress = fu_synaptics_mst_device_set_progress; } diff --git a/plugins/synaptics-prometheus/fu-synaprom-config.c b/plugins/synaptics-prometheus/fu-synaprom-config.c index beeb49639..60edc399c 100644 --- a/plugins/synaptics-prometheus/fu-synaprom-config.c +++ b/plugins/synaptics-prometheus/fu-synaprom-config.c @@ -76,6 +76,7 @@ fu_synaprom_config_setup(FuDevice *device, GError **error) g_autofree gchar *version = NULL; g_autoptr(GByteArray) reply = NULL; g_autoptr(GByteArray) request = NULL; + g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC); g_autofree gchar *devid = NULL; /* get IOTA */ @@ -84,7 +85,12 @@ fu_synaprom_config_setup(FuDevice *device, GError **error) request = fu_synaprom_request_new(FU_SYNAPROM_CMD_IOTA_FIND, &cmd, sizeof(cmd)); reply = fu_synaprom_reply_new(sizeof(FuSynapromReplyIotaFindHdr) + FU_SYNAPROM_MAX_IOTA_READ_SIZE); - if (!fu_synaprom_device_cmd_send(FU_SYNAPROM_DEVICE(parent), request, reply, 5000, error)) + if (!fu_synaprom_device_cmd_send(FU_SYNAPROM_DEVICE(parent), + request, + reply, + progress, + 5000, + error)) return FALSE; if (reply->len < sizeof(hdr) + sizeof(cfg)) { g_set_error(error, @@ -213,6 +219,7 @@ fu_synaprom_config_prepare_firmware(FuDevice *device, static gboolean fu_synaprom_config_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -225,7 +232,7 @@ fu_synaprom_config_write_firmware(FuDevice *device, return FALSE; /* I assume the CFG/MFW difference is detected in the device...*/ - return fu_synaprom_device_write_fw(FU_SYNAPROM_DEVICE(parent), fw, error); + return fu_synaprom_device_write_fw(FU_SYNAPROM_DEVICE(parent), fw, progress, error); } static void @@ -259,17 +266,17 @@ fu_synaprom_config_constructed(GObject *obj) } static gboolean -fu_synaprom_config_attach(FuDevice *device, GError **error) +fu_synaprom_config_attach(FuDevice *device, FuProgress *progress, GError **error) { FuDevice *parent = fu_device_get_parent(device); - return fu_device_attach(parent, error); + return fu_device_attach(parent, progress, error); } static gboolean -fu_synaprom_config_detach(FuDevice *device, GError **error) +fu_synaprom_config_detach(FuDevice *device, FuProgress *progress, GError **error) { FuDevice *parent = fu_device_get_parent(device); - return fu_device_detach(parent, error); + return fu_device_detach(parent, progress, error); } static void diff --git a/plugins/synaptics-prometheus/fu-synaprom-device.c b/plugins/synaptics-prometheus/fu-synaprom-device.c index c97581b72..ac7534ded 100644 --- a/plugins/synaptics-prometheus/fu-synaprom-device.c +++ b/plugins/synaptics-prometheus/fu-synaprom-device.c @@ -85,6 +85,7 @@ gboolean fu_synaprom_device_cmd_send(FuSynapromDevice *device, GByteArray *request, GByteArray *reply, + FuProgress *progress, guint timeout_ms, GError **error) { @@ -92,6 +93,12 @@ fu_synaprom_device_cmd_send(FuSynapromDevice *device, gboolean ret; gsize actual_len = 0; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_NO_PROFILE); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 25); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_VERIFY, 75); + if (g_getenv("FWUPD_SYNAPROM_VERBOSE") != NULL) { fu_common_dump_full(G_LOG_DOMAIN, "REQST", @@ -121,6 +128,7 @@ fu_synaprom_device_cmd_send(FuSynapromDevice *device, request->len); return FALSE; } + fu_progress_step_done(progress); ret = g_usb_device_bulk_transfer(usb_device, FU_SYNAPROM_USB_REPLY_EP, @@ -142,6 +150,7 @@ fu_synaprom_device_cmd_send(FuSynapromDevice *device, 16, FU_DUMP_FLAGS_SHOW_ADDRESSES); } + fu_progress_step_done(progress); /* parse as FuSynapromReplyGeneric */ if (reply->len >= sizeof(FuSynapromReplyGeneric)) { @@ -195,6 +204,7 @@ fu_synaprom_device_setup(FuDevice *device, GError **error) guint64 serial_number = 0; g_autoptr(GByteArray) request = NULL; g_autoptr(GByteArray) reply = NULL; + g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC); /* FuUsbDevice->setup */ if (!FU_DEVICE_CLASS(fu_synaprom_device_parent_class)->setup(device, error)) @@ -203,7 +213,7 @@ fu_synaprom_device_setup(FuDevice *device, GError **error) /* get version */ request = fu_synaprom_request_new(FU_SYNAPROM_CMD_GET_VERSION, NULL, 0); reply = fu_synaprom_reply_new(sizeof(FuSynapromReplyGetVersion)); - if (!fu_synaprom_device_cmd_send(self, request, reply, 250, error)) { + if (!fu_synaprom_device_cmd_send(self, request, reply, progress, 250, error)) { g_prefix_error(error, "failed to get version: "); return FALSE; } @@ -248,18 +258,6 @@ fu_synaprom_device_setup(FuDevice *device, GError **error) return TRUE; } -static gboolean -fu_synaprom_device_cmd_download_chunk(FuSynapromDevice *device, - const GByteArray *chunk, - GError **error) -{ - g_autoptr(GByteArray) request = NULL; - g_autoptr(GByteArray) reply = NULL; - request = fu_synaprom_request_new(FU_SYNAPROM_CMD_BOOTLDR_PATCH, chunk->data, chunk->len); - reply = fu_synaprom_reply_new(sizeof(FuSynapromReplyGeneric)); - return fu_synaprom_device_cmd_send(device, request, reply, 20000, error); -} - FuFirmware * fu_synaprom_device_prepare_fw(FuDevice *device, GBytes *fw, FwupdInstallFlags flags, GError **error) { @@ -307,57 +305,104 @@ fu_synaprom_device_prepare_fw(FuDevice *device, GBytes *fw, FwupdInstallFlags fl return g_steal_pointer(&firmware); } +static gboolean +fu_synaprom_device_write_chunks(FuSynapromDevice *self, + GPtrArray *chunks, + FuProgress *progress, + GError **error) +{ + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_set_steps(progress, chunks->len); + for (guint i = 0; i < chunks->len; i++) { + GByteArray *chunk = g_ptr_array_index(chunks, i); + g_autoptr(GByteArray) request = NULL; + g_autoptr(GByteArray) reply = NULL; + + /* patch */ + request = + fu_synaprom_request_new(FU_SYNAPROM_CMD_BOOTLDR_PATCH, chunk->data, chunk->len); + reply = fu_synaprom_reply_new(sizeof(FuSynapromReplyGeneric)); + if (!fu_synaprom_device_cmd_send(self, + request, + reply, + fu_progress_get_child(progress), + 20000, + error)) + return FALSE; + fu_progress_step_done(progress); + } + + /* success */ + return TRUE; +} + gboolean -fu_synaprom_device_write_fw(FuSynapromDevice *self, GBytes *fw, GError **error) +fu_synaprom_device_write_fw(FuSynapromDevice *self, + GBytes *fw, + FuProgress *progress, + GError **error) { const guint8 *buf; - gsize sz = 0; + gsize bufsz = 0; + gsize offset = 0; + g_autoptr(GPtrArray) chunks = NULL; - /* write chunks */ - fu_device_set_progress(FU_DEVICE(self), 10); - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_DEVICE_WRITE); - buf = g_bytes_get_data(fw, &sz); - while (sz != 0) { - guint32 chunksz; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 1); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 99); + + /* collect chunks */ + buf = g_bytes_get_data(fw, &bufsz); + chunks = g_ptr_array_new_with_free_func((GDestroyNotify)g_byte_array_unref); + while (offset != bufsz) { + guint32 chunksz = 0; + g_autofree guint8 *chunkbuf = NULL; g_autoptr(GByteArray) chunk = g_byte_array_new(); /* get chunk size */ - if (sz < sizeof(guint32)) { - g_set_error_literal(error, - G_IO_ERROR, - G_IO_ERROR_NOT_SUPPORTED, - "No enough data for patch len"); + if (!fu_common_read_uint32_safe(buf, + bufsz, + offset, + &chunksz, + G_LITTLE_ENDIAN, + error)) return FALSE; - } - memcpy(&chunksz, buf, sizeof(guint32)); - buf += sizeof(guint32); - sz -= sizeof(guint32); - if (sz < chunksz) { - g_set_error_literal(error, - G_IO_ERROR, - G_IO_ERROR_NOT_SUPPORTED, - "No enough data for patch chunk"); - return FALSE; - } + offset += sizeof(guint32); - /* download chunk */ - g_byte_array_append(chunk, buf, chunksz); - if (!fu_synaprom_device_cmd_download_chunk(self, chunk, error)) + /* read out chunk */ + chunkbuf = g_malloc0(chunksz); + if (!fu_memcpy_safe(chunkbuf, + chunksz, + 0x0, /* dst */ + buf, + bufsz, + offset, /* src */ + chunksz, + error)) return FALSE; + offset += chunksz; - /* next chunk */ - buf += chunksz; - sz -= chunksz; + /* add chunk */ + g_byte_array_append(chunk, chunkbuf, chunksz); + g_ptr_array_add(chunks, g_steal_pointer(&chunk)); } + fu_progress_step_done(progress); + + /* write chunks */ + if (!fu_synaprom_device_write_chunks(self, chunks, fu_progress_get_child(progress), error)) + return FALSE; + fu_progress_step_done(progress); /* success! */ - fu_device_set_progress(FU_DEVICE(self), 100); return TRUE; } static gboolean fu_synaprom_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -369,11 +414,11 @@ fu_synaprom_device_write_firmware(FuDevice *device, if (fw == NULL) return FALSE; - return fu_synaprom_device_write_fw(self, fw, error); + return fu_synaprom_device_write_fw(self, fw, progress, error); } static gboolean -fu_synaprom_device_attach(FuDevice *device, GError **error) +fu_synaprom_device_attach(FuDevice *device, FuProgress *progress, GError **error) { GUsbDevice *usb_device = fu_usb_device_get_dev(FU_USB_DEVICE(device)); gboolean ret; @@ -410,7 +455,6 @@ fu_synaprom_device_attach(FuDevice *device, GError **error) (guint)sizeof(data)); return FALSE; } - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); if (!g_usb_device_reset(usb_device, error)) { g_prefix_error(error, "failed to force-reset device: "); return FALSE; @@ -420,7 +464,7 @@ fu_synaprom_device_attach(FuDevice *device, GError **error) } static gboolean -fu_synaprom_device_detach(FuDevice *device, GError **error) +fu_synaprom_device_detach(FuDevice *device, FuProgress *progress, GError **error) { GUsbDevice *usb_device = fu_usb_device_get_dev(FU_USB_DEVICE(device)); gboolean ret; @@ -457,7 +501,7 @@ fu_synaprom_device_detach(FuDevice *device, GError **error) (guint)sizeof(data)); return FALSE; } - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_RESTART); if (!g_usb_device_reset(usb_device, error)) { g_prefix_error(error, "failed to force-reset device: "); return FALSE; @@ -466,6 +510,17 @@ fu_synaprom_device_detach(FuDevice *device, GError **error) return TRUE; } +static void +fu_synaprom_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 94); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* reload */ +} + static void fu_synaprom_device_init(FuSynapromDevice *self) { @@ -492,6 +547,7 @@ fu_synaprom_device_class_init(FuSynapromDeviceClass *klass) klass_device->attach = fu_synaprom_device_attach; klass_device->detach = fu_synaprom_device_detach; klass_device->open = fu_synaprom_device_open; + klass_device->set_progress = fu_synaprom_device_set_progress; } FuSynapromDevice * diff --git a/plugins/synaptics-prometheus/fu-synaprom-device.h b/plugins/synaptics-prometheus/fu-synaprom-device.h index 54fc8abed..9f039b318 100644 --- a/plugins/synaptics-prometheus/fu-synaprom-device.h +++ b/plugins/synaptics-prometheus/fu-synaprom-device.h @@ -26,10 +26,14 @@ gboolean fu_synaprom_device_cmd_send(FuSynapromDevice *device, GByteArray *request, GByteArray *reply, + FuProgress *progress, guint timeout_ms, GError **error); gboolean -fu_synaprom_device_write_fw(FuSynapromDevice *self, GBytes *fw, GError **error); +fu_synaprom_device_write_fw(FuSynapromDevice *self, + GBytes *fw, + FuProgress *progress, + GError **error); /* for self tests */ void diff --git a/plugins/synaptics-rmi/fu-synaptics-rmi-device.c b/plugins/synaptics-rmi/fu-synaptics-rmi-device.c index 0e8d71896..e6a8c23da 100644 --- a/plugins/synaptics-rmi/fu-synaptics-rmi-device.c +++ b/plugins/synaptics-rmi/fu-synaptics-rmi-device.c @@ -819,16 +819,25 @@ fu_synaptics_rmi_device_disable_irqs(FuSynapticsRmiDevice *self, GError **error) static gboolean fu_synaptics_rmi_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { FuSynapticsRmiDevice *self = FU_SYNAPTICS_RMI_DEVICE(device); FuSynapticsRmiDevicePrivate *priv = GET_PRIVATE(self); if (priv->f34->function_version == 0x0 || priv->f34->function_version == 0x1) { - return fu_synaptics_rmi_v5_device_write_firmware(device, firmware, flags, error); + return fu_synaptics_rmi_v5_device_write_firmware(device, + firmware, + progress, + flags, + error); } if (priv->f34->function_version == 0x2) { - return fu_synaptics_rmi_v7_device_write_firmware(device, firmware, flags, error); + return fu_synaptics_rmi_v7_device_write_firmware(device, + firmware, + progress, + flags, + error); } g_set_error(error, FWUPD_ERROR, diff --git a/plugins/synaptics-rmi/fu-synaptics-rmi-hid-device.c b/plugins/synaptics-rmi/fu-synaptics-rmi-hid-device.c index 2b8218ad6..c91ce3417 100644 --- a/plugins/synaptics-rmi/fu-synaptics-rmi-hid-device.c +++ b/plugins/synaptics-rmi/fu-synaptics-rmi-hid-device.c @@ -428,7 +428,7 @@ fu_synaptics_rmi_hid_device_rebind_driver(FuSynapticsRmiDevice *self, GError **e } static gboolean -fu_synaptics_rmi_hid_device_detach(FuDevice *device, GError **error) +fu_synaptics_rmi_hid_device_detach(FuDevice *device, FuProgress *progress, GError **error) { FuSynapticsRmiDevice *self = FU_SYNAPTICS_RMI_DEVICE(device); FuSynapticsRmiFunction *f34; @@ -437,10 +437,10 @@ fu_synaptics_rmi_hid_device_detach(FuDevice *device, GError **error) if (f34 == NULL) return FALSE; if (f34->function_version == 0x0 || f34->function_version == 0x1) { - if (!fu_synaptics_rmi_v5_device_detach(device, error)) + if (!fu_synaptics_rmi_v5_device_detach(device, progress, error)) return FALSE; } else if (f34->function_version == 0x2) { - if (!fu_synaptics_rmi_v7_device_detach(device, error)) + if (!fu_synaptics_rmi_v7_device_detach(device, progress, error)) return FALSE; } else { g_set_error(error, @@ -454,7 +454,7 @@ fu_synaptics_rmi_hid_device_detach(FuDevice *device, GError **error) } static gboolean -fu_synaptics_rmi_hid_device_attach(FuDevice *device, GError **error) +fu_synaptics_rmi_hid_device_attach(FuDevice *device, FuProgress *progress, GError **error) { FuSynapticsRmiDevice *self = FU_SYNAPTICS_RMI_DEVICE(device); @@ -469,7 +469,6 @@ fu_synaptics_rmi_hid_device_attach(FuDevice *device, GError **error) return FALSE; /* rebind to rescan PDT with new firmware running */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); return fu_synaptics_rmi_hid_device_rebind_driver(self, error); } @@ -549,6 +548,17 @@ fu_synaptics_rmi_hid_device_query_status(FuSynapticsRmiDevice *rmi_device, GErro return FALSE; } +static void +fu_synaptics_rmi_hid_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 94); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* reload */ +} + static void fu_synaptics_rmi_hid_device_init(FuSynapticsRmiHidDevice *self) { @@ -567,6 +577,7 @@ fu_synaptics_rmi_hid_device_class_init(FuSynapticsRmiHidDeviceClass *klass) klass_device->probe = fu_synaptics_rmi_hid_device_probe; klass_device->open = fu_synaptics_rmi_hid_device_open; klass_device->close = fu_synaptics_rmi_hid_device_close; + klass_device->set_progress = fu_synaptics_rmi_hid_device_set_progress; klass_rmi->write = fu_synaptics_rmi_hid_device_write; klass_rmi->read = fu_synaptics_rmi_hid_device_read; klass_rmi->wait_for_attr = fu_synaptics_rmi_hid_device_wait_for_attr; diff --git a/plugins/synaptics-rmi/fu-synaptics-rmi-ps2-device.c b/plugins/synaptics-rmi/fu-synaptics-rmi-ps2-device.c index 975e661c3..39db92d70 100644 --- a/plugins/synaptics-rmi/fu-synaptics-rmi-ps2-device.c +++ b/plugins/synaptics-rmi/fu-synaptics-rmi-ps2-device.c @@ -882,7 +882,7 @@ fu_synaptics_rmi_ps2_device_close(FuDevice *device, GError **error) } static gboolean -fu_synaptics_rmi_ps2_device_detach(FuDevice *device, GError **error) +fu_synaptics_rmi_ps2_device_detach(FuDevice *device, FuProgress *progress, GError **error) { FuSynapticsRmiDevice *self = FU_SYNAPTICS_RMI_DEVICE(device); FuSynapticsRmiFunction *f34; @@ -911,10 +911,10 @@ fu_synaptics_rmi_ps2_device_detach(FuDevice *device, GError **error) if (f34 == NULL) return FALSE; if (f34->function_version == 0x0 || f34->function_version == 0x1) { - if (!fu_synaptics_rmi_v5_device_detach(device, error)) + if (!fu_synaptics_rmi_v5_device_detach(device, progress, error)) return FALSE; } else if (f34->function_version == 0x2) { - if (!fu_synaptics_rmi_v7_device_detach(device, error)) + if (!fu_synaptics_rmi_v7_device_detach(device, progress, error)) return FALSE; } else { g_set_error(error, @@ -950,7 +950,7 @@ fu_synaptics_rmi_ps2_device_setup(FuDevice *device, GError **error) } static gboolean -fu_synaptics_rmi_ps2_device_attach(FuDevice *device, GError **error) +fu_synaptics_rmi_ps2_device_attach(FuDevice *device, FuProgress *progress, GError **error) { FuSynapticsRmiDevice *rmi_device = FU_SYNAPTICS_RMI_DEVICE(device); @@ -964,8 +964,7 @@ fu_synaptics_rmi_ps2_device_attach(FuDevice *device, GError **error) fu_synaptics_rmi_device_set_iepmode(rmi_device, FALSE); /* delay after writing */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); - fu_device_sleep_with_progress(device, 2); + fu_progress_sleep(progress, 2000); /* reset device */ if (!fu_synaptics_rmi_device_enter_iep_mode(rmi_device, @@ -978,7 +977,7 @@ fu_synaptics_rmi_ps2_device_attach(FuDevice *device, GError **error) } /* delay after reset */ - fu_device_sleep_with_progress(device, 5); + fu_progress_sleep(progress, 5000); /* back to psmouse */ if (!fu_udev_device_write_sysfs(FU_UDEV_DEVICE(device), "drvctl", "psmouse", error)) { diff --git a/plugins/synaptics-rmi/fu-synaptics-rmi-v5-device.c b/plugins/synaptics-rmi/fu-synaptics-rmi-v5-device.c index 39994751c..60d713f89 100644 --- a/plugins/synaptics-rmi/fu-synaptics-rmi-v5-device.c +++ b/plugins/synaptics-rmi/fu-synaptics-rmi-v5-device.c @@ -27,7 +27,7 @@ #define RMI_F34_ERASE_WAIT_MS (5 * 1000) /* ms */ gboolean -fu_synaptics_rmi_v5_device_detach(FuDevice *device, GError **error) +fu_synaptics_rmi_v5_device_detach(FuDevice *device, FuProgress *progress, GError **error) { FuSynapticsRmiDevice *self = FU_SYNAPTICS_RMI_DEVICE(device); FuSynapticsRmiFlash *flash = fu_synaptics_rmi_device_get_flash(self); @@ -60,7 +60,6 @@ fu_synaptics_rmi_v5_device_detach(FuDevice *device, GError **error) return FALSE; } - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); g_usleep(1000 * RMI_F34_ENABLE_WAIT_MS); return TRUE; } @@ -238,6 +237,7 @@ fu_synaptics_rmi_v5_device_secure_check(FuDevice *device, gboolean fu_synaptics_rmi_v5_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -256,6 +256,14 @@ fu_synaptics_rmi_v5_device_write_firmware(FuDevice *device, g_autoptr(GPtrArray) chunks_cfg = NULL; g_autoptr(GByteArray) req_addr = g_byte_array_new(); + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 10); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_ERASE, 10); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 90); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 10); + /* we should be in bootloader mode now, but check anyway */ if (!fu_device_has_flag(device, FWUPD_DEVICE_FLAG_IS_BOOTLOADER)) { g_set_error_literal(error, @@ -331,17 +339,19 @@ fu_synaptics_rmi_v5_device_write_firmware(FuDevice *device, g_prefix_error(error, "failed to unlock again: "); return FALSE; } + fu_progress_step_done(progress); /* erase all */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_ERASE); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_ERASE); if (!fu_synaptics_rmi_v5_device_erase_all(self, error)) { g_prefix_error(error, "failed to erase all: "); return FALSE; } + fu_progress_step_done(progress); /* write initial address */ fu_byte_array_append_uint16(req_addr, 0x0, G_LITTLE_ENDIAN); - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_WRITE); if (!fu_synaptics_rmi_device_write(self, f34->data_base, req_addr, @@ -377,10 +387,11 @@ fu_synaptics_rmi_v5_device_write_firmware(FuDevice *device, fu_chunk_get_idx(chk)); return FALSE; } - fu_device_set_progress_full(device, - (gsize)i, - (gsize)chunks_bin->len + chunks_cfg->len); + fu_progress_set_percentage_full(fu_progress_get_child(progress), + (gsize)i + 1, + (gsize)chunks_bin->len); } + fu_progress_step_done(progress); /* payload signature */ if (signature_bin != NULL && fu_synaptics_rmi_device_get_sig_size(self) != 0) { @@ -410,9 +421,9 @@ fu_synaptics_rmi_v5_device_write_firmware(FuDevice *device, fu_chunk_get_idx(chk)); return FALSE; } - fu_device_set_progress_full(device, - (gsize)i, - (gsize)chunks_bin->len + chunks_cfg->len); + fu_progress_set_percentage_full(progress, + (gsize)i + 1, + (gsize)chunks_sig->len); } g_usleep(1000 * 1000); } @@ -444,10 +455,11 @@ fu_synaptics_rmi_v5_device_write_firmware(FuDevice *device, fu_chunk_get_idx(chk)); return FALSE; } - fu_device_set_progress_full(device, - (gsize)chunks_bin->len + i, - (gsize)chunks_bin->len + chunks_cfg->len); + fu_progress_set_percentage_full(fu_progress_get_child(progress), + (gsize)i + 1, + (gsize)chunks_cfg->len); } + fu_progress_step_done(progress); /* success */ return TRUE; diff --git a/plugins/synaptics-rmi/fu-synaptics-rmi-v5-device.h b/plugins/synaptics-rmi/fu-synaptics-rmi-v5-device.h index 79ac8c5e9..032b8df1a 100644 --- a/plugins/synaptics-rmi/fu-synaptics-rmi-v5-device.h +++ b/plugins/synaptics-rmi/fu-synaptics-rmi-v5-device.h @@ -11,10 +11,11 @@ #include "fu-synaptics-rmi-device.h" gboolean -fu_synaptics_rmi_v5_device_detach(FuDevice *device, GError **error); +fu_synaptics_rmi_v5_device_detach(FuDevice *device, FuProgress *progress, GError **error); gboolean fu_synaptics_rmi_v5_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error); gboolean diff --git a/plugins/synaptics-rmi/fu-synaptics-rmi-v7-device.c b/plugins/synaptics-rmi/fu-synaptics-rmi-v7-device.c index dcca77476..0f6ecd34d 100644 --- a/plugins/synaptics-rmi/fu-synaptics-rmi-v7-device.c +++ b/plugins/synaptics-rmi/fu-synaptics-rmi-v7-device.c @@ -73,7 +73,7 @@ rmi_firmware_partition_id_to_string(RmiPartitionId partition_id) } gboolean -fu_synaptics_rmi_v7_device_detach(FuDevice *device, GError **error) +fu_synaptics_rmi_v7_device_detach(FuDevice *device, FuProgress *progress, GError **error) { FuSynapticsRmiDevice *self = FU_SYNAPTICS_RMI_DEVICE(device); g_autoptr(GByteArray) enable_req = g_byte_array_new(); @@ -112,7 +112,6 @@ fu_synaptics_rmi_v7_device_detach(FuDevice *device, GError **error) return FALSE; if (!fu_synaptics_rmi_device_poll_wait(self, error)) return FALSE; - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); g_usleep(1000 * RMI_F34_ENABLE_WAIT_MS); return TRUE; } @@ -254,6 +253,7 @@ static gboolean fu_synaptics_rmi_v7_device_write_partition(FuSynapticsRmiDevice *self, RmiPartitionId partition_id, GBytes *bytes, + FuProgress *progress, GError **error) { FuSynapticsRmiFunction *f34; @@ -324,7 +324,7 @@ fu_synaptics_rmi_v7_device_write_partition(FuSynapticsRmiDevice *self, fu_chunk_get_data_sz(chk), error)) return FALSE; - fu_device_set_progress_full(FU_DEVICE(self), (gsize)i, (gsize)chunks->len); + fu_progress_set_percentage_full(progress, (gsize)i + 1, (gsize)chunks->len); } return TRUE; } @@ -332,6 +332,7 @@ fu_synaptics_rmi_v7_device_write_partition(FuSynapticsRmiDevice *self, gboolean fu_synaptics_rmi_v7_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -342,6 +343,15 @@ fu_synaptics_rmi_v7_device_write_firmware(FuDevice *device, g_autoptr(GBytes) bytes_cfg = NULL; g_autoptr(GBytes) bytes_flashcfg = NULL; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 1); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_ERASE, 10); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 20); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 20); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 20); + /* we should be in bootloader mode now, but check anyway */ if (!fu_device_has_flag(device, FWUPD_DEVICE_FLAG_IS_BOOTLOADER)) { g_set_error_literal(error, @@ -372,36 +382,43 @@ fu_synaptics_rmi_v7_device_write_firmware(FuDevice *device, /* disable powersaving */ if (!fu_synaptics_rmi_device_disable_sleep(self, error)) return FALSE; + fu_progress_step_done(progress); /* erase all */ - g_debug("erasing…"); if (!fu_synaptics_rmi_v7_device_erase_all(self, error)) { g_prefix_error(error, "failed to erase all: "); return FALSE; } + fu_progress_step_done(progress); /* write flash config for v8 */ if (bytes_flashcfg != NULL) { if (!fu_synaptics_rmi_v7_device_write_partition(self, RMI_PARTITION_ID_FLASH_CONFIG, bytes_flashcfg, + fu_progress_get_child(progress), error)) return FALSE; } + fu_progress_step_done(progress); /* write core code */ if (!fu_synaptics_rmi_v7_device_write_partition(self, RMI_PARTITION_ID_CORE_CODE, bytes_bin, + fu_progress_get_child(progress), error)) return FALSE; + fu_progress_step_done(progress); /* write core config */ if (!fu_synaptics_rmi_v7_device_write_partition(self, RMI_PARTITION_ID_CORE_CONFIG, bytes_cfg, + fu_progress_get_child(progress), error)) return FALSE; + fu_progress_step_done(progress); /* success */ return TRUE; diff --git a/plugins/synaptics-rmi/fu-synaptics-rmi-v7-device.h b/plugins/synaptics-rmi/fu-synaptics-rmi-v7-device.h index b17e6e775..315cd01e6 100644 --- a/plugins/synaptics-rmi/fu-synaptics-rmi-v7-device.h +++ b/plugins/synaptics-rmi/fu-synaptics-rmi-v7-device.h @@ -11,10 +11,11 @@ #include "fu-synaptics-rmi-device.h" gboolean -fu_synaptics_rmi_v7_device_detach(FuDevice *device, GError **error); +fu_synaptics_rmi_v7_device_detach(FuDevice *device, FuProgress *progress, GError **error); gboolean fu_synaptics_rmi_v7_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error); gboolean diff --git a/plugins/system76-launch/fu-system76-launch-device.c b/plugins/system76-launch/fu-system76-launch-device.c index bc02bf362..d2241df60 100644 --- a/plugins/system76-launch/fu-system76-launch-device.c +++ b/plugins/system76-launch/fu-system76-launch-device.c @@ -111,7 +111,7 @@ fu_system76_launch_device_reset(FuDevice *device, guint8 *rc, GError **error) } static gboolean -fu_system76_launch_device_detach(FuDevice *device, GError **error) +fu_system76_launch_device_detach(FuDevice *device, FuProgress *progress, GError **error) { guint8 rc = 0x0; g_autoptr(FwupdRequest) request = fwupd_request_new(); @@ -142,7 +142,6 @@ fu_system76_launch_device_detach(FuDevice *device, GError **error) fu_device_emit_request(device, request); /* poll for the user-unlock */ - fu_device_set_progress(device, 0); do { g_usleep(G_USEC_PER_SEC); if (!fu_system76_launch_device_reset(device, &rc, error)) @@ -198,6 +197,17 @@ fu_system76_launch_device_close(FuDevice *device, GError **error) return FU_DEVICE_CLASS(fu_system76_launch_device_parent_class)->close(device, error); } +static void +fu_system76_launch_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 94); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* reload */ +} + static void fu_system76_launch_device_init(FuSystem76LaunchDevice *self) { @@ -218,4 +228,5 @@ fu_system76_launch_device_class_init(FuSystem76LaunchDeviceClass *klass) klass_device->detach = fu_system76_launch_device_detach; klass_device->open = fu_system76_launch_device_open; klass_device->close = fu_system76_launch_device_close; + klass_device->set_progress = fu_system76_launch_device_set_progress; } diff --git a/plugins/test/fu-plugin-test.c b/plugins/test/fu-plugin-test.c index 6442ccd5a..092141c82 100644 --- a/plugins/test/fu-plugin-test.c +++ b/plugins/test/fu-plugin-test.c @@ -196,6 +196,7 @@ gboolean fu_plugin_write_firmware(FuPlugin *plugin, FuDevice *device, GBytes *blob_fw, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -210,23 +211,20 @@ fu_plugin_write_firmware(FuPlugin *plugin, "device was not in supported mode"); return FALSE; } - fu_device_set_status(device, FWUPD_STATUS_DECOMPRESSING); - for (guint i = 1; i <= data->delay_decompress_ms; i++) { - guint progress = (100 * i) / data->delay_decompress_ms; + fu_progress_set_status(progress, FWUPD_STATUS_DECOMPRESSING); + for (guint i = 0; i <= data->delay_decompress_ms; i++) { g_usleep(1000); - fu_device_set_progress(device, progress); + fu_progress_set_percentage_full(progress, i, data->delay_decompress_ms); } - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); - for (guint i = 1; i <= data->delay_write_ms; i++) { - guint progress = (100 * i) / data->delay_write_ms; + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_WRITE); + for (guint i = 0; i <= data->delay_write_ms; i++) { g_usleep(1000); - fu_device_set_progress(device, progress); + fu_progress_set_percentage_full(progress, i, data->delay_write_ms); } - fu_device_set_status(device, FWUPD_STATUS_DEVICE_VERIFY); - for (guint i = 1; i <= data->delay_verify_ms; i++) { - guint progress = (100 * i) / data->delay_verify_ms; + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_VERIFY); + for (guint i = 0; i <= data->delay_verify_ms; i++) { g_usleep(1000); - fu_device_set_progress(device, progress); + fu_progress_set_percentage_full(progress, i, data->delay_verify_ms); } /* composite test, upgrade composite devices */ @@ -275,7 +273,7 @@ fu_plugin_write_firmware(FuPlugin *plugin, } gboolean -fu_plugin_activate(FuPlugin *plugin, FuDevice *device, GError **error) +fu_plugin_activate(FuPlugin *plugin, FuDevice *device, FuProgress *process, GError **error) { fu_device_set_version_format(device, FWUPD_VERSION_FORMAT_TRIPLET); fu_device_set_version(device, "1.2.3"); diff --git a/plugins/thelio-io/fu-thelio-io-device.c b/plugins/thelio-io/fu-thelio-io-device.c index 98e2ccb79..a8f19422e 100644 --- a/plugins/thelio-io/fu-thelio-io-device.c +++ b/plugins/thelio-io/fu-thelio-io-device.c @@ -61,7 +61,7 @@ fu_thelio_io_device_probe(FuDevice *device, GError **error) } static gboolean -fu_thelio_io_device_detach(FuDevice *device, GError **error) +fu_thelio_io_device_detach(FuDevice *device, FuProgress *progress, GError **error) { const gchar *devpath; g_autofree gchar *fn = NULL; @@ -73,8 +73,6 @@ fu_thelio_io_device_detach(FuDevice *device, GError **error) udev_device = fu_usb_device_find_udev_device(FU_USB_DEVICE(device), error); if (udev_device == NULL) return FALSE; - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); - devpath = g_udev_device_get_sysfs_path(udev_device); if (G_UNLIKELY(devpath == NULL)) { g_set_error_literal(error, @@ -99,6 +97,17 @@ fu_thelio_io_device_detach(FuDevice *device, GError **error) return TRUE; } +static void +fu_thelio_io_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 94); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* reload */ +} + static void fu_thelio_io_device_init(FuThelioIoDevice *self) { @@ -115,4 +124,5 @@ fu_thelio_io_device_class_init(FuThelioIoDeviceClass *klass) FuDeviceClass *klass_device = FU_DEVICE_CLASS(klass); klass_device->probe = fu_thelio_io_device_probe; klass_device->detach = fu_thelio_io_device_detach; + klass_device->set_progress = fu_thelio_io_device_set_progress; } diff --git a/plugins/thunderbolt/fu-self-test.c b/plugins/thunderbolt/fu-self-test.c index c7760a14c..38b49712e 100644 --- a/plugins/thunderbolt/fu-self-test.c +++ b/plugins/thunderbolt/fu-self-test.c @@ -1186,6 +1186,7 @@ test_update_working(ThunderboltTest *tt, gconstpointer user_data) const gchar *version_after; g_autoptr(GError) error = NULL; g_autoptr(UpdateContext) up_ctx = NULL; + g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC); /* test sanity check */ g_assert_nonnull(tree); @@ -1194,7 +1195,8 @@ test_update_working(ThunderboltTest *tt, gconstpointer user_data) /* simulate an update, where the device goes away and comes back * after the time in the last parameter (given in ms) */ up_ctx = mock_tree_prepare_for_update(tree, plugin, "42.23", fw_data, 1000); - ret = fu_plugin_runner_write_firmware(plugin, tree->fu_device, fw_data, 0, &error); + ret = + fu_plugin_runner_write_firmware(plugin, tree->fu_device, fw_data, progress, 0, &error); g_assert_no_error(error); g_assert_true(ret); @@ -1203,7 +1205,7 @@ test_update_working(ThunderboltTest *tt, gconstpointer user_data) ret = mock_tree_settle(tree, plugin); g_assert_true(ret); - ret = fu_plugin_runner_attach(plugin, tree->fu_device, &error); + ret = fu_plugin_runner_attach(plugin, tree->fu_device, progress, &error); g_assert_no_error(error); g_assert_true(ret); @@ -1232,6 +1234,7 @@ test_update_wd19(ThunderboltTest *tt, gconstpointer user_data) const gchar *version_before; const gchar *version_after; g_autoptr(GError) error = NULL; + g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC); /* test sanity check */ g_assert_nonnull(tree); @@ -1242,7 +1245,8 @@ test_update_wd19(ThunderboltTest *tt, gconstpointer user_data) fu_device_add_flag(tree->fu_device, FWUPD_DEVICE_FLAG_USABLE_DURING_UPDATE); version_before = fu_device_get_version(tree->fu_device); - ret = fu_plugin_runner_write_firmware(plugin, tree->fu_device, fw_data, 0, &error); + ret = + fu_plugin_runner_write_firmware(plugin, tree->fu_device, fw_data, progress, 0, &error); g_assert_no_error(error); g_assert_true(ret); @@ -1263,6 +1267,7 @@ test_update_fail(ThunderboltTest *tt, gconstpointer user_data) const gchar *version_after; g_autoptr(GError) error = NULL; g_autoptr(UpdateContext) up_ctx = NULL; + g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC); /* test sanity check */ g_assert_nonnull(tree); @@ -1274,7 +1279,8 @@ test_update_fail(ThunderboltTest *tt, gconstpointer user_data) up_ctx = mock_tree_prepare_for_update(tree, plugin, "42.23", fw_data, 1000); up_ctx->result = UPDATE_FAIL_DEVICE_INTERNAL; - ret = fu_plugin_runner_write_firmware(plugin, tree->fu_device, fw_data, 0, &error); + ret = + fu_plugin_runner_write_firmware(plugin, tree->fu_device, fw_data, progress, 0, &error); g_assert_no_error(error); g_assert_true(ret); @@ -1284,7 +1290,7 @@ test_update_fail(ThunderboltTest *tt, gconstpointer user_data) ret = mock_tree_settle(tree, plugin); g_assert_true(ret); - ret = fu_plugin_runner_attach(plugin, tree->fu_device, &error); + ret = fu_plugin_runner_attach(plugin, tree->fu_device, progress, &error); g_assert_error(error, FWUPD_ERROR, FWUPD_ERROR_INTERNAL); g_assert_false(ret); @@ -1310,6 +1316,7 @@ test_update_fail_nowshow(ThunderboltTest *tt, gconstpointer user_data) gboolean ret; g_autoptr(GError) error = NULL; g_autoptr(UpdateContext) up_ctx = NULL; + g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC); /* test sanity check */ g_assert_nonnull(tree); @@ -1321,7 +1328,8 @@ test_update_fail_nowshow(ThunderboltTest *tt, gconstpointer user_data) up_ctx = mock_tree_prepare_for_update(tree, plugin, "42.23", fw_data, 1000); up_ctx->result = UPDATE_FAIL_DEVICE_NOSHOW; - ret = fu_plugin_runner_write_firmware(plugin, tree->fu_device, fw_data, 0, &error); + ret = + fu_plugin_runner_write_firmware(plugin, tree->fu_device, fw_data, progress, 0, &error); g_assert_no_error(error); g_assert_true(ret); diff --git a/plugins/thunderbolt/fu-thunderbolt-device.c b/plugins/thunderbolt/fu-thunderbolt-device.c index 880f7086e..7ffc6aeae 100644 --- a/plugins/thunderbolt/fu-thunderbolt-device.c +++ b/plugins/thunderbolt/fu-thunderbolt-device.c @@ -498,7 +498,7 @@ fu_thunderbolt_device_setup(FuDevice *device, GError **error) } static gboolean -fu_thunderbolt_device_activate(FuDevice *device, GError **error) +fu_thunderbolt_device_activate(FuDevice *device, FuProgress *progress, GError **error) { FuUdevDevice *udev = FU_UDEV_DEVICE(device); @@ -524,7 +524,7 @@ fu_thunderbolt_device_flush_update(FuDevice *device, GError **error) } static gboolean -fu_thunderbolt_device_attach(FuDevice *device, GError **error) +fu_thunderbolt_device_attach(FuDevice *device, FuProgress *progress, GError **error) { const gchar *attribute; guint64 status; @@ -571,7 +571,10 @@ fu_thunderbolt_device_rescan(FuDevice *device, GError **error) } static gboolean -fu_thunderbolt_device_write_data(FuThunderboltDevice *self, GBytes *blob_fw, GError **error) +fu_thunderbolt_device_write_data(FuThunderboltDevice *self, + GBytes *blob_fw, + FuProgress *progress, + GError **error) { gsize fw_size; gsize nwritten; @@ -590,7 +593,6 @@ fu_thunderbolt_device_write_data(FuThunderboltDevice *self, GBytes *blob_fw, GEr nwritten = 0; fw_size = g_bytes_get_size(blob_fw); - fu_device_set_progress_full(FU_DEVICE(self), nwritten, fw_size); do { g_autoptr(GBytes) fw_data = NULL; @@ -604,7 +606,7 @@ fu_thunderbolt_device_write_data(FuThunderboltDevice *self, GBytes *blob_fw, GEr return FALSE; nwritten += n; - fu_device_set_progress_full(FU_DEVICE(self), nwritten, fw_size); + fu_progress_set_percentage_full(progress, nwritten, fw_size); } while (nwritten < fw_size); @@ -716,6 +718,7 @@ fu_thunderbolt_device_prepare_firmware(FuDevice *device, static gboolean fu_thunderbolt_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -727,8 +730,8 @@ fu_thunderbolt_device_write_firmware(FuDevice *device, if (blob_fw == NULL) return FALSE; - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); - if (!fu_thunderbolt_device_write_data(self, blob_fw, error)) { + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_WRITE); + if (!fu_thunderbolt_device_write_data(self, blob_fw, progress, error)) { g_prefix_error(error, "could not write firmware to thunderbolt device at %s: ", self->devpath); @@ -757,7 +760,7 @@ fu_thunderbolt_device_write_firmware(FuDevice *device, /* whether to wait for a device replug or not */ if (!fu_device_has_flag(device, FWUPD_DEVICE_FLAG_USABLE_DURING_UPDATE)) { - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_RESTART); fu_device_set_remove_delay(device, FU_PLUGIN_THUNDERBOLT_UPDATE_TIMEOUT); fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG); } @@ -765,6 +768,16 @@ fu_thunderbolt_device_write_firmware(FuDevice *device, return TRUE; } +static void +fu_thunderbolt_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 100); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 0); /* reload */ +} + static void fu_thunderbolt_device_init(FuThunderboltDevice *self) { @@ -796,4 +809,5 @@ fu_thunderbolt_device_class_init(FuThunderboltDeviceClass *klass) klass_device->attach = fu_thunderbolt_device_attach; klass_device->rescan = fu_thunderbolt_device_rescan; klass_device->probe = fu_thunderbolt_device_probe; + klass_device->set_progress = fu_thunderbolt_device_set_progress; } diff --git a/plugins/uefi-capsule/fu-plugin-uefi-capsule.c b/plugins/uefi-capsule/fu-plugin-uefi-capsule.c index 870797538..4a10d54ff 100644 --- a/plugins/uefi-capsule/fu-plugin-uefi-capsule.c +++ b/plugins/uefi-capsule/fu-plugin-uefi-capsule.c @@ -320,6 +320,7 @@ gboolean fu_plugin_write_firmware(FuPlugin *plugin, FuDevice *device, GBytes *blob_fw, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -352,12 +353,12 @@ fu_plugin_write_firmware(FuPlugin *plugin, g_assert(str != NULL); /* perform the update */ - fu_device_set_status(device, FWUPD_STATUS_SCHEDULING); + fu_progress_set_status(progress, FWUPD_STATUS_SCHEDULING); if (!fu_plugin_uefi_capsule_update_splash(plugin, device, &error_splash)) { g_debug("failed to upload UEFI UX capsule text: %s", error_splash->message); } - return fu_device_write_firmware(device, blob_fw, flags, error); + return fu_device_write_firmware(device, blob_fw, progress, flags, error); } static void diff --git a/plugins/uefi-capsule/fu-uefi-cod-device.c b/plugins/uefi-capsule/fu-uefi-cod-device.c index cbc610490..9c2724f23 100644 --- a/plugins/uefi-capsule/fu-uefi-cod-device.c +++ b/plugins/uefi-capsule/fu-uefi-cod-device.c @@ -147,6 +147,7 @@ fu_uefi_cod_device_get_results(FuDevice *device, GError **error) static gboolean fu_uefi_cod_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { diff --git a/plugins/uefi-capsule/fu-uefi-device.c b/plugins/uefi-capsule/fu-uefi-device.c index 273813609..8c7d77faf 100644 --- a/plugins/uefi-capsule/fu-uefi-device.c +++ b/plugins/uefi-capsule/fu-uefi-device.c @@ -765,6 +765,17 @@ fu_uefi_device_set_property(GObject *object, guint prop_id, const GValue *value, } } +static void +fu_uefi_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 98); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* reload */ +} + static void fu_uefi_device_init(FuUefiDevice *self) { @@ -824,6 +835,7 @@ fu_uefi_device_class_init(FuUefiDeviceClass *klass) klass_device->report_metadata_pre = fu_uefi_device_report_metadata_pre; klass_device->report_metadata_post = fu_uefi_device_report_metadata_post; klass_device->get_results = fu_uefi_device_get_results; + klass_device->set_progress = fu_uefi_device_set_progress; pspec = g_param_spec_string("fw-class", diff --git a/plugins/uefi-capsule/fu-uefi-grub-device.c b/plugins/uefi-capsule/fu-uefi-grub-device.c index efbcf02f0..7cc2bd354 100644 --- a/plugins/uefi-capsule/fu-uefi-grub-device.c +++ b/plugins/uefi-capsule/fu-uefi-grub-device.c @@ -109,6 +109,7 @@ fu_uefi_grub_device_mkconfig(FuDevice *device, static gboolean fu_uefi_grub_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { diff --git a/plugins/uefi-capsule/fu-uefi-nvram-device.c b/plugins/uefi-capsule/fu-uefi-nvram-device.c index 7cb00a757..bfe4f5e44 100644 --- a/plugins/uefi-capsule/fu-uefi-nvram-device.c +++ b/plugins/uefi-capsule/fu-uefi-nvram-device.c @@ -47,6 +47,7 @@ fu_uefi_nvram_device_get_results(FuDevice *device, GError **error) static gboolean fu_uefi_nvram_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { diff --git a/plugins/uefi-capsule/fu-uefi-tool.c b/plugins/uefi-capsule/fu-uefi-tool.c index d17f9f5b7..ea888ae8a 100644 --- a/plugins/uefi-capsule/fu-uefi-tool.c +++ b/plugins/uefi-capsule/fu-uefi-tool.c @@ -387,6 +387,7 @@ main(int argc, char *argv[]) if (apply != NULL) { g_autoptr(FuContext) ctx = fu_context_new(); g_autoptr(FuBackend) backend = fu_uefi_backend_new(ctx); + g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC); g_autoptr(FuUefiDevice) dev = NULL; g_autoptr(GError) error_local = NULL; g_autoptr(GBytes) fw = NULL; @@ -427,6 +428,7 @@ main(int argc, char *argv[]) } if (!fu_device_write_firmware(FU_DEVICE(dev), fw, + progress, FWUPD_INSTALL_FLAG_NONE, &error_local)) { g_printerr("failed: %s\n", error_local->message); diff --git a/plugins/uefi-dbx/fu-uefi-dbx-device.c b/plugins/uefi-dbx/fu-uefi-dbx-device.c index c4c9caa75..46fa7fe85 100644 --- a/plugins/uefi-dbx/fu-uefi-dbx-device.c +++ b/plugins/uefi-dbx/fu-uefi-dbx-device.c @@ -20,6 +20,7 @@ G_DEFINE_TYPE(FuUefiDbxDevice, fu_uefi_dbx_device, FU_TYPE_DEVICE) static gboolean fu_uefi_dbx_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags install_flags, GError **error) { @@ -33,7 +34,7 @@ fu_uefi_dbx_device_write_firmware(FuDevice *device, return FALSE; /* write entire chunk to efivarfs */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_WRITE); buf = g_bytes_get_data(fw, &bufsz); if (!fu_efivar_set_data(FU_EFIVAR_GUID_SECURITY_DATABASE, "dbx", @@ -80,7 +81,7 @@ fu_uefi_dbx_prepare_firmware(FuDevice *device, GBytes *fw, FwupdInstallFlags fla /* validate this is safe to apply */ if ((flags & FWUPD_INSTALL_FLAG_FORCE) == 0) { - fu_device_set_status(device, FWUPD_STATUS_DEVICE_VERIFY); + // fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_VERIFY); if (!fu_uefi_dbx_signature_list_validate(FU_EFI_SIGNATURE_LIST(siglist), error)) { g_prefix_error(error, "Blocked executable in the ESP, " @@ -128,6 +129,17 @@ fu_uefi_dbx_device_probe(FuDevice *device, GError **error) return fu_uefi_dbx_device_set_version_number(device, error); } +static void +fu_uefi_dbx_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 98); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* reload */ +} + static void fu_uefi_dbx_device_init(FuUefiDbxDevice *self) { @@ -154,6 +166,7 @@ fu_uefi_dbx_device_class_init(FuUefiDbxDeviceClass *klass) klass_device->probe = fu_uefi_dbx_device_probe; klass_device->write_firmware = fu_uefi_dbx_device_write_firmware; klass_device->prepare_firmware = fu_uefi_dbx_prepare_firmware; + klass_device->set_progress = fu_uefi_dbx_device_set_progress; } FuUefiDbxDevice * diff --git a/plugins/vli/fu-vli-device.c b/plugins/vli/fu-vli-device.c index e2dd6eae2..516f12df9 100644 --- a/plugins/vli/fu-vli-device.c +++ b/plugins/vli/fu-vli-device.c @@ -242,7 +242,11 @@ fu_vli_device_spi_erase_sector(FuVliDevice *self, guint32 addr, GError **error) } GBytes * -fu_vli_device_spi_read(FuVliDevice *self, guint32 address, gsize bufsz, GError **error) +fu_vli_device_spi_read(FuVliDevice *self, + guint32 address, + gsize bufsz, + FuProgress *progress, + GError **error) { g_autofree guint8 *buf = g_malloc0(bufsz); g_autoptr(GPtrArray) chunks = NULL; @@ -261,7 +265,7 @@ fu_vli_device_spi_read(FuVliDevice *self, guint32 address, gsize bufsz, GError * fu_chunk_get_address(chk)); return NULL; } - fu_device_set_progress_full(FU_DEVICE(self), (gsize)i, (gsize)chunks->len); + fu_progress_set_percentage_full(progress, (gsize)i + 1, (gsize)chunks->len); } return g_bytes_new_take(g_steal_pointer(&buf), bufsz); } @@ -271,6 +275,7 @@ fu_vli_device_spi_write_block(FuVliDevice *self, guint32 address, const guint8 *buf, gsize bufsz, + FuProgress *progress, GError **error) { g_autofree guint8 *buf_tmp = g_malloc0(bufsz); @@ -311,49 +316,66 @@ fu_vli_device_spi_write(FuVliDevice *self, guint32 address, const guint8 *buf, gsize bufsz, + FuProgress *progress, GError **error) { FuChunk *chk; g_autoptr(GPtrArray) chunks = NULL; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 99); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 1); /* chk0 */ + /* write SPI data, then CRC bytes last */ g_debug("writing 0x%x bytes @0x%x", (guint)bufsz, address); chunks = fu_chunk_array_new(buf, bufsz, 0x0, 0x0, FU_VLI_DEVICE_TXSIZE); if (chunks->len > 1) { + FuProgress *progress_local = fu_progress_get_child(progress); + fu_progress_set_id(progress_local, G_STRLOC); + fu_progress_set_steps(progress_local, chunks->len - 1); for (guint i = 1; i < chunks->len; i++) { chk = g_ptr_array_index(chunks, i); if (!fu_vli_device_spi_write_block(self, fu_chunk_get_address(chk) + address, fu_chunk_get_data(chk), fu_chunk_get_data_sz(chk), + fu_progress_get_child(progress_local), error)) { g_prefix_error(error, "failed to write block 0x%x: ", fu_chunk_get_idx(chk)); return FALSE; } - fu_device_set_progress_full(FU_DEVICE(self), - (gsize)i - 1, - (gsize)chunks->len); + fu_progress_step_done(progress_local); } } + fu_progress_step_done(progress); + + /* chk0 */ chk = g_ptr_array_index(chunks, 0); if (!fu_vli_device_spi_write_block(self, fu_chunk_get_address(chk) + address, fu_chunk_get_data(chk), fu_chunk_get_data_sz(chk), + fu_progress_get_child(progress), error)) { g_prefix_error(error, "failed to write CRC block: "); return FALSE; } - fu_device_set_progress_full(FU_DEVICE(self), (gsize)chunks->len, (gsize)chunks->len); + fu_progress_step_done(progress); return TRUE; } gboolean -fu_vli_device_spi_erase_all(FuVliDevice *self, GError **error) +fu_vli_device_spi_erase_all(FuVliDevice *self, FuProgress *progress, GError **error) { - fu_device_set_progress(FU_DEVICE(self), 0); + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_ERASE, 99); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_VERIFY, 1); + if (!fu_vli_device_spi_write_enable(self, error)) return FALSE; if (!fu_vli_device_spi_write_status(self, 0x00, error)) @@ -362,7 +384,8 @@ fu_vli_device_spi_erase_all(FuVliDevice *self, GError **error) return FALSE; if (!fu_vli_device_spi_chip_erase(self, error)) return FALSE; - fu_device_sleep_with_progress(FU_DEVICE(self), 4); /* seconds */ + fu_progress_sleep(fu_progress_get_child(progress), 4000); + fu_progress_step_done(progress); /* verify chip was erased */ for (guint addr = 0; addr < 0x10000; addr += 0x1000) { @@ -381,13 +404,20 @@ fu_vli_device_spi_erase_all(FuVliDevice *self, GError **error) return FALSE; } } - fu_device_set_progress_full(FU_DEVICE(self), (gsize)addr, (gsize)0x10000); + fu_progress_set_percentage_full(fu_progress_get_child(progress), + (gsize)addr + 0x1000, + (gsize)0x10000); } + fu_progress_step_done(progress); return TRUE; } gboolean -fu_vli_device_spi_erase(FuVliDevice *self, guint32 addr, gsize sz, GError **error) +fu_vli_device_spi_erase(FuVliDevice *self, + guint32 addr, + gsize sz, + FuProgress *progress, + GError **error) { g_autoptr(GPtrArray) chunks = fu_chunk_array_new(NULL, sz, addr, 0x0, 0x1000); g_debug("erasing 0x%x bytes @0x%x", (guint)sz, addr); @@ -403,7 +433,7 @@ fu_vli_device_spi_erase(FuVliDevice *self, guint32 addr, gsize sz, GError **erro fu_chunk_get_address(chk)); return FALSE; } - fu_device_set_progress_full(FU_DEVICE(self), (gsize)i, (gsize)chunks->len); + fu_progress_set_percentage_full(progress, (gsize)i + 1, (gsize)chunks->len); } return TRUE; } diff --git a/plugins/vli/fu-vli-device.h b/plugins/vli/fu-vli-device.h index 8daa26d0a..027b790c2 100644 --- a/plugins/vli/fu-vli-device.h +++ b/plugins/vli/fu-vli-device.h @@ -60,9 +60,13 @@ fu_vli_device_get_spi_cmd(FuVliDevice *self, FuVliDeviceSpiReq req, guint8 *cmd, gboolean fu_vli_device_spi_erase_sector(FuVliDevice *self, guint32 addr, GError **error); gboolean -fu_vli_device_spi_erase_all(FuVliDevice *self, GError **error); +fu_vli_device_spi_erase_all(FuVliDevice *self, FuProgress *progress, GError **error); gboolean -fu_vli_device_spi_erase(FuVliDevice *self, guint32 addr, gsize sz, GError **error); +fu_vli_device_spi_erase(FuVliDevice *self, + guint32 addr, + gsize sz, + FuProgress *progress, + GError **error); gboolean fu_vli_device_spi_read_block(FuVliDevice *self, guint32 addr, @@ -70,16 +74,22 @@ fu_vli_device_spi_read_block(FuVliDevice *self, gsize bufsz, GError **error); GBytes * -fu_vli_device_spi_read(FuVliDevice *self, guint32 address, gsize bufsz, GError **error); +fu_vli_device_spi_read(FuVliDevice *self, + guint32 address, + gsize bufsz, + FuProgress *progress, + GError **error); gboolean fu_vli_device_spi_write_block(FuVliDevice *self, guint32 address, const guint8 *buf, gsize bufsz, + FuProgress *progress, GError **error); gboolean fu_vli_device_spi_write(FuVliDevice *self, guint32 address, const guint8 *buf, gsize bufsz, + FuProgress *progress, GError **error); diff --git a/plugins/vli/fu-vli-pd-device.c b/plugins/vli/fu-vli-pd-device.c index a2ac9c46e..a6d21adf1 100644 --- a/plugins/vli/fu-vli-pd-device.c +++ b/plugins/vli/fu-vli-pd-device.c @@ -426,7 +426,7 @@ fu_vli_pd_device_prepare_firmware(FuDevice *device, } static GBytes * -fu_vli_pd_device_dump_firmware(FuDevice *device, GError **error) +fu_vli_pd_device_dump_firmware(FuDevice *device, FuProgress *progress, GError **error) { FuVliPdDevice *self = FU_VLI_PD_DEVICE(device); g_autoptr(FuDeviceLocker) locker = NULL; @@ -438,10 +438,11 @@ fu_vli_pd_device_dump_firmware(FuDevice *device, GError **error) error); if (locker == NULL) return NULL; - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_DEVICE_READ); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_READ); return fu_vli_device_spi_read(FU_VLI_DEVICE(self), 0x0, fu_device_get_firmware_size_max(device), + progress, error); } @@ -461,7 +462,10 @@ fu_vli_pd_device_write_gpios(FuVliPdDevice *self, GError **error) } static gboolean -fu_vli_pd_device_write_dual_firmware(FuVliPdDevice *self, GBytes *fw, GError **error) +fu_vli_pd_device_write_dual_firmware(FuVliPdDevice *self, + GBytes *fw, + FuProgress *progress, + GError **error) { const guint8 *buf = NULL; const guint8 *sbuf = NULL; @@ -472,11 +476,18 @@ fu_vli_pd_device_write_dual_firmware(FuVliPdDevice *self, GBytes *fw, GError **e guint32 sec_addr = 0x28000; g_autoptr(GBytes) spi_fw = NULL; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 10); /* crc */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 45); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 45); + /* check spi fw1 crc16 */ - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_DEVICE_VERIFY); spi_fw = fu_vli_device_spi_read(FU_VLI_DEVICE(self), fu_vli_device_get_offset(FU_VLI_DEVICE(self)), fu_device_get_firmware_size_max(FU_DEVICE(self)), + fu_progress_get_child(progress), error); if (spi_fw == NULL) return FALSE; @@ -493,19 +504,27 @@ fu_vli_pd_device_write_dual_firmware(FuVliPdDevice *self, GBytes *fw, GError **e return FALSE; } crc_actual = fu_common_crc16(sbuf, sbufsz - 2); - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_DEVICE_WRITE); + fu_progress_step_done(progress); /* update fw2 first if fw1 correct */ buf = g_bytes_get_data(fw, &bufsz); if (crc_actual == crc_file) { - if (!fu_vli_device_spi_write(FU_VLI_DEVICE(self), sec_addr, buf, bufsz, error)) + if (!fu_vli_device_spi_write(FU_VLI_DEVICE(self), + sec_addr, + buf, + bufsz, + fu_progress_get_child(progress), + error)) return FALSE; + fu_progress_step_done(progress); if (!fu_vli_device_spi_write(FU_VLI_DEVICE(self), fu_vli_device_get_offset(FU_VLI_DEVICE(self)), buf, bufsz, + fu_progress_get_child(progress), error)) return FALSE; + fu_progress_step_done(progress); /* else update fw1 first */ } else { @@ -513,10 +532,18 @@ fu_vli_pd_device_write_dual_firmware(FuVliPdDevice *self, GBytes *fw, GError **e fu_vli_device_get_offset(FU_VLI_DEVICE(self)), buf, bufsz, + fu_progress_get_child(progress), error)) return FALSE; - if (!fu_vli_device_spi_write(FU_VLI_DEVICE(self), sec_addr, buf, bufsz, error)) + fu_progress_step_done(progress); + if (!fu_vli_device_spi_write(FU_VLI_DEVICE(self), + sec_addr, + buf, + bufsz, + fu_progress_get_child(progress), + error)) return FALSE; + fu_progress_step_done(progress); } /* success */ @@ -526,6 +553,7 @@ fu_vli_pd_device_write_dual_firmware(FuVliPdDevice *self, GBytes *fw, GError **e static gboolean fu_vli_pd_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -553,29 +581,37 @@ fu_vli_pd_device_write_firmware(FuDevice *device, /* dual image on VL103 */ if (fu_vli_device_get_kind(FU_VLI_DEVICE(device)) == FU_VLI_DEVICE_KIND_VL103 && fu_device_has_flag(device, FWUPD_DEVICE_FLAG_DUAL_IMAGE)) - return fu_vli_pd_device_write_dual_firmware(self, fw, error); + return fu_vli_pd_device_write_dual_firmware(self, fw, progress, error); + + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_ERASE, 63); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 37); /* erase */ - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_DEVICE_ERASE); - if (!fu_vli_device_spi_erase_all(FU_VLI_DEVICE(self), error)) + if (!fu_vli_device_spi_erase_all(FU_VLI_DEVICE(self), + fu_progress_get_child(progress), + error)) return FALSE; + fu_progress_step_done(progress); /* write in chunks */ - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_DEVICE_WRITE); buf = g_bytes_get_data(fw, &bufsz); if (!fu_vli_device_spi_write(FU_VLI_DEVICE(self), fu_vli_device_get_offset(FU_VLI_DEVICE(self)), buf, bufsz, + fu_progress_get_child(progress), error)) return FALSE; /* success */ + fu_progress_step_done(progress); return TRUE; } static gboolean -fu_vli_pd_device_detach(FuDevice *device, GError **error) +fu_vli_pd_device_detach(FuDevice *device, FuProgress *progress, GError **error) { FuVliPdDevice *self = FU_VLI_PD_DEVICE(device); g_autoptr(GError) error_local = NULL; @@ -592,7 +628,6 @@ fu_vli_pd_device_detach(FuDevice *device, GError **error) /* VL103 set ROM sig does not work, so use alternate function */ if (fu_vli_device_get_kind(FU_VLI_DEVICE(device)) == FU_VLI_DEVICE_KIND_VL103) { - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); if (!g_usb_device_control_transfer(fu_usb_device_get_dev(FU_USB_DEVICE(device)), G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE, G_USB_DEVICE_REQUEST_TYPE_VENDOR, @@ -656,7 +691,6 @@ fu_vli_pd_device_detach(FuDevice *device, GError **error) return FALSE; /* reset from SPI_Code into ROM_Code */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); if (!g_usb_device_control_transfer(fu_usb_device_get_dev(FU_USB_DEVICE(device)), G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE, G_USB_DEVICE_REQUEST_TYPE_VENDOR, @@ -684,7 +718,7 @@ fu_vli_pd_device_detach(FuDevice *device, GError **error) } static gboolean -fu_vli_pd_device_attach(FuDevice *device, GError **error) +fu_vli_pd_device_attach(FuDevice *device, FuProgress *progress, GError **error) { FuVliPdDevice *self = FU_VLI_PD_DEVICE(device); g_autoptr(GError) error_local = NULL; @@ -699,7 +733,6 @@ fu_vli_pd_device_attach(FuDevice *device, GError **error) return FALSE; if (!fu_vli_pd_device_write_reg(self, 0x1001, 0xf6, error)) return FALSE; - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG); return TRUE; } @@ -741,7 +774,6 @@ fu_vli_pd_device_attach(FuDevice *device, GError **error) } /* replug */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG); return TRUE; } @@ -755,6 +787,17 @@ fu_vli_pd_device_kind_changed_cb(FuVliDevice *device, GParamSpec *pspec, gpointe } } +static void +fu_vli_pd_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 94); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* reload */ +} + static void fu_vli_pd_device_init(FuVliPdDevice *self) { @@ -785,6 +828,7 @@ fu_vli_pd_device_class_init(FuVliPdDeviceClass *klass) klass_device->attach = fu_vli_pd_device_attach; klass_device->detach = fu_vli_pd_device_detach; klass_device->setup = fu_vli_pd_device_setup; + klass_device->set_progress = fu_vli_pd_device_set_progress; klass_vli_device->spi_chip_erase = fu_vli_pd_device_spi_chip_erase; klass_vli_device->spi_sector_erase = fu_vli_pd_device_spi_sector_erase; klass_vli_device->spi_read_data = fu_vli_pd_device_spi_read_data; diff --git a/plugins/vli/fu-vli-pd-parade-device.c b/plugins/vli/fu-vli-pd-parade-device.c index be12cd295..ae791cdf0 100644 --- a/plugins/vli/fu-vli-pd-parade-device.c +++ b/plugins/vli/fu-vli-pd-parade-device.c @@ -454,6 +454,7 @@ fu_vli_pd_parade_device_block_read(FuVliPdParadeDevice *self, static gboolean fu_vli_pd_parade_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -468,6 +469,14 @@ fu_vli_pd_parade_device_write_firmware(FuDevice *device, g_autoptr(GBytes) fw_verify = NULL; g_autoptr(GPtrArray) blocks = NULL; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_ERASE, 19); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 45); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_VERIFY, 36); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 1); + /* simple image */ fw = fu_firmware_get_bytes(firmware, error); if (fw == NULL) @@ -483,7 +492,6 @@ fu_vli_pd_parade_device_write_firmware(FuDevice *device, return FALSE; /* 64K block erase */ - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_DEVICE_ERASE); if (!fu_vli_pd_parade_device_write_enable(self, error)) return FALSE; if (!fu_vli_pd_parade_device_write_status(self, 0x00, error)) @@ -495,8 +503,11 @@ fu_vli_pd_parade_device_write_firmware(FuDevice *device, FuChunk *chk = g_ptr_array_index(blocks, i); if (!fu_vli_pd_parade_device_block_erase(self, fu_chunk_get_idx(chk), error)) return FALSE; - fu_device_set_progress_full(FU_DEVICE(self), i, blocks->len); + fu_progress_set_percentage_full(fu_progress_get_child(progress), + i + 1, + blocks->len); } + fu_progress_step_done(progress); /* load F/W to SPI ROM */ if (!fu_vli_pd_parade_device_enable_mapping(self, error)) @@ -508,7 +519,6 @@ fu_vli_pd_parade_device_write_firmware(FuDevice *device, return FALSE; /* write blocks */ - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_DEVICE_WRITE); for (guint i = 1; i < blocks->len; i++) { FuChunk *chk = g_ptr_array_index(blocks, i); if (!fu_vli_pd_parade_device_block_write(self, @@ -516,10 +526,13 @@ fu_vli_pd_parade_device_write_firmware(FuDevice *device, fu_chunk_get_data(chk), error)) return FALSE; - fu_device_set_progress_full(FU_DEVICE(self), i, blocks->len); + fu_progress_set_percentage_full(fu_progress_get_child(progress), + i + 1, + blocks->len); } if (!fu_vli_pd_parade_device_write_disable(self, error)) return FALSE; + fu_progress_step_done(progress); /* add the new boot config into the verify buffer */ buf_verify = g_byte_array_sized_new(g_bytes_get_size(fw)); @@ -527,7 +540,6 @@ fu_vli_pd_parade_device_write_firmware(FuDevice *device, g_byte_array_append(buf_verify, fu_chunk_get_data(chk0), fu_chunk_get_data_sz(chk0)); /* verify SPI ROM, ignoring the boot config */ - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_DEVICE_VERIFY); for (guint i = 1; i < blocks->len; i++) { FuChunk *chk = g_ptr_array_index(blocks, i); gsize bufsz = fu_chunk_get_data_sz(chk); @@ -539,11 +551,14 @@ fu_vli_pd_parade_device_write_firmware(FuDevice *device, error)) return FALSE; g_byte_array_append(buf_verify, vbuf, bufsz); - fu_device_set_progress_full(FU_DEVICE(self), i, blocks->len); + fu_progress_set_percentage_full(fu_progress_get_child(progress), + i + 1, + blocks->len); } fw_verify = g_byte_array_free_to_bytes(g_steal_pointer(&buf_verify)); if (!fu_common_bytes_compare(fw, fw_verify, error)) return FALSE; + fu_progress_step_done(progress); /* save boot config into Block_0 */ if (!fu_vli_pd_parade_device_write_enable(self, error)) @@ -606,13 +621,14 @@ fu_vli_pd_parade_device_write_firmware(FuDevice *device, return FALSE; if (!fu_vli_pd_parade_device_write_disable(self, error)) return FALSE; + fu_progress_step_done(progress); /* success */ return TRUE; } static GBytes * -fu_vli_pd_parade_device_dump_firmware(FuDevice *device, GError **error) +fu_vli_pd_parade_device_dump_firmware(FuDevice *device, FuProgress *progress, GError **error) { FuVliPdDevice *parent = FU_VLI_PD_DEVICE(fu_device_get_parent(device)); FuVliPdParadeDevice *self = FU_VLI_PD_PARADE_DEVICE(device); @@ -630,7 +646,7 @@ fu_vli_pd_parade_device_dump_firmware(FuDevice *device, GError **error) return NULL; /* read */ - fu_device_set_status(FU_DEVICE(device), FWUPD_STATUS_DEVICE_VERIFY); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_VERIFY); fu_byte_array_set_size(fw, fu_device_get_firmware_size_max(device)); blocks = fu_chunk_array_mutable_new(fw->data, fw->len, 0x0, 0x0, 0x10000); for (guint i = 0; i < blocks->len; i++) { @@ -641,6 +657,7 @@ fu_vli_pd_parade_device_dump_firmware(FuDevice *device, GError **error) fu_chunk_get_data_sz(chk), error)) return NULL; + fu_progress_set_percentage_full(progress, i + 1, blocks->len); } return g_byte_array_free_to_bytes(g_steal_pointer(&fw)); } @@ -667,6 +684,17 @@ fu_vli_pd_parade_device_probe(FuDevice *device, GError **error) return TRUE; } +static void +fu_vli_pd_parade_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 98); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* reload */ +} + static void fu_vli_pd_parade_device_init(FuVliPdParadeDevice *self) { @@ -691,6 +719,7 @@ fu_vli_pd_parade_device_class_init(FuVliPdParadeDeviceClass *klass) klass_device->probe = fu_vli_pd_parade_device_probe; klass_device->dump_firmware = fu_vli_pd_parade_device_dump_firmware; klass_device->write_firmware = fu_vli_pd_parade_device_write_firmware; + klass_device->set_progress = fu_vli_pd_parade_device_set_progress; } FuDevice * diff --git a/plugins/vli/fu-vli-usbhub-device.c b/plugins/vli/fu-vli-usbhub-device.c index 081e0c85a..26f15a5e3 100644 --- a/plugins/vli/fu-vli-usbhub-device.c +++ b/plugins/vli/fu-vli-usbhub-device.c @@ -346,14 +346,11 @@ fu_vli_usbhub_device_spi_write_data(FuVliDevice *self, #define VL817_ADDR_GPIO_GET_INPUT_DATA 0xF6A2 /* 0=low, 1=high */ static gboolean -fu_vli_usbhub_device_attach(FuDevice *device, GError **error) +fu_vli_usbhub_device_attach(FuDevice *device, FuProgress *progress, GError **error) { FuDevice *proxy = fu_device_get_proxy_with_fallback(device); g_autoptr(GError) error_local = NULL; - /* update UI */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); - /* some hardware has to toggle a GPIO to reset the entire PCB */ if (fu_vli_device_get_kind(FU_VLI_DEVICE(proxy)) == FU_VLI_DEVICE_KIND_VL817 && fu_device_has_private_flag(device, FU_VLI_USBHUB_DEVICE_FLAG_ATTACH_WITH_GPIOB)) { @@ -840,59 +837,87 @@ fu_vli_usbhub_device_prepare_firmware(FuDevice *device, } static gboolean -fu_vli_usbhub_device_update_v1(FuVliUsbhubDevice *self, FuFirmware *firmware, GError **error) +fu_vli_usbhub_device_update_v1(FuVliUsbhubDevice *self, + FuFirmware *firmware, + FuProgress *progress, + GError **error) { gsize bufsz = 0; const guint8 *buf; g_autoptr(GBytes) fw = NULL; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_ERASE, 20); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 80); + /* simple image */ fw = fu_firmware_get_bytes(firmware, error); if (fw == NULL) return FALSE; /* erase */ - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_DEVICE_ERASE); - if (!fu_vli_device_spi_erase_all(FU_VLI_DEVICE(self), error)) { + if (!fu_vli_device_spi_erase_all(FU_VLI_DEVICE(self), + fu_progress_get_child(progress), + error)) { g_prefix_error(error, "failed to erase chip: "); return FALSE; } + fu_progress_step_done(progress); /* write in chunks */ - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_DEVICE_WRITE); buf = g_bytes_get_data(fw, &bufsz); - if (!fu_vli_device_spi_write(FU_VLI_DEVICE(self), 0x0, buf, bufsz, error)) + if (!fu_vli_device_spi_write(FU_VLI_DEVICE(self), + 0x0, + buf, + bufsz, + fu_progress_get_child(progress), + error)) return FALSE; /* success */ + fu_progress_step_done(progress); return TRUE; } /* if no header1 or ROM code update, write data directly */ static gboolean -fu_vli_usbhub_device_update_v2_recovery(FuVliUsbhubDevice *self, GBytes *fw, GError **error) +fu_vli_usbhub_device_update_v2_recovery(FuVliUsbhubDevice *self, + GBytes *fw, + FuProgress *progress, + GError **error) { gsize bufsz = 0; const guint8 *buf = g_bytes_get_data(fw, &bufsz); + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_ERASE, 20); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 80); + /* erase */ - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_DEVICE_ERASE); for (guint32 addr = 0; addr < bufsz; addr += 0x1000) { if (!fu_vli_device_spi_erase_sector(FU_VLI_DEVICE(self), addr, error)) { g_prefix_error(error, "failed to erase sector @0x%x: ", addr); return FALSE; } - fu_device_set_progress_full(FU_DEVICE(self), (gsize)addr, bufsz); + fu_progress_set_percentage_full(fu_progress_get_child(progress), + (gsize)addr, + bufsz); } + fu_progress_step_done(progress); /* write in chunks */ - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_DEVICE_WRITE); if (!fu_vli_device_spi_write(FU_VLI_DEVICE(self), VLI_USBHUB_FLASHMAP_ADDR_HD1, buf, bufsz, + fu_progress_get_child(progress), error)) return FALSE; + fu_progress_step_done(progress); /* success */ return TRUE; @@ -909,7 +934,10 @@ fu_vli_usbhub_device_hd1_is_valid(FuVliUsbhubHeader *hdr) } static gboolean -fu_vli_usbhub_device_hd1_recover(FuVliUsbhubDevice *self, FuVliUsbhubHeader *hdr, GError **error) +fu_vli_usbhub_device_hd1_recover(FuVliUsbhubDevice *self, + FuVliUsbhubHeader *hdr, + FuProgress *progress, + GError **error) { /* point to HD2, i.e. updated firmware */ if (hdr->next_ptr != VLI_USBHUB_FLASHMAP_IDX_HD2) { @@ -930,6 +958,7 @@ fu_vli_usbhub_device_hd1_recover(FuVliUsbhubDevice *self, FuVliUsbhubHeader *hdr VLI_USBHUB_FLASHMAP_ADDR_HD1, (const guint8 *)hdr, sizeof(FuVliUsbhubHeader), + progress, error)) { g_prefix_error(error, "failed to write header1 block at 0x%x: ", @@ -943,7 +972,10 @@ fu_vli_usbhub_device_hd1_recover(FuVliUsbhubDevice *self, FuVliUsbhubHeader *hdr } static gboolean -fu_vli_usbhub_device_update_v2(FuVliUsbhubDevice *self, FuFirmware *firmware, GError **error) +fu_vli_usbhub_device_update_v2(FuVliUsbhubDevice *self, + FuFirmware *firmware, + FuProgress *progress, + GError **error) { gsize buf_fwsz = 0; guint32 hd1_fw_sz; @@ -974,11 +1006,15 @@ fu_vli_usbhub_device_update_v2(FuVliUsbhubDevice *self, FuFirmware *firmware, GE VLI_USBHUB_FLASHMAP_ADDR_HD1_BACKUP, (const guint8 *)&self->hd1_hdr, sizeof(hdr), + progress, error)) { g_prefix_error(error, "failed to write block at header 1: "); return FALSE; } - if (!fu_vli_usbhub_device_hd1_recover(self, &self->hd1_hdr, error)) { + if (!fu_vli_usbhub_device_hd1_recover(self, + &self->hd1_hdr, + progress, + error)) { g_prefix_error(error, "failed to write header: "); return FALSE; } @@ -999,9 +1035,9 @@ fu_vli_usbhub_device_update_v2(FuVliUsbhubDevice *self, FuFirmware *firmware, GE } if (!fu_vli_usbhub_device_hd1_is_valid(&self->hd1_hdr)) { g_debug("backup header is also invalid, starting recovery"); - return fu_vli_usbhub_device_update_v2_recovery(self, fw, error); + return fu_vli_usbhub_device_update_v2_recovery(self, fw, progress, error); } - if (!fu_vli_usbhub_device_hd1_recover(self, &self->hd1_hdr, error)) { + if (!fu_vli_usbhub_device_hd1_recover(self, &self->hd1_hdr, progress, error)) { g_prefix_error(error, "failed to get root header in backup zone: "); return FALSE; } @@ -1027,21 +1063,32 @@ fu_vli_usbhub_device_update_v2(FuVliUsbhubDevice *self, FuFirmware *firmware, GE hd2_fw_offset = GUINT16_FROM_BE(hdr.usb3_fw_addr); g_debug("FW2 @0x%x (length 0x%x, offset 0x%x)", hd2_fw_addr, hd2_fw_sz, hd2_fw_offset); + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_ERASE, 72); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 20); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 8); /* HD2 */ + /* make space */ - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_DEVICE_ERASE); - if (!fu_vli_device_spi_erase(FU_VLI_DEVICE(self), hd2_fw_addr, hd2_fw_sz, error)) + if (!fu_vli_device_spi_erase(FU_VLI_DEVICE(self), + hd2_fw_addr, + hd2_fw_sz, + fu_progress_get_child(progress), + error)) return FALSE; + fu_progress_step_done(progress); /* perform the actual write */ - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_DEVICE_WRITE); if (!fu_vli_device_spi_write(FU_VLI_DEVICE(self), hd2_fw_addr, buf_fw + hd2_fw_offset, hd2_fw_sz, + fu_progress_get_child(progress), error)) { g_prefix_error(error, "failed to write payload: "); return FALSE; } + fu_progress_step_done(progress); /* map into header */ if (!fu_memcpy_safe((guint8 *)&self->hd2_hdr, @@ -1072,29 +1119,33 @@ fu_vli_usbhub_device_update_v2(FuVliUsbhubDevice *self, FuFirmware *firmware, GE VLI_USBHUB_FLASHMAP_ADDR_HD2, (const guint8 *)&self->hd2_hdr, sizeof(self->hd2_hdr), + fu_progress_get_child(progress), error)) { g_prefix_error(error, "failed to write HD2: "); return FALSE; } + fu_progress_step_done(progress); /* success */ return TRUE; } static GBytes * -fu_vli_usbhub_device_dump_firmware(FuDevice *device, GError **error) +fu_vli_usbhub_device_dump_firmware(FuDevice *device, FuProgress *progress, GError **error) { FuVliUsbhubDevice *self = FU_VLI_USBHUB_DEVICE(device); - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_DEVICE_READ); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_READ); return fu_vli_device_spi_read(FU_VLI_DEVICE(self), 0x0, fu_device_get_firmware_size_max(device), + progress, error); } static gboolean fu_vli_usbhub_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -1110,9 +1161,9 @@ fu_vli_usbhub_device_write_firmware(FuDevice *device, /* use correct method */ if (self->update_protocol == 0x1) - return fu_vli_usbhub_device_update_v1(self, firmware, error); + return fu_vli_usbhub_device_update_v1(self, firmware, progress, error); if (self->update_protocol == 0x2) - return fu_vli_usbhub_device_update_v2(self, firmware, error); + return fu_vli_usbhub_device_update_v2(self, firmware, progress, error); /* not sure what to do */ g_set_error(error, @@ -1123,6 +1174,17 @@ fu_vli_usbhub_device_write_firmware(FuDevice *device, return FALSE; } +static void +fu_vli_usbhub_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 94); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* reload */ +} + static void fu_vli_usbhub_device_init(FuVliUsbhubDevice *self) { @@ -1161,6 +1223,7 @@ fu_vli_usbhub_device_class_init(FuVliUsbhubDeviceClass *klass) klass_device->attach = fu_vli_usbhub_device_attach; klass_device->to_string = fu_vli_usbhub_device_to_string; klass_device->ready = fu_vli_usbhub_device_ready; + klass_device->set_progress = fu_vli_usbhub_device_set_progress; klass_vli_device->spi_chip_erase = fu_vli_usbhub_device_spi_chip_erase; klass_vli_device->spi_sector_erase = fu_vli_usbhub_device_spi_sector_erase; klass_vli_device->spi_read_data = fu_vli_usbhub_device_spi_read_data; diff --git a/plugins/vli/fu-vli-usbhub-msp430-device.c b/plugins/vli/fu-vli-usbhub-msp430-device.c index e0784cec2..b9827072e 100644 --- a/plugins/vli/fu-vli-usbhub-msp430-device.c +++ b/plugins/vli/fu-vli-usbhub-msp430-device.c @@ -139,7 +139,7 @@ fu_vli_usbhub_msp430_device_setup(FuDevice *device, GError **error) } static gboolean -fu_vli_usbhub_msp430_device_detach(FuDevice *device, GError **error) +fu_vli_usbhub_msp430_device_detach(FuDevice *device, FuProgress *progress, GError **error) { FuVliUsbhubDevice *parent = FU_VLI_USBHUB_DEVICE(fu_device_get_parent(device)); FuVliUsbhubI2cStatus status = 0xff; @@ -157,8 +157,7 @@ fu_vli_usbhub_msp430_device_detach(FuDevice *device, GError **error) return FALSE; /* avoid power instability by waiting T1 */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); - fu_device_sleep_with_progress(device, 1); /* seconds */ + fu_progress_sleep(progress, 1000); /* check the device came back */ if (!fu_vli_usbhub_device_i2c_read_status(parent, &status, error)) { @@ -225,6 +224,7 @@ fu_vli_usbhub_msp430_device_write_firmware_cb(FuDevice *device, gpointer user_da static gboolean fu_vli_usbhub_msp430_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -238,7 +238,7 @@ fu_vli_usbhub_msp430_device_write_firmware(FuDevice *device, return FALSE; /* transfer by I²C write, and check status by I²C read */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_WRITE); for (guint j = 0; j < records->len; j++) { FuIhexFirmwareRecord *rcd = g_ptr_array_index(records, j); FuVliUsbhubDeviceRequest req = {0x0}; @@ -289,12 +289,10 @@ fu_vli_usbhub_msp430_device_write_firmware(FuDevice *device, &req, error)) return FALSE; - fu_device_set_progress_full(device, (gsize)j, (gsize)records->len); + fu_progress_set_percentage_full(progress, (gsize)j + 1, (gsize)records->len); } /* the device automatically reboots */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); - fu_device_set_progress(device, 0); fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG); /* success */ @@ -321,6 +319,17 @@ fu_vli_usbhub_msp430_device_probe(FuDevice *device, GError **error) return TRUE; } +static void +fu_vli_usbhub_msp430_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 94); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* reload */ +} + static void fu_vli_usbhub_msp430_device_init(FuVliUsbhubMsp430Device *self) { @@ -344,6 +353,7 @@ fu_vli_usbhub_msp430_device_class_init(FuVliUsbhubMsp430DeviceClass *klass) klass_device->detach = fu_vli_usbhub_msp430_device_detach; klass_device->write_firmware = fu_vli_usbhub_msp430_device_write_firmware; klass_device->prepare_firmware = fu_vli_usbhub_msp430_device_prepare_firmware; + klass_device->set_progress = fu_vli_usbhub_msp430_device_set_progress; } FuDevice * diff --git a/plugins/vli/fu-vli-usbhub-pd-device.c b/plugins/vli/fu-vli-usbhub-pd-device.c index 00b996d89..c789e1d5f 100644 --- a/plugins/vli/fu-vli-usbhub-pd-device.c +++ b/plugins/vli/fu-vli-usbhub-pd-device.c @@ -171,7 +171,7 @@ fu_vli_usbhub_pd_device_prepare_firmware(FuDevice *device, } static GBytes * -fu_vli_usbhub_pd_device_dump_firmware(FuDevice *device, GError **error) +fu_vli_usbhub_pd_device_dump_firmware(FuDevice *device, FuProgress *progress, GError **error) { FuVliUsbhubDevice *parent = FU_VLI_USBHUB_DEVICE(fu_device_get_parent(device)); FuVliUsbhubPdDevice *self = FU_VLI_USBHUB_PD_DEVICE(device); @@ -183,16 +183,18 @@ fu_vli_usbhub_pd_device_dump_firmware(FuDevice *device, GError **error) return NULL; /* read */ - fu_device_set_status(FU_DEVICE(device), FWUPD_STATUS_DEVICE_READ); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_READ); return fu_vli_device_spi_read(FU_VLI_DEVICE(parent), fu_vli_common_device_kind_get_offset(self->device_kind), fu_device_get_firmware_size_max(device), + progress, error); } static gboolean fu_vli_usbhub_pd_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -203,6 +205,11 @@ fu_vli_usbhub_pd_device_write_firmware(FuDevice *device, g_autoptr(FuDeviceLocker) locker = NULL; g_autoptr(GBytes) fw = NULL; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_ERASE, 78); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 22); + /* simple image */ fw = fu_firmware_get_bytes(firmware, error); if (fw == NULL) @@ -214,22 +221,24 @@ fu_vli_usbhub_pd_device_write_firmware(FuDevice *device, return FALSE; /* erase */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_ERASE); buf = g_bytes_get_data(fw, &bufsz); if (!fu_vli_device_spi_erase(FU_VLI_DEVICE(parent), fu_vli_common_device_kind_get_offset(self->device_kind), bufsz, + fu_progress_get_child(progress), error)) return FALSE; + fu_progress_step_done(progress); /* write */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); if (!fu_vli_device_spi_write(FU_VLI_DEVICE(parent), fu_vli_common_device_kind_get_offset(self->device_kind), buf, bufsz, + fu_progress_get_child(progress), error)) return FALSE; + fu_progress_step_done(progress); /* success */ return TRUE; @@ -237,13 +246,13 @@ fu_vli_usbhub_pd_device_write_firmware(FuDevice *device, /* reboot the parent FuVliUsbhubDevice if we update the FuVliUsbhubPdDevice */ static gboolean -fu_vli_usbhub_pd_device_attach(FuDevice *device, GError **error) +fu_vli_usbhub_pd_device_attach(FuDevice *device, FuProgress *progress, GError **error) { FuDevice *parent = fu_device_get_parent(device); g_autoptr(FuDeviceLocker) locker = fu_device_locker_new(parent, error); if (locker == NULL) return FALSE; - return fu_device_attach(parent, error); + return fu_device_attach(parent, progress, error); } static gboolean @@ -254,6 +263,17 @@ fu_vli_usbhub_pd_device_probe(FuDevice *device, GError **error) return TRUE; } +static void +fu_vli_usbhub_pd_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 94); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* reload */ +} + static void fu_vli_usbhub_pd_device_init(FuVliUsbhubPdDevice *self) { @@ -279,6 +299,7 @@ fu_vli_usbhub_pd_device_class_init(FuVliUsbhubPdDeviceClass *klass) klass_device->dump_firmware = fu_vli_usbhub_pd_device_dump_firmware; klass_device->write_firmware = fu_vli_usbhub_pd_device_write_firmware; klass_device->prepare_firmware = fu_vli_usbhub_pd_device_prepare_firmware; + klass_device->set_progress = fu_vli_usbhub_pd_device_set_progress; } FuDevice * diff --git a/plugins/vli/fu-vli-usbhub-rtd21xx-device.c b/plugins/vli/fu-vli-usbhub-rtd21xx-device.c index c41465bbc..324d9cfee 100644 --- a/plugins/vli/fu-vli-usbhub-rtd21xx-device.c +++ b/plugins/vli/fu-vli-usbhub-rtd21xx-device.c @@ -257,7 +257,7 @@ fu_vli_usbhub_device_rtd21xx_detach_cb(FuDevice *device, gpointer user_data, GEr } static gboolean -fu_vli_usbhub_rtd21xx_device_detach(FuDevice *device, GError **error) +fu_vli_usbhub_rtd21xx_device_detach(FuDevice *device, FuProgress *progress, GError **error) { FuVliUsbhubDevice *parent = FU_VLI_USBHUB_DEVICE(fu_device_get_parent(device)); g_autoptr(FuDeviceLocker) locker = NULL; @@ -275,7 +275,7 @@ fu_vli_usbhub_rtd21xx_device_detach(FuDevice *device, GError **error) } static gboolean -fu_vli_usbhub_rtd21xx_device_attach(FuDevice *device, GError **error) +fu_vli_usbhub_rtd21xx_device_attach(FuDevice *device, FuProgress *progress, GError **error) { FuVliUsbhubDevice *parent = FU_VLI_USBHUB_DEVICE(fu_device_get_parent(device)); guint8 buf[] = {ISP_CMD_FW_UPDATE_RESET}; @@ -303,6 +303,7 @@ fu_vli_usbhub_rtd21xx_device_attach(FuDevice *device, GError **error) static gboolean fu_vli_usbhub_rtd21xx_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -318,6 +319,13 @@ fu_vli_usbhub_rtd21xx_device_write_firmware(FuDevice *device, g_autoptr(GBytes) fw = NULL; g_autoptr(GPtrArray) chunks = NULL; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 10); /* enable ISP */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 50); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 10); /* restart */ + /* open device */ locker = fu_device_locker_new(parent, error); if (locker == NULL) @@ -332,7 +340,6 @@ fu_vli_usbhub_rtd21xx_device_write_firmware(FuDevice *device, /* enable ISP high priority */ write_buf[0] = ISP_CMD_ENTER_FW_UPDATE; write_buf[1] = 0x01; - fu_device_set_status(device, FWUPD_STATUS_DEVICE_BUSY); if (!fu_vli_usbhub_device_i2c_write(parent, UC_FOREGROUND_SLAVE_ADDR, UC_FOREGROUND_OPCODE, @@ -347,7 +354,6 @@ fu_vli_usbhub_rtd21xx_device_write_firmware(FuDevice *device, /* get project ID address */ write_buf[0] = ISP_CMD_GET_PROJECT_ID_ADDR; - fu_device_set_status(device, FWUPD_STATUS_DEVICE_READ); if (!fu_vli_usbhub_device_i2c_write(parent, UC_FOREGROUND_SLAVE_ADDR, UC_FOREGROUND_OPCODE, @@ -395,7 +401,6 @@ fu_vli_usbhub_rtd21xx_device_write_firmware(FuDevice *device, g_prefix_error(error, "failed to write project ID from 0x%04x: ", project_addr); return FALSE; } - fu_device_set_status(device, FWUPD_STATUS_DEVICE_BUSY); if (!fu_vli_usbhub_device_i2c_write(parent, UC_FOREGROUND_SLAVE_ADDR, UC_FOREGROUND_OPCODE, @@ -420,9 +425,9 @@ fu_vli_usbhub_rtd21xx_device_write_firmware(FuDevice *device, g_prefix_error(error, "failed to send fw update start cmd: "); return FALSE; } + fu_progress_step_done(progress); /* send data */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); chunks = fu_chunk_array_new_from_bytes(fw, 0x00, /* start addr */ 0x00, /* page_sz */ @@ -444,11 +449,13 @@ fu_vli_usbhub_rtd21xx_device_write_firmware(FuDevice *device, } /* update progress */ - fu_device_set_progress_full(device, (gsize)i, (gsize)chunks->len); + fu_progress_set_percentage_full(fu_progress_get_child(progress), + (gsize)i + 1, + (gsize)chunks->len); } + fu_progress_step_done(progress); /* update finish command */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_BUSY); if (!fu_vli_usbhub_device_rtd21xx_read_status(self, NULL, error)) return FALSE; write_buf[0] = ISP_CMD_FW_UPDATE_ISP_DONE; @@ -461,10 +468,9 @@ fu_vli_usbhub_rtd21xx_device_write_firmware(FuDevice *device, g_prefix_error(error, "failed update finish cmd: "); return FALSE; } + fu_progress_step_done(progress); /* exit background-fw mode */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); - fu_device_set_progress(device, 0); if (!fu_vli_usbhub_device_rtd21xx_read_status(self, NULL, error)) return FALSE; write_buf[0] = ISP_CMD_FW_UPDATE_EXIT; @@ -480,9 +486,10 @@ fu_vli_usbhub_rtd21xx_device_write_firmware(FuDevice *device, /* the device needs some time to restart with the new firmware before * it can be queried again */ - fu_device_sleep_with_progress(device, 20); + fu_progress_sleep(progress, 20000); /* success */ + fu_progress_step_done(progress); return TRUE; } @@ -518,6 +525,17 @@ fu_vli_usbhub_rtd21xx_device_probe(FuDevice *device, GError **error) return TRUE; } +static void +fu_vli_usbhub_rtd21xx_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 94); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* reload */ +} + static void fu_vli_usbhub_rtd21xx_device_init(FuVliUsbhubRtd21xxDevice *self) { @@ -541,6 +559,7 @@ fu_vli_usbhub_rtd21xx_device_class_init(FuVliUsbhubRtd21xxDeviceClass *klass) klass_device->attach = fu_vli_usbhub_rtd21xx_device_attach; klass_device->detach = fu_vli_usbhub_rtd21xx_device_detach; klass_device->write_firmware = fu_vli_usbhub_rtd21xx_device_write_firmware; + klass_device->set_progress = fu_vli_usbhub_rtd21xx_device_set_progress; } FuDevice * diff --git a/plugins/wacom-raw/fu-wacom-aes-device.c b/plugins/wacom-raw/fu-wacom-aes-device.c index 5fe47404e..a9bcd9d02 100644 --- a/plugins/wacom-raw/fu-wacom-aes-device.c +++ b/plugins/wacom-raw/fu-wacom-aes-device.c @@ -153,7 +153,7 @@ fu_wacom_aes_device_setup(FuDevice *device, GError **error) } static gboolean -fu_wacom_aes_device_erase_all(FuWacomAesDevice *self, GError **error) +fu_wacom_aes_device_erase_all(FuWacomAesDevice *self, FuProgress *progress, GError **error) { FuWacomRawRequest req = {.cmd = FU_WACOM_RAW_BL_CMD_ALL_ERASE, .echo = FU_WACOM_RAW_ECHO_DEFAULT, @@ -168,7 +168,7 @@ fu_wacom_aes_device_erase_all(FuWacomAesDevice *self, GError **error) g_prefix_error(error, "failed to send eraseall command: "); return FALSE; } - fu_device_sleep_with_progress(FU_DEVICE(self), 2); /* seconds */ + fu_progress_sleep(progress, 2000); return TRUE; } @@ -224,17 +224,25 @@ fu_wacom_aes_device_write_block(FuWacomAesDevice *self, } static gboolean -fu_wacom_aes_device_write_firmware(FuDevice *device, GPtrArray *chunks, GError **error) +fu_wacom_aes_device_write_firmware(FuDevice *device, + GPtrArray *chunks, + FuProgress *progress, + GError **error) { FuWacomAesDevice *self = FU_WACOM_AES_DEVICE(device); + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_ERASE, 20); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 80); + /* erase */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_ERASE); - if (!fu_wacom_aes_device_erase_all(self, error)) + if (!fu_wacom_aes_device_erase_all(self, progress, error)) return FALSE; + fu_progress_step_done(progress); /* write */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); for (guint i = 0; i < chunks->len; i++) { FuChunk *chk = g_ptr_array_index(chunks, i); if (!fu_wacom_aes_device_write_block(self, @@ -244,8 +252,11 @@ fu_wacom_aes_device_write_firmware(FuDevice *device, GPtrArray *chunks, GError * fu_chunk_get_data_sz(chk), error)) return FALSE; - fu_device_set_progress_full(device, (gsize)i, (gsize)chunks->len); + fu_progress_set_percentage_full(fu_progress_get_child(progress), + (gsize)i, + (gsize)chunks->len); } + fu_progress_step_done(progress); return TRUE; } diff --git a/plugins/wacom-raw/fu-wacom-device.c b/plugins/wacom-raw/fu-wacom-device.c index ba8cc534a..0d1653d4f 100644 --- a/plugins/wacom-raw/fu-wacom-device.c +++ b/plugins/wacom-raw/fu-wacom-device.c @@ -106,7 +106,7 @@ fu_wacom_device_probe(FuDevice *device, GError **error) } static gboolean -fu_wacom_device_detach(FuDevice *device, GError **error) +fu_wacom_device_detach(FuDevice *device, FuProgress *progress, GError **error) { FuWacomDevice *self = FU_WACOM_DEVICE(device); guint8 buf[FU_WACOM_RAW_FW_REPORT_SZ] = { @@ -127,7 +127,7 @@ fu_wacom_device_detach(FuDevice *device, GError **error) } static gboolean -fu_wacom_device_attach(FuDevice *device, GError **error) +fu_wacom_device_attach(FuDevice *device, FuProgress *progress, GError **error) { FuWacomDevice *self = FU_WACOM_DEVICE(device); FuWacomRawRequest req = {.report_id = FU_WACOM_RAW_BL_REPORT_ID_SET, @@ -212,6 +212,7 @@ fu_wacom_device_prepare_firmware(FuDevice *device, static gboolean fu_wacom_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -256,7 +257,7 @@ fu_wacom_device_write_firmware(FuDevice *device, priv->flash_base_addr, 0x00, /* page_sz */ priv->flash_block_size); - return klass->write_firmware(device, chunks, error); + return klass->write_firmware(device, chunks, progress, error); } gboolean @@ -342,6 +343,17 @@ fu_wacom_device_set_quirk_kv(FuDevice *device, const gchar *key, const gchar *va return FALSE; } +static void +fu_wacom_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 98); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* reload */ +} + static void fu_wacom_device_init(FuWacomDevice *self) { @@ -363,4 +375,5 @@ fu_wacom_device_class_init(FuWacomDeviceClass *klass) klass_device->detach = fu_wacom_device_detach; klass_device->set_quirk_kv = fu_wacom_device_set_quirk_kv; klass_device->probe = fu_wacom_device_probe; + klass_device->set_progress = fu_wacom_device_set_progress; } diff --git a/plugins/wacom-raw/fu-wacom-device.h b/plugins/wacom-raw/fu-wacom-device.h index 7cbca021b..f82c558c1 100644 --- a/plugins/wacom-raw/fu-wacom-device.h +++ b/plugins/wacom-raw/fu-wacom-device.h @@ -15,7 +15,10 @@ G_DECLARE_DERIVABLE_TYPE(FuWacomDevice, fu_wacom_device, FU, WACOM_DEVICE, FuUde struct _FuWacomDeviceClass { FuUdevDeviceClass parent_class; - gboolean (*write_firmware)(FuDevice *self, GPtrArray *chunks, GError **error); + gboolean (*write_firmware)(FuDevice *self, + GPtrArray *chunks, + FuProgress *progress, + GError **error); }; typedef enum { diff --git a/plugins/wacom-raw/fu-wacom-emr-device.c b/plugins/wacom-raw/fu-wacom-emr-device.c index c64b8e021..ecafedf1f 100644 --- a/plugins/wacom-raw/fu-wacom-emr-device.c +++ b/plugins/wacom-raw/fu-wacom-emr-device.c @@ -197,14 +197,22 @@ fu_wacom_emr_device_write_block(FuWacomEmrDevice *self, } static gboolean -fu_wacom_emr_device_write_firmware(FuDevice *device, GPtrArray *chunks, GError **error) +fu_wacom_emr_device_write_firmware(FuDevice *device, + GPtrArray *chunks, + FuProgress *progress, + GError **error) { FuWacomEmrDevice *self = FU_WACOM_EMR_DEVICE(device); guint8 idx = 0; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_ERASE, 10); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 90); + /* erase W9013 */ if (fu_device_has_instance_id(device, "WacomEMR_W9013")) { - fu_device_set_status(device, FWUPD_STATUS_DEVICE_ERASE); if (!fu_wacom_emr_device_w9013_erase_data(self, error)) return FALSE; for (guint i = 127; i >= 8; i--) { @@ -218,9 +226,9 @@ fu_wacom_emr_device_write_firmware(FuDevice *device, GPtrArray *chunks, GError * if (!fu_wacom_device_w9021_erase_all(self, error)) return FALSE; } + fu_progress_step_done(progress); /* write */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); for (guint i = 0; i < chunks->len; i++) { FuChunk *chk = g_ptr_array_index(chunks, i); if (fu_wacom_common_block_is_empty(fu_chunk_get_data(chk), @@ -233,10 +241,12 @@ fu_wacom_emr_device_write_firmware(FuDevice *device, GPtrArray *chunks, GError * fu_chunk_get_data_sz(chk), error)) return FALSE; - fu_device_set_progress_full(device, (gsize)i, (gsize)chunks->len); + fu_progress_set_percentage_full(fu_progress_get_child(progress), + (gsize)i + 1, + (gsize)chunks->len); } + fu_progress_step_done(progress); - fu_device_set_progress(device, 100); return TRUE; } diff --git a/plugins/wacom-usb/fu-plugin-wacom-usb.c b/plugins/wacom-usb/fu-plugin-wacom-usb.c index 44f15b94a..c7bc24dec 100644 --- a/plugins/wacom-usb/fu-plugin-wacom-usb.c +++ b/plugins/wacom-usb/fu-plugin-wacom-usb.c @@ -25,6 +25,7 @@ gboolean fu_plugin_write_firmware(FuPlugin *plugin, FuDevice *device, GBytes *blob_fw, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -33,5 +34,5 @@ fu_plugin_write_firmware(FuPlugin *plugin, locker = fu_device_locker_new(parent != NULL ? parent : device, error); if (locker == NULL) return FALSE; - return fu_device_write_firmware(device, blob_fw, flags, error); + return fu_device_write_firmware(device, blob_fw, progress, flags, error); } diff --git a/plugins/wacom-usb/fu-wac-device.c b/plugins/wacom-usb/fu-wac-device.c index 34f555b00..3cab6fc58 100644 --- a/plugins/wacom-usb/fu-wac-device.c +++ b/plugins/wacom-usb/fu-wac-device.c @@ -471,6 +471,7 @@ fu_wac_device_prepare_firmware(FuDevice *device, static gboolean fu_wac_device_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -481,6 +482,14 @@ fu_wac_device_write_firmware(FuDevice *device, g_autoptr(FuFirmware) img = NULL; g_autoptr(GHashTable) fd_blobs = NULL; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 1); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_ERASE, 1); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 95); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_VERIFY, 2); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 1); + /* get current selected device */ if (!fu_wac_device_ensure_firmware_index(self, error)) return FALSE; @@ -506,9 +515,9 @@ fu_wac_device_write_firmware(FuDevice *device, /* get the updater protocol version */ if (!fu_wac_device_ensure_checksums(self, error)) return FALSE; + fu_progress_step_done(progress); /* clear all checksums of pages */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_ERASE); for (guint16 i = 0; i < self->flash_descriptors->len; i++) { FuWacFlashDescriptor *fd = g_ptr_array_index(self->flash_descriptors, i); if (fu_wav_device_flash_descriptor_is_wp(fd)) @@ -516,6 +525,7 @@ fu_wac_device_write_firmware(FuDevice *device, if (!fu_wac_device_set_checksum_of_block(self, i, 0x0, error)) return FALSE; } + fu_progress_step_done(progress); /* get the blobs for each chunk */ fd_blobs = g_hash_table_new_full(g_direct_hash, @@ -537,10 +547,9 @@ fu_wac_device_write_firmware(FuDevice *device, } /* checksum actions post-write */ - blocks_total = g_hash_table_size(fd_blobs) + 2; + blocks_total = g_hash_table_size(fd_blobs); /* write the data into the flash page */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); csum_local = g_new0(guint32, self->flash_descriptors->len); for (guint16 i = 0; i < self->flash_descriptors->len; i++) { FuWacFlashDescriptor *fd = g_ptr_array_index(self->flash_descriptors, i); @@ -559,7 +568,9 @@ fu_wac_device_write_firmware(FuDevice *device, /* ignore empty blocks */ if (fu_common_bytes_is_empty(blob_block)) { g_debug("empty block, ignoring"); - fu_device_set_progress_full(device, blocks_done++, blocks_total); + fu_progress_set_percentage_full(fu_progress_get_child(progress), + blocks_done++, + blocks_total); continue; } @@ -590,8 +601,11 @@ fu_wac_device_write_firmware(FuDevice *device, return FALSE; /* update device progress */ - fu_device_set_progress_full(device, blocks_done++, blocks_total); + fu_progress_set_percentage_full(fu_progress_get_child(progress), + blocks_done++, + blocks_total); } + fu_progress_step_done(progress); /* check at least one block was written */ if (blocks_done == 0) { @@ -608,9 +622,6 @@ fu_wac_device_write_firmware(FuDevice *device, return FALSE; } - /* update device progress */ - fu_device_set_progress_full(device, blocks_done++, blocks_total); - /* read all CRC of all pages and verify with local CRC */ if (!fu_wac_device_ensure_checksums(self, error)) return FALSE; @@ -646,16 +657,14 @@ fu_wac_device_write_firmware(FuDevice *device, if (g_getenv("FWUPD_WACOM_USB_VERBOSE") != NULL) g_debug("matched checksum at block %u of 0x%08x", i, csum_rom); } - - /* update device progress */ - fu_device_set_progress_full(device, blocks_done++, blocks_total); + fu_progress_step_done(progress); /* store host CRC into flash */ if (!fu_wac_device_write_checksum_table(self, error)) return FALSE; + fu_progress_step_done(progress); - /* update progress */ - fu_device_set_progress_full(device, blocks_total, blocks_total); + /* success */ return TRUE; } @@ -861,11 +870,20 @@ fu_wac_device_close(FuDevice *device, GError **error) static gboolean fu_wac_device_cleanup(FuDevice *device, FwupdInstallFlags flags, GError **error) { - fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG); return fu_wac_device_update_reset(FU_WAC_DEVICE(device), error); } +static void +fu_wac_device_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 98); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* reload */ +} + static void fu_wac_device_init(FuWacDevice *self) { @@ -904,4 +922,5 @@ fu_wac_device_class_init(FuWacDeviceClass *klass) klass_device->setup = fu_wac_device_setup; klass_device->cleanup = fu_wac_device_cleanup; klass_device->close = fu_wac_device_close; + klass_device->set_progress = fu_wac_device_set_progress; } diff --git a/plugins/wacom-usb/fu-wac-module-bluetooth.c b/plugins/wacom-usb/fu-wac-module-bluetooth.c index c480ec8c5..b62aab89f 100644 --- a/plugins/wacom-usb/fu-wac-module-bluetooth.c +++ b/plugins/wacom-usb/fu-wac-module-bluetooth.c @@ -116,18 +116,24 @@ fu_wac_module_bluetooth_parse_blocks(const guint8 *data, static gboolean fu_wac_module_bluetooth_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { FuWacModule *self = FU_WAC_MODULE(device); const guint8 *data; gsize len = 0; - gsize blocks_total = 0; const guint8 buf_start[] = {0x00}; g_autoptr(GPtrArray) blocks = NULL; g_autoptr(GBytes) blob_start = g_bytes_new_static(buf_start, 1); g_autoptr(GBytes) fw = NULL; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_ERASE, 20); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 79); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 1); + /* get default image */ fw = fu_firmware_get_bytes(firmware, error); if (fw == NULL) @@ -138,18 +144,17 @@ fu_wac_module_bluetooth_write_firmware(FuDevice *device, blocks = fu_wac_module_bluetooth_parse_blocks(data, len, TRUE, error); if (blocks == NULL) return FALSE; - blocks_total = blocks->len + 2; /* start, which will erase the module */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_ERASE); - if (!fu_wac_module_set_feature(self, FU_WAC_MODULE_COMMAND_START, blob_start, error)) + if (!fu_wac_module_set_feature(self, + FU_WAC_MODULE_COMMAND_START, + blob_start, + fu_progress_get_child(progress), + error)) return FALSE; - - /* update progress */ - fu_device_set_progress_full(device, 1, blocks_total); + fu_progress_step_done(progress); /* data */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); for (guint i = 0; i < blocks->len; i++) { FuWacModuleBluetoothBlockData *bd = g_ptr_array_index(blocks, i); guint8 buf[256 + 11]; @@ -162,19 +167,30 @@ fu_wac_module_bluetooth_write_firmware(FuDevice *device, buf[10] = bd->crc; memcpy(&buf[11], bd->cdata, sizeof(bd->cdata)); blob_chunk = g_bytes_new(buf, sizeof(buf)); - if (!fu_wac_module_set_feature(self, FU_WAC_MODULE_COMMAND_DATA, blob_chunk, error)) + if (!fu_wac_module_set_feature(self, + FU_WAC_MODULE_COMMAND_DATA, + blob_chunk, + fu_progress_get_child(progress), + error)) return FALSE; /* update progress */ - fu_device_set_progress_full(device, i + 1, blocks_total); + fu_progress_set_percentage_full(fu_progress_get_child(progress), + i + 1, + blocks->len); } + fu_progress_step_done(progress); /* end */ - if (!fu_wac_module_set_feature(self, FU_WAC_MODULE_COMMAND_END, NULL, error)) + if (!fu_wac_module_set_feature(self, + FU_WAC_MODULE_COMMAND_END, + NULL, + fu_progress_get_child(progress), + error)) return FALSE; + fu_progress_step_done(progress); - /* update progress */ - fu_device_set_progress_full(device, blocks_total, blocks_total); + /* success */ return TRUE; } diff --git a/plugins/wacom-usb/fu-wac-module-touch.c b/plugins/wacom-usb/fu-wac-module-touch.c index 1a991396c..981d13fea 100644 --- a/plugins/wacom-usb/fu-wac-module-touch.c +++ b/plugins/wacom-usb/fu-wac-module-touch.c @@ -34,14 +34,21 @@ fu_wac_module_touch_prepare_firmware(FuDevice *device, static gboolean fu_wac_module_touch_write_firmware(FuDevice *device, FuFirmware *firmware, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { FuWacModule *self = FU_WAC_MODULE(device); - gsize blocks_total = 0; g_autoptr(GBytes) fw = NULL; g_autoptr(GPtrArray) chunks = NULL; + /* progress */ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_ERASE, 10); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 90); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 10); + g_debug("using element at addr 0x%0x", (guint)fu_firmware_get_addr(firmware)); /* build each data packet */ @@ -52,18 +59,17 @@ fu_wac_module_touch_write_firmware(FuDevice *device, fu_firmware_get_addr(firmware), 0x0, /* page_sz */ 128); /* packet_sz */ - blocks_total = chunks->len + 2; /* start, which will erase the module */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_ERASE); - if (!fu_wac_module_set_feature(self, FU_WAC_MODULE_COMMAND_START, NULL, error)) + if (!fu_wac_module_set_feature(self, + FU_WAC_MODULE_COMMAND_START, + NULL, + fu_progress_get_child(progress), + error)) return FALSE; - - /* update progress */ - fu_device_set_progress_full(device, 1, blocks_total); + fu_progress_step_done(progress); /* data */ - fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); for (guint i = 0; i < chunks->len; i++) { FuChunk *chk = g_ptr_array_index(chunks, i); guint8 buf[128 + 7] = {0xff}; @@ -80,21 +86,29 @@ fu_wac_module_touch_write_firmware(FuDevice *device, if (!fu_wac_module_set_feature(self, FU_WAC_MODULE_COMMAND_DATA, blob_chunk, + fu_progress_get_child(progress), error)) { g_prefix_error(error, "failed to write block %u: ", fu_chunk_get_idx(chk)); return FALSE; } /* update progress */ - fu_device_set_progress_full(device, i + 1, blocks_total); + fu_progress_set_percentage_full(fu_progress_get_child(progress), + i + 1, + chunks->len); } + fu_progress_step_done(progress); /* end */ - if (!fu_wac_module_set_feature(self, FU_WAC_MODULE_COMMAND_END, NULL, error)) + if (!fu_wac_module_set_feature(self, + FU_WAC_MODULE_COMMAND_END, + NULL, + fu_progress_get_child(progress), + error)) return FALSE; + fu_progress_step_done(progress); - /* update progress */ - fu_device_set_progress_full(device, blocks_total, blocks_total); + /* success */ return TRUE; } diff --git a/plugins/wacom-usb/fu-wac-module.c b/plugins/wacom-usb/fu-wac-module.c index e1395cb73..4e1a4eda6 100644 --- a/plugins/wacom-usb/fu-wac-module.c +++ b/plugins/wacom-usb/fu-wac-module.c @@ -169,6 +169,7 @@ gboolean fu_wac_module_set_feature(FuWacModule *self, guint8 command, GBytes *blob, /* optional */ + FuProgress *progress, GError **error) { FuWacDevice *parent_device = FU_WAC_DEVICE(fu_device_get_parent(FU_DEVICE(self))); @@ -204,13 +205,13 @@ fu_wac_module_set_feature(FuWacModule *self, /* tell the daemon the current status */ switch (command) { case FU_WAC_MODULE_COMMAND_START: - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_DEVICE_ERASE); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_ERASE); break; case FU_WAC_MODULE_COMMAND_DATA: - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_DEVICE_WRITE); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_WRITE); break; case FU_WAC_MODULE_COMMAND_END: - fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_DEVICE_VERIFY); + fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_VERIFY); break; default: break; @@ -344,6 +345,16 @@ fu_wac_module_constructed(GObject *object) G_OBJECT_CLASS(fu_wac_module_parent_class)->constructed(object); } +static void +fu_wac_module_set_progress(FuDevice *self, FuProgress *progress) +{ + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 100); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 0); /* reload */ +} + static void fu_wac_module_finalize(GObject *object) { @@ -383,4 +394,5 @@ fu_wac_module_class_init(FuWacModuleClass *klass) object_class->finalize = fu_wac_module_finalize; klass_device->to_string = fu_wac_module_to_string; klass_device->cleanup = fu_wac_module_cleanup; + klass_device->set_progress = fu_wac_module_set_progress; } diff --git a/plugins/wacom-usb/fu-wac-module.h b/plugins/wacom-usb/fu-wac-module.h index 74f8d676b..9b69b449c 100644 --- a/plugins/wacom-usb/fu-wac-module.h +++ b/plugins/wacom-usb/fu-wac-module.h @@ -26,4 +26,8 @@ struct _FuWacModuleClass { #define FU_WAC_MODULE_COMMAND_END 0x03 gboolean -fu_wac_module_set_feature(FuWacModule *self, guint8 command, GBytes *blob, GError **error); +fu_wac_module_set_feature(FuWacModule *self, + guint8 command, + GBytes *blob, + FuProgress *progress, + GError **error); diff --git a/src/fu-engine.c b/src/fu-engine.c index b81f7917e..a81c6349b 100644 --- a/src/fu-engine.c +++ b/src/fu-engine.c @@ -54,6 +54,7 @@ #include "fu-plugin-list.h" #include "fu-plugin-private.h" #include "fu-plugin.h" +#include "fu-progress.h" #include "fu-quirks.h" #include "fu-remote-list.h" #include "fu-security-attr.h" @@ -202,19 +203,21 @@ fu_engine_set_percentage(FuEngine *self, guint percentage) } static void -fu_engine_progress_notify_cb(FuDevice *device, GParamSpec *pspec, FuEngine *self) +fu_engine_progress_percentage_changed_cb(FuProgress *progress, guint percentage, FuEngine *self) { - if (fu_device_get_status(device) == FWUPD_STATUS_UNKNOWN) - return; - fu_engine_set_percentage(self, fu_device_get_progress(device)); - fu_engine_emit_device_changed(self, device); + /* this is global for all the tasks and divisions */ + fu_engine_set_percentage(self, percentage); } static void -fu_engine_status_notify_cb(FuDevice *device, GParamSpec *pspec, FuEngine *self) +fu_engine_progress_status_changed_cb(FuProgress *progress, FwupdStatus status, FuEngine *self) { - fu_engine_set_status(self, fu_device_get_status(device)); - fu_engine_emit_device_changed(self, device); + /* ignore */ + if (status == FWUPD_STATUS_UNKNOWN) + return; + + /* this is global for all the tasks and divisions */ + fu_engine_set_status(self, status); } static void @@ -249,19 +252,10 @@ fu_engine_watch_device(FuEngine *self, FuDevice *device) { g_autoptr(FuDevice) device_old = fu_device_list_get_old(self->device_list, device); if (device_old != NULL) { - g_signal_handlers_disconnect_by_func(device_old, - fu_engine_progress_notify_cb, - self); - g_signal_handlers_disconnect_by_func(device_old, fu_engine_status_notify_cb, self); g_signal_handlers_disconnect_by_func(device_old, fu_engine_generic_notify_cb, self); g_signal_handlers_disconnect_by_func(device_old, fu_engine_history_notify_cb, self); g_signal_handlers_disconnect_by_func(device_old, fu_engine_device_request_cb, self); } - g_signal_connect(device, - "notify::progress", - G_CALLBACK(fu_engine_progress_notify_cb), - self); - g_signal_connect(device, "notify::status", G_CALLBACK(fu_engine_status_notify_cb), self); g_signal_connect(device, "notify::flags", G_CALLBACK(fu_engine_generic_notify_cb), self); g_signal_connect(device, "notify::update-message", @@ -847,6 +841,7 @@ fu_engine_verify_update(FuEngine *self, const gchar *device_id, GError **error) g_autofree gchar *fn = NULL; g_autofree gchar *localstatedir = NULL; g_autoptr(FuDevice) device = NULL; + g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC); g_autoptr(GFile) file = NULL; g_autoptr(XbBuilder) builder = xb_builder_new(); g_autoptr(XbBuilderNode) component = NULL; @@ -859,6 +854,17 @@ fu_engine_verify_update(FuEngine *self, const gchar *device_id, GError **error) g_return_val_if_fail(device_id != NULL, FALSE); g_return_val_if_fail(error == NULL || *error == NULL, FALSE); + /* progress */ + fu_progress_set_profile(progress, g_getenv("FWUPD_VERBOSE") != NULL); + g_signal_connect(progress, + "percentage-changed", + G_CALLBACK(fu_engine_progress_percentage_changed_cb), + self); + g_signal_connect(progress, + "status-changed", + G_CALLBACK(fu_engine_progress_status_changed_cb), + self); + /* check the devices still exists */ device = fu_device_list_get_by_id(self->device_list, device_id, error); if (device == NULL) @@ -873,7 +879,11 @@ fu_engine_verify_update(FuEngine *self, const gchar *device_id, GError **error) /* get the checksum */ checksums = fu_device_get_checksums(device); if (checksums->len == 0) { - if (!fu_plugin_runner_verify(plugin, device, FU_PLUGIN_VERIFY_FLAG_NONE, error)) + if (!fu_plugin_runner_verify(plugin, + device, + progress, + FU_PLUGIN_VERIFY_FLAG_NONE, + error)) return FALSE; fu_engine_emit_device_changed(self, device); } @@ -1071,6 +1081,7 @@ fu_engine_verify(FuEngine *self, const gchar *device_id, GError **error) FuPlugin *plugin; GPtrArray *checksums; g_autoptr(FuDevice) device = NULL; + g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC); g_autoptr(GError) error_local = NULL; g_autoptr(GString) xpath_csum = g_string_new(NULL); g_autoptr(XbNode) csum = NULL; @@ -1080,6 +1091,17 @@ fu_engine_verify(FuEngine *self, const gchar *device_id, GError **error) g_return_val_if_fail(device_id != NULL, FALSE); g_return_val_if_fail(error == NULL || *error == NULL, FALSE); + /* progress */ + fu_progress_set_profile(progress, g_getenv("FWUPD_VERBOSE") != NULL); + g_signal_connect(progress, + "percentage-changed", + G_CALLBACK(fu_engine_progress_percentage_changed_cb), + self); + g_signal_connect(progress, + "status-changed", + G_CALLBACK(fu_engine_progress_status_changed_cb), + self); + /* check the id exists */ device = fu_device_list_get_by_id(self->device_list, device_id, error); if (device == NULL) @@ -1093,7 +1115,11 @@ fu_engine_verify(FuEngine *self, const gchar *device_id, GError **error) /* update the device firmware hashes if possible */ if (fu_device_has_flag(device, FWUPD_DEVICE_FLAG_CAN_VERIFY_IMAGE)) { - if (!fu_plugin_runner_verify(plugin, device, FU_PLUGIN_VERIFY_FLAG_NONE, error)) + if (!fu_plugin_runner_verify(plugin, + device, + progress, + FU_PLUGIN_VERIFY_FLAG_NONE, + error)) return FALSE; } @@ -2057,6 +2083,7 @@ fu_engine_install_tasks(FuEngine *self, g_autoptr(FuIdleLocker) locker = NULL; g_autoptr(GPtrArray) devices = NULL; g_autoptr(GPtrArray) devices_new = NULL; + g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC); /* do not allow auto-shutdown during this time */ locker = fu_idle_locker_new(self->idle, "update"); @@ -2077,9 +2104,25 @@ fu_engine_install_tasks(FuEngine *self, } /* all authenticated, so install all the things */ + fu_progress_set_steps(progress, install_tasks->len); + fu_progress_set_profile(progress, g_getenv("FWUPD_VERBOSE") != NULL); + g_signal_connect(progress, + "percentage-changed", + G_CALLBACK(fu_engine_progress_percentage_changed_cb), + self); + g_signal_connect(progress, + "status-changed", + G_CALLBACK(fu_engine_progress_status_changed_cb), + self); for (guint i = 0; i < install_tasks->len; i++) { FuInstallTask *task = g_ptr_array_index(install_tasks, i); - if (!fu_engine_install(self, task, blob_cab, flags, feature_flags, error)) { + if (!fu_engine_install(self, + task, + blob_cab, + fu_progress_get_child(progress), + flags, + feature_flags, + error)) { g_autoptr(GError) error_local = NULL; if (!fu_engine_composite_cleanup(self, devices, &error_local)) { g_warning("failed to cleanup failed composite action: %s", @@ -2087,13 +2130,14 @@ fu_engine_install_tasks(FuEngine *self, } return FALSE; } + fu_progress_step_done(progress); } /* set all the device statuses back to unknown */ for (guint i = 0; i < install_tasks->len; i++) { FuInstallTask *task = g_ptr_array_index(install_tasks, i); FuDevice *device = fu_install_task_get_device(task); - fu_device_set_status(device, FWUPD_STATUS_UNKNOWN); + fwupd_device_set_status(FWUPD_DEVICE(device), FWUPD_STATUS_UNKNOWN); } /* get a new list of devices in case they replugged */ @@ -2120,6 +2164,7 @@ fu_engine_install_tasks(FuEngine *self, } /* success */ + fu_engine_set_status(self, FWUPD_STATUS_IDLE); return TRUE; } @@ -2312,7 +2357,6 @@ fu_engine_schedule_update(FuEngine *self, filename = g_build_filename(dirname, tmpname, NULL); /* just copy to the temp file */ - fu_device_set_status(device, FWUPD_STATUS_SCHEDULING); if (!g_file_set_contents(filename, g_bytes_get_data(blob_cab, NULL), (gssize)g_bytes_get_size(blob_cab), @@ -2332,7 +2376,6 @@ fu_engine_schedule_update(FuEngine *self, return FALSE; /* next boot we run offline */ - fu_device_set_progress(device, 100); return fu_engine_offline_setup(error); } @@ -2341,6 +2384,7 @@ fu_engine_install_release(FuEngine *self, FuDevice *device_orig, XbNode *component, XbNode *rel, + FuProgress *progress, FwupdInstallFlags flags, FwupdFeatureFlags feature_flags, GError **error) @@ -2414,8 +2458,13 @@ fu_engine_install_release(FuEngine *self, /* install firmware blob */ version_orig = g_strdup(fu_device_get_version(device)); - if (!fu_engine_install_blob(self, device, blob_fw2, flags, feature_flags, &error_local)) { - fu_device_set_status(device, FWUPD_STATUS_IDLE); + if (!fu_engine_install_blob(self, + device, + blob_fw2, + progress, + flags, + feature_flags, + &error_local)) { if (g_error_matches(error_local, FWUPD_ERROR, FWUPD_ERROR_AC_POWER_REQUIRED) || g_error_matches(error_local, FWUPD_ERROR, FWUPD_ERROR_BATTERY_LEVEL_TOO_LOW) || g_error_matches(error_local, FWUPD_ERROR, FWUPD_ERROR_NEEDS_USER_ACTION) || @@ -2513,6 +2562,7 @@ fu_engine_sort_releases(FuEngine *self, FuDevice *device, GPtrArray *rels, GErro * @self: a #FuEngine * @task: a #FuInstallTask * @blob_cab: the #GBytes of the .cab file + * @progress: a #FuProgress * @flags: install flags, e.g. %FWUPD_INSTALL_FLAG_ALLOW_OLDER * @feature_flags: feature flags, e.g. %FWUPD_FEATURE_FLAG_NONE * @error: (nullable): optional return location for an error @@ -2529,6 +2579,7 @@ gboolean fu_engine_install(FuEngine *self, FuInstallTask *task, GBytes *blob_cab, + FuProgress *progress, FwupdInstallFlags flags, FwupdFeatureFlags feature_flags, GError **error) @@ -2542,6 +2593,7 @@ fu_engine_install(FuEngine *self, #endif g_return_val_if_fail(FU_IS_ENGINE(self), FALSE); + g_return_val_if_fail(FU_IS_PROGRESS(progress), FALSE); g_return_val_if_fail(XB_IS_NODE(component), FALSE); g_return_val_if_fail(blob_cab != NULL, FALSE); g_return_val_if_fail(error == NULL || *error == NULL, FALSE); @@ -2597,6 +2649,7 @@ fu_engine_install(FuEngine *self, if (!fu_plugin_runner_prepare(plugin, device, flags, error)) return FALSE; } + fu_progress_set_status(progress, FWUPD_STATUS_SCHEDULING); release_tmp = fu_engine_create_release_metadata(self, device, plugin, error); if (release_tmp == NULL) return FALSE; @@ -2622,22 +2675,26 @@ fu_engine_install(FuEngine *self, } if (!fu_engine_sort_releases(self, device, rels, error)) return FALSE; + fu_progress_set_steps(progress, rels->len); for (guint i = 0; i < rels->len; i++) { XbNode *rel = g_ptr_array_index(rels, i); if (!fu_engine_install_release(self, device, component, rel, + fu_progress_get_child(progress), flags, feature_flags, error)) return FALSE; + fu_progress_step_done(progress); } } else { if (!fu_engine_install_release(self, device, component, rel_newest, + progress, flags, feature_flags, error)) @@ -2856,6 +2913,7 @@ fu_engine_cleanup(FuEngine *self, FwupdInstallFlags flags, const gchar *device_i static gboolean fu_engine_detach(FuEngine *self, const gchar *device_id, + FuProgress *progress, FwupdFeatureFlags feature_flags, GError **error) { @@ -2875,7 +2933,7 @@ fu_engine_detach(FuEngine *self, fu_plugin_list_find_by_name(self->plugin_list, fu_device_get_plugin(device), error); if (plugin == NULL) return FALSE; - if (!fu_plugin_runner_detach(plugin, device, error)) + if (!fu_plugin_runner_detach(plugin, device, progress, error)) return FALSE; /* support older clients without the ability to do immediate requests */ @@ -2903,7 +2961,7 @@ fu_engine_detach(FuEngine *self, } static gboolean -fu_engine_attach(FuEngine *self, const gchar *device_id, GError **error) +fu_engine_attach(FuEngine *self, const gchar *device_id, FuProgress *progress, GError **error) { FuPlugin *plugin; g_autofree gchar *str = NULL; @@ -2922,15 +2980,31 @@ fu_engine_attach(FuEngine *self, const gchar *device_id, GError **error) if (plugin == NULL) return FALSE; - if (!fu_plugin_runner_attach(plugin, device, error)) + if (!fu_plugin_runner_attach(plugin, device, progress, error)) return FALSE; return TRUE; } +static gboolean +fu_engine_set_progress(FuEngine *self, const gchar *device_id, FuProgress *progress, GError **error) +{ + g_autoptr(FuDevice) device = NULL; + + /* the device and plugin both may have changed */ + device = fu_engine_get_device(self, device_id, error); + if (device == NULL) { + g_prefix_error(error, "failed to get device before setting progress: "); + return FALSE; + } + fu_device_set_progress(device, progress); + return TRUE; +} + gboolean fu_engine_activate(FuEngine *self, const gchar *device_id, GError **error) { FuPlugin *plugin; + g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC); g_autofree gchar *str = NULL; g_autoptr(FuDevice) device = NULL; @@ -2938,6 +3012,17 @@ fu_engine_activate(FuEngine *self, const gchar *device_id, GError **error) g_return_val_if_fail(device_id != NULL, FALSE); g_return_val_if_fail(error == NULL || *error == NULL, FALSE); + /* progress */ + fu_progress_set_profile(progress, g_getenv("FWUPD_VERBOSE") != NULL); + g_signal_connect(progress, + "percentage-changed", + G_CALLBACK(fu_engine_progress_percentage_changed_cb), + self); + g_signal_connect(progress, + "status-changed", + G_CALLBACK(fu_engine_progress_status_changed_cb), + self); + /* check the device exists */ device = fu_device_list_get_by_id(self->device_list, device_id, error); if (device == NULL) @@ -2950,7 +3035,7 @@ fu_engine_activate(FuEngine *self, const gchar *device_id, GError **error) return FALSE; g_debug("Activating %s", fu_device_get_name(device)); - if (!fu_plugin_runner_activate(plugin, device, error)) + if (!fu_plugin_runner_activate(plugin, device, progress, error)) return FALSE; fu_engine_emit_device_changed(self, device); @@ -2995,6 +3080,7 @@ static gboolean fu_engine_write_firmware(FuEngine *self, const gchar *device_id, GBytes *blob_fw, + FuProgress *progress, FwupdInstallFlags flags, GError **error) { @@ -3020,12 +3106,12 @@ fu_engine_write_firmware(FuEngine *self, fu_plugin_list_find_by_name(self->plugin_list, fu_device_get_plugin(device), error); if (plugin == NULL) return FALSE; - if (!fu_plugin_runner_write_firmware(plugin, device, blob_fw, flags, error)) { + if (!fu_plugin_runner_write_firmware(plugin, device, blob_fw, progress, flags, error)) { g_autoptr(GError) error_attach = NULL; g_autoptr(GError) error_cleanup = NULL; /* attack back into runtime then cleanup */ - if (!fu_plugin_runner_attach(plugin, device, &error_attach)) { + if (!fu_plugin_runner_attach(plugin, device, progress, &error_attach)) { g_warning("failed to attach device after failed update: %s", error_attach->message); } @@ -3068,7 +3154,11 @@ fu_engine_write_firmware(FuEngine *self, } GBytes * -fu_engine_firmware_dump(FuEngine *self, FuDevice *device, FwupdInstallFlags flags, GError **error) +fu_engine_firmware_dump(FuEngine *self, + FuDevice *device, + FuProgress *progress, + FwupdInstallFlags flags, + GError **error) { g_autoptr(FuDeviceLocker) locker = NULL; @@ -3078,13 +3168,14 @@ fu_engine_firmware_dump(FuEngine *self, FuDevice *device, FwupdInstallFlags flag g_prefix_error(error, "failed to open device for firmware read: "); return NULL; } - return fu_device_dump_firmware(device, error); + return fu_device_dump_firmware(device, progress, error); } gboolean fu_engine_install_blob(FuEngine *self, FuDevice *device, GBytes *blob_fw, + FuProgress *progress, FwupdInstallFlags flags, FwupdFeatureFlags feature_flags, GError **error) @@ -3124,17 +3215,46 @@ fu_engine_install_blob(FuEngine *self, if (!fu_engine_prepare(self, flags, device_id, error)) return FALSE; - /* detach to bootloader mode */ - if (!fu_engine_detach(self, device_id, feature_flags, error)) + /* progress */ + if (!fu_engine_set_progress(self, device_id, progress, error)) return FALSE; + if (fu_progress_get_steps(progress) == 0) { + fu_progress_set_id(progress, G_STRLOC); + fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED); + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* detach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 94); /* write */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 2); /* attach */ + fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2); /* reload */ + } + + /* detach to bootloader mode */ + if (!fu_engine_detach(self, + device_id, + fu_progress_get_child(progress), + feature_flags, + error)) + return FALSE; + fu_progress_step_done(progress); /* install */ - if (!fu_engine_write_firmware(self, device_id, blob_fw, flags, error)) + if (!fu_engine_write_firmware(self, + device_id, + blob_fw, + fu_progress_get_child(progress), + flags, + error)) return FALSE; + fu_progress_step_done(progress); /* attach into runtime mode */ - if (!fu_engine_attach(self, device_id, error)) + if (!fu_engine_attach(self, device_id, fu_progress_get_child(progress), error)) return FALSE; + fu_progress_step_done(progress); + + /* get the new version number */ + if (!fu_engine_reload(self, device_id, error)) + return FALSE; + fu_progress_step_done(progress); /* the device and plugin both may have changed */ device_tmp = fu_engine_get_device(self, device_id, error); @@ -3145,18 +3265,16 @@ fu_engine_install_blob(FuEngine *self, if (!fu_device_has_flag(device_tmp, FWUPD_DEVICE_FLAG_ANOTHER_WRITE_REQUIRED)) break; - } while (TRUE); + /* not sure we can do any better than this */ + fu_progress_reset(progress); - /* get the new version number */ - if (!fu_engine_reload(self, device_id, error)) - return FALSE; + } while (TRUE); /* signal to all the plugins the update has happened */ if (!fu_engine_cleanup(self, flags, device_id, error)) return FALSE; /* make the UI update */ - fu_engine_set_status(self, FWUPD_STATUS_IDLE); g_debug("Updating %s took %f seconds", fu_device_get_name(device), g_timer_elapsed(timer, NULL)); diff --git a/src/fu-engine.h b/src/fu-engine.h index 6e93899c9..1c35b99b4 100644 --- a/src/fu-engine.h +++ b/src/fu-engine.h @@ -129,7 +129,11 @@ fu_engine_verify(FuEngine *self, const gchar *device_id, GError **error); gboolean fu_engine_verify_update(FuEngine *self, const gchar *device_id, GError **error); GBytes * -fu_engine_firmware_dump(FuEngine *self, FuDevice *device, FwupdInstallFlags flags, GError **error); +fu_engine_firmware_dump(FuEngine *self, + FuDevice *device, + FuProgress *progress, + FwupdInstallFlags flags, + GError **error); gboolean fu_engine_modify_remote(FuEngine *self, const gchar *remote_id, @@ -150,6 +154,7 @@ gboolean fu_engine_install(FuEngine *self, FuInstallTask *task, GBytes *blob_cab, + FuProgress *progress, FwupdInstallFlags flags, FwupdFeatureFlags feature_flags, GError **error); @@ -157,6 +162,7 @@ gboolean fu_engine_install_blob(FuEngine *self, FuDevice *device, GBytes *blob_fw, + FuProgress *progress, FwupdInstallFlags flags, FwupdFeatureFlags feature_flags, GError **error); diff --git a/src/fu-self-test.c b/src/fu-self-test.c index d267bf008..f89bc3a0a 100644 --- a/src/fu-self-test.c +++ b/src/fu-self-test.c @@ -1693,6 +1693,7 @@ fu_engine_history_func(gconstpointer user_data) g_autoptr(FuEngine) engine = fu_engine_new(FU_APP_FLAGS_NONE); g_autoptr(FuHistory) history = NULL; g_autoptr(FuInstallTask) task = NULL; + g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC); g_autoptr(FwupdDevice) device3 = NULL; g_autoptr(FwupdDevice) device4 = NULL; g_autoptr(GBytes) blob_cab = NULL; @@ -1761,6 +1762,7 @@ fu_engine_history_func(gconstpointer user_data) ret = fu_engine_install(engine, task, blob_cab, + progress, FWUPD_INSTALL_FLAG_NONE, FWUPD_FEATURE_FLAG_NONE, &error); @@ -1829,6 +1831,7 @@ fu_engine_multiple_rels_func(gconstpointer user_data) g_autoptr(FuDevice) device = fu_device_new_with_context(self->ctx); g_autoptr(FuEngine) engine = fu_engine_new(FU_APP_FLAGS_NONE); g_autoptr(FuInstallTask) task = NULL; + g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC); g_autoptr(GBytes) blob_cab = NULL; g_autoptr(GError) error = NULL; g_autoptr(XbNode) component = NULL; @@ -1890,6 +1893,7 @@ fu_engine_multiple_rels_func(gconstpointer user_data) ret = fu_engine_install(engine, task, blob_cab, + progress, FWUPD_INSTALL_FLAG_NONE, FWUPD_FEATURE_FLAG_NONE, &error); @@ -1912,6 +1916,7 @@ fu_engine_history_inherit(gconstpointer user_data) g_autoptr(FuDevice) device = fu_device_new_with_context(self->ctx); g_autoptr(FuEngine) engine = fu_engine_new(FU_APP_FLAGS_NONE); g_autoptr(FuInstallTask) task = NULL; + g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC); g_autoptr(GBytes) blob_cab = NULL; g_autoptr(GError) error = NULL; g_autoptr(GPtrArray) devices = NULL; @@ -1976,6 +1981,7 @@ fu_engine_history_inherit(gconstpointer user_data) ret = fu_engine_install(engine, task, blob_cab, + progress, FWUPD_INSTALL_FLAG_NONE, FWUPD_FEATURE_FLAG_NONE, &error); @@ -1996,11 +2002,13 @@ fu_engine_history_inherit(gconstpointer user_data) g_assert_cmpstr(fu_device_get_version(device), ==, "1.2.3"); /* emulate getting the flag for a fresh boot on old firmware */ + fu_progress_reset(progress); fu_device_set_version_format(device, FWUPD_VERSION_FORMAT_TRIPLET); fu_device_set_version(device, "1.2.2"); ret = fu_engine_install(engine, task, blob_cab, + progress, FWUPD_INSTALL_FLAG_NONE, FWUPD_FEATURE_FLAG_NONE, &error); @@ -2050,6 +2058,7 @@ fu_engine_install_needs_reboot(gconstpointer user_data) g_autoptr(FuDevice) device = fu_device_new_with_context(self->ctx); g_autoptr(FuEngine) engine = fu_engine_new(FU_APP_FLAGS_NONE); g_autoptr(FuInstallTask) task = NULL; + g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC); g_autoptr(GBytes) blob_cab = NULL; g_autoptr(GError) error = NULL; g_autoptr(GPtrArray) devices = NULL; @@ -2109,6 +2118,7 @@ fu_engine_install_needs_reboot(gconstpointer user_data) ret = fu_engine_install(engine, task, blob_cab, + progress, FWUPD_INSTALL_FLAG_NONE, FWUPD_FEATURE_FLAG_NONE, &error); @@ -2135,6 +2145,7 @@ fu_engine_history_error_func(gconstpointer user_data) g_autoptr(FuEngine) engine = fu_engine_new(FU_APP_FLAGS_NONE); g_autoptr(FuHistory) history = NULL; g_autoptr(FuInstallTask) task = NULL; + g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC); g_autoptr(GBytes) blob_cab = NULL; g_autoptr(GError) error2 = NULL; g_autoptr(GError) error = NULL; @@ -2192,6 +2203,7 @@ fu_engine_history_error_func(gconstpointer user_data) ret = fu_engine_install(engine, task, blob_cab, + progress, FWUPD_INSTALL_FLAG_NONE, FWUPD_FEATURE_FLAG_NONE, &error); @@ -2780,12 +2792,10 @@ fu_history_migrate_func(gconstpointer user_data) } static void -_plugin_status_changed_cb(FuDevice *device, GParamSpec *pspec, gpointer user_data) +_plugin_status_changed_cb(FuDevice *device, FwupdStatus status, gpointer user_data) { guint *cnt = (guint *)user_data; - g_debug("device %s now %s", - fu_device_get_id(device), - fwupd_status_to_string(fu_device_get_status(device))); + g_debug("status now %s", fwupd_status_to_string(status)); (*cnt)++; fu_test_loop_quit(); } @@ -2823,6 +2833,7 @@ fu_plugin_module_func(gconstpointer user_data) g_autoptr(FuDevice) device3 = NULL; g_autoptr(FuEngine) engine = fu_engine_new(FU_APP_FLAGS_NONE); g_autoptr(FuHistory) history = NULL; + g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC); g_autoptr(GBytes) blob_cab = NULL; g_autoptr(GMappedFile) mapped_file = NULL; g_autoptr(XbSilo) silo_empty = xb_silo_new(); @@ -2864,7 +2875,7 @@ fu_plugin_module_func(gconstpointer user_data) return; #endif /* schedule an offline update */ - g_signal_connect(device, "notify::status", G_CALLBACK(_plugin_status_changed_cb), &cnt); + g_signal_connect(progress, "status-changed", G_CALLBACK(_plugin_status_changed_cb), &cnt); mapped_file_fn = g_build_filename(TESTDATADIR_SRC, "colorhug", "firmware.bin", NULL); mapped_file = g_mapped_file_new(mapped_file_fn, FALSE, &error); g_assert_no_error(error); @@ -2880,7 +2891,6 @@ fu_plugin_module_func(gconstpointer user_data) &error); g_assert_no_error(error); g_assert(ret); - g_assert_cmpint(cnt, ==, 1); /* set on the current device */ g_assert_true(fu_device_has_flag(device, FWUPD_DEVICE_FLAG_NEEDS_REBOOT)); @@ -2907,12 +2917,13 @@ fu_plugin_module_func(gconstpointer user_data) ret = fu_engine_install_blob(engine, device, blob_cab, + progress, FWUPD_INSTALL_FLAG_NONE, FWUPD_FEATURE_FLAG_NONE, &error); g_assert_no_error(error); g_assert(ret); - g_assert_cmpint(cnt, ==, 4); + g_assert_cmpint(cnt, ==, 8); /* check the new version */ g_assert_cmpstr(fu_device_get_version(device), ==, "1.2.3"); diff --git a/src/fu-tool.c b/src/fu-tool.c index ddf3039f3..710aa05cb 100644 --- a/src/fu-tool.c +++ b/src/fu-tool.c @@ -59,6 +59,7 @@ struct FuUtilPrivate { GOptionContext *context; FuEngine *engine; FuEngineRequest *request; + FuProgress *progress; FuProgressbar *progressbar; gboolean as_json; gboolean no_reboot_check; @@ -339,6 +340,8 @@ fu_util_private_free(FuUtilPrivate *priv) g_object_unref(priv->cancellable); if (priv->progressbar != NULL) g_object_unref(priv->progressbar); + if (priv->progress != NULL) + g_object_unref(priv->progress); if (priv->context != NULL) g_option_context_free(priv->context); if (priv->lock_fd != 0) @@ -830,6 +833,7 @@ static gboolean fu_util_install_blob(FuUtilPrivate *priv, gchar **values, GError **error) { g_autoptr(FuDevice) device = NULL; + g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC); g_autoptr(GBytes) blob_fw = NULL; /* invalid args */ @@ -841,6 +845,9 @@ fu_util_install_blob(FuUtilPrivate *priv, gchar **values, GError **error) return FALSE; } + /* progress */ + fu_progress_set_profile(progress, g_getenv("FWUPD_VERBOSE") != NULL); + /* parse blob */ blob_fw = fu_common_get_contents_bytes(values[0], error); if (blob_fw == NULL) { @@ -886,6 +893,7 @@ fu_util_install_blob(FuUtilPrivate *priv, gchar **values, GError **error) if (!fu_engine_install_blob(priv->engine, device, blob_fw, + progress, priv->flags, fu_engine_request_get_feature_flags(priv->request), error)) @@ -1010,7 +1018,7 @@ fu_util_firmware_dump(FuUtilPrivate *priv, gchar **values, GError **error) priv); /* dump firmware */ - blob_fw = fu_engine_firmware_dump(priv->engine, device, priv->flags, error); + blob_fw = fu_engine_firmware_dump(priv->engine, device, priv->progress, priv->flags, error); if (blob_fw == NULL) return FALSE; return fu_common_set_contents_bytes(values[0], blob_fw, error); @@ -1517,7 +1525,7 @@ fu_util_detach(FuUtilPrivate *priv, gchar **values, GError **error) locker = fu_device_locker_new(device, error); if (locker == NULL) return FALSE; - return fu_device_detach(device, error); + return fu_device_detach(device, priv->progress, error); } static gboolean @@ -1614,7 +1622,7 @@ fu_util_attach(FuUtilPrivate *priv, gchar **values, GError **error) locker = fu_device_locker_new(device, error); if (locker == NULL) return FALSE; - return fu_device_attach(device, error); + return fu_device_attach(device, priv->progress, error); } static gboolean @@ -3085,6 +3093,7 @@ main(int argc, char *argv[]) /* create helper object */ priv->main_ctx = g_main_context_new(); priv->loop = g_main_loop_new(priv->main_ctx, FALSE); + priv->progress = fu_progress_new(G_STRLOC); priv->progressbar = fu_progressbar_new(); fu_progressbar_set_main_context(priv->progressbar, priv->main_ctx); priv->request = fu_engine_request_new();