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.
This commit is contained in:
Richard Hughes 2021-08-26 07:52:29 +01:00
parent f959b198d2
commit 40cd18fa97
143 changed files with 4709 additions and 1531 deletions

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -0,0 +1,921 @@
/*
* Copyright (C) 2021 Richard Hughes <richard@hughsie.com>
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#define G_LOG_DOMAIN "FuProgress"
#include "config.h"
#include <math.h>
#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);
}

View File

@ -0,0 +1,110 @@
/*
* Copyright (C) 2021 Richard Hughes <richard@hughsie.com>
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#pragma once
#include <fwupd.h>
#include <gio/gio.h>
#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);

View File

@ -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}",

View File

@ -36,6 +36,7 @@
#include <libfwupdplugin/fu-io-channel.h>
#include <libfwupdplugin/fu-plugin-vfuncs.h>
#include <libfwupdplugin/fu-plugin.h>
#include <libfwupdplugin/fu-progress.h>
#include <libfwupdplugin/fu-security-attrs.h>
#include <libfwupdplugin/fu-srec-firmware.h>
#include <libfwupdplugin/fu-udev-device.h>

View File

@ -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;

View File

@ -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',

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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 *

View File

@ -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;
}

View File

@ -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 *

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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 *

View File

@ -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 *

View File

@ -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 *

View File

@ -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);

View File

@ -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 *

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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");
}

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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;
}

View File

@ -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);

View File

@ -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)) {

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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 */

View File

@ -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<bit 2> = b'0
* 0x6C00<bit 1> = 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;
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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 *

View File

@ -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)

View File

@ -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))

View File

@ -16,4 +16,5 @@ fu_intel_spi_device_dump(FuIntelSpiDevice *self,
FuDevice *device,
guint32 offset,
guint32 length,
FuProgress *progress,
GError **error);

View File

@ -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;
}

View File

@ -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,

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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();

View File

@ -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

View File

@ -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 *

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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),

View File

@ -1,3 +1,4 @@
/*
* Copyright (C) 2018 Richard Hughes <richard@hughsie.com>
*
@ -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 */

View File

@ -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 *

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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 *

View File

@ -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;
}

View File

@ -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 {

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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! */

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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

Some files were not shown because too many files have changed in this diff Show More