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, fu_plugin_write_firmware (FuPlugin *plugin,
FuDevice *dev, FuDevice *dev,
GBytes *blob_fw, GBytes *blob_fw,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -212,19 +213,19 @@ handle the device ID, although the registered plugin can change during the
attach and detach phases. attach and detach phases.
gboolean 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) if (hardware_in_bootloader)
return TRUE; return TRUE;
return _device_detach(device, error); return _device_detach(device, progress, error);
} }
gboolean 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) if (!hardware_in_bootloader)
return TRUE; return TRUE;
return _device_attach(device, error); return _device_attach(device, progress, error);
} }
gboolean 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_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_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_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 ## Planned API/ABI changes for next release

View File

@ -50,3 +50,5 @@ guint64
fu_device_get_private_flags(FuDevice *self); fu_device_get_private_flags(FuDevice *self);
void void
fu_device_set_private_flags(FuDevice *self, guint64 flag); 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; GRWLock parent_guids_mutex;
GPtrArray *parent_physical_ids; /* (nullable) */ GPtrArray *parent_physical_ids; /* (nullable) */
guint remove_delay; /* ms */ guint remove_delay; /* ms */
guint progress;
guint battery_level; guint battery_level;
guint battery_threshold; guint battery_threshold;
guint request_cnts[FWUPD_REQUEST_KIND_LAST]; guint request_cnts[FWUPD_REQUEST_KIND_LAST];
@ -90,7 +89,6 @@ typedef struct {
enum { enum {
PROP_0, PROP_0,
PROP_PROGRESS,
PROP_BATTERY_LEVEL, PROP_BATTERY_LEVEL,
PROP_BATTERY_THRESHOLD, PROP_BATTERY_THRESHOLD,
PROP_PHYSICAL_ID, PROP_PHYSICAL_ID,
@ -115,9 +113,6 @@ fu_device_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec
FuDevice *self = FU_DEVICE(object); FuDevice *self = FU_DEVICE(object);
FuDevicePrivate *priv = GET_PRIVATE(self); FuDevicePrivate *priv = GET_PRIVATE(self);
switch (prop_id) { switch (prop_id) {
case PROP_PROGRESS:
g_value_set_uint(value, priv->progress);
break;
case PROP_BATTERY_LEVEL: case PROP_BATTERY_LEVEL:
g_value_set_uint(value, priv->battery_level); g_value_set_uint(value, priv->battery_level);
break; break;
@ -153,9 +148,6 @@ fu_device_set_property(GObject *object, guint prop_id, const GValue *value, GPar
{ {
FuDevice *self = FU_DEVICE(object); FuDevice *self = FU_DEVICE(object);
switch (prop_id) { switch (prop_id) {
case PROP_PROGRESS:
fu_device_set_progress(self, g_value_get_uint(value));
break;
case PROP_BATTERY_LEVEL: case PROP_BATTERY_LEVEL:
fu_device_set_battery_level(self, g_value_get_uint(value)); fu_device_set_battery_level(self, g_value_get_uint(value));
break; break;
@ -3065,123 +3057,6 @@ fu_device_set_remove_delay(FuDevice *self, guint remove_delay)
priv->remove_delay = 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: * fu_device_set_update_state:
* @self: a #FuDevice * @self: a #FuDevice
@ -3547,6 +3422,7 @@ fu_device_get_results(FuDevice *self, GError **error)
* fu_device_write_firmware: * fu_device_write_firmware:
* @self: a #FuDevice * @self: a #FuDevice
* @fw: firmware blob * @fw: firmware blob
* @progress: a #FuProgress
* @flags: install flags, e.g. %FWUPD_INSTALL_FLAG_FORCE * @flags: install flags, e.g. %FWUPD_INSTALL_FLAG_FORCE
* @error: (nullable): optional return location for an error * @error: (nullable): optional return location for an error
* *
@ -3557,7 +3433,11 @@ fu_device_get_results(FuDevice *self, GError **error)
* Since: 1.0.8 * Since: 1.0.8
**/ **/
gboolean 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); FuDeviceClass *klass = FU_DEVICE_GET_CLASS(self);
FuDevicePrivate *priv = GET_PRIVATE(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_autofree gchar *str = NULL;
g_return_val_if_fail(FU_IS_DEVICE(self), FALSE); 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); g_return_val_if_fail(error == NULL || *error == NULL, FALSE);
/* no plugin-specific method */ /* no plugin-specific method */
@ -3574,6 +3455,7 @@ fu_device_write_firmware(FuDevice *self, GBytes *fw, FwupdInstallFlags flags, GE
} }
/* prepare (e.g. decompress) firmware */ /* prepare (e.g. decompress) firmware */
fu_progress_set_status(progress, FWUPD_STATUS_DECOMPRESSING);
firmware = fu_device_prepare_firmware(self, fw, flags, error); firmware = fu_device_prepare_firmware(self, fw, flags, error);
if (firmware == NULL) if (firmware == NULL)
return FALSE; 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); g_debug("installing onto %s:\n%s", fu_device_get_id(self), str);
/* call vfunc */ /* call vfunc */
if (!klass->write_firmware(self, firmware, flags, error)) if (!klass->write_firmware(self, firmware, progress, flags, error))
return FALSE; return FALSE;
/* the device set an UpdateMessage (possibly from a quirk, or XML file) /* 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 */ /* optionally subclassed */
if (klass->prepare_firmware != NULL) { if (klass->prepare_firmware != NULL) {
fu_device_set_status(self, FWUPD_STATUS_DECOMPRESSING);
firmware = klass->prepare_firmware(self, fw, flags, error); firmware = klass->prepare_firmware(self, fw, flags, error);
if (firmware == NULL) if (firmware == NULL)
return NULL; return NULL;
@ -3674,6 +3555,7 @@ fu_device_prepare_firmware(FuDevice *self, GBytes *fw, FwupdInstallFlags flags,
/** /**
* fu_device_read_firmware: * fu_device_read_firmware:
* @self: a #FuDevice * @self: a #FuDevice
* @progress: a #FuProgress
* @error: (nullable): optional return location for an error * @error: (nullable): optional return location for an error
* *
* Reads firmware from the device by calling a plugin-specific vfunc. * 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 * Since: 1.0.8
**/ **/
FuFirmware * 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); FuDeviceClass *klass = FU_DEVICE_GET_CLASS(self);
g_autoptr(GBytes) fw = NULL; g_autoptr(GBytes) fw = NULL;
g_return_val_if_fail(FU_IS_DEVICE(self), 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); g_return_val_if_fail(error == NULL || *error == NULL, NULL);
/* device does not support reading for verification CRCs */ /* device does not support reading for verification CRCs */
@ -3704,10 +3587,10 @@ fu_device_read_firmware(FuDevice *self, GError **error)
/* call vfunc */ /* call vfunc */
if (klass->read_firmware != NULL) 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 */ /* 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) if (fw == NULL)
return NULL; return NULL;
return fu_firmware_new_from_bytes(fw); return fu_firmware_new_from_bytes(fw);
@ -3716,6 +3599,7 @@ fu_device_read_firmware(FuDevice *self, GError **error)
/** /**
* fu_device_dump_firmware: * fu_device_dump_firmware:
* @self: a #FuDevice * @self: a #FuDevice
* @progress: a #FuProgress
* @error: (nullable): optional return location for an error * @error: (nullable): optional return location for an error
* *
* Reads the raw firmware image from the device by calling a plugin-specific * 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 * Since: 1.5.0
**/ **/
GBytes * 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); FuDeviceClass *klass = FU_DEVICE_GET_CLASS(self);
g_return_val_if_fail(FU_IS_DEVICE(self), 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); g_return_val_if_fail(error == NULL || *error == NULL, NULL);
/* use the default FuFirmware when only ->dump_firmware is provided */ /* use the default FuFirmware when only ->dump_firmware is provided */
@ -3742,12 +3627,13 @@ fu_device_dump_firmware(FuDevice *self, GError **error)
} }
/* proxy */ /* proxy */
return klass->dump_firmware(self, error); return klass->dump_firmware(self, progress, error);
} }
/** /**
* fu_device_detach: * fu_device_detach:
* @self: a #FuDevice * @self: a #FuDevice
* @progress: a #FuProgress
* @error: (nullable): optional return location for an error * @error: (nullable): optional return location for an error
* *
* Detaches a device from the application into bootloader mode. * 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 * Since: 1.0.8
**/ **/
gboolean gboolean
fu_device_detach(FuDevice *self, GError **error) fu_device_detach(FuDevice *self, FuProgress *progress, GError **error)
{ {
FuDeviceClass *klass = FU_DEVICE_GET_CLASS(self); FuDeviceClass *klass = FU_DEVICE_GET_CLASS(self);
g_return_val_if_fail(FU_IS_DEVICE(self), FALSE); 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); g_return_val_if_fail(error == NULL || *error == NULL, FALSE);
/* no plugin-specific method */ /* no plugin-specific method */
@ -3769,12 +3656,13 @@ fu_device_detach(FuDevice *self, GError **error)
return TRUE; return TRUE;
/* call vfunc */ /* call vfunc */
return klass->detach(self, error); return klass->detach(self, progress, error);
} }
/** /**
* fu_device_attach: * fu_device_attach:
* @self: a #FuDevice * @self: a #FuDevice
* @progress: a #FuProgress
* @error: (nullable): optional return location for an error * @error: (nullable): optional return location for an error
* *
* Attaches a device from the bootloader into application mode. * Attaches a device from the bootloader into application mode.
@ -3784,11 +3672,12 @@ fu_device_detach(FuDevice *self, GError **error)
* Since: 1.0.8 * Since: 1.0.8
**/ **/
gboolean gboolean
fu_device_attach(FuDevice *self, GError **error) fu_device_attach(FuDevice *self, FuProgress *progress, GError **error)
{ {
FuDeviceClass *klass = FU_DEVICE_GET_CLASS(self); FuDeviceClass *klass = FU_DEVICE_GET_CLASS(self);
g_return_val_if_fail(FU_IS_DEVICE(self), FALSE); 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); g_return_val_if_fail(error == NULL || *error == NULL, FALSE);
/* no plugin-specific method */ /* no plugin-specific method */
@ -3796,7 +3685,7 @@ fu_device_attach(FuDevice *self, GError **error)
return TRUE; return TRUE;
/* call vfunc */ /* 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; 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: * fu_device_convert_instance_ids:
* @self: a #FuDevice * @self: a #FuDevice
@ -4217,6 +4130,7 @@ fu_device_setup(FuDevice *self, GError **error)
/** /**
* fu_device_activate: * fu_device_activate:
* @self: a #FuDevice * @self: a #FuDevice
* @progress: a #FuProgress
* @error: (nullable): optional return location for an error * @error: (nullable): optional return location for an error
* *
* Activates up a device, which normally means the device switches to a new * 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 * Since: 1.2.6
**/ **/
gboolean gboolean
fu_device_activate(FuDevice *self, GError **error) fu_device_activate(FuDevice *self, FuProgress *progress, GError **error)
{ {
FuDeviceClass *klass = FU_DEVICE_GET_CLASS(self); FuDeviceClass *klass = FU_DEVICE_GET_CLASS(self);
g_return_val_if_fail(FU_IS_DEVICE(self), FALSE); 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); g_return_val_if_fail(error == NULL || *error == NULL, FALSE);
/* subclassed */ /* subclassed */
if (klass->activate != NULL) { if (klass->activate != NULL) {
if (!klass->activate(self, error)) if (!klass->activate(self, progress, error))
return FALSE; return FALSE;
} }
@ -4647,15 +4562,6 @@ fu_device_class_init(FuDeviceClass *klass)
G_PARAM_READWRITE | G_PARAM_STATIC_NAME); G_PARAM_READWRITE | G_PARAM_STATIC_NAME);
g_object_class_install_property(object_class, PROP_BACKEND_ID, pspec); 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", pspec = g_param_spec_uint("battery-level",
NULL, NULL,
NULL, NULL,

View File

@ -12,6 +12,7 @@
#include "fu-common-version.h" #include "fu-common-version.h"
#include "fu-context.h" #include "fu-context.h"
#include "fu-firmware.h" #include "fu-firmware.h"
#include "fu-progress.h"
#include "fu-security-attrs.h" #include "fu-security-attrs.h"
#define FU_TYPE_DEVICE (fu_device_get_type()) #define FU_TYPE_DEVICE (fu_device_get_type())
@ -23,11 +24,18 @@ struct _FuDeviceClass {
void (*to_string)(FuDevice *self, guint indent, GString *str); void (*to_string)(FuDevice *self, guint indent, GString *str);
gboolean (*write_firmware)(FuDevice *self, gboolean (*write_firmware)(FuDevice *self,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) G_GNUC_WARN_UNUSED_RESULT; GError **error) G_GNUC_WARN_UNUSED_RESULT;
FuFirmware *(*read_firmware)(FuDevice *self, GError **error)G_GNUC_WARN_UNUSED_RESULT; FuFirmware *(*read_firmware)(FuDevice *self,
gboolean (*detach)(FuDevice *self, GError **error) G_GNUC_WARN_UNUSED_RESULT; FuProgress *progress,
gboolean (*attach)(FuDevice *self, GError **error) G_GNUC_WARN_UNUSED_RESULT; 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 (*open)(FuDevice *self, GError **error) G_GNUC_WARN_UNUSED_RESULT;
gboolean (*close)(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; 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; gboolean (*setup)(FuDevice *self, GError **error) G_GNUC_WARN_UNUSED_RESULT;
void (*incorporate)(FuDevice *self, FuDevice *donor); void (*incorporate)(FuDevice *self, FuDevice *donor);
gboolean (*poll)(FuDevice *self, GError **error) G_GNUC_WARN_UNUSED_RESULT; 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 (*reload)(FuDevice *self, GError **error) G_GNUC_WARN_UNUSED_RESULT;
gboolean (*prepare)(FuDevice *self, gboolean (*prepare)(FuDevice *self,
FwupdInstallFlags flags, FwupdInstallFlags flags,
@ -58,7 +68,9 @@ struct _FuDeviceClass {
const gchar *driver, const gchar *driver,
GError **error) G_GNUC_WARN_UNUSED_RESULT; GError **error) G_GNUC_WARN_UNUSED_RESULT;
gboolean (*unbind_driver)(FuDevice *self, 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); void (*add_security_attrs)(FuDevice *self, FuSecurityAttrs *attrs);
gboolean (*ready)(FuDevice *self, GError **error) G_GNUC_WARN_UNUSED_RESULT; gboolean (*ready)(FuDevice *self, GError **error) G_GNUC_WARN_UNUSED_RESULT;
void (*child_added)(FuDevice *self, /* signal */ void (*child_added)(FuDevice *self, /* signal */
@ -68,8 +80,9 @@ struct _FuDeviceClass {
void (*request)(FuDevice *self, /* signal */ void (*request)(FuDevice *self, /* signal */
FwupdRequest *request); FwupdRequest *request);
gboolean (*get_results)(FuDevice *self, GError **error) G_GNUC_WARN_UNUSED_RESULT; gboolean (*get_results)(FuDevice *self, GError **error) G_GNUC_WARN_UNUSED_RESULT;
void (*set_progress)(FuDevice *self, FuProgress *progress);
/*< private >*/ /*< private >*/
gpointer padding[5]; gpointer padding[16];
#endif #endif
}; };
@ -498,10 +511,6 @@ guint
fu_device_get_remove_delay(FuDevice *self); fu_device_get_remove_delay(FuDevice *self);
void void
fu_device_set_remove_delay(FuDevice *self, guint remove_delay); 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 void
fu_device_set_firmware_size(FuDevice *self, guint64 size); fu_device_set_firmware_size(FuDevice *self, guint64 size);
void void
@ -513,10 +522,6 @@ fu_device_get_firmware_size_min(FuDevice *self);
guint64 guint64
fu_device_get_firmware_size_max(FuDevice *self); fu_device_get_firmware_size_max(FuDevice *self);
guint guint
fu_device_get_progress(FuDevice *self);
void
fu_device_set_progress(FuDevice *self, guint progress);
guint
fu_device_get_battery_level(FuDevice *self); fu_device_get_battery_level(FuDevice *self);
void void
fu_device_set_battery_level(FuDevice *self, guint battery_level); fu_device_set_battery_level(FuDevice *self, guint battery_level);
@ -525,10 +530,6 @@ fu_device_get_battery_threshold(FuDevice *self);
void void
fu_device_set_battery_threshold(FuDevice *self, guint battery_threshold); fu_device_set_battery_threshold(FuDevice *self, guint battery_threshold);
void 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); fu_device_set_update_state(FuDevice *self, FwupdUpdateState update_state);
void void
fu_device_set_context(FuDevice *self, FuContext *ctx); fu_device_set_context(FuDevice *self, FuContext *ctx);
@ -547,19 +548,26 @@ fu_device_has_internal_flag(FuDevice *self, FuDeviceInternalFlags flag);
gboolean gboolean
fu_device_get_results(FuDevice *self, GError **error); fu_device_get_results(FuDevice *self, GError **error);
gboolean gboolean
fu_device_write_firmware(FuDevice *self, GBytes *fw, FwupdInstallFlags flags, GError **error) fu_device_write_firmware(FuDevice *self,
G_GNUC_WARN_UNUSED_RESULT; GBytes *fw,
FuProgress *progress,
FwupdInstallFlags flags,
GError **error) G_GNUC_WARN_UNUSED_RESULT;
FuFirmware * FuFirmware *
fu_device_prepare_firmware(FuDevice *self, GBytes *fw, FwupdInstallFlags flags, GError **error) fu_device_prepare_firmware(FuDevice *self, GBytes *fw, FwupdInstallFlags flags, GError **error)
G_GNUC_WARN_UNUSED_RESULT; G_GNUC_WARN_UNUSED_RESULT;
FuFirmware * 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 * 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 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 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 gboolean
fu_device_reload(FuDevice *self, GError **error) G_GNUC_WARN_UNUSED_RESULT; fu_device_reload(FuDevice *self, GError **error) G_GNUC_WARN_UNUSED_RESULT;
gboolean gboolean
@ -585,7 +593,7 @@ fu_device_setup(FuDevice *self, GError **error) G_GNUC_WARN_UNUSED_RESULT;
gboolean gboolean
fu_device_rescan(FuDevice *self, GError **error) G_GNUC_WARN_UNUSED_RESULT; fu_device_rescan(FuDevice *self, GError **error) G_GNUC_WARN_UNUSED_RESULT;
gboolean 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 void
fu_device_probe_invalidate(FuDevice *self); fu_device_probe_invalidate(FuDevice *self);
gboolean gboolean

View File

@ -57,9 +57,11 @@ fu_plugin_runner_composite_cleanup(FuPlugin *self,
GPtrArray *devices, GPtrArray *devices,
GError **error) G_GNUC_WARN_UNUSED_RESULT; GError **error) G_GNUC_WARN_UNUSED_RESULT;
gboolean 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 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 gboolean
fu_plugin_runner_reload(FuPlugin *self, FuDevice *device, GError **error) G_GNUC_WARN_UNUSED_RESULT; fu_plugin_runner_reload(FuPlugin *self, FuDevice *device, GError **error) G_GNUC_WARN_UNUSED_RESULT;
gboolean gboolean
@ -84,13 +86,17 @@ gboolean
fu_plugin_runner_write_firmware(FuPlugin *self, fu_plugin_runner_write_firmware(FuPlugin *self,
FuDevice *device, FuDevice *device,
GBytes *blob_fw, GBytes *blob_fw,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) G_GNUC_WARN_UNUSED_RESULT; GError **error) G_GNUC_WARN_UNUSED_RESULT;
gboolean gboolean
fu_plugin_runner_verify(FuPlugin *self, FuDevice *device, FuPluginVerifyFlags flags, GError **error) fu_plugin_runner_verify(FuPlugin *self,
G_GNUC_WARN_UNUSED_RESULT; FuDevice *device,
FuProgress *progress,
FuPluginVerifyFlags flags,
GError **error) G_GNUC_WARN_UNUSED_RESULT;
gboolean gboolean
fu_plugin_runner_activate(FuPlugin *self, FuDevice *device, GError **error); fu_plugin_runner_activate(FuPlugin *self, FuDevice *device, FuProgress *progress, GError **error);
gboolean gboolean
fu_plugin_runner_unlock(FuPlugin *self, FuDevice *device, GError **error) G_GNUC_WARN_UNUSED_RESULT; fu_plugin_runner_unlock(FuPlugin *self, FuDevice *device, GError **error) G_GNUC_WARN_UNUSED_RESULT;
gboolean gboolean

View File

@ -98,6 +98,7 @@ fu_plugin_coldplug_cleanup(FuPlugin *plugin, GError **error);
* @plugin: a plugin * @plugin: a plugin
* @dev: a device * @dev: a device
* @blob_fw: a data blob * @blob_fw: a data blob
* @progress: a #FuProgress
* @flags: install flags * @flags: install flags
* @error: (nullable): optional return location for an error * @error: (nullable): optional return location for an error
* *
@ -109,6 +110,7 @@ gboolean
fu_plugin_write_firmware(FuPlugin *plugin, fu_plugin_write_firmware(FuPlugin *plugin,
FuDevice *dev, FuDevice *dev,
GBytes *blob_fw, GBytes *blob_fw,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error); GError **error);
/** /**
@ -150,7 +152,7 @@ fu_plugin_unlock(FuPlugin *plugin, FuDevice *dev, GError **error);
* Since: 1.2.6 * Since: 1.2.6
**/ **/
gboolean 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: * fu_plugin_clear_results:
* @plugin: a plugin * @plugin: a plugin
@ -186,7 +188,7 @@ fu_plugin_get_results(FuPlugin *plugin, FuDevice *dev, GError **error);
* Since: 1.0.2 * Since: 1.0.2
**/ **/
gboolean gboolean
fu_plugin_attach(FuPlugin *plugin, FuDevice *dev, GError **error); fu_plugin_attach(FuPlugin *plugin, FuDevice *dev, FuProgress *progress, GError **error);
/** /**
* fu_plugin_detach: * fu_plugin_detach:
* @plugin: a plugin * @plugin: a plugin
@ -198,7 +200,7 @@ fu_plugin_attach(FuPlugin *plugin, FuDevice *dev, GError **error);
* Since: 1.7.0 * Since: 1.7.0
**/ **/
gboolean gboolean
fu_plugin_detach(FuPlugin *plugin, FuDevice *dev, GError **error); fu_plugin_detach(FuPlugin *plugin, FuDevice *dev, FuProgress *progress, GError **error);
/** /**
* fu_plugin_prepare: * fu_plugin_prepare:
* @plugin: a plugin * @plugin: a plugin

View File

@ -68,6 +68,10 @@ typedef void (*FuPluginInitFunc)(FuPlugin *self);
typedef gboolean (*FuPluginStartupFunc)(FuPlugin *self, GError **error); typedef gboolean (*FuPluginStartupFunc)(FuPlugin *self, GError **error);
typedef void (*FuPluginDeviceRegisterFunc)(FuPlugin *self, FuDevice *device); typedef void (*FuPluginDeviceRegisterFunc)(FuPlugin *self, FuDevice *device);
typedef gboolean (*FuPluginDeviceFunc)(FuPlugin *self, FuDevice *device, GError **error); 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, typedef gboolean (*FuPluginFlaggedDeviceFunc)(FuPlugin *self,
FuDevice *device, FuDevice *device,
FwupdInstallFlags flags, FwupdInstallFlags flags,
@ -80,6 +84,7 @@ typedef gboolean (*FuPluginVerifyFunc)(FuPlugin *self,
typedef gboolean (*FuPluginUpdateFunc)(FuPlugin *self, typedef gboolean (*FuPluginUpdateFunc)(FuPlugin *self,
FuDevice *device, FuDevice *device,
GBytes *blob_fw, GBytes *blob_fw,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error); GError **error);
typedef void (*FuPluginSecurityAttrsFunc)(FuPlugin *self, FuSecurityAttrs *attrs); typedef void (*FuPluginSecurityAttrsFunc)(FuPlugin *self, FuSecurityAttrs *attrs);
@ -670,42 +675,43 @@ fu_plugin_get_context(FuPlugin *self)
} }
static gboolean 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); FuDevice *proxy = fu_device_get_proxy_with_fallback(device);
g_autoptr(FuDeviceLocker) locker = NULL; g_autoptr(FuDeviceLocker) locker = NULL;
locker = fu_device_locker_new(proxy, error); locker = fu_device_locker_new(proxy, error);
if (locker == NULL) if (locker == NULL)
return FALSE; return FALSE;
return fu_device_attach(device, error); return fu_device_attach(device, progress, error);
} }
static gboolean 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); FuDevice *proxy = fu_device_get_proxy_with_fallback(device);
g_autoptr(FuDeviceLocker) locker = NULL; g_autoptr(FuDeviceLocker) locker = NULL;
locker = fu_device_locker_new(proxy, error); locker = fu_device_locker_new(proxy, error);
if (locker == NULL) if (locker == NULL)
return FALSE; return FALSE;
return fu_device_detach(device, error); return fu_device_detach(device, progress, error);
} }
static gboolean 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); FuDevice *proxy = fu_device_get_proxy_with_fallback(device);
g_autoptr(FuDeviceLocker) locker = NULL; g_autoptr(FuDeviceLocker) locker = NULL;
locker = fu_device_locker_new(proxy, error); locker = fu_device_locker_new(proxy, error);
if (locker == NULL) if (locker == NULL)
return FALSE; return FALSE;
return fu_device_activate(device, error); return fu_device_activate(device, progress, error);
} }
static gboolean static gboolean
fu_plugin_device_write_firmware(FuPlugin *self, fu_plugin_device_write_firmware(FuPlugin *self,
FuDevice *device, FuDevice *device,
GBytes *fw, GBytes *fw,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -722,7 +728,7 @@ fu_plugin_device_write_firmware(FuPlugin *self,
g_autofree gchar *fn = NULL; g_autofree gchar *fn = NULL;
g_autofree gchar *localstatedir = 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) { if (fw_old == NULL) {
g_prefix_error(error, "failed to backup old firmware: "); g_prefix_error(error, "failed to backup old firmware: ");
return FALSE; return FALSE;
@ -740,7 +746,7 @@ fu_plugin_device_write_firmware(FuPlugin *self,
return FALSE; return FALSE;
} }
return fu_device_write_firmware(device, fw, flags, error); return fu_device_write_firmware(device, fw, progress, flags, error);
} }
static gboolean static gboolean
@ -761,7 +767,10 @@ fu_plugin_device_get_results(FuPlugin *self, FuDevice *device, GError **error)
} }
static gboolean 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); FuDevice *proxy = fu_device_get_proxy_with_fallback(device);
g_autoptr(FuDeviceLocker) locker = NULL; 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); locker = fu_device_locker_new(proxy, error);
if (locker == NULL) if (locker == NULL)
return FALSE; return FALSE;
if (!fu_device_detach(device, error)) if (!fu_device_detach(device, progress, error))
return FALSE; return FALSE;
firmware = fu_device_read_firmware(device, error); firmware = fu_device_read_firmware(device, progress, error);
if (firmware == NULL) { if (firmware == NULL) {
g_autoptr(GError) error_local = 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_debug("ignoring attach failure: %s", error_local->message);
g_prefix_error(error, "failed to read firmware: "); g_prefix_error(error, "failed to read firmware: ");
return FALSE; return FALSE;
@ -784,7 +793,7 @@ fu_plugin_device_read_firmware(FuPlugin *self, FuDevice *device, GError **error)
fw = fu_firmware_write(firmware, error); fw = fu_firmware_write(firmware, error);
if (fw == NULL) { if (fw == NULL) {
g_autoptr(GError) error_local = 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_debug("ignoring attach failure: %s", error_local->message);
g_prefix_error(error, "failed to write firmware: "); g_prefix_error(error, "failed to write firmware: ");
return FALSE; 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); hash = g_compute_checksum_for_bytes(checksum_types[i], fw);
fu_device_add_checksum(device, hash); 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; 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 static gboolean
fu_plugin_runner_flagged_device_generic(FuPlugin *self, fu_plugin_runner_flagged_device_generic(FuPlugin *self,
FuDevice *device, FuDevice *device,
@ -1238,6 +1299,7 @@ fu_plugin_runner_cleanup(FuPlugin *self, FuDevice *device, FwupdInstallFlags fla
* fu_plugin_runner_attach: * fu_plugin_runner_attach:
* @self: a #FuPlugin * @self: a #FuPlugin
* @device: a device * @device: a device
* @progress: a #FuProgress
* @error: (nullable): optional return location for an error * @error: (nullable): optional return location for an error
* *
* Runs the update_attach routine for the plugin * Runs the update_attach routine for the plugin
@ -1247,10 +1309,11 @@ fu_plugin_runner_cleanup(FuPlugin *self, FuDevice *device, FwupdInstallFlags fla
* Since: 1.7.0 * Since: 1.7.0
**/ **/
gboolean 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, return fu_plugin_runner_device_generic_progress(self,
device, device,
progress,
"fu_plugin_attach", "fu_plugin_attach",
fu_plugin_device_attach, fu_plugin_device_attach,
error); error);
@ -1260,6 +1323,7 @@ fu_plugin_runner_attach(FuPlugin *self, FuDevice *device, GError **error)
* fu_plugin_runner_detach: * fu_plugin_runner_detach:
* @self: a #FuPlugin * @self: a #FuPlugin
* @device: a device * @device: a device
* @progress: a #FuProgress
* @error: (nullable): optional return location for an error * @error: (nullable): optional return location for an error
* *
* Runs the update_detach routine for the plugin * Runs the update_detach routine for the plugin
@ -1269,10 +1333,11 @@ fu_plugin_runner_attach(FuPlugin *self, FuDevice *device, GError **error)
* Since: 1.7.0 * Since: 1.7.0
**/ **/
gboolean 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, return fu_plugin_runner_device_generic_progress(self,
device, device,
progress,
"fu_plugin_detach", "fu_plugin_detach",
fu_plugin_device_detach, fu_plugin_device_detach,
error); error);
@ -1770,6 +1835,7 @@ fu_plugin_runner_device_created(FuPlugin *self, FuDevice *device, GError **error
* fu_plugin_runner_verify: * fu_plugin_runner_verify:
* @self: a #FuPlugin * @self: a #FuPlugin
* @device: a device * @device: a device
* @progress: a #FuProgress
* @flags: verify flags * @flags: verify flags
* @error: (nullable): optional return location for an error * @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 * Since: 0.8.0
**/ **/
gboolean 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); FuPluginPrivate *priv = GET_PRIVATE(self);
FuPluginVerifyFunc func = NULL; 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_PLUGIN(self), FALSE);
g_return_val_if_fail(FU_IS_DEVICE(device), 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); g_return_val_if_fail(error == NULL || *error == NULL, FALSE);
/* not enabled */ /* not enabled */
@ -1810,7 +1881,7 @@ fu_plugin_runner_verify(FuPlugin *self, FuDevice *device, FuPluginVerifyFlags fl
fu_device_get_id(device)); fu_device_get_id(device));
return FALSE; 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 */ /* clear any existing verification checksums */
@ -1818,8 +1889,9 @@ fu_plugin_runner_verify(FuPlugin *self, FuDevice *device, FuPluginVerifyFlags fl
g_ptr_array_set_size(checksums, 0); g_ptr_array_set_size(checksums, 0);
/* run additional detach */ /* run additional detach */
if (!fu_plugin_runner_device_generic(self, if (!fu_plugin_runner_device_generic_progress(self,
device, device,
progress,
"fu_plugin_detach", "fu_plugin_detach",
fu_plugin_device_detach, fu_plugin_device_detach,
error)) error))
@ -1841,8 +1913,9 @@ fu_plugin_runner_verify(FuPlugin *self, FuDevice *device, FuPluginVerifyFlags fl
"failed to verify using %s: ", "failed to verify using %s: ",
fu_plugin_get_name(self)); fu_plugin_get_name(self));
/* make the device "work" again, but don't prefix the error */ /* make the device "work" again, but don't prefix the error */
if (!fu_plugin_runner_device_generic(self, if (!fu_plugin_runner_device_generic_progress(self,
device, device,
progress,
"fu_plugin_attach", "fu_plugin_attach",
fu_plugin_device_attach, fu_plugin_device_attach,
&error_attach)) { &error_attach)) {
@ -1853,8 +1926,9 @@ fu_plugin_runner_verify(FuPlugin *self, FuDevice *device, FuPluginVerifyFlags fl
} }
/* run optional attach */ /* run optional attach */
if (!fu_plugin_runner_device_generic(self, if (!fu_plugin_runner_device_generic_progress(self,
device, device,
progress,
"fu_plugin_attach", "fu_plugin_attach",
fu_plugin_device_attach, fu_plugin_device_attach,
error)) error))
@ -1868,6 +1942,7 @@ fu_plugin_runner_verify(FuPlugin *self, FuDevice *device, FuPluginVerifyFlags fl
* fu_plugin_runner_activate: * fu_plugin_runner_activate:
* @self: a #FuPlugin * @self: a #FuPlugin
* @device: a device * @device: a device
* @progress: a #FuProgress
* @error: (nullable): optional return location for an error * @error: (nullable): optional return location for an error
* *
* Call into the plugin's activate routine * 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 * Since: 1.2.6
**/ **/
gboolean 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; guint64 flags;
g_return_val_if_fail(FU_IS_PLUGIN(self), FALSE); 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_DEVICE(device), FALSE);
g_return_val_if_fail(FU_IS_PROGRESS(progress), FALSE);
g_return_val_if_fail(error == NULL || *error == NULL, FALSE); g_return_val_if_fail(error == NULL || *error == NULL, FALSE);
/* final check */ /* final check */
@ -1897,8 +1973,9 @@ fu_plugin_runner_activate(FuPlugin *self, FuDevice *device, GError **error)
} }
/* run vfunc */ /* run vfunc */
if (!fu_plugin_runner_device_generic(self, if (!fu_plugin_runner_device_generic_progress(self,
device, device,
progress,
"fu_plugin_activate", "fu_plugin_activate",
fu_plugin_device_activate, fu_plugin_device_activate,
error)) error))
@ -1957,6 +2034,7 @@ fu_plugin_runner_unlock(FuPlugin *self, FuDevice *device, GError **error)
* @self: a #FuPlugin * @self: a #FuPlugin
* @device: a device * @device: a device
* @blob_fw: a data blob * @blob_fw: a data blob
* @progress: a #FuProgress
* @flags: install flags * @flags: install flags
* @error: (nullable): optional return location for an error * @error: (nullable): optional return location for an error
* *
@ -1970,6 +2048,7 @@ gboolean
fu_plugin_runner_write_firmware(FuPlugin *self, fu_plugin_runner_write_firmware(FuPlugin *self,
FuDevice *device, FuDevice *device,
GBytes *blob_fw, GBytes *blob_fw,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) 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_PLUGIN(self), FALSE);
g_return_val_if_fail(FU_IS_DEVICE(device), 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); g_return_val_if_fail(error == NULL || *error == NULL, FALSE);
/* not enabled */ /* 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); g_module_symbol(priv->module, "fu_plugin_write_firmware", (gpointer *)&update_func);
if (update_func == NULL) { if (update_func == NULL) {
g_debug("superclassed write_firmware(%s)", fu_plugin_get_name(self)); 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 */ /* 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) { if (error_local == NULL) {
g_critical("unset plugin error in update(%s)", fu_plugin_get_name(self)); g_critical("unset plugin error in update(%s)", fu_plugin_get_name(self));
g_set_error_literal(&error_local, 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); 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 int
main(int argc, char **argv) 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_OFFLINE_TRIGGER", "/tmp/fwupd-self-test/system-update", TRUE);
g_setenv("FWUPD_LOCALSTATEDIR", "/tmp/fwupd-self-test/var", 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/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{devices}", fu_plugin_devices_func);
g_test_add_func("/fwupd/plugin{device-inhibit-children}", g_test_add_func("/fwupd/plugin{device-inhibit-children}",

View File

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

View File

@ -150,11 +150,6 @@ LIBFWUPDPLUGIN_1.0.3 {
fu_common_read_uint32; fu_common_read_uint32;
fu_common_write_uint16; fu_common_write_uint16;
fu_common_write_uint32; 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; fu_usb_device_is_open;
local: *; local: *;
} LIBFWUPDPLUGIN_1.0.2; } LIBFWUPDPLUGIN_1.0.2;
@ -550,7 +545,6 @@ LIBFWUPDPLUGIN_1.5.0 {
fu_device_dump_firmware; fu_device_dump_firmware;
fu_device_report_metadata_post; fu_device_report_metadata_post;
fu_device_report_metadata_pre; fu_device_report_metadata_pre;
fu_device_sleep_with_progress;
fu_device_unbind_driver; fu_device_unbind_driver;
fu_efivar_get_data_bytes; fu_efivar_get_data_bytes;
fu_efivar_secure_boot_enabled_full; fu_efivar_secure_boot_enabled_full;
@ -867,6 +861,7 @@ LIBFWUPDPLUGIN_1.6.2 {
LIBFWUPDPLUGIN_1.7.0 { LIBFWUPDPLUGIN_1.7.0 {
global: global:
fu_device_set_progress;
fu_plugin_runner_attach; fu_plugin_runner_attach;
fu_plugin_runner_cleanup; fu_plugin_runner_cleanup;
fu_plugin_runner_detach; fu_plugin_runner_detach;
@ -874,5 +869,28 @@ LIBFWUPDPLUGIN_1.7.0 {
fu_plugin_runner_reload; fu_plugin_runner_reload;
fu_plugin_runner_write_firmware; fu_plugin_runner_write_firmware;
fu_plugin_set_config_value; 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: *; local: *;
} LIBFWUPDPLUGIN_1.6.2; } LIBFWUPDPLUGIN_1.6.2;

View File

@ -28,6 +28,7 @@ fwupdplugin_src = [
'fu-io-channel.c', # fuzzing 'fu-io-channel.c', # fuzzing
'fu-plugin.c', 'fu-plugin.c',
'fu-quirks.c', # fuzzing 'fu-quirks.c', # fuzzing
'fu-progress.c', # fuzzing
'fu-security-attrs.c', 'fu-security-attrs.c',
'fu-smbios.c', # fuzzing 'fu-smbios.c', # fuzzing
'fu-srec-firmware.c', # fuzzing 'fu-srec-firmware.c', # fuzzing
@ -101,6 +102,7 @@ fwupdplugin_headers = [
'fu-plugin.h', 'fu-plugin.h',
'fu-quirks.h', 'fu-quirks.h',
'fu-security-attrs.h', 'fu-security-attrs.h',
'fu-progress.h',
'fu-smbios.h', 'fu-smbios.h',
'fu-srec-firmware.h', 'fu-srec-firmware.h',
'fu-efi-signature.h', 'fu-efi-signature.h',

View File

@ -238,6 +238,7 @@ fu_altos_device_prepare_firmware(FuDevice *device,
static gboolean static gboolean
fu_altos_device_write_firmware(FuDevice *device, fu_altos_device_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -258,6 +259,13 @@ fu_altos_device_write_firmware(FuDevice *device,
return FALSE; 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 */ /* check sizes */
if (self->addr_base == 0x0 || self->addr_bound == 0x0) { if (self->addr_base == 0x0 || self->addr_bound == 0x0) {
g_set_error_literal(error, g_set_error_literal(error,
@ -311,7 +319,8 @@ fu_altos_device_write_firmware(FuDevice *device,
error); error);
if (locker == NULL) if (locker == NULL)
return FALSE; 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) { for (guint i = 0; i < flash_len; i += 0x100) {
g_autoptr(GString) str = NULL; g_autoptr(GString) str = NULL;
guint8 buf_tmp[0x100]; guint8 buf_tmp[0x100];
@ -360,23 +369,24 @@ fu_altos_device_write_firmware(FuDevice *device,
} }
/* progress */ /* 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); g_string_append_len(buf, str->str, str->len);
} }
fu_progress_step_done(progress);
/* go to application mode */ /* go to application mode */
if (!fu_altos_device_tty_write(self, "a\n", -1, error)) if (!fu_altos_device_tty_write(self, "a\n", -1, error))
return FALSE; return FALSE;
fu_progress_step_done(progress);
/* progress complete */
fu_device_set_progress_full(device, flash_len, flash_len);
/* success */ /* success */
return TRUE; return TRUE;
} }
static GBytes * 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); FuAltosDevice *self = FU_ALTOS_DEVICE(device);
guint flash_len; guint flash_len;
@ -427,7 +437,7 @@ fu_altos_device_dump_firmware(FuDevice *device, GError **error)
return NULL; return NULL;
/* progress */ /* progress */
fu_device_set_progress_full(device, fu_progress_set_percentage_full(progress,
i - self->addr_base, i - self->addr_base,
self->addr_bound - self->addr_base); self->addr_bound - self->addr_base);
g_string_append_len(buf, str->str, str->len); g_string_append_len(buf, str->str, str->len);
@ -542,6 +552,17 @@ fu_altos_device_probe(FuDevice *device, GError **error)
return TRUE; 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 static void
fu_altos_device_init(FuAltosDevice *self) 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->prepare_firmware = fu_altos_device_prepare_firmware;
klass_device->write_firmware = fu_altos_device_write_firmware; klass_device->write_firmware = fu_altos_device_write_firmware;
klass_device->dump_firmware = fu_altos_device_dump_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; object_class->finalize = fu_altos_device_finalize;
} }

View File

@ -275,6 +275,7 @@ static gboolean
fu_analogix_device_write_image(FuAnalogixDevice *self, fu_analogix_device_write_image(FuAnalogixDevice *self,
FuFirmware *image, FuFirmware *image,
guint16 req_val, guint16 req_val,
FuProgress *progress,
GError **error) GError **error)
{ {
AnxUpdateStatus status = UPDATE_STATUS_INVALID; AnxUpdateStatus status = UPDATE_STATUS_INVALID;
@ -282,6 +283,12 @@ fu_analogix_device_write_image(FuAnalogixDevice *self,
g_autoptr(GBytes) block_bytes = NULL; g_autoptr(GBytes) block_bytes = NULL;
g_autoptr(GPtrArray) chunks = 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 */ /* offset into firmware */
block_bytes = fu_firmware_get_bytes(image, error); block_bytes = fu_firmware_get_bytes(image, error);
if (block_bytes == NULL) 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)) if (!fu_analogix_device_get_update_status(self, &status, error))
return FALSE; return FALSE;
fu_progress_step_done(progress);
/* write data */ /* 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); chunks = fu_chunk_array_new_from_bytes(block_bytes, 0x00, 0x00, BILLBOARD_MAX_PACKET_SIZE);
for (guint i = 0; i < chunks->len; i++) { for (guint i = 0; i < chunks->len; i++) {
FuChunk *chk = g_ptr_array_index(chunks, 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); g_prefix_error(error, "failed status on chk %u: ", i);
return FALSE; 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 */ /* success */
return TRUE; return TRUE;
@ -331,6 +341,7 @@ fu_analogix_device_write_image(FuAnalogixDevice *self,
static gboolean static gboolean
fu_analogix_device_write_firmware(FuDevice *device, fu_analogix_device_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -340,44 +351,69 @@ fu_analogix_device_write_firmware(FuDevice *device,
g_autoptr(FuFirmware) fw_srx = NULL; g_autoptr(FuFirmware) fw_srx = NULL;
g_autoptr(FuFirmware) fw_stx = 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); fw_cus = fu_firmware_get_image_by_id(firmware, "custom", NULL);
if (fw_cus != NULL) { if (fw_cus != NULL) {
if (!fu_analogix_device_write_image(self, if (!fu_analogix_device_write_image(self,
fw_cus, fw_cus,
ANX_BB_WVAL_UPDATE_CUSTOM_DEF, ANX_BB_WVAL_UPDATE_CUSTOM_DEF,
fu_progress_get_child(progress),
error)) { error)) {
g_prefix_error(error, "program custom define failed: "); g_prefix_error(error, "program custom define failed: ");
return FALSE; return FALSE;
} }
} }
fu_progress_step_done(progress);
/* SECURE_TX */
fw_stx = fu_firmware_get_image_by_id(firmware, "stx", NULL); fw_stx = fu_firmware_get_image_by_id(firmware, "stx", NULL);
if (fw_stx != NULL) { if (fw_stx != NULL) {
if (!fu_analogix_device_write_image(self, if (!fu_analogix_device_write_image(self,
fw_stx, fw_stx,
ANX_BB_WVAL_UPDATE_SECURE_TX, ANX_BB_WVAL_UPDATE_SECURE_TX,
fu_progress_get_child(progress),
error)) { error)) {
g_prefix_error(error, "program secure TX failed: "); g_prefix_error(error, "program secure TX failed: ");
return FALSE; return FALSE;
} }
} }
fu_progress_step_done(progress);
/* SECURE_RX */
fw_srx = fu_firmware_get_image_by_id(firmware, "srx", NULL); fw_srx = fu_firmware_get_image_by_id(firmware, "srx", NULL);
if (fw_srx != NULL) { if (fw_srx != NULL) {
if (!fu_analogix_device_write_image(self, if (!fu_analogix_device_write_image(self,
fw_srx, fw_srx,
ANX_BB_WVAL_UPDATE_SECURE_RX, ANX_BB_WVAL_UPDATE_SECURE_RX,
fu_progress_get_child(progress),
error)) { error)) {
g_prefix_error(error, "program secure RX failed: "); g_prefix_error(error, "program secure RX failed: ");
return FALSE; return FALSE;
} }
} }
fu_progress_step_done(progress);
/* OCM */
fw_ocm = fu_firmware_get_image_by_id(firmware, "ocm", NULL); fw_ocm = fu_firmware_get_image_by_id(firmware, "ocm", NULL);
if (fw_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: "); g_prefix_error(error, "program OCM failed: ");
return FALSE; return FALSE;
} }
} }
fu_progress_step_done(progress);
/* success */ /* success */
return TRUE; 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); 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 static void
fu_analogix_device_init(FuAnalogixDevice *self) 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->probe = fu_analogix_device_probe;
klass_device->prepare_firmware = fu_analogix_device_prepare_firmware; klass_device->prepare_firmware = fu_analogix_device_prepare_firmware;
klass_device->close = fu_analogix_device_close; 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 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); FuAtaDevice *self = FU_ATA_DEVICE(device);
struct ata_tf tf = {0x0}; struct ata_tf tf = {0x0};
@ -760,6 +760,7 @@ fu_ata_device_fw_download(FuAtaDevice *self,
static gboolean static gboolean
fu_ata_device_write_firmware(FuDevice *device, fu_ata_device_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -797,7 +798,7 @@ fu_ata_device_write_firmware(FuDevice *device,
} }
/* write each block */ /* 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); chunks = fu_chunk_array_new_from_bytes(fw, 0x00, 0x00, chunksz);
for (guint i = 0; i < chunks->len; i++) { for (guint i = 0; i < chunks->len; i++) {
FuChunk *chk = g_ptr_array_index(chunks, 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); g_prefix_error(error, "failed to write chunk %u: ", i);
return FALSE; 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! */ /* success! */
fu_device_add_flag(device, FWUPD_DEVICE_FLAG_NEEDS_ACTIVATION); fu_device_add_flag(device, FWUPD_DEVICE_FLAG_NEEDS_ACTIVATION);
fu_device_set_progress(device, 100);
return TRUE; return TRUE;
} }
@ -855,6 +855,17 @@ fu_ata_device_set_quirk_kv(FuDevice *device, const gchar *key, const gchar *valu
return FALSE; 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 static void
fu_ata_device_init(FuAtaDevice *self) 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->activate = fu_ata_device_activate;
klass_device->write_firmware = fu_ata_device_write_firmware; klass_device->write_firmware = fu_ata_device_write_firmware;
klass_device->probe = fu_ata_device_probe; klass_device->probe = fu_ata_device_probe;
klass_device->set_progress = fu_ata_device_set_progress;
} }
FuAtaDevice * FuAtaDevice *

View File

@ -300,7 +300,7 @@ fu_bcm57xx_device_nvram_check(FuBcm57xxDevice *self, GError **error)
} }
static gboolean 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); FuBcm57xxDevice *self = FU_BCM57XX_DEVICE(device);
g_autoptr(FuDeviceLocker) locker1 = NULL; g_autoptr(FuDeviceLocker) locker1 = NULL;
@ -320,7 +320,7 @@ fu_bcm57xx_device_activate(FuDevice *device, GError **error)
return FALSE; return FALSE;
/* activate, causing APE reset, then close, then attach */ /* 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; return FALSE;
/* ensure we attach before we close */ /* ensure we attach before we close */
@ -328,20 +328,20 @@ fu_bcm57xx_device_activate(FuDevice *device, GError **error)
return FALSE; return FALSE;
/* wait for the device to restart before calling reload() */ /* wait for the device to restart before calling reload() */
fu_device_set_status(device, FWUPD_STATUS_DEVICE_BUSY); fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_BUSY);
fu_device_sleep_with_progress(device, 5); /* seconds */ fu_progress_sleep(progress, 5000);
return TRUE; return TRUE;
} }
static GBytes * 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); FuBcm57xxDevice *self = FU_BCM57XX_DEVICE(device);
const gsize bufsz = fu_device_get_firmware_size_max(FU_DEVICE(self)); const gsize bufsz = fu_device_get_firmware_size_max(FU_DEVICE(self));
g_autofree guint8 *buf = g_malloc0(bufsz); g_autofree guint8 *buf = g_malloc0(bufsz);
g_autoptr(GPtrArray) chunks = NULL; 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); chunks = fu_chunk_array_mutable_new(buf, bufsz, 0x0, 0x0, FU_BCM57XX_BLOCK_SZ);
for (guint i = 0; i < chunks->len; i++) { for (guint i = 0; i < chunks->len; i++) {
FuChunk *chk = g_ptr_array_index(chunks, 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), fu_chunk_get_data_sz(chk),
error)) error))
return NULL; 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 */ /* read from hardware */
@ -359,13 +359,13 @@ fu_bcm57xx_device_dump_firmware(FuDevice *device, GError **error)
} }
static FuFirmware * 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(FuFirmware) firmware = fu_bcm57xx_firmware_new();
g_autoptr(GBytes) fw = NULL; g_autoptr(GBytes) fw = NULL;
/* read from hardware */ /* read from hardware */
fw = fu_bcm57xx_device_dump_firmware(device, error); fw = fu_bcm57xx_device_dump_firmware(device, progress, error);
if (fw == NULL) if (fw == NULL)
return NULL; return NULL;
if (!fu_firmware_parse(firmware, fw, FWUPD_INSTALL_FLAG_NONE, error)) 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_ape = NULL;
g_autoptr(FuFirmware) img_stage1 = NULL; g_autoptr(FuFirmware) img_stage1 = NULL;
g_autoptr(FuFirmware) img_stage2 = NULL; g_autoptr(FuFirmware) img_stage2 = NULL;
g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC);
g_autoptr(GPtrArray) images = NULL; g_autoptr(GPtrArray) images = NULL;
/* try to parse NVRAM, stage1 or APE */ /* 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 */ /* 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) if (fw_old == NULL)
return NULL; return NULL;
if (!fu_firmware_parse(firmware, fw_old, flags, error)) { if (!fu_firmware_parse(firmware, fw_old, flags, error)) {
@ -467,6 +468,7 @@ fu_bcm57xx_device_prepare_firmware(FuDevice *device,
static gboolean static gboolean
fu_bcm57xx_device_write_firmware(FuDevice *device, fu_bcm57xx_device_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -475,14 +477,21 @@ fu_bcm57xx_device_write_firmware(FuDevice *device,
g_autoptr(GBytes) blob_verify = NULL; g_autoptr(GBytes) blob_verify = NULL;
g_autoptr(GPtrArray) chunks = 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 */ /* 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); blob = fu_firmware_write(firmware, error);
if (blob == NULL) if (blob == NULL)
return FALSE; return FALSE;
fu_progress_step_done(progress);
/* hit hardware */ /* 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); chunks = fu_chunk_array_new_from_bytes(blob, 0x0, 0x0, FU_BCM57XX_BLOCK_SZ);
for (guint i = 0; i < chunks->len; i++) { for (guint i = 0; i < chunks->len; i++) {
FuChunk *chk = g_ptr_array_index(chunks, 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), fu_chunk_get_data_sz(chk),
error)) error))
return FALSE; 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 */ /* verify */
fu_device_set_status(device, FWUPD_STATUS_DEVICE_VERIFY); blob_verify =
blob_verify = fu_bcm57xx_device_dump_firmware(device, error); fu_bcm57xx_device_dump_firmware(device, fu_progress_get_child(progress), error);
if (blob_verify == NULL) if (blob_verify == NULL)
return FALSE; return FALSE;
if (!fu_common_bytes_compare(blob, blob_verify, error)) if (!fu_common_bytes_compare(blob, blob_verify, error))
return FALSE; return FALSE;
fu_progress_step_done(progress);
/* reset APE */ /* 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 static gboolean
@ -616,6 +634,17 @@ fu_bcm57xx_device_close(FuDevice *device, GError **error)
return g_close(self->ethtool_fd, 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 static void
fu_bcm57xx_device_init(FuBcm57xxDevice *self) 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->dump_firmware = fu_bcm57xx_device_dump_firmware;
klass_device->probe = fu_bcm57xx_device_probe; klass_device->probe = fu_bcm57xx_device_probe;
klass_device->to_string = fu_bcm57xx_device_to_string; 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 address,
guint32 *buf, guint32 *buf,
gsize bufsz, gsize bufsz,
FuProgress *progress,
GError **error) GError **error)
{ {
for (guint i = 0; i < bufsz; i++) { for (guint i = 0; i < bufsz; i++) {
@ -376,7 +377,7 @@ fu_bcm57xx_recovery_device_nvram_read(FuBcm57xxRecoveryDevice *self,
return FALSE; return FALSE;
buf[i] = GUINT32_FROM_BE(val32); buf[i] = GUINT32_FROM_BE(val32);
address += sizeof(guint32); address += sizeof(guint32);
fu_device_set_progress_full(FU_DEVICE(self), i, bufsz); fu_progress_set_percentage_full(progress, i + 1, bufsz);
} }
/* success */ /* success */
@ -388,6 +389,7 @@ fu_bcm57xx_recovery_device_nvram_write(FuBcm57xxRecoveryDevice *self,
guint32 address, guint32 address,
const guint32 *buf, const guint32 *buf,
gsize bufsz_dwrds, gsize bufsz_dwrds,
FuProgress *progress,
GError **error) GError **error)
{ {
const guint32 page_size_dwrds = 64; const guint32 page_size_dwrds = 64;
@ -434,7 +436,7 @@ fu_bcm57xx_recovery_device_nvram_write(FuBcm57xxRecoveryDevice *self,
return FALSE; return FALSE;
} }
address += sizeof(guint32); 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 */ /* success */
@ -442,14 +444,14 @@ fu_bcm57xx_recovery_device_nvram_write(FuBcm57xxRecoveryDevice *self,
} }
static gboolean static gboolean
fu_bcm57xx_recovery_device_detach(FuDevice *device, GError **error) fu_bcm57xx_recovery_device_detach(FuDevice *device, FuProgress *progress, GError **error)
{ {
/* unbind tg3 */ /* unbind tg3 */
return fu_device_unbind_driver(device, error); return fu_device_unbind_driver(device, error);
} }
static gboolean 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; g_autoptr(GError) error_local = NULL;
@ -470,7 +472,7 @@ fu_bcm57xx_recovery_device_attach(FuDevice *device, GError **error)
} }
static gboolean 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}; BcmRegAPEMode mode = {0};
FuBcm57xxRecoveryDevice *self = FU_BCM57XX_RECOVERY_DEVICE(device); FuBcm57xxRecoveryDevice *self = FU_BCM57XX_RECOVERY_DEVICE(device);
@ -497,7 +499,7 @@ fu_bcm57xx_recovery_device_activate(FuDevice *device, GError **error)
} }
static GBytes * 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); FuBcm57xxRecoveryDevice *self = FU_BCM57XX_RECOVERY_DEVICE(device);
gsize bufsz_dwrds = fu_device_get_firmware_size_max(FU_DEVICE(self)) / sizeof(guint32); 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; g_autoptr(FuDeviceLocker) locker2 = NULL;
/* read from hardware */ /* 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( locker = fu_device_locker_new_full(
self, self,
(FuDeviceLockerFunc)fu_bcm57xx_recovery_device_nvram_acquire_lock, (FuDeviceLockerFunc)fu_bcm57xx_recovery_device_nvram_acquire_lock,
@ -521,7 +523,12 @@ fu_bcm57xx_recovery_device_dump_firmware(FuDevice *device, GError **error)
error); error);
if (locker2 == NULL) if (locker2 == NULL)
return 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; return NULL;
if (!fu_device_locker_close(locker2, error)) if (!fu_device_locker_close(locker2, error))
return NULL; return NULL;
@ -557,6 +564,7 @@ fu_bcm57xx_recovery_device_prepare_firmware(FuDevice *device,
static gboolean static gboolean
fu_bcm57xx_recovery_device_write_firmware(FuDevice *device, fu_bcm57xx_recovery_device_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -569,11 +577,18 @@ fu_bcm57xx_recovery_device_write_firmware(FuDevice *device,
g_autoptr(FuDeviceLocker) locker2 = NULL; g_autoptr(FuDeviceLocker) locker2 = NULL;
g_autoptr(GBytes) blob = 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 */ /* 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); blob = fu_firmware_write(firmware, error);
if (blob == NULL) if (blob == NULL)
return FALSE; return FALSE;
fu_progress_step_done(progress);
/* align into uint32_t buffer */ /* align into uint32_t buffer */
buf = g_bytes_get_data(blob, &bufsz); buf = g_bytes_get_data(blob, &bufsz);
@ -590,7 +605,6 @@ fu_bcm57xx_recovery_device_write_firmware(FuDevice *device,
return FALSE; return FALSE;
/* hit hardware */ /* hit hardware */
fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE);
locker = fu_device_locker_new_full( locker = fu_device_locker_new_full(
self, self,
(FuDeviceLockerFunc)fu_bcm57xx_recovery_device_nvram_acquire_lock, (FuDeviceLockerFunc)fu_bcm57xx_recovery_device_nvram_acquire_lock,
@ -605,15 +619,26 @@ fu_bcm57xx_recovery_device_write_firmware(FuDevice *device,
error); error);
if (locker2 == NULL) if (locker2 == NULL)
return FALSE; 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; return FALSE;
if (!fu_device_locker_close(locker2, error)) if (!fu_device_locker_close(locker2, error))
return FALSE; return FALSE;
if (!fu_device_locker_close(locker, error)) if (!fu_device_locker_close(locker, error))
return FALSE; return FALSE;
fu_progress_step_done(progress);
/* reset APE */ /* 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 static gboolean
@ -623,6 +648,15 @@ fu_bcm57xx_recovery_device_setup(FuDevice *device, GError **error)
guint32 fwversion = 0; guint32 fwversion = 0;
g_autoptr(FuDeviceLocker) locker = NULL; g_autoptr(FuDeviceLocker) locker = NULL;
g_autoptr(FuDeviceLocker) locker2 = 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( locker = fu_device_locker_new_full(
self, self,
@ -638,14 +672,17 @@ fu_bcm57xx_recovery_device_setup(FuDevice *device, GError **error)
error); error);
if (locker2 == NULL) if (locker2 == NULL)
return FALSE; return FALSE;
fu_progress_step_done(progress);
/* get NVRAM version */ /* get NVRAM version */
if (!fu_bcm57xx_recovery_device_nvram_read(self, if (!fu_bcm57xx_recovery_device_nvram_read(self,
BCM_NVRAM_STAGE1_BASE + BCM_NVRAM_STAGE1_VERSION, BCM_NVRAM_STAGE1_BASE + BCM_NVRAM_STAGE1_VERSION,
&fwversion, &fwversion,
1, 1,
fu_progress_get_child(progress),
error)) error))
return FALSE; return FALSE;
fu_progress_step_done(progress);
if (fwversion != 0x0) { if (fwversion != 0x0) {
g_autofree gchar *fwversion_str = NULL; 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(device, fwversion_str);
fu_device_set_version_raw(device, fwversion); fu_device_set_version_raw(device, fwversion);
fu_device_set_branch(device, BCM_FW_BRANCH_OSS_FIRMWARE); fu_device_set_branch(device, BCM_FW_BRANCH_OSS_FIRMWARE);
fu_progress_step_done(progress);
fu_progress_step_done(progress);
} else { } else {
guint32 bufver[4] = {0x0}; guint32 bufver[4] = {0x0};
guint32 veraddr = 0; guint32 veraddr = 0;
@ -667,8 +706,10 @@ fu_bcm57xx_recovery_device_setup(FuDevice *device, GError **error)
BCM_NVRAM_STAGE1_VERADDR, BCM_NVRAM_STAGE1_VERADDR,
&veraddr, &veraddr,
1, 1,
fu_progress_get_child(progress),
error)) error))
return FALSE; return FALSE;
fu_progress_step_done(progress);
veraddr = GUINT32_FROM_BE(veraddr); veraddr = GUINT32_FROM_BE(veraddr);
if (veraddr > BCM_PHYS_ADDR_DEFAULT) if (veraddr > BCM_PHYS_ADDR_DEFAULT)
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, BCM_NVRAM_STAGE1_BASE + veraddr,
bufver, bufver,
4, 4,
fu_progress_get_child(progress),
error)) error))
return FALSE; return FALSE;
fu_progress_step_done(progress);
veritem = fu_bcm57xx_veritem_new((guint8 *)bufver, sizeof(bufver)); veritem = fu_bcm57xx_veritem_new((guint8 *)bufver, sizeof(bufver));
if (veritem != NULL) { if (veritem != NULL) {
fu_device_set_version(device, veritem->version); fu_device_set_version(device, veritem->version);
@ -796,6 +839,17 @@ fu_bcm57xx_recovery_device_close(FuDevice *device, GError **error)
#endif #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 static void
fu_bcm57xx_recovery_device_init(FuBcm57xxRecoveryDevice *self) 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->attach = fu_bcm57xx_recovery_device_attach;
klass_device->detach = fu_bcm57xx_recovery_device_detach; klass_device->detach = fu_bcm57xx_recovery_device_detach;
klass_device->probe = fu_bcm57xx_recovery_device_probe; klass_device->probe = fu_bcm57xx_recovery_device_probe;
klass_device->set_progress = fu_bcm57xx_recovery_device_set_progress;
} }
FuBcm57xxRecoveryDevice * FuBcm57xxRecoveryDevice *

View File

@ -354,11 +354,68 @@ fu_ccgx_dmc_get_image_write_status_cb(FuDevice *device, gpointer user_data, GErr
return TRUE; 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 static gboolean
fu_ccgx_dmc_write_firmware_image(FuDevice *device, fu_ccgx_dmc_write_firmware_image(FuDevice *device,
FuCcgxDmcFirmwareRecord *img_rcd, FuCcgxDmcFirmwareRecord *img_rcd,
gsize *fw_data_written, gsize *fw_data_written,
const gsize fw_data_size, const gsize fw_data_size,
FuProgress *progress,
GError **error) GError **error)
{ {
FuCcgxDmcDevice *self = FU_CCGX_DMC_DEVICE(device); FuCcgxDmcDevice *self = FU_CCGX_DMC_DEVICE(device);
@ -369,44 +426,17 @@ fu_ccgx_dmc_write_firmware_image(FuDevice *device,
/* get segment records */ /* get segment records */
seg_records = img_rcd->seg_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++) { 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); FuCcgxDmcFirmwareSegmentRecord *seg_rcd = g_ptr_array_index(seg_records, seg_index);
if (!fu_ccgx_dmc_write_firmware_record(self,
/* write start row and number of rows to a device */ seg_rcd,
if (!fu_ccgx_dmc_device_send_write_command(self, fw_data_written,
seg_rcd->start_row, fu_progress_get_child(progress),
seg_rcd->num_rows,
error)) error))
return FALSE; return FALSE;
fu_progress_step_done(progress);
/* 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;
}
} }
return TRUE; return TRUE;
} }
@ -414,6 +444,7 @@ fu_ccgx_dmc_write_firmware_image(FuDevice *device,
static gboolean static gboolean
fu_ccgx_dmc_write_firmware(FuDevice *device, fu_ccgx_dmc_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -431,6 +462,12 @@ fu_ccgx_dmc_write_firmware(FuDevice *device,
gsize fw_data_written = 0; gsize fw_data_written = 0;
guint8 img_index = 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 */ /* get fwct record */
fwct_blob = fu_ccgx_dmc_firmware_get_fwct_record(FU_CCGX_DMC_FIRMWARE(firmware)); fwct_blob = fu_ccgx_dmc_firmware_get_fwct_record(FU_CCGX_DMC_FIRMWARE(firmware));
fwct_buf = g_bytes_get_data(fwct_blob, &fwct_sz); 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); custom_meta_data = g_bytes_get_data(custom_meta_blob, &custom_meta_bufsz);
/* reset */ /* reset */
fu_device_set_status(device, FWUPD_STATUS_DEVICE_BUSY);
if (!fu_ccgx_dmc_device_send_reset_state_machine(self, error)) if (!fu_ccgx_dmc_device_send_reset_state_machine(self, error))
return FALSE; return FALSE;
fu_progress_step_done(progress);
/* start fw upgrade with custom metadata */ /* start fw upgrade with custom metadata */
if (!fu_ccgx_dmc_device_send_start_upgrade(self, if (!fu_ccgx_dmc_device_send_start_upgrade(self,
@ -463,11 +500,11 @@ fu_ccgx_dmc_write_firmware(FuDevice *device,
/* send fwct data */ /* send fwct data */
if (!fu_ccgx_dmc_device_send_fwct(self, fwct_buf, fwct_sz, error)) if (!fu_ccgx_dmc_device_send_fwct(self, fwct_buf, fwct_sz, error))
return FALSE; return FALSE;
fu_progress_step_done(progress);
/* get total fw size */ /* get total fw size */
image_records = fu_ccgx_dmc_firmware_get_image_records(FU_CCGX_DMC_FIRMWARE(firmware)); 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)); 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) { while (1) {
/* get interrupt request */ /* get interrupt request */
if (!fu_ccgx_dmc_device_read_intr_req(self, &dmc_int_rqt, error)) 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, img_rcd,
&fw_data_written, &fw_data_written,
fw_data_size, fw_data_size,
fu_progress_get_child(progress),
error)) error))
return FALSE; return FALSE;
} }
if (dmc_int_rqt.opcode != DMC_INT_OPCODE_FW_UPGRADE_STATUS) { if (dmc_int_rqt.opcode != DMC_INT_OPCODE_FW_UPGRADE_STATUS) {
if (dmc_int_rqt.opcode == DMC_INT_OPCODE_FWCT_ANALYSIS_STATUS) { if (dmc_int_rqt.opcode == DMC_INT_OPCODE_FWCT_ANALYSIS_STATUS) {
g_set_error(error, g_set_error(error,
@ -515,7 +552,6 @@ fu_ccgx_dmc_write_firmware(FuDevice *device,
dmc_int_rqt.data[0]); dmc_int_rqt.data[0]);
return FALSE; return FALSE;
} }
if (dmc_int_rqt.data[0] == DMC_DEVICE_STATUS_UPDATE_PHASE_1_COMPLETE) { if (dmc_int_rqt.data[0] == DMC_DEVICE_STATUS_UPDATE_PHASE_1_COMPLETE) {
self->update_model = DMC_UPDATE_MODEL_DOWNLOAD_TRIGGER; self->update_model = DMC_UPDATE_MODEL_DOWNLOAD_TRIGGER;
} else if (dmc_int_rqt.data[0] == DMC_DEVICE_STATUS_FW_DOWNLOADED_UPDATE_PEND) { } 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]); dmc_int_rqt.data[0]);
return FALSE; return FALSE;
} }
fu_progress_step_done(progress);
/* success */
return TRUE; return TRUE;
} }
@ -565,7 +604,7 @@ fu_ccgx_dmc_device_prepare_firmware(FuDevice *device,
} }
static gboolean 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); FuCcgxDmcDevice *self = FU_CCGX_DMC_DEVICE(device);
gboolean manual_replug; gboolean manual_replug;
@ -603,7 +642,6 @@ fu_ccgx_dmc_device_attach(FuDevice *device, GError **error)
if (manual_replug) if (manual_replug)
return TRUE; return TRUE;
fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART);
fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG); fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG);
return TRUE; return TRUE;
} }
@ -671,6 +709,17 @@ fu_ccgx_dmc_device_set_quirk_kv(FuDevice *device,
return FALSE; 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 static void
fu_ccgx_dmc_device_init(FuCcgxDmcDevice *self) 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->attach = fu_ccgx_dmc_device_attach;
klass_device->setup = fu_ccgx_dmc_device_setup; klass_device->setup = fu_ccgx_dmc_device_setup;
klass_device->set_quirk_kv = fu_ccgx_dmc_device_set_quirk_kv; 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}; 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), if (!fu_hid_device_set_report(FU_HID_DEVICE(device),
buf[0], buf[0],
buf, buf,
@ -39,7 +38,7 @@ fu_ccgx_hid_device_enable_hpi_mode_cb(FuDevice *device, gpointer user_data, GErr
} }
static gboolean 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, if (!fu_device_retry(device,
fu_ccgx_hid_device_enable_hpi_mode_cb, fu_ccgx_hid_device_enable_hpi_mode_cb,
@ -77,6 +76,17 @@ fu_ccgx_hid_device_setup(FuDevice *device, GError **error)
return FALSE; 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 static void
fu_ccgx_hid_device_init(FuCcgxHidDevice *self) 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); FuDeviceClass *klass_device = FU_DEVICE_CLASS(klass);
klass_device->detach = fu_ccgx_hid_device_detach; klass_device->detach = fu_ccgx_hid_device_detach;
klass_device->setup = fu_ccgx_hid_device_setup; 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; 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) G_DEFINE_TYPE(FuCcgxHpiDevice, fu_ccgx_hpi_device, FU_TYPE_USB_DEVICE)
#define HPI_CMD_REG_READ_WRITE_DELAY_US 10000 #define HPI_CMD_REG_READ_WRITE_DELAY_US 10000
@ -1027,7 +1036,7 @@ fu_ccgx_hpi_read_flash(FuCcgxHpiDevice *self,
} }
static gboolean 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); FuCcgxHpiDevice *self = FU_CCGX_HPI_DEVICE(device);
guint8 buf[] = { guint8 buf[] = {
@ -1042,7 +1051,6 @@ fu_ccgx_hpi_device_detach(FuDevice *device, GError **error)
/* jump to Alt FW */ /* jump to Alt FW */
if (!fu_ccgx_hpi_device_clear_all_events(self, HPI_CMD_COMMAND_CLEAR_EVENT_TIME_MS, error)) if (!fu_ccgx_hpi_device_clear_all_events(self, HPI_CMD_COMMAND_CLEAR_EVENT_TIME_MS, error))
return FALSE; return FALSE;
fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART);
if (!fu_ccgx_hpi_device_reg_write(self, if (!fu_ccgx_hpi_device_reg_write(self,
CY_PD_JUMP_TO_BOOT_REG_ADDR, CY_PD_JUMP_TO_BOOT_REG_ADDR,
buf, buf,
@ -1054,13 +1062,14 @@ fu_ccgx_hpi_device_detach(FuDevice *device, GError **error)
/* sym not required */ /* sym not required */
fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG); 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 */ /* success */
return TRUE; return TRUE;
} }
static gboolean 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); FuCcgxHpiDevice *self = FU_CCGX_HPI_DEVICE(device);
guint8 buf[] = { 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)) if (!fu_ccgx_hpi_device_clear_all_events(self, HPI_CMD_COMMAND_CLEAR_EVENT_TIME_MS, error))
return FALSE; return FALSE;
fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART);
if (!fu_ccgx_hpi_device_reg_write_no_resp(self, if (!fu_ccgx_hpi_device_reg_write_no_resp(self,
CY_PD_REG_RESET_ADDR, CY_PD_REG_RESET_ADDR,
buf, buf,
@ -1079,6 +1087,7 @@ fu_ccgx_hpi_device_attach(FuDevice *device, GError **error)
return FALSE; return FALSE;
} }
fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG); 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; return TRUE;
} }
@ -1252,6 +1261,7 @@ fu_ccgx_hpi_save_metadata(FuCcgxHpiDevice *self,
static gboolean static gboolean
fu_ccgx_hpi_write_firmware(FuDevice *device, fu_ccgx_hpi_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) 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); FWMode fw_mode_alt = fu_ccgx_fw_mode_get_alternate(self->fw_mode);
g_autoptr(FuDeviceLocker) locker = NULL; 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 */ /* enter flash mode */
locker = fu_device_locker_new_full(self, locker = fu_device_locker_new_full(self,
(FuDeviceLockerFunc)fu_ccgx_hpi_enter_flash_mode, (FuDeviceLockerFunc)fu_ccgx_hpi_enter_flash_mode,
@ -1270,16 +1288,14 @@ fu_ccgx_hpi_write_firmware(FuDevice *device,
return FALSE; return FALSE;
/* invalidate metadata for alternate image */ /* 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)) if (!fu_ccgx_hpi_load_metadata(self, fw_mode_alt, &metadata, error))
return FALSE; return FALSE;
fu_device_set_status(device, FWUPD_STATUS_DEVICE_ERASE);
metadata.metadata_valid = 0x00; metadata.metadata_valid = 0x00;
if (!fu_ccgx_hpi_save_metadata(self, fw_mode_alt, &metadata, error)) if (!fu_ccgx_hpi_save_metadata(self, fw_mode_alt, &metadata, error))
return FALSE; return FALSE;
fu_progress_step_done(progress);
/* write new image */ /* write new image */
fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE);
for (guint i = 0; i < records->len; i++) { for (guint i = 0; i < records->len; i++) {
FuCcgxFirmwareRecord *rcd = g_ptr_array_index(records, i); FuCcgxFirmwareRecord *rcd = g_ptr_array_index(records, i);
@ -1294,19 +1310,23 @@ fu_ccgx_hpi_write_firmware(FuDevice *device,
} }
/* update progress */ /* 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 */ /* validate fw */
fu_device_set_status(device, FWUPD_STATUS_DEVICE_VERIFY);
if (!fu_ccgx_hpi_validate_fw(self, fw_mode_alt, error)) { if (!fu_ccgx_hpi_validate_fw(self, fw_mode_alt, error)) {
g_prefix_error(error, "fw validate error: "); g_prefix_error(error, "fw validate error: ");
return FALSE; return FALSE;
} }
fu_progress_step_done(progress);
/* this is a good time to leave the flash mode *before* rebooting */ /* this is a good time to leave the flash mode *before* rebooting */
if (!fu_device_locker_close(locker, error)) if (!fu_device_locker_close(locker, error))
return FALSE; return FALSE;
fu_progress_step_done(progress);
/* success */ /* success */
return TRUE; return TRUE;
@ -1586,7 +1606,7 @@ fu_ccgx_hpi_device_close(FuDevice *device, GError **error)
g_autoptr(GError) error_local = NULL; g_autoptr(GError) error_local = NULL;
/* do not close handle when device restarts */ /* 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; return TRUE;
if (!g_usb_device_release_interface(fu_usb_device_get_dev(FU_USB_DEVICE(device)), if (!g_usb_device_release_interface(fu_usb_device_get_dev(FU_USB_DEVICE(device)),
self->inf_num, 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); 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 static void
fu_ccgx_hpi_device_init(FuCcgxHpiDevice *self) 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->set_quirk_kv = fu_ccgx_hpi_device_set_quirk_kv;
klass_device->open = fu_ccgx_hpi_device_open; klass_device->open = fu_ccgx_hpi_device_open;
klass_device->close = fu_ccgx_hpi_device_close; 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 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); FuColorhugDevice *self = FU_COLORHUG_DEVICE(device);
g_autoptr(GError) error_local = NULL; 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"); g_debug("already in bootloader mode, skipping");
return TRUE; return TRUE;
} }
fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART);
if (!fu_colorhug_device_msg(self, if (!fu_colorhug_device_msg(self,
CH_CMD_RESET, CH_CMD_RESET,
NULL, NULL,
@ -227,7 +225,7 @@ fu_colorhug_device_detach(FuDevice *device, GError **error)
} }
static gboolean 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); FuColorhugDevice *self = FU_COLORHUG_DEVICE(device);
g_autoptr(GError) error_local = NULL; 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"); g_debug("already in runtime mode, skipping");
return TRUE; return TRUE;
} }
fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART);
if (!fu_colorhug_device_msg(self, if (!fu_colorhug_device_msg(self,
CH_CMD_BOOT_FLASH, CH_CMD_BOOT_FLASH,
NULL, NULL,
@ -444,6 +440,7 @@ ch_colorhug_device_calculate_checksum(const guint8 *data, guint32 len)
static gboolean static gboolean
fu_colorhug_device_write_firmware(FuDevice *device, fu_colorhug_device_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -451,27 +448,33 @@ fu_colorhug_device_write_firmware(FuDevice *device,
g_autoptr(GBytes) fw = NULL; g_autoptr(GBytes) fw = NULL;
g_autoptr(GPtrArray) chunks = 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 */ /* get default image */
fw = fu_firmware_get_bytes(firmware, error); fw = fu_firmware_get_bytes(firmware, error);
if (fw == NULL) if (fw == NULL)
return FALSE; 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 */ /* don't auto-boot firmware */
fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE);
if (!fu_colorhug_device_set_flash_success(self, FALSE, error)) if (!fu_colorhug_device_set_flash_success(self, FALSE, error))
return FALSE; return FALSE;
fu_progress_step_done(progress);
/* erase flash */ /* erase flash */
if (!fu_colorhug_device_erase(self, self->start_addr, g_bytes_get_size(fw), error)) if (!fu_colorhug_device_erase(self, self->start_addr, g_bytes_get_size(fw), error))
return FALSE; return FALSE;
fu_progress_step_done(progress);
/* write each block */ /* 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++) { for (guint i = 0; i < chunks->len; i++) {
FuChunk *chk = g_ptr_array_index(chunks, i); FuChunk *chk = g_ptr_array_index(chunks, i);
guint8 buf[CH_FLASH_TRANSFER_BLOCK_SIZE + 4]; guint8 buf[CH_FLASH_TRANSFER_BLOCK_SIZE + 4];
@ -507,11 +510,13 @@ fu_colorhug_device_write_firmware(FuDevice *device,
} }
/* update progress */ /* 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 */ /* verify each block */
fu_device_set_status(device, FWUPD_STATUS_DEVICE_VERIFY);
for (guint i = 0; i < chunks->len; i++) { for (guint i = 0; i < chunks->len; i++) {
FuChunk *chk = g_ptr_array_index(chunks, i); FuChunk *chk = g_ptr_array_index(chunks, i);
guint8 buf[3]; guint8 buf[3];
@ -550,13 +555,26 @@ fu_colorhug_device_write_firmware(FuDevice *device,
} }
/* update progress */ /* 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! */ /* success! */
return TRUE; 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 static void
fu_colorhug_device_init(FuColorhugDevice *self) 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->setup = fu_colorhug_device_setup;
klass_device->open = fu_colorhug_device_open; klass_device->open = fu_colorhug_device_open;
klass_device->probe = fu_colorhug_device_probe; 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, fu_cros_ec_usb_device_transfer_section(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuCrosEcFirmwareSection *section, FuCrosEcFirmwareSection *section,
FuProgress *progress,
GError **error) GError **error)
{ {
FuCrosEcUsbDevice *self = FU_CROS_EC_USB_DEVICE(device); FuCrosEcUsbDevice *self = FU_CROS_EC_USB_DEVICE(device);
@ -805,6 +806,7 @@ fu_cros_ec_usb_device_jump_to_rw(FuDevice *device)
static gboolean static gboolean
fu_cros_ec_usb_device_write_firmware(FuDevice *device, fu_cros_ec_usb_device_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -880,7 +882,10 @@ fu_cros_ec_usb_device_write_firmware(FuDevice *device,
return FALSE; 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++) { for (guint i = 0; i < sections->len; i++) {
FuCrosEcFirmwareSection *section = g_ptr_array_index(sections, 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, if (!fu_cros_ec_usb_device_transfer_section(device,
firmware, firmware,
section, section,
fu_progress_get_child(progress),
&error_local)) { &error_local)) {
if (g_error_matches(error_local, if (g_error_matches(error_local,
G_USB_DEVICE_ERROR, G_USB_DEVICE_ERROR,
@ -900,6 +906,7 @@ fu_cros_ec_usb_device_write_firmware(FuDevice *device,
fu_device_add_flag( fu_device_add_flag(
device, device,
FWUPD_DEVICE_FLAG_ANOTHER_WRITE_REQUIRED); FWUPD_DEVICE_FLAG_ANOTHER_WRITE_REQUIRED);
fu_progress_finished(progress);
return TRUE; return TRUE;
} }
g_propagate_error(error, g_steal_pointer(&error_local)); 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); section->version.triplet);
} }
} }
fu_progress_step_done(progress);
} }
/* send done */ /* send done */
fu_cros_ec_usb_device_send_done(device); fu_cros_ec_usb_device_send_done(device);
@ -981,7 +989,7 @@ fu_cros_ec_usb_device_prepare_firmware(FuDevice *device,
} }
static gboolean 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); FuCrosEcUsbDevice *self = FU_CROS_EC_USB_DEVICE(device);
@ -996,7 +1004,6 @@ fu_cros_ec_usb_device_attach(FuDevice *device, GError **error)
* ro -> rw. * ro -> rw.
*/ */
fu_device_remove_private_flag(device, FU_CROS_EC_USB_DEVICE_FLAG_SPECIAL); 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); fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG);
return TRUE; return TRUE;
} }
@ -1009,7 +1016,6 @@ fu_cros_ec_usb_device_attach(FuDevice *device, GError **error)
} else { } else {
fu_cros_ec_usb_device_jump_to_rw(device); 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); fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG);
/* success */ /* success */
@ -1017,7 +1023,7 @@ fu_cros_ec_usb_device_attach(FuDevice *device, GError **error)
} }
static gboolean 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); 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); fu_device_set_remove_delay(device, CROS_EC_REMOVE_DELAY_RE_ENUMERATE);
if (!fu_cros_ec_usb_device_reset_to_ro(device, error)) if (!fu_cros_ec_usb_device_reset_to_ro(device, error))
return FALSE; return FALSE;
fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART);
fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG); 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); 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 static void
fu_cros_ec_usb_device_class_init(FuCrosEcUsbDeviceClass *klass) 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->open = fu_cros_ec_usb_device_open;
klass_device->probe = fu_cros_ec_usb_device_probe; klass_device->probe = fu_cros_ec_usb_device_probe;
klass_device->close = fu_cros_ec_usb_device_close; 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 static gboolean
fu_dell_dock_hub_write_fw(FuDevice *device, fu_dell_dock_hub_write_fw(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) 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(device != NULL, FALSE);
g_return_val_if_fail(FU_IS_FIRMWARE(firmware), 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 */ /* get default image */
fw = fu_firmware_get_bytes(firmware, error); fw = fu_firmware_get_bytes(firmware, error);
if (fw == NULL) 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)) if (!fu_dell_dock_hid_raise_mcu_clock(device, TRUE, error))
return FALSE; return FALSE;
fu_device_set_status(device, FWUPD_STATUS_DEVICE_ERASE); /* erase */
if (!fu_dell_dock_hid_erase_bank(device, 1, error)) if (!fu_dell_dock_hid_erase_bank(device, 1, error))
return FALSE; return FALSE;
fu_progress_step_done(progress);
fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); /* write */
do { do {
/* last packet */ /* last packet */
if (fw_size - nwritten < write_size) if (fw_size - nwritten < write_size)
@ -96,10 +104,11 @@ fu_dell_dock_hub_write_fw(FuDevice *device,
nwritten += write_size; nwritten += write_size;
data += write_size; data += write_size;
address += 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); } 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)) if (!fu_dell_dock_hid_verify_update(device, &result, error))
return FALSE; return FALSE;
if (!result) { if (!result) {
@ -109,9 +118,9 @@ fu_dell_dock_hub_write_fw(FuDevice *device,
"Failed to verify the update"); "Failed to verify the update");
return FALSE; return FALSE;
} }
fu_progress_step_done(progress);
/* dock will reboot to re-read; this is to appease the daemon */ /* 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_format(device, FWUPD_VERSION_FORMAT_PAIR);
fu_device_set_version(device, dynamic_version); fu_device_set_version(device, dynamic_version);
return TRUE; return TRUE;
@ -166,6 +175,16 @@ fu_dell_dock_hub_finalize(GObject *object)
G_OBJECT_CLASS(fu_dell_dock_hub_parent_class)->finalize(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 static void
fu_dell_dock_hub_init(FuDellDockHub *self) 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->probe = fu_dell_dock_hub_probe;
klass_device->write_firmware = fu_dell_dock_hub_write_fw; 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_quirk_kv = fu_dell_dock_hub_set_quirk_kv;
klass_device->set_progress = fu_dell_dock_hub_set_progress;
} }
FuDellDockHub * FuDellDockHub *

View File

@ -660,7 +660,7 @@ fu_dell_dock_ec_reset(FuDevice *device, GError **error)
} }
static gboolean static gboolean
fu_dell_dock_ec_activate(FuDevice *device, GError **error) fu_dell_dock_ec_activate(FuDevice *device, FuProgress *progress, GError **error)
{ {
FuDellDockECFWUpdateStatus status; FuDellDockECFWUpdateStatus status;
@ -787,6 +787,7 @@ fu_dell_dock_ec_commit_package(FuDevice *device, GBytes *blob_fw, GError **error
static gboolean static gboolean
fu_dell_dock_ec_write_fw(FuDevice *device, fu_dell_dock_ec_write_fw(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) 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(device != NULL, FALSE);
g_return_val_if_fail(FU_IS_FIRMWARE(firmware), 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 */ /* get default image */
fw = fu_firmware_get_bytes(firmware, error); fw = fu_firmware_get_bytes(firmware, error);
if (fw == NULL) 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)) if (!fu_dell_dock_hid_raise_mcu_clock(fu_device_get_proxy(device), TRUE, error))
return FALSE; 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)) if (!fu_dell_dock_hid_erase_bank(fu_device_get_proxy(device), 0xff, error))
return FALSE; return FALSE;
fu_progress_step_done(progress);
fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); /* write */
do { do {
/* last packet */ /* last packet */
if (fw_size - nwritten < write_size) 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: "); g_prefix_error(error, "write over HID failed: ");
return FALSE; 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; nwritten += write_size;
data += write_size; data += write_size;
address += write_size; address += write_size;
} while (nwritten < fw_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)) if (!fu_dell_dock_hid_raise_mcu_clock(fu_device_get_proxy(device), FALSE, error))
return FALSE; return FALSE;
@ -989,6 +997,17 @@ fu_dell_dock_ec_finalize(GObject *object)
G_OBJECT_CLASS(fu_dell_dock_ec_parent_class)->finalize(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 static void
fu_dell_dock_ec_init(FuDellDockEc *self) 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->close = fu_dell_dock_ec_close;
klass_device->write_firmware = fu_dell_dock_ec_write_fw; 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_quirk_kv = fu_dell_dock_ec_set_quirk_kv;
klass_device->set_progress = fu_dell_dock_ec_set_progress;
} }
FuDellDockEc * FuDellDockEc *

View File

@ -500,7 +500,11 @@ fu_dell_dock_mst_erase_bank(FuDevice *proxy, MSTBank bank, GError **error)
} }
static gboolean 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; const MSTBankAttributes *attribs = NULL;
gsize write_size = 32; gsize write_size = 32;
@ -527,7 +531,7 @@ fu_dell_dock_write_flash_bank(FuDevice *device, GBytes *blob_fw, MSTBank bank, G
i); i);
return FALSE; 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; return TRUE;
@ -706,15 +710,67 @@ fu_dell_dock_mst_invalidate_bank(FuDevice *proxy, MSTBank bank_in_use, GError **
return TRUE; 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 static gboolean
fu_dell_dock_mst_write_fw(FuDevice *device, fu_dell_dock_mst_write_fw(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
FuDellDockMst *self = FU_DELL_DOCK_MST(device); FuDellDockMst *self = FU_DELL_DOCK_MST(device);
FuProgress *progress_local;
MSTBank bank_in_use = 0; MSTBank bank_in_use = 0;
guint retries = 2;
gboolean checksum = FALSE; gboolean checksum = FALSE;
guint8 order[2] = {ESM, Bank0}; guint8 order[2] = {ESM, Bank0};
guint16 chip_id; 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_IS_FIRMWARE(firmware), FALSE);
g_return_val_if_fail(fu_device_get_proxy(device) != NULL, 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 */ /* get default image */
fw = fu_firmware_get_bytes(firmware, error); fw = fu_firmware_get_bytes(firmware, error);
if (fw == NULL) if (fw == NULL)
@ -764,8 +825,12 @@ fu_dell_dock_mst_write_fw(FuDevice *device,
/* ESM needs special handling during flash process*/ /* ESM needs special handling during flash process*/
if (!fu_dell_dock_mst_stop_esm(fu_device_get_proxy(device), error)) if (!fu_dell_dock_mst_stop_esm(fu_device_get_proxy(device), error))
return FALSE; return FALSE;
fu_progress_step_done(progress);
/* Write each bank in order */ /* 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++) { for (guint phase = 0; phase < 2; phase++) {
g_debug("MST: Checking bank %u", order[phase]); g_debug("MST: Checking bank %u", order[phase]);
if (!fu_dell_dock_mst_checksum_bank(fu_device_get_proxy(device), 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; return FALSE;
if (checksum) { if (checksum) {
g_debug("MST: bank %u is already up to date", order[phase]); g_debug("MST: bank %u is already up to date", order[phase]);
fu_progress_step_done(progress_local);
continue; continue;
} }
g_debug("MST: bank %u needs to be updated", order[phase]); g_debug("MST: bank %u needs to be updated", order[phase]);
for (guint i = 0; i < retries; i++) { if (!fu_dell_dock_mst_write_bank(device,
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, fw,
order[phase], order[phase],
&checksum, fu_progress_get_child(progress_local),
error)) error))
return FALSE; return FALSE;
fu_device_set_status(device, FWUPD_STATUS_DEVICE_BUSY); fu_progress_step_done(progress_local);
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]);
return FALSE;
}
} }
/* invalidate the previous bank */ /* invalidate the previous bank */
if (!fu_dell_dock_mst_invalidate_bank(fu_device_get_proxy(device), bank_in_use, error)) { 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); g_prefix_error(error, "failed to invalidate bank %u: ", bank_in_use);
return FALSE; return FALSE;
} }
fu_progress_step_done(progress);
/* dock will reboot to re-read; this is to appease the daemon */ /* 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_format(device, FWUPD_VERSION_FORMAT_TRIPLET);
fu_device_set_version(device, dynamic_version); 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); 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 static void
fu_dell_dock_mst_init(FuDellDockMst *self) 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->probe = fu_dell_dock_mst_probe;
klass_device->write_firmware = fu_dell_dock_mst_write_fw; 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_quirk_kv = fu_dell_dock_mst_set_quirk_kv;
klass_device->set_progress = fu_dell_dock_mst_set_progress;
} }
FuDellDockMst * FuDellDockMst *

View File

@ -50,6 +50,7 @@ G_DEFINE_TYPE(FuDellDockTbt, fu_dell_dock_tbt, FU_TYPE_DEVICE)
static gboolean static gboolean
fu_dell_dock_tbt_write_fw(FuDevice *device, fu_dell_dock_tbt_write_fw(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -106,7 +107,7 @@ fu_dell_dock_tbt_write_fw(FuDevice *device,
return FALSE; return FALSE;
g_usleep(2000000); 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) { 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 guint8 write_size = (image_size - i) > HIDI2C_MAX_WRITE ? HIDI2C_MAX_WRITE
: (image_size - i); : (image_size - i);
@ -119,11 +120,11 @@ fu_dell_dock_tbt_write_fw(FuDevice *device,
error)) error))
return FALSE; 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)); 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))) { if (fu_dell_dock_ec_tbt_passive(fu_device_get_parent(device))) {
g_debug("using passive flow for Thunderbolt"); 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 */ /* 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_format(device, FWUPD_VERSION_FORMAT_PAIR);
fu_device_set_version(device, dynamic_version); fu_device_set_version(device, dynamic_version);

View File

@ -60,6 +60,7 @@ fu_dell_dock_status_setup(FuDevice *device, GError **error)
static gboolean static gboolean
fu_dell_dock_status_write(FuDevice *device, fu_dell_dock_status_write(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -96,7 +97,6 @@ fu_dell_dock_status_write(FuDevice *device,
return FALSE; return FALSE;
/* dock will reboot to re-read; this is to appease the daemon */ /* 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_format(device, FWUPD_VERSION_FORMAT_QUAD);
fu_device_set_version(device, dynamic_version); fu_device_set_version(device, dynamic_version);
return TRUE; return TRUE;
@ -143,6 +143,16 @@ fu_dell_dock_status_finalize(GObject *object)
G_OBJECT_CLASS(fu_dell_dock_status_parent_class)->finalize(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 static void
fu_dell_dock_status_init(FuDellDockStatus *self) 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->open = fu_dell_dock_status_open;
klass_device->close = fu_dell_dock_status_close; klass_device->close = fu_dell_dock_status_close;
klass_device->set_quirk_kv = fu_dell_dock_status_set_quirk_kv; klass_device->set_quirk_kv = fu_dell_dock_status_set_quirk_kv;
klass_device->set_progress = fu_dell_dock_status_set_progress;
} }
FuDellDockStatus * FuDellDockStatus *

View File

@ -357,6 +357,7 @@ fu_dell_dock_usb4_hub_nvm_write(FuDevice *device,
const guint8 *buf, const guint8 *buf,
guint32 length, guint32 length,
guint32 nvm_addr, guint32 nvm_addr,
FuProgress *progress,
GError **error) GError **error)
{ {
guint8 metadata[4]; guint8 metadata[4];
@ -389,8 +390,8 @@ fu_dell_dock_usb4_hub_nvm_write(FuDevice *device,
} }
/* 2 Write data in 64 byte blocks */ /* 2 Write data in 64 byte blocks */
fu_device_set_progress_full(device, bytes_done, bytes_total); fu_progress_set_percentage_full(progress, bytes_done, bytes_total);
fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_WRITE);
while (length > 0) { while (length > 0) {
/* write data to mbox data regs */ /* write data to mbox data regs */
if (!fu_dell_dock_usb4_mbox_data_write(device, buf, 64, error)) { 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; buf += 64;
length -= 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; return TRUE;
} }
static gboolean 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); g_autoptr(FuDeviceLocker) locker = fu_device_locker_new(device, error);
if (locker == NULL) if (locker == NULL)
@ -429,6 +430,7 @@ fu_dell_dock_usb4_activate(FuDevice *device, GError **error)
static gboolean static gboolean
fu_dell_dock_usb4_write_fw(FuDevice *device, fu_dell_dock_usb4_write_fw(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -522,7 +524,7 @@ fu_dell_dock_usb4_write_fw(FuDevice *device,
/* firmware install */ /* firmware install */
fw_buf += fw_header_offset; fw_buf += fw_header_offset;
fw_blob_size -= 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; return FALSE;
fu_device_add_flag(device, FWUPD_DEVICE_FLAG_NEEDS_ACTIVATION); 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; return FALSE;
if (needs_activation && dev != NULL) { 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; 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(GBytes) blob_fw = g_bytes_new_static(fw, sizeof(fw));
g_autoptr(GError) error = NULL; g_autoptr(GError) error = NULL;
g_autoptr(GPtrArray) devices = NULL; g_autoptr(GPtrArray) devices = NULL;
g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC);
#ifdef HAVE_GETUID #ifdef HAVE_GETUID
if (tpm_server_running == NULL && (getuid() != 0 || geteuid() != 0)) { 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, ret = fu_plugin_runner_write_firmware(self->plugin_uefi_capsule,
device_v20, device_v20,
blob_fw, blob_fw,
progress,
FWUPD_INSTALL_FLAG_NONE, FWUPD_INSTALL_FLAG_NONE,
&error); &error);
g_assert_error(error, FWUPD_ERROR, FWUPD_ERROR_NOT_SUPPORTED); 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, ret = fu_plugin_runner_write_firmware(self->plugin_uefi_capsule,
device_v20, device_v20,
blob_fw, blob_fw,
progress,
FWUPD_INSTALL_FLAG_FORCE, FWUPD_INSTALL_FLAG_FORCE,
&error); &error);
g_assert_no_error(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 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}; guint8 buf[] = {FU_DFU_CSR_REPORT_ID_CONTROL, FU_DFU_CSR_CONTROL_RESET};
if (!fu_hid_device_set_report(FU_HID_DEVICE(device), 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 * 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); FuDfuCsrDevice *self = FU_DFU_CSR_DEVICE(device);
g_autoptr(GPtrArray) chunks = NULL; g_autoptr(GPtrArray) chunks = NULL;
@ -188,7 +188,7 @@ fu_dfu_csr_device_upload(FuDevice *device, GError **error)
gsize done_sz = 0; gsize done_sz = 0;
/* notify UI */ /* 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); chunks = g_ptr_array_new_with_free_func((GDestroyNotify)g_bytes_unref);
for (guint32 i = 0; i < 0x3ffffff; i++) { for (guint32 i = 0; i < 0x3ffffff; i++) {
@ -253,7 +253,7 @@ fu_dfu_csr_device_upload(FuDevice *device, GError **error)
/* add to chunk array */ /* add to chunk array */
done_sz += chunk_sz; done_sz += chunk_sz;
g_ptr_array_add(chunks, g_steal_pointer(&chunk)); 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 */ /* we're done */
if (chunk_sz < 64 - FU_DFU_CSR_COMMAND_HEADER_SIZE) if (chunk_sz < 64 - FU_DFU_CSR_COMMAND_HEADER_SIZE)
@ -366,6 +366,7 @@ fu_dfu_csr_device_prepare_firmware(FuDevice *device,
static gboolean static gboolean
fu_dfu_csr_device_download(FuDevice *device, fu_dfu_csr_device_download(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -381,7 +382,7 @@ fu_dfu_csr_device_download(FuDevice *device,
return FALSE; return FALSE;
/* notify UI */ /* notify UI */
fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_WRITE);
/* create chunks */ /* create chunks */
chunks = fu_chunk_array_new_from_bytes(blob, chunks = fu_chunk_array_new_from_bytes(blob,
@ -400,7 +401,7 @@ fu_dfu_csr_device_download(FuDevice *device,
return FALSE; return FALSE;
/* update progress */ /* 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 */ /* all done */
@ -438,6 +439,17 @@ fu_dfu_csr_device_setup(FuDevice *device, GError **error)
return TRUE; 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 static void
fu_dfu_csr_device_init(FuDfuCsrDevice *self) 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->attach = fu_dfu_csr_device_attach;
klass_device->setup = fu_dfu_csr_device_setup; klass_device->setup = fu_dfu_csr_device_setup;
klass_device->probe = fu_dfu_csr_device_probe; 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 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); FuDfuDevicePrivate *priv = GET_PRIVATE(self);
GUsbDevice *usb_device = fu_usb_device_get_dev(FU_USB_DEVICE(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 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); FuDfuDevice *self = FU_DFU_DEVICE(device);
FuDfuDevicePrivate *priv = GET_PRIVATE(self); FuDfuDevicePrivate *priv = GET_PRIVATE(self);
@ -989,20 +989,18 @@ fu_dfu_device_detach(FuDevice *device, GError **error)
return FALSE; return FALSE;
/* inform UI there's going to be a detach:attach */ /* 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, progress, error))
if (!fu_dfu_device_request_detach(self, error))
return FALSE; return FALSE;
/* do a host reset */ /* do a host reset */
if ((priv->attributes & FU_DFU_DEVICE_ATTR_WILL_DETACH) == 0) { if ((priv->attributes & FU_DFU_DEVICE_ATTR_WILL_DETACH) == 0) {
g_debug("doing device reset as host will not self-reset"); 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; return FALSE;
} }
/* success */ /* success */
priv->force_version = 0x0; priv->force_version = 0x0;
fu_device_set_status(device, FWUPD_STATUS_IDLE);
fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG); fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG);
return TRUE; 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 /* hardware from Jabra literally reboots if you try to retry a failed
* write -- there's no way to avoid blocking the daemon like this... */ * 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)) if (fu_device_has_private_flag(FU_DEVICE(self), FU_DFU_DEVICE_FLAG_ATTACH_EXTRA_RESET)) {
fu_device_sleep_with_progress(device, 10); /* seconds */ g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC);
fu_progress_sleep(progress, 10000);
}
/* success */ /* success */
return TRUE; 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 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)); GUsbDevice *usb_device = fu_usb_device_get_dev(FU_USB_DEVICE(self));
g_autoptr(GError) error_local = NULL; g_autoptr(GError) error_local = NULL;
@ -1358,7 +1349,7 @@ fu_dfu_device_reset(FuDfuDevice *self, GError **error)
} }
static gboolean 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); FuDfuDevice *self = FU_DFU_DEVICE(device);
FuDfuDevicePrivate *priv = GET_PRIVATE(self); 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)) if (!fu_device_has_flag(device, FWUPD_DEVICE_FLAG_IS_BOOTLOADER))
return TRUE; return TRUE;
/* inform UI there's going to be a re-attach */
fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART);
/* handle weirdness */ /* handle weirdness */
if (fu_device_has_private_flag(FU_DEVICE(self), FU_DFU_DEVICE_FLAG_DETACH_FOR_ATTACH)) { 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; return FALSE;
fu_device_set_status(device, FWUPD_STATUS_IDLE);
fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG); fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG);
return TRUE; 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); target_zero = fu_dfu_device_get_target_by_alt_setting(self, 0, error);
if (target_zero == NULL) if (target_zero == NULL)
return FALSE; 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) if (chunk == NULL)
return FALSE; 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) && 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)) fu_dfu_device_has_attribute(self, FU_DFU_DEVICE_ATTR_WILL_DETACH))
g_debug("Bus reset is not required. Device will reboot to normal"); 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; return FALSE;
/* success */ /* success */
priv->force_version = 0x0; priv->force_version = 0x0;
fu_device_set_status(device, FWUPD_STATUS_IDLE);
fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG); fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG);
return TRUE; 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: * fu_dfu_device_upload:
* @self: a #FuDfuDevice * @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 * Returns: (transfer full): the uploaded firmware, or %NULL for error
**/ **/
FuFirmware * 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); FuDfuDevicePrivate *priv = GET_PRIVATE(self);
GUsbDevice *usb_device = fu_usb_device_get_dev(FU_USB_DEVICE(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); fu_dfu_firmware_set_release(FU_DFU_FIRMWARE(firmware), 0xffff);
/* upload from each target */ /* 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++) { for (guint i = 0; i < priv->targets->len; i++) {
FuDfuTarget *target; FuDfuTarget *target;
const gchar *alt_name; const gchar *alt_name;
gulong id1;
gulong id2;
/* upload to target and proxy signals */ /* upload to target and proxy signals */
target = g_ptr_array_index(priv->targets, i); 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); g_debug("ignoring target %s", alt_name);
continue; continue;
} }
if (!fu_dfu_target_upload(target,
id1 = g_signal_connect(target, firmware,
"percentage-changed", fu_progress_get_child(progress),
G_CALLBACK(fu_dfu_device_percentage_cb), DFU_TARGET_TRANSFER_FLAG_NONE,
self); error))
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))
return NULL; return NULL;
g_signal_handler_disconnect(target, id1); fu_progress_step_done(progress);
g_signal_handler_disconnect(target, id2);
} }
/* do not do the dummy upload for quirked devices */ /* do not do the dummy upload for quirked devices */
priv->done_upload_or_download = TRUE; priv->done_upload_or_download = TRUE;
/* success */ /* success */
fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_IDLE);
return g_object_ref(firmware); 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 static gboolean
fu_dfu_device_download(FuDfuDevice *self, fu_dfu_device_download(FuDfuDevice *self,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FuDfuTargetTransferFlags flags, FuDfuTargetTransferFlags flags,
GError **error) GError **error)
{ {
@ -1625,13 +1596,13 @@ fu_dfu_device_download(FuDfuDevice *self,
images = fu_firmware_get_images(firmware); images = fu_firmware_get_images(firmware);
if (images->len == 0) if (images->len == 0)
g_ptr_array_add(images, g_object_ref(firmware)); 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++) { for (guint i = 0; i < images->len; i++) {
FuFirmware *image = g_ptr_array_index(images, i); FuFirmware *image = g_ptr_array_index(images, i);
FuDfuTargetTransferFlags flags_local = DFU_TARGET_TRANSFER_FLAG_NONE; FuDfuTargetTransferFlags flags_local = DFU_TARGET_TRANSFER_FLAG_NONE;
const gchar *alt_name; const gchar *alt_name;
guint8 alt; guint8 alt;
gulong id1;
gulong id2;
g_autoptr(FuDfuTarget) target_tmp = NULL; g_autoptr(FuDfuTarget) target_tmp = NULL;
g_autoptr(GError) error_local = NULL; g_autoptr(GError) error_local = NULL;
@ -1658,26 +1629,20 @@ fu_dfu_device_download(FuDfuDevice *self,
if (!FU_IS_DFU_FIRMWARE(firmware) || if (!FU_IS_DFU_FIRMWARE(firmware) ||
fu_dfu_firmware_get_version(FU_DFU_FIRMWARE(firmware)) == 0x0) fu_dfu_firmware_get_version(FU_DFU_FIRMWARE(firmware)) == 0x0)
flags_local |= DFU_TARGET_TRANSFER_FLAG_ADDR_HEURISTIC; flags_local |= DFU_TARGET_TRANSFER_FLAG_ADDR_HEURISTIC;
id1 = g_signal_connect(target_tmp, ret = fu_dfu_target_download(target_tmp,
"percentage-changed", image,
G_CALLBACK(fu_dfu_device_percentage_cb), fu_progress_get_child(progress),
self); flags_local,
id2 = g_signal_connect(target_tmp, error);
"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);
if (!ret) if (!ret)
return FALSE; return FALSE;
fu_progress_step_done(progress);
} }
/* do not do the dummy upload for quirked devices */ /* do not do the dummy upload for quirked devices */
priv->done_upload_or_download = TRUE; priv->done_upload_or_download = TRUE;
/* success */ /* success */
fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_IDLE);
return TRUE; return TRUE;
} }
@ -1720,7 +1685,7 @@ fu_dfu_device_error_fixup(FuDfuDevice *self, GError **error)
} }
static GBytes * 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); FuDfuDevice *self = FU_DFU_DEVICE(device);
g_autoptr(FuFirmware) firmware = NULL; g_autoptr(FuFirmware) firmware = NULL;
@ -1738,7 +1703,7 @@ fu_dfu_device_dump_firmware(FuDevice *device, GError **error)
g_debug("uploading from device->host"); g_debug("uploading from device->host");
if (!fu_dfu_device_refresh_and_clear(self, error)) if (!fu_dfu_device_refresh_and_clear(self, error))
return NULL; 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) if (firmware == NULL)
return NULL; return NULL;
@ -1764,6 +1729,7 @@ fu_dfu_device_prepare_firmware(FuDevice *device,
static gboolean static gboolean
fu_dfu_device_write_firmware(FuDevice *device, fu_dfu_device_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -1779,7 +1745,7 @@ fu_dfu_device_write_firmware(FuDevice *device,
} }
/* hit hardware */ /* 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 static gboolean
@ -1869,6 +1835,16 @@ fu_dfu_device_get_attributes_as_string(FuDfuDevice *self)
return g_string_free(str, FALSE); 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 static void
fu_dfu_device_finalize(GObject *object) 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->open = fu_dfu_device_open;
klass_device->close = fu_dfu_device_close; klass_device->close = fu_dfu_device_close;
klass_device->probe = fu_dfu_device_probe; klass_device->probe = fu_dfu_device_probe;
klass_device->set_progress = fu_dfu_device_set_progress;
object_class->finalize = fu_dfu_device_finalize; 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, FU_DFU_DEVICE_FLAG_NO_BUS_RESET_ATTACH,
"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_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 guint16
fu_dfu_device_get_runtime_release(FuDfuDevice *self); fu_dfu_device_get_runtime_release(FuDfuDevice *self);
gboolean gboolean
fu_dfu_device_reset(FuDfuDevice *self, GError **error); fu_dfu_device_reset(FuDfuDevice *self, FuProgress *progress, GError **error);
FuFirmware * FuFirmware *
fu_dfu_device_upload(FuDfuDevice *self, FuDfuTargetTransferFlags flags, GError **error); fu_dfu_device_upload(FuDfuDevice *self,
FuProgress *progress,
FuDfuTargetTransferFlags flags,
GError **error);
gboolean gboolean
fu_dfu_device_refresh(FuDfuDevice *self, GError **error); fu_dfu_device_refresh(FuDfuDevice *self, GError **error);
gboolean 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 #define ATMEL_MANUFACTURER_CODE2 0x1e
static gboolean 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; g_autoptr(GBytes) data_in = NULL;
guint8 buf[3]; guint8 buf[3];
@ -95,18 +95,15 @@ fu_dfu_target_avr_mass_erase(FuDfuTarget *target, GError **error)
buf[1] = DFU_AVR32_CMD_ERASE; buf[1] = DFU_AVR32_CMD_ERASE;
buf[2] = 0xff; buf[2] = 0xff;
data_in = g_bytes_new_static(buf, sizeof(buf)); data_in = g_bytes_new_static(buf, sizeof(buf));
g_debug("mass erasing"); if (!fu_dfu_target_download_chunk(target, 0, data_in, progress, error)) {
fu_dfu_target_set_action(target, FWUPD_STATUS_DEVICE_ERASE);
if (!fu_dfu_target_download_chunk(target, 0, data_in, error)) {
g_prefix_error(error, "cannot mass-erase: "); g_prefix_error(error, "cannot mass-erase: ");
return FALSE; return FALSE;
} }
fu_dfu_target_set_action(target, FWUPD_STATUS_IDLE);
return TRUE; return TRUE;
} }
static gboolean 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]; guint8 buf[3];
g_autoptr(GBytes) data_empty = NULL; 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[1] = DFU_AVR32_CMD_START_APPLI;
buf[2] = DFU_AVR32_START_APPLI_RESET; buf[2] = DFU_AVR32_START_APPLI_RESET;
data_in = g_bytes_new_static(buf, sizeof(buf)); 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)) { if (g_error_matches(error_local, FWUPD_ERROR, FWUPD_ERROR_NOT_SUPPORTED)) {
g_debug("ignoring as device rebooting: %s", error_local->message); g_debug("ignoring as device rebooting: %s", error_local->message);
return TRUE; return TRUE;
@ -129,7 +126,7 @@ fu_dfu_target_avr_attach(FuDfuTarget *target, GError **error)
/* do zero-sized download to initiate the reset */ /* do zero-sized download to initiate the reset */
data_empty = g_bytes_new(NULL, 0); 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)) { if (g_error_matches(error_local, FWUPD_ERROR, FWUPD_ERROR_NOT_SUPPORTED)) {
g_debug("ignoring as device rebooting: %s", error_local->message); g_debug("ignoring as device rebooting: %s", error_local->message);
return TRUE; return TRUE;
@ -153,7 +150,10 @@ fu_dfu_target_avr_attach(FuDfuTarget *target, GError **error)
* Returns: %TRUE for success * Returns: %TRUE for success
**/ **/
static gboolean 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; g_autoptr(GBytes) data_in = NULL;
guint8 buf[4]; guint8 buf[4];
@ -172,7 +172,7 @@ fu_dfu_target_avr_select_memory_unit(FuDfuTarget *target, guint8 memory_unit, GE
buf[3] = memory_unit; buf[3] = memory_unit;
data_in = g_bytes_new_static(buf, sizeof(buf)); data_in = g_bytes_new_static(buf, sizeof(buf));
g_debug("selecting memory unit 0x%02x", (guint)memory_unit); 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: "); g_prefix_error(error, "cannot select memory unit: ");
return FALSE; return FALSE;
} }
@ -190,7 +190,10 @@ fu_dfu_target_avr_select_memory_unit(FuDfuTarget *target, guint8 memory_unit, GE
* Returns: %TRUE for success * Returns: %TRUE for success
**/ **/
static gboolean 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; g_autoptr(GBytes) data_in = NULL;
guint8 buf[4]; 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; buf[3] = memory_page & 0xff;
data_in = g_bytes_new_static(buf, sizeof(buf)); data_in = g_bytes_new_static(buf, sizeof(buf));
g_debug("selecting memory page 0x%01x", (guint)memory_page); 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: "); g_prefix_error(error, "cannot select memory page: ");
return FALSE; return FALSE;
} }
@ -231,7 +234,10 @@ fu_dfu_target_avr_select_memory_page(FuDfuTarget *target, guint16 memory_page, G
* Returns: %TRUE for success * Returns: %TRUE for success
**/ **/
static gboolean 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; g_autoptr(GBytes) data_in = NULL;
guint8 buf[5]; 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); fu_common_write_uint16(&buf[3], memory_page, G_BIG_ENDIAN);
data_in = g_bytes_new_static(buf, sizeof(buf)); data_in = g_bytes_new_static(buf, sizeof(buf));
g_debug("selecting memory page 0x%02x", (guint)memory_page); 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: "); g_prefix_error(error, "cannot select memory page: ");
return FALSE; return FALSE;
} }
@ -265,6 +271,7 @@ static gboolean
fu_dfu_target_avr_read_memory(FuDfuTarget *target, fu_dfu_target_avr_read_memory(FuDfuTarget *target,
guint16 addr_start, guint16 addr_start,
guint16 addr_end, guint16 addr_end,
FuProgress *progress,
GError **error) GError **error)
{ {
g_autoptr(GBytes) data_in = NULL; 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); fu_common_write_uint16(&buf[4], addr_end, G_BIG_ENDIAN);
data_in = g_bytes_new_static(buf, sizeof(buf)); 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); 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, g_prefix_error(error,
"cannot read memory 0x%04x to 0x%04x: ", "cannot read memory 0x%04x to 0x%04x: ",
(guint)addr_start, (guint)addr_start,
@ -298,7 +305,11 @@ fu_dfu_target_avr_read_memory(FuDfuTarget *target,
* Returns: %TRUE for success * Returns: %TRUE for success
**/ **/
static gboolean 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; g_autoptr(GBytes) data_in = NULL;
guint8 buf[3]; guint8 buf[3];
@ -309,7 +320,7 @@ fu_dfu_target_avr_read_command(FuDfuTarget *target, guint8 page, guint8 addr, GE
buf[2] = addr; buf[2] = addr;
data_in = g_bytes_new_static(buf, sizeof(buf)); data_in = g_bytes_new_static(buf, sizeof(buf));
g_debug("read command page:0x%02x addr:0x%02x", (guint)page, (guint)addr); 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: "); g_prefix_error(error, "cannot read command page: ");
return FALSE; 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 * Returns: a 4-byte %GBytes object for success, else %NULL
**/ **/
static GBytes * 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 */ /* 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; 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; 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; return NULL;
/* get data back */ /* 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 * Returns: a 4-byte %GBytes object for success, else %NULL
**/ **/
static GBytes * 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 { struct {
guint8 page; 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, if (!fu_dfu_target_avr_read_command(target,
signature_locations[i].page, signature_locations[i].page,
signature_locations[i].addr, signature_locations[i].addr,
progress,
error)) error))
return NULL; return NULL;
/* get data back */ /* 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) if (chunk_byte == NULL)
return NULL; return NULL;
if (g_bytes_get_size(chunk_byte) != 1) { if (g_bytes_get_size(chunk_byte) != 1) {
@ -405,6 +420,7 @@ fu_dfu_target_avr_setup(FuDfuTarget *target, GError **error)
gsize sz; gsize sz;
guint32 device_id_be; guint32 device_id_be;
g_autofree gchar *chip_id_guid = NULL; g_autofree gchar *chip_id_guid = NULL;
g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC);
g_autoptr(GBytes) chunk_sig = NULL; g_autoptr(GBytes) chunk_sig = NULL;
/* already done */ /* already done */
@ -414,11 +430,11 @@ fu_dfu_target_avr_setup(FuDfuTarget *target, GError **error)
/* different methods for AVR vs. AVR32 */ /* different methods for AVR vs. AVR32 */
if (fu_device_has_private_flag(FU_DEVICE(fu_dfu_target_get_device(target)), if (fu_device_has_private_flag(FU_DEVICE(fu_dfu_target_get_device(target)),
FU_DFU_DEVICE_FLAG_LEGACY_PROTOCOL)) { 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) if (chunk_sig == NULL)
return FALSE; return FALSE;
} else { } 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) { if (chunk_sig == NULL) {
g_prefix_error(error, "failed to get chip signature: "); g_prefix_error(error, "failed to get chip signature: ");
return FALSE; return FALSE;
@ -477,6 +493,7 @@ fu_dfu_target_avr_setup(FuDfuTarget *target, GError **error)
static gboolean static gboolean
fu_dfu_target_avr_download_element(FuDfuTarget *target, fu_dfu_target_avr_download_element(FuDfuTarget *target,
FuChunk *chk, FuChunk *chk,
FuProgress *progress,
FuDfuTargetTransferFlags flags, FuDfuTargetTransferFlags flags,
GError **error) GError **error)
{ {
@ -505,13 +522,21 @@ fu_dfu_target_avr_download_element(FuDfuTarget *target,
0xff, 0xff,
0xff}; /* release */ 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 */ /* select a memory and erase everything */
if (!fu_dfu_target_avr_select_memory_unit(target, if (!fu_dfu_target_avr_select_memory_unit(target,
fu_dfu_target_get_alt_setting(target), fu_dfu_target_get_alt_setting(target),
progress,
error)) error))
return FALSE; return FALSE;
if (!fu_dfu_target_avr_mass_erase(target, error)) if (!fu_dfu_target_avr_mass_erase(target, progress, error))
return FALSE; return FALSE;
fu_progress_step_done(progress);
/* verify the element isn't larger than the target size */ /* verify the element isn't larger than the target size */
blob = fu_chunk_get_bytes(chk); blob = fu_chunk_get_bytes(chk);
@ -554,11 +579,8 @@ fu_dfu_target_avr_download_element(FuDfuTarget *target,
fu_dfu_sector_get_address(sector), fu_dfu_sector_get_address(sector),
ATMEL_64KB_PAGE, ATMEL_64KB_PAGE,
ATMEL_MAX_TRANSFER_SIZE); ATMEL_MAX_TRANSFER_SIZE);
fu_progress_set_id(fu_progress_get_child(progress), G_STRLOC);
/* update UI */ fu_progress_set_steps(fu_progress_get_child(progress), chunks->len);
fu_dfu_target_set_action(target, FWUPD_STATUS_DEVICE_WRITE);
/* process each chunk */
for (guint i = 0; i < chunks->len; i++) { for (guint i = 0; i < chunks->len; i++) {
FuChunk *chk2 = g_ptr_array_index(chunks, i); FuChunk *chk2 = g_ptr_array_index(chunks, i);
g_autofree guint8 *buf = NULL; g_autofree guint8 *buf = NULL;
@ -570,11 +592,13 @@ fu_dfu_target_avr_download_element(FuDfuTarget *target,
FU_DFU_DEVICE_FLAG_LEGACY_PROTOCOL)) { FU_DFU_DEVICE_FLAG_LEGACY_PROTOCOL)) {
if (!fu_dfu_target_avr_select_memory_page(target, if (!fu_dfu_target_avr_select_memory_page(target,
fu_chunk_get_page(chk2), fu_chunk_get_page(chk2),
progress,
error)) error))
return FALSE; return FALSE;
} else { } else {
if (!fu_dfu_target_avr32_select_memory_page(target, if (!fu_dfu_target_avr32_select_memory_page(target,
fu_chunk_get_page(chk2), fu_chunk_get_page(chk2),
progress,
error)) error))
return FALSE; return FALSE;
} }
@ -598,16 +622,15 @@ fu_dfu_target_avr_download_element(FuDfuTarget *target,
fu_chunk_get_data_sz(chk2) + header_sz + sizeof(footer)); fu_chunk_get_data_sz(chk2) + header_sz + sizeof(footer));
g_debug("sending %" G_GSIZE_FORMAT " bytes to the hardware", g_debug("sending %" G_GSIZE_FORMAT " bytes to the hardware",
g_bytes_get_size(chunk_tmp)); 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; return FALSE;
/* update UI */ /* 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 */ /* done */
fu_dfu_target_set_percentage_raw(target, 100);
fu_dfu_target_set_action(target, FWUPD_STATUS_IDLE);
return TRUE; return TRUE;
} }
@ -616,6 +639,7 @@ fu_dfu_target_avr_upload_element(FuDfuTarget *target,
guint32 address, guint32 address,
gsize expected_size, gsize expected_size,
gsize maximum_size, gsize maximum_size,
FuProgress *progress,
GError **error) GError **error)
{ {
guint16 page_last = G_MAXUINT16; guint16 page_last = G_MAXUINT16;
@ -630,6 +654,7 @@ fu_dfu_target_avr_upload_element(FuDfuTarget *target,
/* select unit */ /* select unit */
if (!fu_dfu_target_avr_select_memory_unit(target, if (!fu_dfu_target_avr_select_memory_unit(target,
fu_dfu_target_get_alt_setting(target), fu_dfu_target_get_alt_setting(target),
progress,
error)) error))
return NULL; return NULL;
@ -661,7 +686,7 @@ fu_dfu_target_avr_upload_element(FuDfuTarget *target,
ATMEL_MAX_TRANSFER_SIZE); ATMEL_MAX_TRANSFER_SIZE);
/* update UI */ /* update UI */
fu_dfu_target_set_action(target, FWUPD_STATUS_DEVICE_READ); fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_READ);
/* process each chunk */ /* process each chunk */
blobs = g_ptr_array_new_with_free_func((GDestroyNotify)g_bytes_unref); 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)) { FU_DFU_DEVICE_FLAG_LEGACY_PROTOCOL)) {
if (!fu_dfu_target_avr_select_memory_page(target, if (!fu_dfu_target_avr_select_memory_page(target,
fu_chunk_get_page(chk), fu_chunk_get_page(chk),
progress,
error)) error))
return NULL; return NULL;
} else { } else {
if (!fu_dfu_target_avr32_select_memory_page(target, if (!fu_dfu_target_avr32_select_memory_page(target,
fu_chunk_get_page(chk), fu_chunk_get_page(chk),
progress,
error)) error))
return NULL; 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_address(chk) + fu_chunk_get_address(chk) +
fu_chunk_get_data_sz(chk) - 1, fu_chunk_get_data_sz(chk) - 1,
progress,
error)) error))
return NULL; 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", g_debug("requesting %i bytes from the hardware for chunk 0x%x",
ATMEL_MAX_TRANSFER_SIZE, ATMEL_MAX_TRANSFER_SIZE,
i); 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) if (blob_tmp == NULL)
return NULL; return NULL;
g_ptr_array_add(blobs, blob_tmp); g_ptr_array_add(blobs, blob_tmp);
@ -714,13 +743,9 @@ fu_dfu_target_avr_upload_element(FuDfuTarget *target,
} }
/* update UI */ /* 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 */ /* truncate the image if any sectors are empty, i.e. all 0xff */
if (chunk_valid == G_MAXUINT) { if (chunk_valid == G_MAXUINT) {
g_debug("all %u chunks are empty", blobs->len); g_debug("all %u chunks are empty", blobs->len);

View File

@ -16,11 +16,19 @@ FuDfuTarget *
fu_dfu_target_new(void); fu_dfu_target_new(void);
GBytes * 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 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 gboolean
fu_dfu_target_attach(FuDfuTarget *self, GError **error); fu_dfu_target_attach(FuDfuTarget *self, FuProgress *progress, GError **error);
void void
fu_dfu_target_set_alt_idx(FuDfuTarget *self, guint8 alt_idx); fu_dfu_target_set_alt_idx(FuDfuTarget *self, guint8 alt_idx);
void void
@ -28,12 +36,6 @@ fu_dfu_target_set_alt_setting(FuDfuTarget *self, guint8 alt_setting);
/* for the other implementations */ /* for the other implementations */
void 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); fu_dfu_target_set_alt_name(FuDfuTarget *self, const gchar *alt_name);
void void
fu_dfu_target_set_device(FuDfuTarget *self, FuDfuDevice *device); 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 #define DFU_STM_CMD_READ_UNPROTECT 0x92
static gboolean 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, /* downloading empty payload will cause a dfu to leave,
* the returned status will be dfuMANIFEST and expect the device to disconnect */ * the returned status will be dfuMANIFEST and expect the device to disconnect */
g_autoptr(GBytes) bytes_tmp = g_bytes_new(NULL, 0); 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 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; GBytes *data_in;
guint8 buf[1]; guint8 buf[1];
@ -44,7 +44,7 @@ fu_dfu_target_stm_mass_erase(FuDfuTarget *target, GError **error)
/* format buffer */ /* format buffer */
buf[0] = DFU_STM_CMD_ERASE; buf[0] = DFU_STM_CMD_ERASE;
data_in = g_bytes_new_static(buf, sizeof(buf)); 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: "); g_prefix_error(error, "cannot mass-erase: ");
return FALSE; return FALSE;
} }
@ -53,18 +53,12 @@ fu_dfu_target_stm_mass_erase(FuDfuTarget *target, GError **error)
return fu_dfu_target_check_status(target, error); return fu_dfu_target_check_status(target, error);
} }
/** /* sets the address used for the next download or upload request */
* 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
**/
static gboolean 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; GBytes *data_in;
guint8 buf[5]; 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; buf[0] = DFU_STM_CMD_SET_ADDRESS_POINTER;
memcpy(buf + 1, &address, 4); memcpy(buf + 1, &address, 4);
data_in = g_bytes_new_static(buf, sizeof(buf)); 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); g_prefix_error(error, "cannot set address 0x%x: ", address);
return FALSE; return FALSE;
} }
@ -88,6 +82,7 @@ fu_dfu_target_stm_upload_element(FuDfuTarget *target,
guint32 address, guint32 address,
gsize expected_size, gsize expected_size,
gsize maximum_size, gsize maximum_size,
FuProgress *progress,
GError **error) GError **error)
{ {
FuDfuDevice *device = fu_dfu_target_get_device(target); FuDfuDevice *device = fu_dfu_target_get_device(target);
@ -123,11 +118,11 @@ fu_dfu_target_stm_upload_element(FuDfuTarget *target,
} }
/* update UI */ /* 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 */ /* manually set the sector address */
g_debug("setting DfuSe address to 0x%04x", (guint)offset); 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; return NULL;
/* abort back to IDLE */ /* abort back to IDLE */
@ -144,6 +139,7 @@ fu_dfu_target_stm_upload_element(FuDfuTarget *target,
chunk_tmp = fu_dfu_target_upload_chunk(target, chunk_tmp = fu_dfu_target_upload_chunk(target,
idx + 2, idx + 2,
0, /* device transfer size */ 0, /* device transfer size */
progress,
error); error);
if (chunk_tmp == NULL) if (chunk_tmp == NULL)
return NULL; return NULL;
@ -160,7 +156,7 @@ fu_dfu_target_stm_upload_element(FuDfuTarget *target,
/* update UI */ /* update UI */
if (chunk_size > 0) 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 */ /* detect short write as EOF */
if (chunk_size < transfer_size) 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 */ /* create new image */
contents = fu_dfu_utils_bytes_join_array(chunks); contents = fu_dfu_utils_bytes_join_array(chunks);
if (expected_size > 0) { if (expected_size > 0) {
@ -218,7 +210,10 @@ fu_dfu_target_stm_upload_element(FuDfuTarget *target,
* Returns: %TRUE for success * Returns: %TRUE for success
**/ **/
static gboolean 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; GBytes *data_in;
guint8 buf[5]; 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; buf[0] = DFU_STM_CMD_ERASE;
memcpy(buf + 1, &address, 4); memcpy(buf + 1, &address, 4);
data_in = g_bytes_new_static(buf, sizeof(buf)); 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); g_prefix_error(error, "cannot erase address 0x%x: ", address);
return FALSE; return FALSE;
} }
@ -240,11 +235,13 @@ fu_dfu_target_stm_erase_address(FuDfuTarget *target, guint32 address, GError **e
static gboolean static gboolean
fu_dfu_target_stm_download_element(FuDfuTarget *target, fu_dfu_target_stm_download_element(FuDfuTarget *target,
FuChunk *chk, FuChunk *chk,
FuProgress *progress,
FuDfuTargetTransferFlags flags, FuDfuTargetTransferFlags flags,
GError **error) GError **error)
{ {
FuDfuDevice *device = fu_dfu_target_get_device(target); FuDfuDevice *device = fu_dfu_target_get_device(target);
FuDfuSector *sector; FuDfuSector *sector;
FuProgress *progress_local;
guint nr_chunks; guint nr_chunks;
guint zone_last = G_MAXUINT; guint zone_last = G_MAXUINT;
guint16 transfer_size = fu_dfu_device_get_transfer_size(device); guint16 transfer_size = fu_dfu_device_get_transfer_size(device);
@ -263,6 +260,13 @@ fu_dfu_target_stm_download_element(FuDfuTarget *target,
return FALSE; 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 */ /* 1st pass: work out which sectors need erasing */
sectors_array = g_ptr_array_new(); sectors_array = g_ptr_array_new();
sectors_hash = g_hash_table_new(g_direct_hash, g_direct_equal); 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); offset_dev += fu_dfu_sector_get_size(sector);
} }
} }
fu_progress_step_done(progress);
/* 2nd pass: actually erase sectors */ /* 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++) { for (guint i = 0; i < sectors_array->len; i++) {
sector = g_ptr_array_index(sectors_array, i); sector = g_ptr_array_index(sectors_array, i);
g_debug("erasing sector at 0x%04x", fu_dfu_sector_get_address(sector)); g_debug("erasing sector at 0x%04x", fu_dfu_sector_get_address(sector));
if (!fu_dfu_target_stm_erase_address(target, if (!fu_dfu_target_stm_erase_address(target,
fu_dfu_sector_get_address(sector), fu_dfu_sector_get_address(sector),
fu_progress_get_child(progress_local),
error)) error))
return FALSE; 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_progress_step_done(progress);
fu_dfu_target_set_action(target, FWUPD_STATUS_IDLE);
/* 3rd pass: write data */ /* 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++) { for (guint i = 0; i < nr_chunks; i++) {
gsize length; gsize length;
guint32 offset; guint32 offset;
@ -340,7 +349,10 @@ fu_dfu_target_stm_download_element(FuDfuTarget *target,
/* manually set the sector address */ /* manually set the sector address */
if (fu_dfu_sector_get_zone(sector) != zone_last) { if (fu_dfu_sector_get_zone(sector) != zone_last) {
g_debug("setting address to 0x%04x", (guint)offset_dev); 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; return FALSE;
zone_last = fu_dfu_sector_get_zone(sector); zone_last = fu_dfu_sector_get_zone(sector);
} }
@ -356,7 +368,11 @@ fu_dfu_target_stm_download_element(FuDfuTarget *target,
offset_dev, offset_dev,
g_bytes_get_size(bytes_tmp)); g_bytes_get_size(bytes_tmp));
/* ST uses wBlockNum=0 for DfuSe commands and wBlockNum=1 is reserved */ /* 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; return FALSE;
/* getting the status moves the state machine to DNLOAD-IDLE */ /* getting the status moves the state machine to DNLOAD-IDLE */
@ -364,12 +380,9 @@ fu_dfu_target_stm_download_element(FuDfuTarget *target,
return FALSE; return FALSE;
/* update UI */ /* update UI */
fu_dfu_target_set_percentage(target, offset, g_bytes_get_size(bytes)); fu_progress_step_done(progress_local);
} }
fu_progress_step_done(progress);
/* done */
fu_dfu_target_set_percentage_raw(target, 100);
fu_dfu_target_set_action(target, FWUPD_STATUS_IDLE);
/* success */ /* success */
return TRUE; return TRUE;

View File

@ -45,10 +45,6 @@ typedef struct {
FwupdStatus old_action; FwupdStatus old_action;
} FuDfuTargetPrivate; } 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) G_DEFINE_TYPE_WITH_PRIVATE(FuDfuTarget, fu_dfu_target, G_TYPE_OBJECT)
#define GET_PRIVATE(o) (fu_dfu_target_get_instance_private(o)) #define GET_PRIVATE(o) (fu_dfu_target_get_instance_private(o))
@ -56,45 +52,6 @@ static void
fu_dfu_target_class_init(FuDfuTargetClass *klass) fu_dfu_target_class_init(FuDfuTargetClass *klass)
{ {
GObjectClass *object_class = G_OBJECT_CLASS(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; object_class->finalize = fu_dfu_target_finalize;
} }
@ -750,7 +707,7 @@ fu_dfu_target_setup(FuDfuTarget *self, GError **error)
* Returns: %TRUE for success * Returns: %TRUE for success
**/ **/
gboolean 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); FuDfuTargetClass *klass = FU_DFU_TARGET_GET_CLASS(self);
if (!fu_dfu_target_setup(self, error)) if (!fu_dfu_target_setup(self, error))
@ -762,11 +719,15 @@ fu_dfu_target_mass_erase(FuDfuTarget *self, GError **error)
"mass erase not supported"); "mass erase not supported");
return FALSE; return FALSE;
} }
return klass->mass_erase(self, error); return klass->mass_erase(self, progress, error);
} }
gboolean 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); FuDfuTargetPrivate *priv = GET_PRIVATE(self);
GUsbDevice *usb_device = fu_usb_device_get_dev(FU_USB_DEVICE(priv->device)); 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 */ /* 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) { 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_progress_set_status(progress, FWUPD_STATUS_DEVICE_BUSY);
fu_dfu_target_set_action(self, FWUPD_STATUS_DEVICE_BUSY);
}
if (fu_dfu_device_get_download_timeout(priv->device) > 0) { if (fu_dfu_device_get_download_timeout(priv->device) > 0) {
g_debug("sleeping for %ums…", fu_dfu_device_get_download_timeout(priv->device)); g_debug("sleeping for %ums…", fu_dfu_device_get_download_timeout(priv->device));
g_usleep(fu_dfu_device_get_download_timeout(priv->device) * 1000); 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 * 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); FuDfuTargetPrivate *priv = GET_PRIVATE(self);
GUsbDevice *usb_device = fu_usb_device_get_dev(FU_USB_DEVICE(priv->device)); 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; 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 * FuDfuDevice *
fu_dfu_target_get_device(FuDfuTarget *self) fu_dfu_target_get_device(FuDfuTarget *self)
{ {
@ -908,34 +852,8 @@ fu_dfu_target_get_device(FuDfuTarget *self)
return priv->device; 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 gboolean
fu_dfu_target_attach(FuDfuTarget *self, GError **error) fu_dfu_target_attach(FuDfuTarget *self, FuProgress *progress, GError **error)
{ {
FuDfuTargetPrivate *priv = GET_PRIVATE(self); FuDfuTargetPrivate *priv = GET_PRIVATE(self);
FuDfuTargetClass *klass = FU_DFU_TARGET_GET_CLASS(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 */ /* implemented as part of a superclass */
if (klass->attach != NULL) if (klass->attach != NULL)
return klass->attach(self, error); return klass->attach(self, progress, error);
/* normal DFU mode just needs a bus reset */ /* 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 * static FuChunk *
@ -957,6 +875,7 @@ fu_dfu_target_upload_element_dfu(FuDfuTarget *self,
guint32 address, guint32 address,
gsize expected_size, gsize expected_size,
gsize maximum_size, gsize maximum_size,
FuProgress *progress,
GError **error) GError **error)
{ {
FuDfuTargetPrivate *priv = GET_PRIVATE(self); FuDfuTargetPrivate *priv = GET_PRIVATE(self);
@ -969,7 +888,7 @@ fu_dfu_target_upload_element_dfu(FuDfuTarget *self,
g_autoptr(GPtrArray) chunks = NULL; g_autoptr(GPtrArray) chunks = NULL;
/* update UI */ /* 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 */ /* get all the chunks from the hardware */
chunks = g_ptr_array_new_with_free_func((GDestroyNotify)g_bytes_unref); 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, chunk_tmp = fu_dfu_target_upload_chunk(self,
idx, idx,
0, /* device transfer size */ 0, /* device transfer size */
progress,
error); error);
if (chunk_tmp == NULL) if (chunk_tmp == NULL)
return NULL; return NULL;
@ -995,7 +915,7 @@ fu_dfu_target_upload_element_dfu(FuDfuTarget *self,
/* update UI */ /* update UI */
if (chunk_size > 0) 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 */ /* detect short write as EOF */
if (chunk_size < transfer_size) if (chunk_size < transfer_size)
@ -1017,8 +937,7 @@ fu_dfu_target_upload_element_dfu(FuDfuTarget *self,
} }
/* done */ /* done */
fu_dfu_target_set_percentage_raw(self, 100); fu_progress_set_percentage(progress, 100);
fu_dfu_target_set_action(self, FWUPD_STATUS_IDLE);
/* create new image */ /* create new image */
contents = fu_dfu_utils_bytes_join_array(chunks); contents = fu_dfu_utils_bytes_join_array(chunks);
@ -1030,15 +949,22 @@ fu_dfu_target_upload_element(FuDfuTarget *self,
guint32 address, guint32 address,
gsize expected_size, gsize expected_size,
gsize maximum_size, gsize maximum_size,
FuProgress *progress,
GError **error) GError **error)
{ {
FuDfuTargetClass *klass = FU_DFU_TARGET_GET_CLASS(self); FuDfuTargetClass *klass = FU_DFU_TARGET_GET_CLASS(self);
/* implemented as part of a superclass */ /* implemented as part of a superclass */
if (klass->upload_element != NULL) { 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 static guint32
@ -1059,6 +985,7 @@ fu_dfu_target_get_size_of_zone(FuDfuTarget *self, guint16 zone)
gboolean gboolean
fu_dfu_target_upload(FuDfuTarget *self, fu_dfu_target_upload(FuDfuTarget *self,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FuDfuTargetTransferFlags flags, FuDfuTargetTransferFlags flags,
GError **error) GError **error)
{ {
@ -1104,6 +1031,8 @@ fu_dfu_target_upload(FuDfuTarget *self,
fu_firmware_set_idx(image, priv->alt_setting); fu_firmware_set_idx(image, priv->alt_setting);
/* get all the sectors for the device */ /* 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++) { for (guint i = 0; i < priv->sectors->len; i++) {
g_autoptr(FuChunk) chk = NULL; g_autoptr(FuChunk) chk = NULL;
@ -1125,12 +1054,14 @@ fu_dfu_target_upload(FuDfuTarget *self,
fu_dfu_sector_get_address(sector), fu_dfu_sector_get_address(sector),
0, /* expected */ 0, /* expected */
zone_size, /* maximum */ zone_size, /* maximum */
fu_progress_get_child(progress),
error); error);
if (chk == NULL) if (chk == NULL)
return FALSE; return FALSE;
/* this chunk was uploaded okay */ /* this chunk was uploaded okay */
fu_firmware_add_chunk(image, chk); fu_firmware_add_chunk(image, chk);
fu_progress_step_done(progress);
} }
/* success */ /* success */
@ -1172,6 +1103,7 @@ _g_bytes_compare_verbose(GBytes *bytes1, GBytes *bytes2)
static gboolean static gboolean
fu_dfu_target_download_element_dfu(FuDfuTarget *self, fu_dfu_target_download_element_dfu(FuDfuTarget *self,
FuChunk *chk, FuChunk *chk,
FuProgress *progress,
FuDfuTargetTransferFlags flags, FuDfuTargetTransferFlags flags,
GError **error) GError **error)
{ {
@ -1190,7 +1122,7 @@ fu_dfu_target_download_element_dfu(FuDfuTarget *self,
"zero-length firmware"); "zero-length firmware");
return FALSE; 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++) { for (guint32 i = 0; i < nr_chunks + 1; i++) {
gsize length; gsize length;
guint32 offset; guint32 offset;
@ -1213,17 +1145,13 @@ fu_dfu_target_download_element_dfu(FuDfuTarget *self,
g_debug("writing #%04x chunk of size %" G_GSIZE_FORMAT, g_debug("writing #%04x chunk of size %" G_GSIZE_FORMAT,
i, i,
g_bytes_get_size(bytes_tmp)); 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; return FALSE;
/* update UI */ /* 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 */ /* success */
return TRUE; return TRUE;
} }
@ -1231,20 +1159,41 @@ fu_dfu_target_download_element_dfu(FuDfuTarget *self,
static gboolean static gboolean
fu_dfu_target_download_element(FuDfuTarget *self, fu_dfu_target_download_element(FuDfuTarget *self,
FuChunk *chk, FuChunk *chk,
FuProgress *progress,
FuDfuTargetTransferFlags flags, FuDfuTargetTransferFlags flags,
GError **error) GError **error)
{ {
FuDfuTargetPrivate *priv = GET_PRIVATE(self); FuDfuTargetPrivate *priv = GET_PRIVATE(self);
FuDfuTargetClass *klass = FU_DFU_TARGET_GET_CLASS(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 */ /* implemented as part of a superclass */
if (klass->download_element != NULL) { 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; return FALSE;
} else { } 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; return FALSE;
} }
fu_progress_step_done(progress);
/* verify */ /* verify */
if (flags & DFU_TARGET_TRANSFER_FLAG_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 = NULL;
g_autoptr(GBytes) bytes_tmp = NULL; g_autoptr(GBytes) bytes_tmp = NULL;
g_autoptr(FuChunk) chunk_tmp = NULL; g_autoptr(FuChunk) chunk_tmp = NULL;
fu_dfu_target_set_action(self, FWUPD_STATUS_DEVICE_VERIFY);
bytes = fu_chunk_get_bytes(chk); bytes = fu_chunk_get_bytes(chk);
chunk_tmp = fu_dfu_target_upload_element(self, chunk_tmp = fu_dfu_target_upload_element(self,
fu_chunk_get_address(chk), fu_chunk_get_address(chk),
g_bytes_get_size(bytes), g_bytes_get_size(bytes),
g_bytes_get_size(bytes), g_bytes_get_size(bytes),
fu_progress_get_child(progress),
error); error);
if (chunk_tmp == NULL) if (chunk_tmp == NULL)
return FALSE; return FALSE;
@ -1272,7 +1221,7 @@ fu_dfu_target_download_element(FuDfuTarget *self,
bytes_cmp_str); bytes_cmp_str);
return FALSE; return FALSE;
} }
fu_dfu_target_set_action(self, FWUPD_STATUS_IDLE); fu_progress_step_done(progress);
} }
return TRUE; return TRUE;
@ -1293,6 +1242,7 @@ fu_dfu_target_download_element(FuDfuTarget *self,
gboolean gboolean
fu_dfu_target_download(FuDfuTarget *self, fu_dfu_target_download(FuDfuTarget *self,
FuFirmware *image, FuFirmware *image,
FuProgress *progress,
FuDfuTargetTransferFlags flags, FuDfuTargetTransferFlags flags,
GError **error) GError **error)
{ {
@ -1348,7 +1298,7 @@ fu_dfu_target_download(FuDfuTarget *self,
} }
/* download to device */ /* 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; return FALSE;
} }

View File

@ -40,19 +40,20 @@ typedef enum {
struct _FuDfuTargetClass { struct _FuDfuTargetClass {
GUsbDeviceClass parent_class; GUsbDeviceClass parent_class;
void (*percentage_changed)(FuDfuTarget *self, guint percentage);
void (*action_changed)(FuDfuTarget *self, FwupdStatus action); void (*action_changed)(FuDfuTarget *self, FwupdStatus action);
gboolean (*setup)(FuDfuTarget *self, GError **error); gboolean (*setup)(FuDfuTarget *self, GError **error);
gboolean (*attach)(FuDfuTarget *self, GError **error); gboolean (*attach)(FuDfuTarget *self, FuProgress *progress, GError **error);
gboolean (*detach)(FuDfuTarget *self, GError **error); gboolean (*detach)(FuDfuTarget *self, FuProgress *progress, GError **error);
gboolean (*mass_erase)(FuDfuTarget *self, GError **error); gboolean (*mass_erase)(FuDfuTarget *self, FuProgress *progress, GError **error);
FuChunk *(*upload_element)(FuDfuTarget *self, FuChunk *(*upload_element)(FuDfuTarget *self,
guint32 address, guint32 address,
gsize expected_size, gsize expected_size,
gsize maximum_size, gsize maximum_size,
FuProgress *progress,
GError **error); GError **error);
gboolean (*download_element)(FuDfuTarget *self, gboolean (*download_element)(FuDfuTarget *self,
FuChunk *chk, FuChunk *chk,
FuProgress *progress,
FuDfuTargetTransferFlags flags, FuDfuTargetTransferFlags flags,
GError **error); GError **error);
}; };
@ -70,6 +71,7 @@ fu_dfu_target_get_alt_name_for_display(FuDfuTarget *self, GError **error);
gboolean gboolean
fu_dfu_target_upload(FuDfuTarget *self, fu_dfu_target_upload(FuDfuTarget *self,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FuDfuTargetTransferFlags flags, FuDfuTargetTransferFlags flags,
GError **error); GError **error);
gboolean gboolean
@ -77,9 +79,10 @@ fu_dfu_target_setup(FuDfuTarget *self, GError **error);
gboolean gboolean
fu_dfu_target_download(FuDfuTarget *self, fu_dfu_target_download(FuDfuTarget *self,
FuFirmware *image, FuFirmware *image,
FuProgress *progress,
FuDfuTargetTransferFlags flags, FuDfuTargetTransferFlags flags,
GError **error); GError **error);
gboolean gboolean
fu_dfu_target_mass_erase(FuDfuTarget *self, GError **error); fu_dfu_target_mass_erase(FuDfuTarget *self, FuProgress *progress, GError **error);
void void
fu_dfu_target_to_string(FuDfuTarget *self, guint idt, GString *str); 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; return FALSE;
/* re-open with new device set */ /* 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); fu_usb_device_set_dev(FU_USB_DEVICE(device), usb_device2);
if (!fu_device_open(FU_DEVICE(device), error)) if (!fu_device_open(FU_DEVICE(device), error))
return FALSE; return FALSE;
@ -444,11 +443,11 @@ fu_dfu_tool_replace_data(FuDfuTool *self, gchar **values, GError **error)
} }
static void 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", g_print("%s:\t%u%%\n",
fwupd_status_to_string(fu_device_get_status(device)), fwupd_status_to_string(fu_progress_get_status(progress)),
fu_device_get_progress(device)); fu_progress_get_percentage(progress));
} }
static gboolean static gboolean
@ -461,6 +460,7 @@ fu_dfu_tool_read_alt(FuDfuTool *self, gchar **values, GError **error)
g_autoptr(FuDfuTarget) target = NULL; g_autoptr(FuDfuTarget) target = NULL;
g_autoptr(FuDeviceLocker) locker = NULL; g_autoptr(FuDeviceLocker) locker = NULL;
g_autoptr(GFile) file = NULL; g_autoptr(GFile) file = NULL;
g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC);
/* check args */ /* check args */
if (g_strv_length(values) < 2) { if (g_strv_length(values) < 2) {
@ -485,13 +485,16 @@ fu_dfu_tool_read_alt(FuDfuTool *self, gchar **values, GError **error)
return FALSE; return FALSE;
/* set up progress */ /* set up progress */
g_signal_connect(device, "notify::status", 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(device, "notify::progress", G_CALLBACK(fu_tool_action_changed_cb), self); g_signal_connect(progress,
"percentage-changed",
G_CALLBACK(fu_tool_action_changed_cb),
self);
/* APP -> DFU */ /* APP -> DFU */
if (!fu_device_has_flag(FU_DEVICE(device), FWUPD_DEVICE_FLAG_IS_BOOTLOADER)) { if (!fu_device_has_flag(FU_DEVICE(device), FWUPD_DEVICE_FLAG_IS_BOOTLOADER)) {
g_debug("detaching"); g_debug("detaching");
if (!fu_device_detach(FU_DEVICE(device), error)) if (!fu_device_detach(FU_DEVICE(device), progress, error))
return FALSE; return FALSE;
if (!fu_dfu_device_wait_for_replug(self, if (!fu_dfu_device_wait_for_replug(self,
device, device,
@ -522,11 +525,11 @@ fu_dfu_tool_read_alt(FuDfuTool *self, gchar **values, GError **error)
firmware = fu_dfuse_firmware_new(); 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_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)); 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; return FALSE;
/* do host reset */ /* do host reset */
if (!fu_device_attach(FU_DEVICE(device), error)) if (!fu_device_attach(FU_DEVICE(device), progress, error))
return FALSE; return FALSE;
if (!fu_dfu_device_wait_for_replug(self, if (!fu_dfu_device_wait_for_replug(self,
device, device,
@ -557,6 +560,7 @@ fu_dfu_tool_read(FuDfuTool *self, gchar **values, GError **error)
g_autoptr(FuFirmware) firmware = NULL; g_autoptr(FuFirmware) firmware = NULL;
g_autoptr(FuDeviceLocker) locker = NULL; g_autoptr(FuDeviceLocker) locker = NULL;
g_autoptr(GFile) file = NULL; g_autoptr(GFile) file = NULL;
g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC);
/* check args */ /* check args */
if (g_strv_length(values) != 1) { if (g_strv_length(values) != 1) {
@ -579,7 +583,7 @@ fu_dfu_tool_read(FuDfuTool *self, gchar **values, GError **error)
/* APP -> DFU */ /* APP -> DFU */
if (!fu_device_has_flag(FU_DEVICE(device), FWUPD_DEVICE_FLAG_IS_BOOTLOADER)) { 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; return FALSE;
if (!fu_dfu_device_wait_for_replug(self, if (!fu_dfu_device_wait_for_replug(self,
device, device,
@ -590,14 +594,14 @@ fu_dfu_tool_read(FuDfuTool *self, gchar **values, GError **error)
} }
/* transfer */ /* transfer */
g_signal_connect(device, "notify::status", 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, "notify::progress", 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, flags, error); firmware = fu_dfu_device_upload(device, progress, flags, error);
if (firmware == NULL) if (firmware == NULL)
return FALSE; return FALSE;
/* do host reset */ /* do host reset */
if (!fu_device_attach(FU_DEVICE(device), error)) if (!fu_device_attach(FU_DEVICE(device), progress, error))
return FALSE; return FALSE;
if (!fu_dfu_device_wait_for_replug(self, if (!fu_dfu_device_wait_for_replug(self,
device, device,
@ -630,6 +634,7 @@ fu_dfu_tool_write_alt(FuDfuTool *self, gchar **values, GError **error)
g_autoptr(FuDfuTarget) target = NULL; g_autoptr(FuDfuTarget) target = NULL;
g_autoptr(FuDeviceLocker) locker = NULL; g_autoptr(FuDeviceLocker) locker = NULL;
g_autoptr(GFile) file = NULL; g_autoptr(GFile) file = NULL;
g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC);
/* check args */ /* check args */
if (g_strv_length(values) < 2) { if (g_strv_length(values) < 2) {
@ -661,13 +666,13 @@ fu_dfu_tool_write_alt(FuDfuTool *self, gchar **values, GError **error)
return FALSE; return FALSE;
/* set up progress */ /* set up progress */
g_signal_connect(device, "notify::status", 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, "notify::progress", G_CALLBACK(fu_tool_action_changed_cb), self); g_signal_connect(device, "percentage-changed", G_CALLBACK(fu_tool_action_changed_cb), self);
/* APP -> DFU */ /* APP -> DFU */
if (!fu_device_has_flag(FU_DEVICE(device), FWUPD_DEVICE_FLAG_IS_BOOTLOADER)) { if (!fu_device_has_flag(FU_DEVICE(device), FWUPD_DEVICE_FLAG_IS_BOOTLOADER)) {
g_debug("detaching"); g_debug("detaching");
if (!fu_device_detach(FU_DEVICE(device), error)) if (!fu_device_detach(FU_DEVICE(device), progress, error))
return FALSE; return FALSE;
if (!fu_dfu_device_wait_for_replug(self, device, 5000, error)) if (!fu_dfu_device_wait_for_replug(self, device, 5000, error))
return FALSE; return FALSE;
@ -721,11 +726,11 @@ fu_dfu_tool_write_alt(FuDfuTool *self, gchar **values, GError **error)
} }
/* transfer */ /* transfer */
if (!fu_dfu_target_download(target, image, flags, error)) if (!fu_dfu_target_download(target, image, progress, flags, error))
return FALSE; return FALSE;
/* do host reset */ /* do host reset */
if (!fu_device_attach(FU_DEVICE(device), error)) if (!fu_device_attach(FU_DEVICE(device), progress, error))
return FALSE; return FALSE;
if (!fu_dfu_device_wait_for_replug(self, if (!fu_dfu_device_wait_for_replug(self,
device, device,
@ -745,6 +750,7 @@ fu_dfu_tool_write(FuDfuTool *self, gchar **values, GError **error)
g_autoptr(FuDfuDevice) device = NULL; g_autoptr(FuDfuDevice) device = NULL;
g_autoptr(GBytes) fw = NULL; g_autoptr(GBytes) fw = NULL;
g_autoptr(FuDeviceLocker) locker = NULL; g_autoptr(FuDeviceLocker) locker = NULL;
g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC);
/* check args */ /* check args */
if (g_strv_length(values) < 1) { if (g_strv_length(values) < 1) {
@ -772,7 +778,7 @@ fu_dfu_tool_write(FuDfuTool *self, gchar **values, GError **error)
/* APP -> DFU */ /* APP -> DFU */
if (!fu_device_has_flag(FU_DEVICE(device), FWUPD_DEVICE_FLAG_IS_BOOTLOADER)) { 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; return FALSE;
if (!fu_dfu_device_wait_for_replug(self, if (!fu_dfu_device_wait_for_replug(self,
device, device,
@ -788,13 +794,13 @@ fu_dfu_tool_write(FuDfuTool *self, gchar **values, GError **error)
} }
/* transfer */ /* transfer */
g_signal_connect(device, "notify::status", 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, "notify::progress", 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, flags, error)) if (!fu_device_write_firmware(FU_DEVICE(device), fw, progress, flags, error))
return FALSE; return FALSE;
/* do host reset */ /* do host reset */
if (!fu_device_attach(FU_DEVICE(device), error)) if (!fu_device_attach(FU_DEVICE(device), progress, error))
return FALSE; return FALSE;
if (fu_dfu_device_has_attribute(device, FU_DFU_DEVICE_ATTR_MANIFEST_TOL)) { 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 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(); g_autoptr(FwupdRequest) request = fwupd_request_new();
@ -437,7 +437,6 @@ fu_ebitdo_device_detach(FuDevice *device, GError **error)
} }
/* wait */ /* wait */
fu_device_set_progress(device, 0);
fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG); fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG);
/* emit request */ /* emit request */
@ -452,6 +451,7 @@ fu_ebitdo_device_detach(FuDevice *device, GError **error)
static gboolean static gboolean
fu_ebitdo_device_write_firmware(FuDevice *device, fu_ebitdo_device_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -489,6 +489,12 @@ fu_ebitdo_device_write_firmware(FuDevice *device,
return FALSE; 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 */ /* get header and payload */
fw_hdr = fu_firmware_get_image_by_id_bytes(firmware, FU_FIRMWARE_ID_HEADER, error); fw_hdr = fu_firmware_get_image_by_id_bytes(firmware, FU_FIRMWARE_ID_HEADER, error);
if (fw_hdr == NULL) if (fw_hdr == NULL)
@ -498,7 +504,6 @@ fu_ebitdo_device_write_firmware(FuDevice *device,
return FALSE; return FALSE;
/* set up the firmware header */ /* set up the firmware header */
fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE);
buf = g_bytes_get_data(fw_hdr, &bufsz); buf = g_bytes_get_data(fw_hdr, &bufsz);
if (!fu_ebitdo_device_send(self, if (!fu_ebitdo_device_send(self,
FU_EBITDO_PKT_TYPE_USER_CMD, 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: "); g_prefix_error(error, "failed to get ACK for fw update header: ");
return FALSE; return FALSE;
} }
fu_progress_step_done(progress);
/* flash the firmware in 32 byte blocks */ /* flash the firmware in 32 byte blocks */
chunks = fu_chunk_array_new_from_bytes(fw_payload, 0x0, 0x0, 32); 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)); fu_chunk_get_address(chk));
return FALSE; 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 /* set the "encode id" which is likely a checksum, bluetooth pairing
* or maybe just security-through-obscurity -- also note: * 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)); g_propagate_error(error, g_steal_pointer(&error_local));
return FALSE; return FALSE;
} }
fu_progress_step_done(progress);
/* success! */ /* success! */
return TRUE; return TRUE;
} }
static gboolean 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)); GUsbDevice *usb_device = fu_usb_device_get_dev(FU_USB_DEVICE(device));
g_autoptr(GError) error_local = NULL; g_autoptr(GError) error_local = NULL;
/* when doing a soft-reboot the device does not re-enumerate properly /* when doing a soft-reboot the device does not re-enumerate properly
* so manually reboot the GUsbDevice */ * so manually reboot the GUsbDevice */
fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART);
if (!g_usb_device_reset(usb_device, &error_local)) { if (!g_usb_device_reset(usb_device, &error_local)) {
g_prefix_error(&error_local, "failed to force-reset device: "); g_prefix_error(&error_local, "failed to force-reset device: ");
if (fu_device_has_flag(device, FWUPD_DEVICE_FLAG_WILL_DISAPPEAR)) { 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); 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 static void
fu_ebitdo_device_init(FuEbitdoDevice *self) 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->open = fu_ebitdo_device_open;
klass_device->probe = fu_ebitdo_device_probe; klass_device->probe = fu_ebitdo_device_probe;
klass_device->prepare_firmware = fu_ebitdo_device_prepare_firmware; 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) G_DEFINE_TYPE(FuElantpHidDevice, fu_elantp_hid_device, FU_TYPE_UDEV_DEVICE)
static gboolean static gboolean
fu_elantp_hid_device_detach(FuDevice *device, GError **error); fu_elantp_hid_device_detach(FuDevice *device, FuProgress *progress, GError **error);
static void static void
fu_elantp_hid_device_to_string(FuDevice *device, guint idt, GString *str) 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 static gboolean
fu_elantp_hid_device_write_firmware(FuDevice *device, fu_elantp_hid_device_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -314,17 +315,25 @@ fu_elantp_hid_device_write_firmware(FuDevice *device,
g_autoptr(GBytes) fw = NULL; g_autoptr(GBytes) fw = NULL;
g_autoptr(GPtrArray) chunks = 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 */ /* simple image */
fw = fu_firmware_get_bytes(firmware, error); fw = fu_firmware_get_bytes(firmware, error);
if (fw == NULL) if (fw == NULL)
return FALSE; return FALSE;
/* detach */ /* detach */
if (!fu_elantp_hid_device_detach(device, error)) if (!fu_elantp_hid_device_detach(device, fu_progress_get_child(progress), error))
return FALSE; return FALSE;
fu_progress_step_done(progress);
/* write each block */ /* write each block */
fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE);
buf = g_bytes_get_data(fw, &bufsz); buf = g_bytes_get_data(fw, &bufsz);
iap_addr = fu_elantp_firmware_get_iap_addr(firmware_elantp); 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); 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 */ /* update progress */
checksum += csum_tmp; 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 */ /* verify the written checksum */
fu_device_set_status(device, FWUPD_STATUS_DEVICE_VERIFY);
if (!fu_elantp_hid_device_read_cmd(self, if (!fu_elantp_hid_device_read_cmd(self,
ETP_CMD_I2C_IAP_CHECKSUM, ETP_CMD_I2C_IAP_CHECKSUM,
csum_buf, csum_buf,
@ -395,16 +406,16 @@ fu_elantp_hid_device_write_firmware(FuDevice *device,
checksum_device); checksum_device);
return FALSE; return FALSE;
} }
fu_progress_step_done(progress);
/* wait for a reset */ /* wait for a reset */
fu_device_set_progress(device, 0); fu_progress_sleep(fu_progress_get_child(progress), ELANTP_DELAY_COMPLETE);
fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); fu_progress_step_done(progress);
g_usleep(ELANTP_DELAY_COMPLETE * 1000);
return TRUE; return TRUE;
} }
static gboolean 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); FuElantpHidDevice *self = FU_ELANTP_HID_DEVICE(device);
guint16 iap_ver; guint16 iap_ver;
@ -415,7 +426,6 @@ fu_elantp_hid_device_detach(FuDevice *device, GError **error)
/* sanity check */ /* sanity check */
if (fu_device_has_flag(device, FWUPD_DEVICE_FLAG_IS_BOOTLOADER)) { if (fu_device_has_flag(device, FWUPD_DEVICE_FLAG_IS_BOOTLOADER)) {
g_debug("in bootloader mode, reset IC"); g_debug("in bootloader mode, reset IC");
fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART);
if (!fu_elantp_hid_device_write_cmd(self, if (!fu_elantp_hid_device_write_cmd(self,
ETP_CMD_I2C_IAP_RESET, ETP_CMD_I2C_IAP_RESET,
ETP_I2C_IAP_RESET, ETP_I2C_IAP_RESET,
@ -513,7 +523,7 @@ fu_elantp_hid_device_detach(FuDevice *device, GError **error)
} }
static gboolean 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); FuElantpHidDevice *self = FU_ELANTP_HID_DEVICE(device);
@ -524,7 +534,6 @@ fu_elantp_hid_device_attach(FuDevice *device, GError **error)
} }
/* reset back to runtime */ /* 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)) if (!fu_elantp_hid_device_write_cmd(self, ETP_CMD_I2C_IAP_RESET, ETP_I2C_IAP_RESET, error))
return FALSE; return FALSE;
g_usleep(ELANTP_DELAY_RESET * 1000); g_usleep(ELANTP_DELAY_RESET * 1000);
@ -583,6 +592,17 @@ fu_elantp_hid_device_set_quirk_kv(FuDevice *device,
return FALSE; 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 static void
fu_elantp_hid_device_init(FuElantpHidDevice *self) 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->write_firmware = fu_elantp_hid_device_write_firmware;
klass_device->prepare_firmware = fu_elantp_hid_device_prepare_firmware; klass_device->prepare_firmware = fu_elantp_hid_device_prepare_firmware;
klass_device->probe = fu_elantp_hid_device_probe; 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) G_DEFINE_TYPE(FuElantpI2cDevice, fu_elantp_i2c_device, FU_TYPE_UDEV_DEVICE)
static gboolean static gboolean
fu_elantp_i2c_device_detach(FuDevice *device, GError **error); fu_elantp_i2c_device_detach(FuDevice *device, FuProgress *progress, GError **error);
static void static void
fu_elantp_i2c_device_to_string(FuDevice *device, guint idt, GString *str) 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 static gboolean
fu_elantp_i2c_device_write_firmware(FuDevice *device, fu_elantp_i2c_device_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -386,17 +387,25 @@ fu_elantp_i2c_device_write_firmware(FuDevice *device,
g_autoptr(GBytes) fw = NULL; g_autoptr(GBytes) fw = NULL;
g_autoptr(GPtrArray) chunks = 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 */ /* simple image */
fw = fu_firmware_get_bytes(firmware, error); fw = fu_firmware_get_bytes(firmware, error);
if (fw == NULL) if (fw == NULL)
return FALSE; return FALSE;
/* detach */ /* detach */
if (!fu_elantp_i2c_device_detach(device, error)) if (!fu_elantp_i2c_device_detach(device, fu_progress_get_child(progress), error))
return FALSE; return FALSE;
fu_progress_step_done(progress);
/* write each block */ /* write each block */
fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE);
buf = g_bytes_get_data(fw, &bufsz); buf = g_bytes_get_data(fw, &bufsz);
iap_addr = fu_elantp_firmware_get_iap_addr(firmware_elantp); 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); 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 */ /* update progress */
checksum += csum_tmp; 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 */ /* verify the written checksum */
fu_device_set_status(device, FWUPD_STATUS_DEVICE_VERIFY);
if (!fu_elantp_i2c_device_read_cmd(self, if (!fu_elantp_i2c_device_read_cmd(self,
ETP_CMD_I2C_IAP_CHECKSUM, ETP_CMD_I2C_IAP_CHECKSUM,
csum_buf, csum_buf,
@ -469,16 +480,16 @@ fu_elantp_i2c_device_write_firmware(FuDevice *device,
checksum_device); checksum_device);
return FALSE; return FALSE;
} }
fu_progress_step_done(progress);
/* wait for a reset */ /* wait for a reset */
fu_device_set_progress(device, 0); fu_progress_sleep(fu_progress_get_child(progress), ELANTP_DELAY_COMPLETE);
fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); fu_progress_step_done(progress);
g_usleep(ELANTP_DELAY_COMPLETE * 1000);
return TRUE; return TRUE;
} }
static gboolean 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 iap_ver;
guint16 ic_type; guint16 ic_type;
@ -489,7 +500,6 @@ fu_elantp_i2c_device_detach(FuDevice *device, GError **error)
/* sanity check */ /* sanity check */
if (fu_device_has_flag(device, FWUPD_DEVICE_FLAG_IS_BOOTLOADER)) { if (fu_device_has_flag(device, FWUPD_DEVICE_FLAG_IS_BOOTLOADER)) {
g_debug("in bootloader mode, reset IC"); g_debug("in bootloader mode, reset IC");
fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART);
if (!fu_elantp_i2c_device_write_cmd(self, if (!fu_elantp_i2c_device_write_cmd(self,
ETP_CMD_I2C_IAP_RESET, ETP_CMD_I2C_IAP_RESET,
ETP_I2C_IAP_RESET, ETP_I2C_IAP_RESET,
@ -607,7 +617,7 @@ fu_elantp_i2c_device_detach(FuDevice *device, GError **error)
} }
static gboolean 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); FuElantpI2cDevice *self = FU_ELANTP_I2C_DEVICE(device);
@ -618,7 +628,6 @@ fu_elantp_i2c_device_attach(FuDevice *device, GError **error)
} }
/* reset back to runtime */ /* 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)) if (!fu_elantp_i2c_device_write_cmd(self, ETP_CMD_I2C_IAP_RESET, ETP_I2C_IAP_RESET, error))
return FALSE; return FALSE;
g_usleep(ELANTP_DELAY_RESET * 1000); g_usleep(ELANTP_DELAY_RESET * 1000);
@ -690,6 +699,17 @@ fu_elantp_i2c_device_set_quirk_kv(FuDevice *device,
return FALSE; 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 static void
fu_elantp_i2c_device_init(FuElantpI2cDevice *self) 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->prepare_firmware = fu_elantp_i2c_device_prepare_firmware;
klass_device->probe = fu_elantp_i2c_device_probe; klass_device->probe = fu_elantp_i2c_device_probe;
klass_device->open = fu_elantp_i2c_device_open; 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 static gboolean
fu_emmc_device_write_firmware(FuDevice *device, fu_emmc_device_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -357,6 +358,13 @@ fu_emmc_device_write_firmware(FuDevice *device,
g_autoptr(GBytes) fw = NULL; g_autoptr(GBytes) fw = NULL;
g_autoptr(GPtrArray) chunks = 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)) if (!fu_emmc_read_extcsd(FU_EMMC_DEVICE(device), ext_csd, sizeof(ext_csd), error))
return FALSE; return FALSE;
@ -394,6 +402,7 @@ fu_emmc_device_write_firmware(FuDevice *device,
(EXT_CSD_NORMAL_MODE << 8) | EXT_CSD_CMD_SET_NORMAL; (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].flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
multi_cmd->cmds[2].write_flag = 1; multi_cmd->cmds[2].write_flag = 1;
fu_progress_step_done(progress);
/* build packets */ /* build packets */
chunks = fu_chunk_array_new_from_bytes(fw, chunks = fu_chunk_array_new_from_bytes(fw,
@ -446,9 +455,12 @@ fu_emmc_device_write_firmware(FuDevice *device,
} }
/* update progress */ /* 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 */ /* sanity check */
total_done = (gsize)sect_done * (gsize)self->sect_size; total_done = (gsize)sect_done * (gsize)self->sect_size;
@ -511,10 +523,22 @@ fu_emmc_device_write_firmware(FuDevice *device,
return FALSE; return FALSE;
} }
} }
fu_progress_step_done(progress);
return TRUE; 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 static void
fu_emmc_device_init(FuEmmcDevice *self) 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->prepare_firmware = fu_emmc_device_prepare_firmware;
klass_device->probe = fu_emmc_device_probe; klass_device->probe = fu_emmc_device_probe;
klass_device->write_firmware = fu_emmc_device_write_firmware; 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 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); FuEp963xDevice *self = FU_EP963X_DEVICE(device);
const guint8 buf[] = {'E', 'P', '9', '6', '3'}; const guint8 buf[] = {'E', 'P', '9', '6', '3'};
@ -135,13 +135,12 @@ fu_ep963x_device_detach(FuDevice *device, GError **error)
return FALSE; return FALSE;
} }
fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART);
fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG); fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG);
return TRUE; return TRUE;
} }
static gboolean 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); FuEp963xDevice *self = FU_EP963X_DEVICE(device);
g_autoptr(GError) error_local = NULL; 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"); g_debug("already in runtime mode, skipping");
return TRUE; return TRUE;
} }
fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART);
if (!fu_ep963x_device_write(self, if (!fu_ep963x_device_write(self,
FU_EP963_USB_CONTROL_ID, FU_EP963_USB_CONTROL_ID,
FU_EP963_OPCODE_SUBMCU_PROGRAM_FINISHED, FU_EP963_OPCODE_SUBMCU_PROGRAM_FINISHED,
@ -244,6 +241,7 @@ fu_ep963x_device_wait_cb(FuDevice *device, gpointer user_data, GError **error)
static gboolean static gboolean
fu_ep963x_device_write_firmware(FuDevice *device, fu_ep963x_device_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -252,13 +250,18 @@ fu_ep963x_device_write_firmware(FuDevice *device,
g_autoptr(GError) error_local = NULL; g_autoptr(GError) error_local = NULL;
g_autoptr(GPtrArray) blocks = 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 */ /* get default image */
fw = fu_firmware_get_bytes(firmware, error); fw = fu_firmware_get_bytes(firmware, error);
if (fw == NULL) if (fw == NULL)
return FALSE; return FALSE;
/* reset the block index */ /* reset the block index */
fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE);
if (!fu_ep963x_device_write(self, if (!fu_ep963x_device_write(self,
FU_EP963_USB_CONTROL_ID, FU_EP963_USB_CONTROL_ID,
FU_EP963_OPCODE_SUBMCU_ENTER_ICP, FU_EP963_OPCODE_SUBMCU_ENTER_ICP,
@ -272,6 +275,7 @@ fu_ep963x_device_write_firmware(FuDevice *device,
error_local->message); error_local->message);
return FALSE; return FALSE;
} }
fu_progress_step_done(progress);
/* write each block */ /* write each block */
blocks = fu_chunk_array_new_from_bytes(fw, 0x00, 0x00, FU_EP963_TRANSFER_BLOCK_SIZE); 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; return FALSE;
/* update progress */ /* 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! */ /* success! */
return TRUE; 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 static void
fu_ep963x_device_init(FuEp963xDevice *self) 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->attach = fu_ep963x_device_attach;
klass_device->detach = fu_ep963x_device_detach; klass_device->detach = fu_ep963x_device_detach;
klass_device->setup = fu_ep963x_device_setup; 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 static gboolean
fu_fastboot_device_read(FuDevice *device, fu_fastboot_device_read(FuDevice *device,
gchar **str, gchar **str,
FuProgress *progress,
FuFastbootDeviceReadFlags flags, FuFastbootDeviceReadFlags flags,
GError **error) GError **error)
{ {
@ -201,9 +202,9 @@ fu_fastboot_device_read(FuDevice *device,
tmp = g_strndup((const gchar *)buf + 4, self->blocksz - 4); tmp = g_strndup((const gchar *)buf + 4, self->blocksz - 4);
if (memcmp(buf, "INFO", 4) == 0) { if (memcmp(buf, "INFO", 4) == 0) {
if (g_strcmp0(tmp, "erasing flash") == 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) 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 else
g_debug("INFO returned unknown: %s", tmp); g_debug("INFO returned unknown: %s", tmp);
continue; 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); g_autofree gchar *tmp = g_strdup_printf("getvar:%s", key);
if (!fu_fastboot_device_writestr(device, tmp, error)) if (!fu_fastboot_device_writestr(device, tmp, error))
return FALSE; 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); g_prefix_error(error, "failed to getvar %s: ", key);
return FALSE; return FALSE;
} }
@ -255,25 +256,33 @@ fu_fastboot_device_getvar(FuDevice *device, const gchar *key, gchar **str, GErro
static gboolean static gboolean
fu_fastboot_device_cmd(FuDevice *device, fu_fastboot_device_cmd(FuDevice *device,
const gchar *cmd, const gchar *cmd,
FuProgress *progress,
FuFastbootDeviceReadFlags flags, FuFastbootDeviceReadFlags flags,
GError **error) GError **error)
{ {
if (!fu_fastboot_device_writestr(device, cmd, error)) if (!fu_fastboot_device_writestr(device, cmd, error))
return FALSE; return FALSE;
if (!fu_fastboot_device_read(device, NULL, flags, error)) if (!fu_fastboot_device_read(device, NULL, progress, flags, error))
return FALSE; return FALSE;
return TRUE; return TRUE;
} }
static gboolean 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); 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 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); FuFastbootDevice *self = FU_FASTBOOT_DEVICE(device);
gsize sz = g_bytes_get_size(fw); 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; g_autoptr(GPtrArray) chunks = NULL;
/* tell the client the size of data to expect */ /* 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; return FALSE;
/* send the data in chunks */ /* 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, chunks = fu_chunk_array_new_from_bytes(fw,
0x00, /* start addr */ 0x00, /* start addr */
0x00, /* page_sz */ 0x00, /* page_sz */
@ -297,9 +310,13 @@ fu_fastboot_device_download(FuDevice *device, GBytes *fw, GError **error)
fu_chunk_get_data_sz(chk), fu_chunk_get_data_sz(chk),
error)) error))
return FALSE; 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 FALSE;
return TRUE; return TRUE;
} }
@ -360,6 +377,7 @@ static gboolean
fu_fastboot_device_write_qfil_part(FuDevice *device, fu_fastboot_device_write_qfil_part(FuDevice *device,
FuArchive *archive, FuArchive *archive,
XbNode *part, XbNode *part,
FuProgress *progress,
GError **error) GError **error)
{ {
GBytes *data; GBytes *data;
@ -384,15 +402,16 @@ fu_fastboot_device_write_qfil_part(FuDevice *device,
partition += 2; partition += 2;
/* flash the partition */ /* flash the partition */
if (!fu_fastboot_device_download(device, data, error)) if (!fu_fastboot_device_download(device, data, progress, error))
return FALSE; return FALSE;
return fu_fastboot_device_flash(device, partition, error); return fu_fastboot_device_flash(device, partition, progress, error);
} }
static gboolean static gboolean
fu_fastboot_device_write_motorola_part(FuDevice *device, fu_fastboot_device_write_motorola_part(FuDevice *device,
FuArchive *archive, FuArchive *archive,
XbNode *part, XbNode *part,
FuProgress *progress,
GError **error) GError **error)
{ {
const gchar *op = xb_node_get_attr(part, "operation"); const gchar *op = xb_node_get_attr(part, "operation");
@ -456,6 +475,7 @@ fu_fastboot_device_write_motorola_part(FuDevice *device,
/* erase the partition */ /* erase the partition */
return fu_fastboot_device_cmd(device, return fu_fastboot_device_cmd(device,
cmd, cmd,
progress,
FU_FASTBOOT_DEVICE_READ_FLAG_NONE, FU_FASTBOOT_DEVICE_READ_FLAG_NONE,
error); error);
} }
@ -512,16 +532,20 @@ fu_fastboot_device_write_motorola_part(FuDevice *device,
} }
/* flash the partition */ /* flash the partition */
if (!fu_fastboot_device_download(device, data, error)) if (!fu_fastboot_device_download(device, data, progress, error))
return FALSE; 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 */ /* dumb operation that doesn't expect a response */
if (g_strcmp0(op, "boot") == 0 || g_strcmp0(op, "continue") == 0 || 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, "reboot") == 0 || g_strcmp0(op, "reboot-bootloader") == 0 ||
g_strcmp0(op, "powerdown") == 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 */ /* unknown */
@ -530,7 +554,10 @@ fu_fastboot_device_write_motorola_part(FuDevice *device,
} }
static gboolean 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; GBytes *data;
g_autoptr(GPtrArray) parts = NULL; 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); parts = xb_silo_query(silo, "parts/part", 0, error);
if (parts == NULL) if (parts == NULL)
return FALSE; return FALSE;
fu_progress_set_id(progress, G_STRLOC);
fu_progress_set_steps(progress, parts->len);
for (guint i = 0; i < parts->len; i++) { for (guint i = 0; i < parts->len; i++) {
XbNode *part = g_ptr_array_index(parts, 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; return FALSE;
fu_progress_step_done(progress);
} }
/* success */ /* success */
@ -564,7 +598,10 @@ fu_fastboot_device_write_motorola(FuDevice *device, FuArchive *archive, GError *
} }
static gboolean 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; GBytes *data;
g_autoptr(GPtrArray) parts = NULL; 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); parts = xb_silo_query(silo, "nandboot/partitions/partition", 0, error);
if (parts == NULL) if (parts == NULL)
return FALSE; return FALSE;
fu_progress_set_id(progress, G_STRLOC);
fu_progress_set_steps(progress, parts->len);
for (guint i = 0; i < parts->len; i++) { for (guint i = 0; i < parts->len; i++) {
XbNode *part = g_ptr_array_index(parts, 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; return FALSE;
fu_progress_step_done(progress);
} }
/* success */ /* success */
@ -600,6 +644,7 @@ fu_fastboot_device_write_qfil(FuDevice *device, FuArchive *archive, GError **err
static gboolean static gboolean
fu_fastboot_device_write_firmware(FuDevice *device, fu_fastboot_device_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -618,9 +663,9 @@ fu_fastboot_device_write_firmware(FuDevice *device,
/* load the manifest of operations */ /* load the manifest of operations */
if (fu_archive_lookup_by_fn(archive, "partition_nand.xml", NULL) != NULL) 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) { 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 */ /* not supported */
@ -675,15 +720,29 @@ fu_fastboot_device_set_quirk_kv(FuDevice *device,
} }
static gboolean 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,
if (!fu_fastboot_device_cmd(device, "reboot", FU_FASTBOOT_DEVICE_READ_FLAG_NONE, error)) "reboot",
progress,
FU_FASTBOOT_DEVICE_READ_FLAG_NONE,
error))
return FALSE; return FALSE;
fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG); fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG);
return TRUE; 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 static void
fu_fastboot_device_init(FuFastbootDevice *self) 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->set_quirk_kv = fu_fastboot_device_set_quirk_kv;
klass_device->open = fu_fastboot_device_open; klass_device->open = fu_fastboot_device_open;
klass_device->close = fu_fastboot_device_close; 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; 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 static void
fu_flashrom_device_class_init(FuFlashromDeviceClass *klass) 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->probe = fu_flashrom_device_probe;
klass_device->open = fu_flashrom_device_open; klass_device->open = fu_flashrom_device_open;
klass_device->close = fu_flashrom_device_close; 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 *firmware_orig = NULL;
g_autofree gchar *localstatedir = NULL; g_autofree gchar *localstatedir = NULL;
g_autofree gchar *basename = 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 */ /* if the original firmware doesn't exist, grab it now */
basename = g_strdup_printf("flashrom-%s.bin", fu_device_get_id(device)); 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; struct flashrom_layout *layout;
g_autofree guint8 *newcontents = g_malloc0(flash_size); g_autofree guint8 *newcontents = g_malloc0(flash_size);
g_autoptr(GBytes) buf = NULL; g_autoptr(GBytes) buf = NULL;
fu_device_set_status(device, FWUPD_STATUS_DEVICE_READ);
if (flashrom_layout_read_from_ifd(&layout, flashctx, NULL, 0)) { if (flashrom_layout_read_from_ifd(&layout, flashctx, NULL, 0)) {
g_set_error_literal(error, g_set_error_literal(error,
@ -85,6 +85,7 @@ fu_flashrom_internal_device_prepare(FuDevice *device, FwupdInstallFlags flags, G
/* read region */ /* read region */
flashrom_layout_set(flashctx, layout); flashrom_layout_set(flashctx, layout);
fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_READ);
if (flashrom_image_read(flashctx, newcontents, flash_size)) { if (flashrom_image_read(flashctx, newcontents, flash_size)) {
g_set_error_literal(error, g_set_error_literal(error,
FWUPD_ERROR, FWUPD_ERROR,
@ -103,6 +104,7 @@ fu_flashrom_internal_device_prepare(FuDevice *device, FwupdInstallFlags flags, G
static gboolean static gboolean
fu_flashrom_internal_device_write_firmware(FuDevice *device, fu_flashrom_internal_device_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -117,6 +119,12 @@ fu_flashrom_internal_device_write_firmware(FuDevice *device,
if (blob_fw == NULL) if (blob_fw == NULL)
return FALSE; 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 */ /* Check if CMOS needs a reset */
if (fu_device_has_private_flag(device, FU_FLASHROM_DEVICE_FLAG_RESET_CMOS)) { if (fu_device_has_private_flag(device, FU_FLASHROM_DEVICE_FLAG_RESET_CMOS)) {
g_debug("Attempting CMOS Reset"); g_debug("Attempting CMOS Reset");
@ -156,9 +164,6 @@ fu_flashrom_internal_device_write_firmware(FuDevice *device,
(guint)flash_size); (guint)flash_size);
return FALSE; 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 */); rc = flashrom_image_write(flashctx, (void *)buf, sz, NULL /* refbuffer */);
if (rc != 0) { if (rc != 0) {
g_set_error(error, g_set_error(error,
@ -168,12 +173,13 @@ fu_flashrom_internal_device_write_firmware(FuDevice *device,
rc); rc);
return FALSE; return FALSE;
} }
fu_progress_step_done(progress);
fu_device_set_status(device, FWUPD_STATUS_DEVICE_VERIFY);
if (flashrom_image_verify(flashctx, (void *)buf, sz)) { if (flashrom_image_verify(flashctx, (void *)buf, sz)) {
g_set_error(error, FWUPD_ERROR, FWUPD_ERROR_WRITE, "image verify failed"); g_set_error(error, FWUPD_ERROR, FWUPD_ERROR_WRITE, "image verify failed");
return FALSE; return FALSE;
} }
fu_progress_step_done(progress);
flashrom_layout_release(layout); flashrom_layout_release(layout);
/* success */ /* 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_autoptr(GError) error_local = NULL;
g_debug("resetting target device"); 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); fu_device_add_flag(FU_DEVICE(self), FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG);
/* ignore when the device reset before completing the transaction */ /* 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 static gboolean
fu_fresco_pd_device_write_firmware(FuDevice *device, fu_fresco_pd_device_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -257,6 +257,15 @@ fu_fresco_pd_device_write_firmware(FuDevice *device,
guint8 start_symbols[2] = {0x0}; guint8 start_symbols[2] = {0x0};
g_autoptr(GBytes) fw = NULL; 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 */ /* get default blob, which we know is already bigger than FirmwareMin */
fw = fu_firmware_get_bytes(firmware, error); fw = fu_firmware_get_bytes(firmware, error);
if (fw == NULL) if (fw == NULL)
@ -277,7 +286,6 @@ fu_fresco_pd_device_write_firmware(FuDevice *device,
/* 0xA001<bit 2> = b'0 /* 0xA001<bit 2> = b'0
* 0x6C00<bit 1> = b'0 * 0x6C00<bit 1> = b'0
* 0x6C04 = 0x08 */ * 0x6C04 = 0x08 */
fu_device_set_status(device, FWUPD_STATUS_DEVICE_BUSY);
g_debug("disable MCU, and enable mtp write"); g_debug("disable MCU, and enable mtp write");
if (!fu_fresco_pd_device_and_byte(self, 0xa001, ~(1 << 2), error)) { if (!fu_fresco_pd_device_and_byte(self, 0xa001, ~(1 << 2), error)) {
g_prefix_error(error, "failed to disable MCU bit 2: "); 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 */ /* 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 (guint16 i = 0; i < 0x400; i += 3) {
for (guint j = 0; j < 3; j++) { for (guint j = 0; j < 3; j++) {
if (!fu_fresco_pd_device_read_byte(self, 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) } else if (config[0] == 0x00 && config[1] == 0x00 && config[2] != 0x00)
break; break;
} }
fu_progress_step_done(progress);
/* copy buf offset [0 - 0x3FFFF] to mmio address [0x2000 - 0x5FFF] */ /* copy buf offset [0 - 0x3FFFF] to mmio address [0x2000 - 0x5FFF] */
g_debug("fill firmware body"); g_debug("fill firmware body");
@ -337,8 +345,11 @@ fu_fresco_pd_device_write_firmware(FuDevice *device,
buf[byte_index], buf[byte_index],
error)) error))
return FALSE; 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 0x4200 ~ 0x4205, 6 bytes to internal address 0x6600 ~ 0x6605
* write file buf 0x4210 ~ 0x4215, 6 bytes to internal address 0x6610 ~ 0x6615 * 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)) if (!fu_fresco_pd_device_set_byte(self, 0x6630, buf[0x4230], error))
return FALSE; return FALSE;
fu_progress_step_done(progress);
/* overwrite firmware file's boot code area (0x4020 ~ 0x41ff) to the area on the device /* 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 ~ * 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)) error))
return FALSE; return FALSE;
} }
fu_progress_step_done(progress);
/* reset the device */ /* 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 static void
@ -412,4 +441,5 @@ fu_fresco_pd_device_class_init(FuFrescoPdDeviceClass *klass)
klass_device->setup = fu_fresco_pd_device_setup; klass_device->setup = fu_fresco_pd_device_setup;
klass_device->write_firmware = fu_fresco_pd_device_write_firmware; klass_device->write_firmware = fu_fresco_pd_device_write_firmware;
klass_device->prepare_firmware = fu_fresco_pd_device_prepare_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 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); FuGoodixMocDevice *self = FU_GOODIXMOC_DEVICE(device);
GxfpCmdResp rsp = {0}; GxfpCmdResp rsp = {0};
g_autoptr(GByteArray) req = g_byte_array_new(); g_autoptr(GByteArray) req = g_byte_array_new();
/* reset device */ /* reset device */
fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART);
if (!fu_goodixmoc_device_cmd_xfer(self, if (!fu_goodixmoc_device_cmd_xfer(self,
GX_CMD_RESET, GX_CMD_RESET,
0x03, 0x03,
@ -356,6 +355,7 @@ fu_goodixmoc_device_setup(FuDevice *device, GError **error)
static gboolean static gboolean
fu_goodixmoc_device_write_firmware(FuDevice *device, fu_goodixmoc_device_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -367,6 +367,12 @@ fu_goodixmoc_device_write_firmware(FuDevice *device,
g_autoptr(GError) error_local = NULL; g_autoptr(GError) error_local = NULL;
g_autoptr(GPtrArray) chunks = 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 */ /* get default image */
fw = fu_firmware_get_bytes(firmware, error); fw = fu_firmware_get_bytes(firmware, error);
if (fw == NULL) if (fw == NULL)
@ -379,7 +385,6 @@ fu_goodixmoc_device_write_firmware(FuDevice *device,
GX_FLASH_TRANSFER_BLOCK_SIZE); GX_FLASH_TRANSFER_BLOCK_SIZE);
/* don't auto-boot firmware */ /* don't auto-boot firmware */
fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE);
if (!fu_goodixmoc_device_update_init(self, &error_local)) { if (!fu_goodixmoc_device_update_init(self, &error_local)) {
g_set_error(error, g_set_error(error,
FWUPD_ERROR, FWUPD_ERROR,
@ -388,6 +393,7 @@ fu_goodixmoc_device_write_firmware(FuDevice *device,
error_local->message); error_local->message);
return FALSE; return FALSE;
} }
fu_progress_step_done(progress);
/* write each block */ /* write each block */
for (guint i = 0; i < chunks->len; i++) { for (guint i = 0; i < chunks->len; i++) {
@ -429,13 +435,27 @@ fu_goodixmoc_device_write_firmware(FuDevice *device,
} }
/* update progress */ /* 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! */ /* success! */
return TRUE; 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 static void
fu_goodixmoc_device_init(FuGoodixMocDevice *self) 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->setup = fu_goodixmoc_device_setup;
klass_device->attach = fu_goodixmoc_device_attach; klass_device->attach = fu_goodixmoc_device_attach;
klass_device->open = fu_goodixmoc_device_open; 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) G_DEFINE_TYPE(FuHailuckBlDevice, fu_hailuck_bl_device, FU_TYPE_HID_DEVICE)
static gboolean 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] = { guint8 buf[6] = {
FU_HAILUCK_REPORT_ID_SHORT, FU_HAILUCK_REPORT_ID_SHORT,
FU_HAILUCK_CMD_ATTACH, FU_HAILUCK_CMD_ATTACH,
}; };
fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART);
if (!fu_hid_device_set_report(FU_HID_DEVICE(device), if (!fu_hid_device_set_report(FU_HID_DEVICE(device),
buf[0], buf[0],
buf, buf,
@ -111,7 +110,7 @@ fu_hailuck_bl_device_read_block(FuHailuckBlDevice *self,
} }
static GBytes * 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); FuHailuckBlDevice *self = FU_HAILUCK_BL_DEVICE(device);
gsize fwsz = fu_device_get_firmware_size_max(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; g_autoptr(GPtrArray) chunks = NULL;
/* tell device amount of data to send */ /* 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)) if (!fu_hailuck_bl_device_read_block_start(self, fwsz, error))
return NULL; return NULL;
@ -133,7 +132,7 @@ fu_hailuck_bl_device_dump_firmware(FuDevice *device, GError **error)
fu_chunk_get_data_sz(chk), fu_chunk_get_data_sz(chk),
error)) error))
return NULL; return NULL;
fu_device_set_progress_full(device, i, chunks->len - 1); fu_progress_set_percentage_full(progress, i + 1, chunks->len);
} }
/* success */ /* success */
@ -141,7 +140,7 @@ fu_hailuck_bl_device_dump_firmware(FuDevice *device, GError **error)
} }
static gboolean 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] = { guint8 buf[6] = {
FU_HAILUCK_REPORT_ID_SHORT, FU_HAILUCK_REPORT_ID_SHORT,
@ -155,7 +154,7 @@ fu_hailuck_bl_device_erase(FuHailuckBlDevice *self, GError **error)
FU_HID_DEVICE_FLAG_IS_FEATURE, FU_HID_DEVICE_FLAG_IS_FEATURE,
error)) error))
return FALSE; return FALSE;
fu_device_sleep_with_progress(FU_DEVICE(self), 2); fu_progress_sleep(progress, 2000);
return TRUE; return TRUE;
} }
@ -225,6 +224,7 @@ fu_hailuck_bl_device_prepare_firmware(FuDevice *device,
static gboolean static gboolean
fu_hailuck_bl_device_write_firmware(FuDevice *device, fu_hailuck_bl_device_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -235,18 +235,25 @@ fu_hailuck_bl_device_write_firmware(FuDevice *device,
g_autoptr(GPtrArray) chunks = NULL; g_autoptr(GPtrArray) chunks = NULL;
g_autofree guint8 *chk0_data = 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 */ /* get default image */
fw = fu_firmware_get_bytes(firmware, error); fw = fu_firmware_get_bytes(firmware, error);
if (fw == NULL) if (fw == NULL)
return FALSE; return FALSE;
/* erase all contents */ /* erase all contents */
fu_device_set_status(device, FWUPD_STATUS_DEVICE_ERASE); if (!fu_hailuck_bl_device_erase(self, fu_progress_get_child(progress), error))
if (!fu_hailuck_bl_device_erase(self, error))
return FALSE; return FALSE;
fu_progress_step_done(progress);
/* tell device amount of data to expect */ /* 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)) if (!fu_hailuck_bl_device_write_block_start(self, g_bytes_get_size(fw), error))
return FALSE; return FALSE;
@ -270,8 +277,11 @@ fu_hailuck_bl_device_write_firmware(FuDevice *device,
fu_chunk_get_data_sz(chk), fu_chunk_get_data_sz(chk),
error)) error))
return FALSE; 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 */ /* retry write of first block */
if (!fu_hailuck_bl_device_write_block_start(self, g_bytes_get_size(fw), error)) 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), fu_chunk_get_data_sz(chk0),
error)) error))
return FALSE; return FALSE;
fu_device_set_progress_full(device, chunks->len, chunks->len); fu_progress_step_done(progress);
/* verify */ /* 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); 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) G_DEFINE_TYPE(FuHailuckKbdDevice, fu_hailuck_kbd_device, FU_TYPE_HID_DEVICE)
static gboolean 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}; 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), if (!fu_hid_device_set_report(FU_HID_DEVICE(device),
buf[0], buf[0],
buf, buf,
@ -62,6 +61,17 @@ fu_hailuck_kbd_device_probe(FuDevice *device, GError **error)
return TRUE; 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 static void
fu_hailuck_kbd_device_init(FuHailuckKbdDevice *self) 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); FuDeviceClass *klass_device = FU_DEVICE_CLASS(klass);
klass_device->detach = fu_hailuck_kbd_device_detach; klass_device->detach = fu_hailuck_kbd_device_detach;
klass_device->probe = fu_hailuck_kbd_device_probe; 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 static gboolean
fu_hailuck_tp_device_write_firmware(FuDevice *device, fu_hailuck_tp_device_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -101,22 +102,30 @@ fu_hailuck_tp_device_write_firmware(FuDevice *device,
.success = 0xff, .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 */ /* get default image */
fw = fu_firmware_get_bytes(firmware, error); fw = fu_firmware_get_bytes(firmware, error);
if (fw == NULL) if (fw == NULL)
return FALSE; return FALSE;
/* erase */ /* erase */
fu_device_set_status(device, FWUPD_STATUS_DEVICE_ERASE);
req.type = FU_HAILUCK_CMD_I2C_ERASE; req.type = FU_HAILUCK_CMD_I2C_ERASE;
if (!fu_device_retry(device, fu_hailuck_tp_device_cmd_cb, 100, &req, error)) { if (!fu_device_retry(device, fu_hailuck_tp_device_cmd_cb, 100, &req, error)) {
g_prefix_error(error, "failed to erase: "); g_prefix_error(error, "failed to erase: ");
return FALSE; return FALSE;
} }
g_usleep(10000); g_usleep(10000);
fu_progress_step_done(progress);
/* write */ /* write */
fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE);
chunks = fu_chunk_array_new_from_bytes(fw, 0x0, 0x0, block_size); chunks = fu_chunk_array_new_from_bytes(fw, 0x0, 0x0, block_size);
for (guint i = 0; i < chunks->len; i++) { for (guint i = 0; i < chunks->len; i++) {
FuChunk *chk = g_ptr_array_index(chunks, i); FuChunk *chk = g_ptr_array_index(chunks, i);
@ -163,9 +172,12 @@ fu_hailuck_tp_device_write_firmware(FuDevice *device,
} }
/* update progress */ /* 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); g_usleep(50 * 1000);
fu_progress_step_done(progress);
/* end-program */ /* end-program */
req.type = FU_HAILUCK_CMD_I2C_END_PROGRAM; req.type = FU_HAILUCK_CMD_I2C_END_PROGRAM;
@ -174,6 +186,7 @@ fu_hailuck_tp_device_write_firmware(FuDevice *device,
return FALSE; return FALSE;
} }
g_usleep(50 * 1000); g_usleep(50 * 1000);
fu_progress_step_done(progress);
/* verify checksum */ /* verify checksum */
req.type = FU_HAILUCK_CMD_I2C_VERIFY_CHECKSUM; req.type = FU_HAILUCK_CMD_I2C_VERIFY_CHECKSUM;
@ -182,6 +195,7 @@ fu_hailuck_tp_device_write_firmware(FuDevice *device,
return FALSE; return FALSE;
} }
g_usleep(50 * 1000); g_usleep(50 * 1000);
fu_progress_step_done(progress);
/* signal that programming has completed */ /* signal that programming has completed */
req.type = FU_HAILUCK_CMD_I2C_PROGRAMPASS; 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: "); g_prefix_error(error, "failed to program: ");
return FALSE; return FALSE;
} }
fu_progress_step_done(progress);
/* success! */ /* success! */
return TRUE; 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 static void
fu_hailuck_tp_device_init(FuHailuckTpDevice *self) 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); FuDeviceClass *klass_device = FU_DEVICE_CLASS(klass);
klass_device->write_firmware = fu_hailuck_tp_device_write_firmware; klass_device->write_firmware = fu_hailuck_tp_device_write_firmware;
klass_device->probe = fu_hailuck_tp_device_probe; klass_device->probe = fu_hailuck_tp_device_probe;
klass_device->set_progress = fu_hailuck_tp_device_set_progress;
} }
FuHailuckTpDevice * FuHailuckTpDevice *

View File

@ -78,7 +78,7 @@ fu_ifd_device_to_string(FuDevice *device, guint idt, GString *str)
} }
static GBytes * 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); FuIfdDevice *self = FU_IFD_DEVICE(device);
FuIfdDevicePrivate *priv = GET_PRIVATE(self); FuIfdDevicePrivate *priv = GET_PRIVATE(self);
@ -88,18 +88,19 @@ fu_ifd_device_dump_firmware(FuDevice *device, GError **error)
device, device,
priv->offset, priv->offset,
total_size, total_size,
progress,
error); error);
} }
static FuFirmware * 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); FuIfdDevice *self = FU_IFD_DEVICE(device);
FuIfdDevicePrivate *priv = GET_PRIVATE(self); FuIfdDevicePrivate *priv = GET_PRIVATE(self);
g_autoptr(FuFirmware) firmware = fu_ifd_image_new(); g_autoptr(FuFirmware) firmware = fu_ifd_image_new();
g_autoptr(GBytes) blob = NULL; 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) if (blob == NULL)
return NULL; return NULL;
if (priv->region == FU_IFD_REGION_BIOS) if (priv->region == FU_IFD_REGION_BIOS)

View File

@ -391,13 +391,14 @@ fu_intel_spi_device_dump(FuIntelSpiDevice *self,
FuDevice *device, FuDevice *device,
guint32 offset, guint32 offset,
guint32 length, guint32 length,
FuProgress *progress,
GError **error) GError **error)
{ {
guint8 block_len = 0x40; guint8 block_len = 0x40;
g_autoptr(GByteArray) buf = g_byte_array_sized_new(length); g_autoptr(GByteArray) buf = g_byte_array_sized_new(length);
/* set FDONE, FCERR, AEL */ /* 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)); 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) { for (guint32 addr = offset; addr < offset + length; addr += block_len) {
guint16 hsfc; guint16 hsfc;
@ -426,7 +427,7 @@ fu_intel_spi_device_dump(FuIntelSpiDevice *self,
} }
/* progress */ /* progress */
fu_device_set_progress_full(device, addr - offset + block_len, length); fu_progress_set_percentage_full(progress, addr - offset + block_len, length);
} }
/* success */ /* success */
@ -434,20 +435,26 @@ fu_intel_spi_device_dump(FuIntelSpiDevice *self,
} }
static GBytes * 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); FuIntelSpiDevice *self = FU_INTEL_SPI_DEVICE(device);
guint64 total_size = fu_device_get_firmware_size_max(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 * 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(FuFirmware) firmware = fu_ifd_firmware_new();
g_autoptr(GBytes) blob = NULL; 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) if (blob == NULL)
return NULL; return NULL;
if (!fu_firmware_parse(firmware, blob, FWUPD_INSTALL_FLAG_NONE, error)) 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, FuDevice *device,
guint32 offset, guint32 offset,
guint32 length, guint32 length,
FuProgress *progress,
GError **error); GError **error);

View File

@ -53,6 +53,7 @@ fu_jabra_device_prepare(FuDevice *device, FwupdInstallFlags flags, GError **erro
guint8 rep = 0x00; guint8 rep = 0x00;
guint8 iface_hid; guint8 iface_hid;
guint8 buf[33] = {0x00}; guint8 buf[33] = {0x00};
g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC);
g_autoptr(GError) error_local = NULL; g_autoptr(GError) error_local = NULL;
/* parse string and create magic packet */ /* 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 */ /* 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); fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG);
return TRUE; return TRUE;
} }

View File

@ -26,6 +26,7 @@ fu_plugin_cleanup(FuPlugin *plugin, FuDevice *device, FwupdInstallFlags flags, G
{ {
GUsbDevice *usb_device; GUsbDevice *usb_device;
g_autoptr(FuDeviceLocker) locker = NULL; g_autoptr(FuDeviceLocker) locker = NULL;
g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC);
g_autoptr(GError) error_local = NULL; g_autoptr(GError) error_local = NULL;
/* check for a property on the *dfu* FuDevice, which is also why we /* 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); locker = fu_device_locker_new(device, error);
if (locker == NULL) if (locker == NULL)
return FALSE; 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)); usb_device = fu_usb_device_get_dev(FU_USB_DEVICE(device));
if (!g_usb_device_reset(usb_device, &error_local)) { if (!g_usb_device_reset(usb_device, &error_local)) {
g_set_error(error, g_set_error(error,

View File

@ -418,6 +418,7 @@ fu_logitech_bulkcontroller_device_compute_hash(GBytes *data)
static gboolean static gboolean
fu_logitech_bulkcontroller_device_write_firmware(FuDevice *device, fu_logitech_bulkcontroller_device_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -428,6 +429,13 @@ fu_logitech_bulkcontroller_device_write_firmware(FuDevice *device,
g_autoptr(GBytes) fw = NULL; g_autoptr(GBytes) fw = NULL;
g_autoptr(GPtrArray) chunks = 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 */ /* get default image */
fw = fu_firmware_get_bytes(firmware, error); fw = fu_firmware_get_bytes(firmware, error);
if (fw == NULL) if (fw == NULL)
@ -440,7 +448,6 @@ fu_logitech_bulkcontroller_device_write_firmware(FuDevice *device,
} }
/* transfer sent */ /* 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); fu_byte_array_append_uint64(start_pkt, g_bytes_get_size(fw), G_LITTLE_ENDIAN);
if (!fu_logitech_bulkcontroller_device_send_upd_cmd(self, if (!fu_logitech_bulkcontroller_device_send_upd_cmd(self,
CMD_START_TRANSFER, 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: "); g_prefix_error(error, "error in writing start transfer packet: ");
return FALSE; return FALSE;
} }
fu_progress_step_done(progress);
/* each block */ /* each block */
chunks = fu_chunk_array_new_from_bytes(fw, 0x0, 0x0, PAYLOAD_SIZE); 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); g_prefix_error(error, "failed to send data packet 0x%x: ", i);
return FALSE; 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 */ /* sending end transfer */
base64hash = fu_logitech_bulkcontroller_device_compute_hash(fw); 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: "); g_prefix_error(error, "error in writing finish transfer packet: ");
return FALSE; return FALSE;
} }
fu_progress_step_done(progress);
/* success! */ /* success! */
return TRUE; return TRUE;
@ -683,6 +695,17 @@ fu_logitech_bulkcontroller_device_setup(FuDevice *device, GError **error)
return TRUE; 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 static void
fu_logitech_bulkcontroller_device_init(FuLogitechBulkcontrollerDevice *self) 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->setup = fu_logitech_bulkcontroller_device_setup;
klass_device->open = fu_logitech_bulkcontroller_device_open; klass_device->open = fu_logitech_bulkcontroller_device_open;
klass_device->close = fu_logitech_bulkcontroller_device_close; 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 static gboolean
fu_logitech_hidpp_bootloader_nordic_write_firmware(FuDevice *device, fu_logitech_hidpp_bootloader_nordic_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -226,25 +227,40 @@ fu_logitech_hidpp_bootloader_nordic_write_firmware(FuDevice *device,
g_autoptr(GBytes) fw = NULL; g_autoptr(GBytes) fw = NULL;
g_autoptr(GPtrArray) reqs = 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 */ /* get default image */
fw = fu_firmware_get_bytes(firmware, error); fw = fu_firmware_get_bytes(firmware, error);
if (fw == NULL) if (fw == NULL)
return FALSE; return FALSE;
/* erase firmware pages up to the bootloader */ /* 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); 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_addr_hi(self);
addr += fu_logitech_hidpp_bootloader_get_blocksize(self)) { addr += fu_logitech_hidpp_bootloader_get_blocksize(self)) {
if (!fu_logitech_hidpp_bootloader_nordic_erase(self, addr, error)) if (!fu_logitech_hidpp_bootloader_nordic_erase(self, addr, error))
return FALSE; return FALSE;
} }
fu_progress_step_done(progress);
/* transfer payload */ /* transfer payload */
reqs = fu_logitech_hidpp_bootloader_parse_requests(self, fw, error); reqs = fu_logitech_hidpp_bootloader_parse_requests(self, fw, error);
if (reqs == NULL) if (reqs == NULL)
return FALSE; 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++) { for (guint i = 1; i < reqs->len; i++) {
gboolean res; gboolean res;
payload = g_ptr_array_index(reqs, i); payload = g_ptr_array_index(reqs, i);
@ -265,8 +281,9 @@ fu_logitech_hidpp_bootloader_nordic_write_firmware(FuDevice *device,
if (!res) if (!res)
return FALSE; 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 */ /* send the first managed packet last, excluding the reset vector */
payload = g_ptr_array_index(reqs, 0); payload = g_ptr_array_index(reqs, 0);
@ -276,12 +293,12 @@ fu_logitech_hidpp_bootloader_nordic_write_firmware(FuDevice *device,
payload->data + 1, payload->data + 1,
error)) error))
return FALSE; return FALSE;
fu_progress_step_done(progress);
/* reset vector */
if (!fu_logitech_hidpp_bootloader_nordic_write(self, 0x0000, 0x01, payload->data, error)) if (!fu_logitech_hidpp_bootloader_nordic_write(self, 0x0000, 0x01, payload->data, error))
return FALSE; return FALSE;
fu_progress_step_done(progress);
/* mark as complete */
fu_device_set_progress_full(device, reqs->len * 32, reqs->len * 32);
/* success! */ /* success! */
return TRUE; return TRUE;

View File

@ -115,6 +115,7 @@ fu_logitech_hidpp_bootloader_texas_clear_ram_buffer(FuLogitechHidPpBootloader *s
static gboolean static gboolean
fu_logitech_hidpp_bootloader_texas_write_firmware(FuDevice *device, fu_logitech_hidpp_bootloader_texas_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -125,6 +126,20 @@ fu_logitech_hidpp_bootloader_texas_write_firmware(FuDevice *device,
g_autoptr(FuLogitechHidPpBootloaderRequest) req = g_autoptr(FuLogitechHidPpBootloaderRequest) req =
fu_logitech_hidpp_bootloader_request_new(); 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 */ /* get default image */
fw = fu_firmware_get_bytes(firmware, error); fw = fu_firmware_get_bytes(firmware, error);
if (fw == NULL) if (fw == NULL)
@ -136,16 +151,16 @@ fu_logitech_hidpp_bootloader_texas_write_firmware(FuDevice *device,
return FALSE; return FALSE;
/* erase all flash pages */ /* erase all flash pages */
fu_device_set_status(device, FWUPD_STATUS_DEVICE_ERASE);
if (!fu_logitech_hidpp_bootloader_texas_erase_all(self, error)) if (!fu_logitech_hidpp_bootloader_texas_erase_all(self, error))
return FALSE; return FALSE;
fu_progress_step_done(progress);
/* set existing RAM buffer to 0xff's */ /* set existing RAM buffer to 0xff's */
if (!fu_logitech_hidpp_bootloader_texas_clear_ram_buffer(self, error)) if (!fu_logitech_hidpp_bootloader_texas_clear_ram_buffer(self, error))
return FALSE; return FALSE;
fu_progress_step_done(progress);
/* write to RAM buffer */ /* write to RAM buffer */
fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE);
for (guint i = 0; i < reqs->len; i++) { for (guint i = 0; i < reqs->len; i++) {
payload = g_ptr_array_index(reqs, i); payload = g_ptr_array_index(reqs, i);
@ -213,15 +228,14 @@ fu_logitech_hidpp_bootloader_texas_write_firmware(FuDevice *device,
} }
/* update progress */ /* 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 */ /* check CRC */
if (!fu_logitech_hidpp_bootloader_texas_compute_and_test_crc(self, error)) if (!fu_logitech_hidpp_bootloader_texas_compute_and_test_crc(self, error))
return FALSE; return FALSE;
fu_progress_step_done(progress);
/* mark as complete */
fu_device_set_progress_full(device, reqs->len * 32, reqs->len * 32);
/* success! */ /* success! */
return TRUE; return TRUE;

View File

@ -208,7 +208,7 @@ fu_logitech_hidpp_bootloader_get_blocksize(FuLogitechHidPpBootloader *self)
} }
static gboolean 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); FuLogitechHidPpBootloader *self = FU_UNIFYING_BOOTLOADER(device);
g_autoptr(FuLogitechHidPpBootloaderRequest) req = 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); 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"); fu_device_add_protocol(FU_DEVICE(self), "com.logitech.unifyingsigned");
else } else {
fu_device_add_protocol(FU_DEVICE(self), "com.logitech.unifying"); fu_device_add_protocol(FU_DEVICE(self), "com.logitech.unifying");
}
return TRUE; 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_name(FU_DEVICE(self), "Unifying Receiver");
fu_device_set_summary(FU_DEVICE(self), "Miniaturised USB wireless receiver (bootloader)"); 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_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 static void

View File

@ -19,6 +19,15 @@ struct _FuLogitechHidPpBootloaderClass {
FuHidDeviceClass parent_class; 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 { typedef enum {
FU_UNIFYING_BOOTLOADER_CMD_GENERAL_ERROR = 0x01, FU_UNIFYING_BOOTLOADER_CMD_GENERAL_ERROR = 0x01,
FU_UNIFYING_BOOTLOADER_CMD_READ = 0x10, FU_UNIFYING_BOOTLOADER_CMD_READ = 0x10,

View File

@ -852,7 +852,7 @@ fu_logitech_hidpp_device_setup(FuDevice *device, GError **error)
} }
static gboolean 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); FuLogitechHidPpDevice *self = FU_HIDPP_DEVICE(device);
FuLogitechHidPpDevicePrivate *priv = GET_PRIVATE(self); 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->hidpp_version = priv->hidpp_version;
msg->flags = FU_UNIFYING_HIDPP_MSG_FLAG_IGNORE_SUB_ID | msg->flags = FU_UNIFYING_HIDPP_MSG_FLAG_IGNORE_SUB_ID |
FU_UNIFYING_HIDPP_MSG_FLAG_LONGER_TIMEOUT; 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_logitech_hidpp_transfer(priv->io_channel, msg, &error_local)) {
if (fu_device_has_private_flag( if (fu_device_has_private_flag(
device, device,
@ -1139,6 +1138,7 @@ fu_logitech_hidpp_device_write_firmware_pkt(FuLogitechHidPpDevice *self,
static gboolean static gboolean
fu_logitech_hidpp_device_write_firmware(FuDevice *device, fu_logitech_hidpp_device_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) 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]); g_warning("updating cached entity 0x%x with 0x%x", priv->cached_fw_entity, data[0]);
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++) { for (gsize i = 0; i < sz / 16; i++) {
/* send packet and wait for reply */ /* send packet and wait for reply */
if (g_getenv("FWUPD_LOGITECH_HIDPP") != NULL) if (g_getenv("FWUPD_LOGITECH_HIDPP") != NULL)
@ -1186,7 +1186,7 @@ fu_logitech_hidpp_device_write_firmware(FuDevice *device,
cmd = (cmd + 1) % 4; cmd = (cmd + 1) % 4;
/* update progress-bar */ /* update progress-bar */
fu_device_set_progress_full(device, i * 16, sz); fu_progress_set_percentage_full(progress, (i + 1) * 16, sz);
} }
return TRUE; return TRUE;
@ -1199,7 +1199,10 @@ fu_logitech_hidpp_device_reprobe_cb(FuDevice *device, gpointer user_data, GError
} }
gboolean 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); FuLogitechHidPpDevicePrivate *priv = GET_PRIVATE(self);
FuDevice *device = FU_DEVICE(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 * Possible race condition: after the device is reset, Linux might enumerate it as
* a different hidraw device depending on timing. * a different hidraw device depending on timing.
*/ */
fu_device_sleep_with_progress(device, 1); /* second */ fu_progress_sleep(progress, 1000); /* ms */
} else { } else {
/* device file hasn't been unbound/re-bound, just probe again */ /* 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)) 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 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); FuLogitechHidPpDevice *self = FU_HIDPP_DEVICE(device);
FuLogitechHidPpDevicePrivate *priv = GET_PRIVATE(self); 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)) 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); 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 static gboolean
@ -1286,6 +1289,17 @@ fu_logitech_hidpp_device_set_quirk_kv(FuDevice *device,
return FALSE; 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 static void
fu_logitech_hidpp_device_finalize(GObject *object) 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->probe = fu_logitech_hidpp_device_probe;
klass_device->set_quirk_kv = fu_logitech_hidpp_device_set_quirk_kv; klass_device->set_quirk_kv = fu_logitech_hidpp_device_set_quirk_kv;
klass_device->cleanup = fu_logitech_hidpp_device_cleanup; klass_device->cleanup = fu_logitech_hidpp_device_cleanup;
klass_device->set_progress = fu_logitech_hidpp_device_set_progress;
} }
static void static void

View File

@ -84,6 +84,9 @@ fu_logitech_hidpp_device_set_hidpp_pid(FuLogitechHidPpDevice *self, guint16 hidp
const gchar * const gchar *
fu_logitech_hidpp_device_get_model_id(FuLogitechHidPpDevice *self); fu_logitech_hidpp_device_get_model_id(FuLogitechHidPpDevice *self);
gboolean 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 * FuLogitechHidPpDevice *
fu_logitech_hidpp_device_new(FuUdevDevice *parent); 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 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); FuLogitechHidPpRadio *self = FU_HIDPP_RADIO(device);
FuDevice *parent = fu_device_get_parent(device); FuDevice *parent = fu_device_get_parent(device);
@ -35,13 +35,15 @@ fu_logitech_hidpp_radio_attach(FuDevice *device, GError **error)
if (locker == NULL) if (locker == NULL)
return FALSE; return FALSE;
fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART);
fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG); 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 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); FuDevice *parent = fu_device_get_parent(device);
g_autoptr(FuDeviceLocker) locker = NULL; g_autoptr(FuDeviceLocker) locker = NULL;
@ -51,16 +53,15 @@ fu_logitech_hidpp_radio_detach(FuDevice *device, GError **error)
if (locker == NULL) if (locker == NULL)
return FALSE; return FALSE;
if (!fu_device_has_flag(parent, FWUPD_DEVICE_FLAG_IS_BOOTLOADER)) { if (!fu_device_has_flag(parent, FWUPD_DEVICE_FLAG_IS_BOOTLOADER))
fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART);
fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG); fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG);
} return fu_device_detach(parent, progress, error);
return fu_device_detach(parent, error);
} }
static gboolean static gboolean
fu_logitech_hidpp_radio_write_firmware(FuDevice *device, fu_logitech_hidpp_radio_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -76,9 +77,7 @@ fu_logitech_hidpp_radio_write_firmware(FuDevice *device,
locker = fu_device_locker_new(parent, error); locker = fu_device_locker_new(parent, error);
if (locker == NULL) if (locker == NULL)
return FALSE; return FALSE;
return fu_device_write_firmware(parent, fw, progress, flags, error);
fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE);
return fu_device_write_firmware(parent, fw, flags, error);
} }
static void static void

View File

@ -20,7 +20,7 @@ struct _FuLogitechHidPpRuntimeBolt {
G_DEFINE_TYPE(FuLogitechHidPpRuntimeBolt, fu_logitech_hidpp_runtime_bolt, FU_TYPE_HIDPP_RUNTIME) G_DEFINE_TYPE(FuLogitechHidPpRuntimeBolt, fu_logitech_hidpp_runtime_bolt, FU_TYPE_HIDPP_RUNTIME)
static gboolean 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); FuLogitechHidPpRuntime *self = FU_HIDPP_RUNTIME(device);
g_autoptr(FuLogitechHidPpHidppMsg) msg = fu_logitech_hidpp_msg_new(); 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)) #define GET_PRIVATE(o) (fu_logitech_hidpp_runtime_unifying_get_instance_private(o))
static gboolean 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); FuLogitechHidPpRuntime *self = FU_HIDPP_RUNTIME(device);
g_autoptr(FuLogitechHidPpHidppMsg) msg = fu_logitech_hidpp_msg_new(); 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; 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 static void
fu_logitech_hidpp_runtime_unifying_class_init(FuLogitechHidPpRuntimeUnifyingClass *klass) 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->detach = fu_logitech_hidpp_runtime_unifying_detach;
klass_device->setup = fu_logitech_hidpp_runtime_unifying_setup; klass_device->setup = fu_logitech_hidpp_runtime_unifying_setup;
klass_device->set_progress = fu_logitech_hidpp_runtime_unifying_set_progress;
} }
static void static void

View File

@ -49,10 +49,6 @@
#define CONFIGURE_ZLP_AWARE_HOST 1 #define CONFIGURE_ZLP_AWARE_HOST 1
#define CONFIGURE_SKIP_STORAGE_INIT 0 #define CONFIGURE_SKIP_STORAGE_INIT 0
enum { SIGNAL_WRITE_PERCENTAGE, SIGNAL_LAST };
static guint signals[SIGNAL_LAST] = {0};
struct _FuFirehoseUpdater { struct _FuFirehoseUpdater {
GObject parent_instance; GObject parent_instance;
gchar *port; gchar *port;
@ -755,6 +751,7 @@ fu_firehose_updater_run_actions(FuFirehoseUpdater *self,
XbSilo *silo, XbSilo *silo,
GPtrArray *action_nodes, GPtrArray *action_nodes,
guint max_payload_size, guint max_payload_size,
FuProgress *progress,
GError **error) GError **error)
{ {
gsize sent_bytes = 0; gsize sent_bytes = 0;
@ -777,10 +774,7 @@ fu_firehose_updater_run_actions(FuFirehoseUpdater *self,
error)) error))
return FALSE; return FALSE;
g_signal_emit(self, fu_progress_set_percentage_full(progress, sent_bytes, total_bytes);
signals[SIGNAL_WRITE_PERCENTAGE],
0,
(guint)((100.0 * (gdouble)sent_bytes) / (gdouble)total_bytes));
} }
return TRUE; return TRUE;
@ -790,14 +784,13 @@ gboolean
fu_firehose_updater_write(FuFirehoseUpdater *self, fu_firehose_updater_write(FuFirehoseUpdater *self,
XbSilo *silo, XbSilo *silo,
GPtrArray *action_nodes, GPtrArray *action_nodes,
FuProgress *progress,
GError **error) GError **error)
{ {
guint max_payload_size; guint max_payload_size;
gboolean result; gboolean result;
g_autoptr(GError) error_local = NULL; g_autoptr(GError) error_local = NULL;
g_signal_emit(self, signals[SIGNAL_WRITE_PERCENTAGE], 0, 0);
if (!fu_firehose_updater_initialize(self, error)) if (!fu_firehose_updater_initialize(self, error))
return FALSE; return FALSE;
@ -805,7 +798,12 @@ fu_firehose_updater_write(FuFirehoseUpdater *self,
if (max_payload_size == 0) if (max_payload_size == 0)
return FALSE; 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 (!fu_firehose_updater_reset(self, &error_local)) {
if (result) if (result)
@ -813,8 +811,6 @@ fu_firehose_updater_write(FuFirehoseUpdater *self,
return FALSE; return FALSE;
} }
g_signal_emit(self, signals[SIGNAL_WRITE_PERCENTAGE], 0, 100);
return result; return result;
} }
@ -837,17 +833,6 @@ fu_firehose_updater_class_init(FuFirehoseUpdaterClass *klass)
{ {
GObjectClass *object_class = G_OBJECT_CLASS(klass); GObjectClass *object_class = G_OBJECT_CLASS(klass);
object_class->finalize = fu_firehose_updater_finalize; 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 * FuFirehoseUpdater *

View File

@ -23,6 +23,7 @@ gboolean
fu_firehose_updater_write(FuFirehoseUpdater *self, fu_firehose_updater_write(FuFirehoseUpdater *self,
XbSilo *silo, XbSilo *silo,
GPtrArray *action_nodes, GPtrArray *action_nodes,
FuProgress *progress,
GError **error); GError **error);
gboolean gboolean
fu_firehose_updater_close(FuFirehoseUpdater *self, GError **error); fu_firehose_updater_close(FuFirehoseUpdater *self, GError **error);

View File

@ -267,6 +267,7 @@ typedef struct {
GPtrArray *chunks; GPtrArray *chunks;
guint chunk_sent; guint chunk_sent;
FuDevice *device; FuDevice *device;
FuProgress *progress;
} WriteContext; } WriteContext;
static gboolean static gboolean
@ -302,10 +303,10 @@ fu_mbim_qdu_updater_file_write_ready(MbimDevice *device, GAsyncResult *res, gpoi
return; return;
} }
fu_device_set_progress_full(FU_DEVICE(ctx->device), ctx->chunk_sent++;
fu_progress_set_percentage_full(ctx->progress,
(gsize)ctx->chunk_sent, (gsize)ctx->chunk_sent,
(gsize)ctx->chunks->len); (gsize)ctx->chunks->len);
ctx->chunk_sent++;
if (ctx->chunk_sent < ctx->chunks->len) { if (ctx->chunk_sent < ctx->chunks->len) {
FuChunk *chk = g_ptr_array_index(ctx->chunks, ctx->chunk_sent); FuChunk *chk = g_ptr_array_index(ctx->chunks, ctx->chunk_sent);
g_autoptr(MbimMessage) request = g_autoptr(MbimMessage) request =
@ -321,8 +322,7 @@ fu_mbim_qdu_updater_file_write_ready(MbimDevice *device, GAsyncResult *res, gpoi
return; return;
} }
fu_device_set_progress(FU_DEVICE(ctx->device), 100); fu_progress_set_status(ctx->progress, FWUPD_STATUS_DEVICE_RESTART);
fu_device_set_status(FU_DEVICE(ctx->device), FWUPD_STATUS_DEVICE_RESTART);
/* device will auto reboot right after update finish */ /* device will auto reboot right after update finish */
g_timeout_add_seconds(10, fu_mbim_qdu_updater_reboot_timeout, ctx); 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, const gchar *filename,
GBytes *blob, GBytes *blob,
FuDevice *device, FuDevice *device,
FuProgress *progress,
GError **error) GError **error)
{ {
g_autoptr(GMainLoop) mainloop = g_main_loop_new(NULL, FALSE); g_autoptr(GMainLoop) mainloop = g_main_loop_new(NULL, FALSE);
@ -476,6 +477,7 @@ fu_mbim_qdu_updater_write(FuMbimQduUpdater *self,
.chunks = chunks, .chunks = chunks,
.chunk_sent = 0, .chunk_sent = 0,
.device = device, .device = device,
.progress = progress,
}; };
fu_mbim_qdu_updater_set_update_session(self->mbim_device, &ctx); 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, const gchar *filename,
GBytes *blob, GBytes *blob,
FuDevice *device, FuDevice *device,
FuProgress *progress,
GError **error); GError **error);
gchar * gchar *
fu_mbim_qdu_updater_check_ready(FuMbimQduUpdater *self, GError **error); 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) */ #endif /* MM_CHECK_VERSION(1,17,2) */
static gboolean 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); FuMmDevice *self = FU_MM_DEVICE(device);
g_autoptr(FuDeviceLocker) locker = NULL; g_autoptr(FuDeviceLocker) locker = NULL;
@ -1094,7 +1094,10 @@ fu_mm_device_writeln(const gchar *fn, const gchar *buf, GError **error)
} }
static gboolean 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; GBytes *data;
XbNode *part = NULL; 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)) if (!fu_mm_device_writeln(autosuspend_delay_filename, "10000", error))
return FALSE; return FALSE;
fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_WRITE);
fu_mbim_qdu_updater_write(self->mbim_qdu_updater, filename, data, device, error); fu_mbim_qdu_updater_write(self->mbim_qdu_updater, filename, data, device, progress, error);
if (!fu_device_locker_close(locker, error)) if (!fu_device_locker_close(locker, error))
return FALSE; 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_set_remove_delay(device, MAX_WAIT_TIME_SECS * 1000);
fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG); fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG);
version = fu_mm_device_get_firmware_version_mbim(device, error); version = fu_mm_device_get_firmware_version_mbim(device, error);
@ -1200,32 +1203,21 @@ static gboolean
fu_mm_device_firehose_write(FuMmDevice *self, fu_mm_device_firehose_write(FuMmDevice *self,
XbSilo *rawprogram_silo, XbSilo *rawprogram_silo,
GPtrArray *rawprogram_actions, GPtrArray *rawprogram_actions,
FuProgress *progress,
GError **error) GError **error)
{ {
g_autoptr(FuDeviceLocker) locker = NULL; g_autoptr(FuDeviceLocker) locker = NULL;
guint progress_signal_id;
gboolean write_result;
locker = fu_device_locker_new_full(self, locker = fu_device_locker_new_full(self,
(FuDeviceLockerFunc)fu_mm_device_firehose_open, (FuDeviceLockerFunc)fu_mm_device_firehose_open,
(FuDeviceLockerFunc)fu_mm_device_firehose_close, (FuDeviceLockerFunc)fu_mm_device_firehose_close,
error); error);
if (locker == NULL) if (locker == NULL)
return FALSE; return FALSE;
return fu_firehose_updater_write(self->firehose_updater,
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_silo,
rawprogram_actions, rawprogram_actions,
progress,
error); error);
g_signal_handler_disconnect(self->firehose_updater, progress_signal_id);
return write_result;
} }
static gboolean static gboolean
@ -1297,20 +1289,30 @@ fu_mm_restore_firmware_search_path(FuMmDevice *self, GError **error)
} }
static gboolean 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); FuMmDevice *self = FU_MM_DEVICE(device);
GBytes *firehose_rawprogram; GBytes *firehose_rawprogram;
g_autoptr(FuDeviceLocker) locker = NULL; g_autoptr(FuDeviceLocker) locker = NULL;
g_autoptr(FuArchive) archive = NULL; g_autoptr(FuArchive) archive = NULL;
g_autoptr(XbSilo) firehose_rawprogram_silo = NULL; g_autoptr(XbSilo) firehose_rawprogram_silo = NULL;
g_autoptr(GPtrArray) firehose_rawprogram_actions = 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 */ /* decompress entire archive ahead of time */
archive = fu_archive_new(fw, FU_ARCHIVE_FLAG_IGNORE_PATH, error); archive = fu_archive_new(fw, FU_ARCHIVE_FLAG_IGNORE_PATH, error);
if (archive == NULL) if (archive == NULL)
return FALSE; return FALSE;
fu_progress_step_done(progress);
/* modify firmware search path and restore it before function returns */ /* modify firmware search path and restore it before function returns */
locker = fu_device_locker_new_full(self, 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)) if (!fu_mm_copy_firehose_prog(self, archive, error))
return FALSE; 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 */ /* switch to embedded downloader (EDL) execution environment */
if (!fu_mm_device_qcdm_switch_to_edl(FU_DEVICE(self), error)) if (!fu_mm_device_qcdm_switch_to_edl(FU_DEVICE(self), error))
return FALSE; 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: "); g_prefix_error(error, "Invalid firehose rawprogram manifest: ");
return FALSE; return FALSE;
} }
fu_progress_step_done(progress);
/* flag as write */
fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_DEVICE_WRITE);
/* download all files in the firehose-rawprogram manifest via Firehose */ /* download all files in the firehose-rawprogram manifest via Firehose */
if (!fu_mm_device_firehose_write(self, if (!fu_mm_device_firehose_write(self,
firehose_rawprogram_silo, firehose_rawprogram_silo,
firehose_rawprogram_actions, firehose_rawprogram_actions,
fu_progress_get_child(progress),
error)) error))
return FALSE; return FALSE;
fu_progress_step_done(progress);
/* flag as restart again, the module is switching to modem mode */ /* 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; return TRUE;
} }
@ -1366,6 +1364,7 @@ fu_mm_device_write_firmware_firehose(FuDevice *device, GBytes *fw, GError **erro
static gboolean static gboolean
fu_mm_device_write_firmware(FuDevice *device, fu_mm_device_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) 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) #if MM_CHECK_VERSION(1, 17, 1) && MBIM_CHECK_VERSION(1, 25, 3)
/* mbim qdu write operation */ /* mbim qdu write operation */
if (self->update_methods & MM_MODEM_FIRMWARE_UPDATE_METHOD_MBIM_QDU) 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) */ #endif /* MM_CHECK_VERSION(1,17,1) && MBIM_CHECK_VERSION(1,25,3) */
#if MM_CHECK_VERSION(1, 17, 2) #if MM_CHECK_VERSION(1, 17, 2)
/* firehose operation */ /* firehose operation */
if (self->update_methods & MM_MODEM_FIRMWARE_UPDATE_METHOD_FIREHOSE) 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 #endif
g_set_error(error, FWUPD_ERROR, FWUPD_ERROR_NOT_SUPPORTED, "unsupported update method"); 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 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); FuMmDevice *self = FU_MM_DEVICE(device);
g_autoptr(FuDeviceLocker) locker = NULL; g_autoptr(FuDeviceLocker) locker = NULL;
@ -1478,6 +1477,17 @@ fu_mm_device_attach(FuDevice *device, GError **error)
return TRUE; 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 static void
fu_mm_device_init(FuMmDevice *self) 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->detach = fu_mm_device_detach;
klass_device->write_firmware = fu_mm_device_write_firmware; klass_device->write_firmware = fu_mm_device_write_firmware;
klass_device->attach = fu_mm_device_attach; 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", signals[SIGNAL_ATTACH_FINISHED] = g_signal_new("attach-finished",
G_TYPE_FROM_CLASS(object_class), G_TYPE_FROM_CLASS(object_class),

View File

@ -1,3 +1,4 @@
/* /*
* Copyright (C) 2018 Richard Hughes <richard@hughsie.com> * Copyright (C) 2018 Richard Hughes <richard@hughsie.com>
* *
@ -370,7 +371,7 @@ fu_plugin_destroy(FuPlugin *plugin)
} }
gboolean 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); FuPluginData *priv = fu_plugin_get_data(plugin);
g_autoptr(FuDeviceLocker) locker = NULL; g_autoptr(FuDeviceLocker) locker = NULL;
@ -397,7 +398,7 @@ fu_plugin_detach(FuPlugin *plugin, FuDevice *device, GError **error)
} }
/* reset */ /* reset */
if (!fu_device_detach(device, error)) { if (!fu_device_detach(device, progress, error)) {
fu_plugin_mm_uninhibit_device(plugin); fu_plugin_mm_uninhibit_device(plugin);
return FALSE; return FALSE;
} }
@ -414,7 +415,7 @@ fu_plugin_mm_device_attach_finished(gpointer user_data)
} }
gboolean 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; 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 * so that engine can setup the device "waiting" logic before the actual
* attach procedure happens (which will reset the module if it worked * attach procedure happens (which will reset the module if it worked
* properly) */ * properly) */
if (!fu_device_attach(device, error)) if (!fu_device_attach(device, progress, error))
return FALSE; return FALSE;
/* this signal will always be emitted asynchronously */ /* this signal will always be emitted asynchronously */

View File

@ -318,6 +318,7 @@ fu_nvme_device_setup(FuDevice *device, GError **error)
static gboolean static gboolean
fu_nvme_device_write_firmware(FuDevice *device, fu_nvme_device_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -327,6 +328,12 @@ fu_nvme_device_write_firmware(FuDevice *device,
g_autoptr(GPtrArray) chunks = NULL; g_autoptr(GPtrArray) chunks = NULL;
guint64 block_size = self->write_block_size > 0 ? self->write_block_size : 0x1000; 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 */ /* get default image */
fw = fu_firmware_get_bytes(firmware, error); fw = fu_firmware_get_bytes(firmware, error);
if (fw == NULL) if (fw == NULL)
@ -340,14 +347,11 @@ fu_nvme_device_write_firmware(FuDevice *device,
fw2 = g_bytes_ref(fw); fw2 = g_bytes_ref(fw);
} }
/* build packets */ /* write each block */
chunks = fu_chunk_array_new_from_bytes(fw2, chunks = fu_chunk_array_new_from_bytes(fw2,
0x00, /* start_addr */ 0x00, /* start_addr */
0x00, /* page_sz */ 0x00, /* page_sz */
block_size); /* block size */ block_size); /* block size */
/* write each block */
fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE);
for (guint i = 0; i < chunks->len; i++) { for (guint i = 0; i < chunks->len; i++) {
FuChunk *chk = g_ptr_array_index(chunks, i); FuChunk *chk = g_ptr_array_index(chunks, i);
if (!fu_nvme_device_fw_download(self, 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); g_prefix_error(error, "failed to write chunk %u: ", i);
return FALSE; 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 */ /* commit */
if (!fu_nvme_device_fw_commit(self, 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: "); g_prefix_error(error, "failed to commit to auto slot: ");
return FALSE; return FALSE;
} }
fu_progress_step_done(progress);
/* success! */ /* success! */
fu_device_set_progress(device, 100);
return TRUE; return TRUE;
} }
@ -389,6 +396,16 @@ fu_nvme_device_set_quirk_kv(FuDevice *device, const gchar *key, const gchar *val
return FALSE; 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 static void
fu_nvme_device_init(FuNvmeDevice *self) 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->setup = fu_nvme_device_setup;
klass_device->write_firmware = fu_nvme_device_write_firmware; klass_device->write_firmware = fu_nvme_device_write_firmware;
klass_device->probe = fu_nvme_device_probe; klass_device->probe = fu_nvme_device_probe;
klass_device->set_progress = fu_nvme_device_set_progress;
} }
FuNvmeDevice * FuNvmeDevice *

View File

@ -38,7 +38,7 @@ fu_optionrom_device_probe(FuDevice *device, GError **error)
} }
static GBytes * 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); FuUdevDevice *udev_device = FU_UDEV_DEVICE(device);
guint number_reads = 0; guint number_reads = 0;

View File

@ -287,9 +287,9 @@ fu_parade_lspcon_flash_read(FuParadeLspconDevice *self,
guint32 base_address, guint32 base_address,
guint8 *data, guint8 *data,
const gsize len, const gsize len,
FuProgress *progress,
GError **error) GError **error)
{ {
FuDevice *device = FU_DEVICE(self);
FuI2cDevice *i2c_device = FU_I2C_DEVICE(self); FuI2cDevice *i2c_device = FU_I2C_DEVICE(self);
gsize offset = 0; gsize offset = 0;
@ -322,7 +322,7 @@ fu_parade_lspcon_flash_read(FuParadeLspconDevice *self,
base_address += page_data_take; base_address += page_data_take;
offset += 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; return TRUE;
@ -417,9 +417,9 @@ static gboolean
fu_parade_lspcon_flash_write(FuParadeLspconDevice *self, fu_parade_lspcon_flash_write(FuParadeLspconDevice *self,
guint32 base_address, guint32 base_address,
GBytes *data, GBytes *data,
FuProgress *progress,
GError **error) GError **error)
{ {
FuDevice *device = FU_DEVICE(self);
FuI2cDevice *i2c_device = FU_I2C_DEVICE(self); FuI2cDevice *i2c_device = FU_I2C_DEVICE(self);
const guint8 unlock_writes[] = {0xaa, 0x55, 0x50, 0x41, 0x52, 0x44}; const guint8 unlock_writes[] = {0xaa, 0x55, 0x50, 0x41, 0x52, 0x44};
gsize data_len = g_bytes_get_size(data); 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)) if (!fu_i2c_device_write_full(i2c_device, write_data, chunk_size + 1, error))
return FALSE; 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 */ /* re-lock map writes */
@ -631,6 +631,7 @@ fu_parade_lspcon_device_reload(FuDevice *device, GError **error)
static gboolean static gboolean
fu_parade_lspcon_device_write_firmware(FuDevice *device, fu_parade_lspcon_device_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -652,6 +653,15 @@ fu_parade_lspcon_device_write_firmware(FuDevice *device,
g_autoptr(GBytes) blob_fw = NULL; g_autoptr(GBytes) blob_fw = NULL;
g_autoptr(GBytes) flag_data_bytes = 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); blob_fw = fu_firmware_get_bytes(firmware, error);
if (blob_fw == NULL) if (blob_fw == NULL)
return FALSE; return FALSE;
@ -688,45 +698,62 @@ fu_parade_lspcon_device_write_firmware(FuDevice *device,
return FALSE; return FALSE;
/* erase entire target partition (one flash block) */ /* 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)) { if (!fu_parade_lspcon_flash_erase_block(self, target_address, bufsz, error)) {
g_prefix_error(error, "failed to erase flash partition %d: ", target_partition); g_prefix_error(error, "failed to erase flash partition %d: ", target_partition);
return FALSE; return FALSE;
} }
fu_progress_step_done(progress);
/* write image */ /* write image */
fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); if (!fu_parade_lspcon_flash_write(self,
if (!fu_parade_lspcon_flash_write(self, target_address, blob_fw, error)) { target_address,
blob_fw,
fu_progress_get_child(progress),
error)) {
g_prefix_error(error, g_prefix_error(error,
"failed to write firmware to partition %d: ", "failed to write firmware to partition %d: ",
target_partition); target_partition);
return FALSE; return FALSE;
} }
fu_progress_step_done(progress);
/* read back written image to verify */ /* read back written image to verify */
fu_device_set_status(device, FWUPD_STATUS_DEVICE_VERIFY);
readback_buf = g_malloc0(bufsz); 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; return FALSE;
if (!fu_common_bytes_compare_raw(buf, bufsz, readback_buf, bufsz, error)) { if (!fu_common_bytes_compare_raw(buf, bufsz, readback_buf, bufsz, error)) {
g_prefix_error(error, "flash contents do not match: "); g_prefix_error(error, "flash contents do not match: ");
return FALSE; return FALSE;
} }
fu_progress_step_done(progress);
/* erase flag partition */ /* 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)) if (!fu_parade_lspcon_flash_erase_block(self, 0, FLASH_BLOCK_SIZE, error))
return FALSE; return FALSE;
/* write flag indicating device should boot the target partition */ /* 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)); 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; return FALSE;
fu_progress_step_done(progress);
/* verify flag partition */ /* verify flag partition */
fu_device_set_status(device, FWUPD_STATUS_DEVICE_VERIFY); if (!fu_parade_lspcon_flash_read(self,
if (!fu_parade_lspcon_flash_read(self, 0, readback_buf, sizeof(flag_data), error)) 0,
readback_buf,
sizeof(flag_data),
fu_progress_get_child(progress),
error))
return FALSE; return FALSE;
if (!fu_common_bytes_compare_raw(flag_data, if (!fu_common_bytes_compare_raw(flag_data,
sizeof(flag_data), sizeof(flag_data),
@ -748,6 +775,7 @@ fu_parade_lspcon_device_write_firmware(FuDevice *device,
sizeof(write_sr_enable_bp), sizeof(write_sr_enable_bp),
error)) error))
return FALSE; return FALSE;
fu_progress_step_done(progress);
/* reassert /WP to flash */ /* reassert /WP to flash */
return fu_parade_lspcon_write_register(self, REG_ADDR_WR_PROTECT, 0, error); 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 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); FuParadeLspconDevice *self = FU_PARADE_LSPCON_DEVICE(device);
return fu_parade_lspcon_set_mpu_running(self, FALSE, error); return fu_parade_lspcon_set_mpu_running(self, FALSE, error);
} }
static gboolean 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); FuParadeLspconDevice *self = FU_PARADE_LSPCON_DEVICE(device);
return fu_parade_lspcon_set_mpu_running(self, TRUE, error); return fu_parade_lspcon_set_mpu_running(self, TRUE, error);
} }
static GBytes * 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); FuParadeLspconDevice *self = FU_PARADE_LSPCON_DEVICE(device);
g_autofree guint8 *data = g_malloc0(FLASH_BLOCK_SIZE); 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, self->active_partition * FLASH_BLOCK_SIZE,
data, data,
FLASH_BLOCK_SIZE, FLASH_BLOCK_SIZE,
progress,
error)) error))
return NULL; return NULL;
return g_bytes_new_take(g_steal_pointer(&data), FLASH_BLOCK_SIZE); 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 static void
fu_parade_lspcon_device_class_init(FuParadeLspconDeviceClass *klass) 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->write_firmware = fu_parade_lspcon_device_write_firmware;
klass_device->attach = fu_parade_lspcon_device_attach; klass_device->attach = fu_parade_lspcon_device_attach;
klass_device->dump_firmware = fu_parade_lspcon_device_dump_firmware; 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 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(GBytes) fw = NULL;
g_autoptr(GPtrArray) chunks = 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, 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, FU_PXI_DEVICE_CMD_FW_MCU_RESET); /* OTA reset command */
fu_byte_array_append_uint8(req, OTA_RESET); /* OTA reset reason */ 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)) { if (!fu_pxi_ble_device_set_feature(self, req, error)) {
g_prefix_error(error, "failed to reset: "); 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 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 gchar *version;
const guint8 *buf; 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)); g_byte_array_append(req, fw_version, sizeof(fw_version));
/* send fw upgrade command */ /* 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)) if (!fu_pxi_ble_device_set_feature(self, req, error))
return FALSE; return FALSE;
@ -637,6 +641,7 @@ fu_pxi_ble_device_fw_upgrade(FuPxiBleDevice *self, FuFirmware *firmware, GError
static gboolean static gboolean
fu_pxi_ble_device_write_firmware(FuDevice *device, fu_pxi_ble_device_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -645,13 +650,21 @@ fu_pxi_ble_device_write_firmware(FuDevice *device,
g_autoptr(GPtrArray) chunks = NULL; g_autoptr(GPtrArray) chunks = NULL;
g_autoptr(GError) error_local = 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 */ /* get the default image */
fw = fu_firmware_get_bytes(firmware, error); fw = fu_firmware_get_bytes(firmware, error);
if (fw == NULL) if (fw == NULL)
return FALSE; return FALSE;
/* send fw ota retransmit command to reset status */ /* 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)) { if (!fu_pxi_ble_device_fw_ota_check_retransmit(self, error)) {
g_prefix_error(error, "failed to OTA check retransmit: "); g_prefix_error(error, "failed to OTA check retransmit: ");
return FALSE; return FALSE;
@ -661,30 +674,43 @@ fu_pxi_ble_device_write_firmware(FuDevice *device,
return FALSE; return FALSE;
if (!fu_pxi_ble_device_fw_ota_init_new(self, g_bytes_get_size(fw), error)) if (!fu_pxi_ble_device_fw_ota_init_new(self, g_bytes_get_size(fw), error))
return FALSE; return FALSE;
fu_progress_step_done(progress);
/* prepare write fw into device */ /* prepare write fw into device */
chunks = fu_chunk_array_new_from_bytes(fw, 0x0, 0x0, FU_PXI_DEVICE_OBJECT_SIZE_MAX); 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); g_debug("do not resume: %s", error_local->message);
self->fwstate.offset = 0; self->fwstate.offset = 0;
self->fwstate.checksum = 0; self->fwstate.checksum = 0;
} }
fu_progress_step_done(progress);
/* write fw into device */ /* write fw into device */
fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE);
for (guint i = self->fwstate.offset; i < chunks->len; i++) { for (guint i = self->fwstate.offset; i < chunks->len; i++) {
FuChunk *chk = g_ptr_array_index(chunks, i); FuChunk *chk = g_ptr_array_index(chunks, i);
if (!fu_pxi_ble_device_write_chunk(self, chk, error)) if (!fu_pxi_ble_device_write_chunk(self, chk, error))
return FALSE; 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 */ /* 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; return FALSE;
fu_progress_step_done(progress);
/* send device reset command */ /* 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 static gboolean
@ -855,6 +881,17 @@ fu_pxi_ble_device_setup(FuDevice *device, GError **error)
return TRUE; 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 static void
fu_pxi_ble_device_init(FuPxiBleDevice *self) 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->to_string = fu_pxi_ble_device_to_string;
klass_device->write_firmware = fu_pxi_ble_device_write_firmware; klass_device->write_firmware = fu_pxi_ble_device_write_firmware;
klass_device->prepare_firmware = fu_pxi_ble_device_prepare_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 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); FuPxiReceiverDevice *self = FU_PXI_RECEIVER_DEVICE(device);
const gchar *version; 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(GByteArray) receiver_device_cmd = g_byte_array_new();
g_autoptr(GBytes) fw = NULL; 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); fw = fu_firmware_get_bytes(firmware, error);
if (fw == NULL) if (fw == NULL)
return FALSE; return FALSE;
@ -464,9 +473,8 @@ fu_pxi_receiver_device_fw_upgrade(FuDevice *device, FuFirmware *firmware, GError
ota_cmd, ota_cmd,
error)) error))
return FALSE; 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 */ /* send ota fw upgrade command */
if (!fu_pxi_receiver_device_set_feature(self, if (!fu_pxi_receiver_device_set_feature(self,
receiver_device_cmd->data, receiver_device_cmd->data,
@ -491,6 +499,7 @@ fu_pxi_receiver_device_fw_upgrade(FuDevice *device, FuFirmware *firmware, GError
result); result);
return FALSE; return FALSE;
} }
fu_progress_step_done(progress);
/* success */ /* success */
return TRUE; return TRUE;
@ -520,9 +529,6 @@ fu_pxi_receiver_device_reset(FuDevice *device, GError **error)
error)) error))
return FALSE; return FALSE;
/* update device status */
fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_DEVICE_RESTART);
/* send ota mcu reset command */ /* send ota mcu reset command */
return fu_pxi_receiver_device_set_feature(self, return fu_pxi_receiver_device_set_feature(self,
receiver_device_cmd->data, receiver_device_cmd->data,
@ -545,6 +551,7 @@ fu_pxi_receiver_device_prepare_firmware(FuDevice *device,
static gboolean static gboolean
fu_pxi_receiver_device_write_firmware(FuDevice *device, fu_pxi_receiver_device_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -552,6 +559,13 @@ fu_pxi_receiver_device_write_firmware(FuDevice *device,
g_autoptr(GBytes) fw = NULL; g_autoptr(GBytes) fw = NULL;
g_autoptr(GPtrArray) chunks = 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 */ /* get the default image */
fw = fu_firmware_get_bytes(firmware, error); fw = fu_firmware_get_bytes(firmware, error);
if (fw == NULL) 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)) if (!fu_pxi_receiver_device_fw_ota_ini_new_check(self, error))
return FALSE; return FALSE;
fu_progress_step_done(progress);
chunks = fu_chunk_array_new_from_bytes(fw, 0x0, 0x0, FU_PXI_DEVICE_OBJECT_SIZE_MAX); chunks = fu_chunk_array_new_from_bytes(fw, 0x0, 0x0, FU_PXI_DEVICE_OBJECT_SIZE_MAX);
/* prepare write fw into device */ /* prepare write fw into device */
@ -570,23 +585,34 @@ fu_pxi_receiver_device_write_firmware(FuDevice *device,
self->fwstate.checksum = 0; self->fwstate.checksum = 0;
/* write fw into device */ /* write fw into device */
fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE);
for (guint i = self->fwstate.offset; i < chunks->len; i++) { for (guint i = self->fwstate.offset; i < chunks->len; i++) {
FuChunk *chk = g_ptr_array_index(chunks, i); FuChunk *chk = g_ptr_array_index(chunks, i);
if (!fu_pxi_receiver_device_write_chunk(device, chk, error)) if (!fu_pxi_receiver_device_write_chunk(device, chk, error))
return FALSE; 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 */ /* 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; return FALSE;
fu_progress_step_done(progress);
/* delay for wireless module device read command */ /* delay for wireless module device read command */
g_usleep(5 * 1000); g_usleep(5 * 1000);
/* send device reset command */ /* 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 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); 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 static void
fu_pxi_receiver_device_init(FuPxiReceiverDevice *self) 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->probe = fu_pxi_receiver_device_probe;
klass_device->write_firmware = fu_pxi_receiver_device_write_firmware; klass_device->write_firmware = fu_pxi_receiver_device_write_firmware;
klass_device->prepare_firmware = fu_pxi_receiver_device_prepare_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 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; FuPxiReceiverDevice *parent;
FuPxiWirelessDevice *self = FU_PXI_WIRELESS_DEVICE(device); 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(GByteArray) receiver_cmd = g_byte_array_new();
g_autoptr(GBytes) fw = NULL; 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 */ /* proxy */
parent = fu_pxi_wireless_device_get_parent(device, error); parent = fu_pxi_wireless_device_get_parent(device, error);
if (parent == NULL) if (parent == NULL)
@ -512,14 +521,16 @@ fu_pxi_wireless_device_fw_upgrade(FuDevice *device, FuFirmware *firmware, GError
ota_cmd, ota_cmd,
error)) error))
return FALSE; return FALSE;
/* update device status */ fu_progress_step_done(progress);
fu_device_set_status(FU_DEVICE(self), FWUPD_STATUS_DEVICE_VERIFY);
/* send ota fw upgrade command */ /* send ota fw upgrade command */
return fu_pxi_wireless_device_set_feature(FU_DEVICE(parent), if (!fu_pxi_wireless_device_set_feature(FU_DEVICE(parent),
receiver_cmd->data, receiver_cmd->data,
receiver_cmd->len, receiver_cmd->len,
error); error))
return FALSE;
fu_progress_step_done(progress);
return TRUE;
} }
static gboolean static gboolean
@ -553,7 +564,6 @@ fu_pxi_wireless_device_reset(FuDevice *device, GError **error)
return FALSE; return FALSE;
/* send ota mcu reset command */ /* 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), return fu_pxi_wireless_device_set_feature(FU_DEVICE(parent),
receiver_cmd->data, receiver_cmd->data,
receiver_cmd->len, receiver_cmd->len,
@ -575,6 +585,7 @@ fu_pxi_wireless_device_prepare_firmware(FuDevice *device,
static gboolean static gboolean
fu_pxi_wireless_device_write_firmware(FuDevice *device, fu_pxi_wireless_device_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -582,6 +593,13 @@ fu_pxi_wireless_device_write_firmware(FuDevice *device,
g_autoptr(GBytes) fw = NULL; g_autoptr(GBytes) fw = NULL;
g_autoptr(GPtrArray) chunks = 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 */ /* get the default image */
fw = fu_firmware_get_bytes(firmware, error); fw = fu_firmware_get_bytes(firmware, error);
if (fw == NULL) if (fw == NULL)
@ -592,6 +610,7 @@ fu_pxi_wireless_device_write_firmware(FuDevice *device,
return FALSE; return FALSE;
if (!fu_pxi_wireless_device_fw_ota_ini_new_check(device, error)) if (!fu_pxi_wireless_device_fw_ota_ini_new_check(device, error))
return FALSE; return FALSE;
fu_progress_step_done(progress);
chunks = fu_chunk_array_new_from_bytes(fw, 0x0, 0x0, FU_PXI_DEVICE_OBJECT_SIZE_MAX); chunks = fu_chunk_array_new_from_bytes(fw, 0x0, 0x0, FU_PXI_DEVICE_OBJECT_SIZE_MAX);
/* prepare write fw into device */ /* prepare write fw into device */
@ -599,21 +618,43 @@ fu_pxi_wireless_device_write_firmware(FuDevice *device,
self->fwstate.checksum = 0; self->fwstate.checksum = 0;
/* write fw into device */ /* write fw into device */
fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE);
for (guint i = self->fwstate.offset; i < chunks->len; i++) { for (guint i = self->fwstate.offset; i < chunks->len; i++) {
FuChunk *chk = g_ptr_array_index(chunks, i); FuChunk *chk = g_ptr_array_index(chunks, i);
if (!fu_pxi_wireless_device_write_chunk(device, chk, error)) if (!fu_pxi_wireless_device_write_chunk(device, chk, error))
return FALSE; 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 */ /* 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; return FALSE;
fu_progress_step_done(progress);
/* send device reset command */ /* send device reset command */
g_usleep(FU_PXI_WIRELESS_DEV_DELAY_US); 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 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->write_firmware = fu_pxi_wireless_device_write_firmware;
klass_device->prepare_firmware = fu_pxi_wireless_device_prepare_firmware; klass_device->prepare_firmware = fu_pxi_wireless_device_prepare_firmware;
klass_device->to_string = fu_pxi_wireless_device_to_string; klass_device->to_string = fu_pxi_wireless_device_to_string;
klass_device->set_progress = fu_pxi_wireless_device_set_progress;
} }
FuPxiWirelessDevice * FuPxiWirelessDevice *

View File

@ -550,6 +550,7 @@ flash_iface_read(FuRealtekMstDevice *self,
guint32 address, guint32 address,
guint8 *buf, guint8 *buf,
const gsize buf_size, const gsize buf_size,
FuProgress *progress,
GError **error) GError **error)
{ {
gsize bytes_read = 0; gsize bytes_read = 0;
@ -591,7 +592,7 @@ flash_iface_read(FuRealtekMstDevice *self,
return FALSE; return FALSE;
bytes_read += read_len; 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; return TRUE;
} }
@ -648,7 +649,11 @@ flash_iface_erase_block(FuRealtekMstDevice *self, guint32 address, GError **erro
} }
static gboolean 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 bytes_written = 0;
gsize total_size = g_bytes_get_size(data); 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; 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; return TRUE;
} }
static gboolean 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); FuRealtekMstDevice *self = FU_REALTEK_MST_DEVICE(device);
@ -719,7 +724,6 @@ fu_realtek_mst_device_detach(FuDevice *device, GError **error)
return FALSE; return FALSE;
/* Switch to programming mode (stops regular operation) */ /* 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)) if (!mst_write_register(self, REG_MCU_MODE, MCU_MODE_ISP, error))
return FALSE; return FALSE;
g_debug("wait for ISP mode ready"); g_debug("wait for ISP mode ready");
@ -733,7 +737,6 @@ fu_realtek_mst_device_detach(FuDevice *device, GError **error)
return FALSE; return FALSE;
fu_device_add_flag(device, FWUPD_DEVICE_FLAG_IS_BOOTLOADER); 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 /* Disable hardware write protect, assuming Flash ~WP is connected to
* device pin 88, a GPIO. */ * device pin 88, a GPIO. */
@ -743,6 +746,7 @@ fu_realtek_mst_device_detach(FuDevice *device, GError **error)
static gboolean static gboolean
fu_realtek_mst_device_write_firmware(FuDevice *device, fu_realtek_mst_device_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) 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); 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)) if (!mst_ensure_device_address(self, I2C_ADDR_ISP, error))
return FALSE; return FALSE;
/* erase old image */ /* erase old image */
g_debug("erase old image from %#x", base_addr); 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) { 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)) if (!flash_iface_erase_block(self, base_addr + offset, error))
return FALSE; 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 */ /* write new image */
g_debug("write new image to %#x", base_addr); g_debug("write new image to %#x", base_addr);
fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); if (!flash_iface_write(self,
if (!flash_iface_write(self, base_addr, firmware_bytes, error)) base_addr,
firmware_bytes,
fu_progress_get_child(progress),
error))
return FALSE; return FALSE;
fu_progress_step_done(progress);
fu_device_set_status(device, FWUPD_STATUS_DEVICE_VERIFY); /* verify */
if (!flash_iface_read(self, base_addr, readback_buf, FLASH_USER_SIZE, error)) if (!flash_iface_read(self,
base_addr,
readback_buf,
FLASH_USER_SIZE,
fu_progress_get_child(progress),
error))
return FALSE; return FALSE;
if (memcmp(g_bytes_get_data(firmware_bytes, NULL), readback_buf, FLASH_USER_SIZE) != 0) { if (memcmp(g_bytes_get_data(firmware_bytes, NULL), readback_buf, FLASH_USER_SIZE) != 0) {
g_set_error(error, 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"); "flash contents after write do not match firmware image");
return FALSE; return FALSE;
} }
fu_progress_step_done(progress);
/* Erase old flag and write new one. The MST appears to modify the /* 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 * flag value once booted, so we always write the same value here and
* it picks up what we've updated. */ * 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)) if (!flash_iface_erase_sector(self, flag_addr & ~(FLASH_SECTOR_SIZE - 1), error))
return FALSE; return FALSE;
fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); if (!flash_iface_write(self,
return flash_iface_write(self,
flag_addr, flag_addr,
g_bytes_new_static(flag_data, sizeof(flag_data)), g_bytes_new_static(flag_data, sizeof(flag_data)),
error); fu_progress_get_child(progress),
error))
return FALSE;
fu_progress_step_done(progress);
/* success */
return TRUE;
} }
static FuFirmware * 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); FuRealtekMstDevice *self = FU_REALTEK_MST_DEVICE(device);
guint32 bank_address; guint32 bank_address;
@ -824,30 +852,30 @@ fu_realtek_mst_device_read_firmware(FuDevice *device, GError **error)
image_bytes = g_malloc0(FLASH_USER_SIZE); image_bytes = g_malloc0(FLASH_USER_SIZE);
if (!mst_ensure_device_address(self, I2C_ADDR_ISP, error)) if (!mst_ensure_device_address(self, I2C_ADDR_ISP, error))
return NULL; 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 NULL;
return fu_firmware_new_from_bytes( return fu_firmware_new_from_bytes(
g_bytes_new_take(g_steal_pointer(&image_bytes), FLASH_USER_SIZE)); g_bytes_new_take(g_steal_pointer(&image_bytes), FLASH_USER_SIZE));
} }
static GBytes * 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); FuRealtekMstDevice *self = FU_REALTEK_MST_DEVICE(device);
g_autofree guint8 *flash_contents = g_malloc0(FLASH_SIZE); g_autofree guint8 *flash_contents = g_malloc0(FLASH_SIZE);
if (!mst_ensure_device_address(self, I2C_ADDR_ISP, error)) if (!mst_ensure_device_address(self, I2C_ADDR_ISP, error))
return NULL; return NULL;
fu_device_set_status(device, FWUPD_STATUS_DEVICE_READ); fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_READ);
if (!flash_iface_read(self, 0, flash_contents, FLASH_SIZE, error)) if (!flash_iface_read(self, 0, flash_contents, FLASH_SIZE, progress, error))
return NULL; 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); return g_bytes_new_take(g_steal_pointer(&flash_contents), FLASH_SIZE);
} }
static gboolean 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); FuRealtekMstDevice *self = FU_REALTEK_MST_DEVICE(device);
guint8 value; guint8 value;
@ -865,7 +893,6 @@ fu_realtek_mst_device_attach(FuDevice *device, GError **error)
g_autoptr(GError) error_local = NULL; g_autoptr(GError) error_local = NULL;
g_debug("resetting device to exit ISP mode"); 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 /* Set register EE bit 2 to request reset. This write can fail
* spuriously, so we ignore the write result and verify the device is * 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_remove_flag(device, FWUPD_DEVICE_FLAG_IS_BOOTLOADER);
fu_device_set_status(device, FWUPD_STATUS_IDLE);
return TRUE; 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 static void
fu_realtek_mst_device_init(FuRealtekMstDevice *self) 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; klass_device->read_firmware = fu_realtek_mst_device_read_firmware;
/* dump whole flash */ /* dump whole flash */
klass_device->dump_firmware = fu_realtek_mst_device_dump_firmware; 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; gchar *location;
gboolean completed; gboolean completed;
GHashTable *messages_seen; GHashTable *messages_seen;
FuProgress *progress;
} FuRedfishDevicePollCtx; } FuRedfishDevicePollCtx;
static void static void
@ -560,43 +561,43 @@ fu_redfish_device_poll_set_message_id(FuRedfishDevice *self,
/* set status */ /* set status */
if (g_strcmp0(message_id, "Update.1.1.TargetDetermined") == 0) { 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; return;
} }
if (g_strcmp0(message_id, "LenovoFirmwareUpdateRegistry.1.0.UpdateAssignment") == 0) { 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; return;
} }
if (g_strcmp0(message_id, "LenovoFirmwareUpdateRegistry.1.0.PayloadApplyInProgress") == 0) { 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; return;
} }
if (g_strcmp0(message_id, "LenovoFirmwareUpdateRegistry.1.0.PayloadApplyCompleted") == 0) { 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; return;
} }
if (g_strcmp0(message_id, "LenovoFirmwareUpdateRegistry.1.0.UpdateVerifyInProgress") == 0) { 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; return;
} }
if (g_strcmp0(message_id, "Update.1.1.TransferringToComponent") == 0) { 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; return;
} }
if (g_strcmp0(message_id, "Update.1.1.VerifyingAtComponent") == 0) { 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; return;
} }
if (g_strcmp0(message_id, "Update.1.1.UpdateInProgress") == 0) { 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; return;
} }
if (g_strcmp0(message_id, "Update.1.1.UpdateSuccessful") == 0) { 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; return;
} }
if (g_strcmp0(message_id, "Update.1.1.InstallingOnComponent") == 0) { 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; return;
} }
} }
@ -622,7 +623,7 @@ fu_redfish_device_poll_task_once(FuRedfishDevice *self, FuRedfishDevicePollCtx *
if (json_object_has_member(json_obj, "PercentComplete")) { if (json_object_has_member(json_obj, "PercentComplete")) {
gint64 pc = json_object_get_int_member(json_obj, "PercentComplete"); gint64 pc = json_object_get_int_member(json_obj, "PercentComplete");
if (pc >= 0 && pc <= 100) 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 */ /* print all messages we've not seen yet */
@ -685,12 +686,13 @@ fu_redfish_device_poll_task_once(FuRedfishDevice *self, FuRedfishDevicePollCtx *
} }
static 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); FuRedfishDevicePollCtx *ctx = g_new0(FuRedfishDevicePollCtx, 1);
ctx->messages_seen = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); ctx->messages_seen = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
ctx->location = g_strdup(location); ctx->location = g_strdup(location);
ctx->error_code = FWUPD_ERROR_INTERNAL; ctx->error_code = FWUPD_ERROR_INTERNAL;
ctx->progress = g_object_ref(progress);
return ctx; return ctx;
} }
@ -698,6 +700,7 @@ static void
fu_redfish_device_poll_ctx_free(FuRedfishDevicePollCtx *ctx) fu_redfish_device_poll_ctx_free(FuRedfishDevicePollCtx *ctx)
{ {
g_hash_table_unref(ctx->messages_seen); g_hash_table_unref(ctx->messages_seen);
g_object_unref(ctx->progress);
g_free(ctx->location); g_free(ctx->location);
g_free(ctx); g_free(ctx);
} }
@ -708,11 +711,14 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(FuRedfishDevicePollCtx, fu_redfish_device_poll_ctx
#pragma clang diagnostic pop #pragma clang diagnostic pop
gboolean 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; const guint timeout = 2400;
g_autoptr(GTimer) timer = g_timer_new(); 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 */ /* sleep and then reprobe hardware */
do { do {

View File

@ -45,4 +45,7 @@ struct _FuRedfishDeviceClass {
FuRedfishBackend * FuRedfishBackend *
fu_redfish_device_get_backend(FuRedfishDevice *self); fu_redfish_device_get_backend(FuRedfishDevice *self);
gboolean 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) G_DEFINE_TYPE(FuRedfishLegacyDevice, fu_redfish_legacy_device, FU_TYPE_REDFISH_DEVICE)
static gboolean 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); FuRedfishLegacyDevice *self = FU_REDFISH_LEGACY_DEVICE(dev);
FuRedfishBackend *backend = fu_redfish_device_get_backend(FU_REDFISH_DEVICE(self)); 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 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); FuRedfishLegacyDevice *self = FU_REDFISH_LEGACY_DEVICE(dev);
FuRedfishBackend *backend = fu_redfish_device_get_backend(FU_REDFISH_DEVICE(self)); 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 static gboolean
fu_redfish_legacy_device_write_firmware(FuDevice *device, fu_redfish_legacy_device_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) 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_CUSTOMREQUEST, "POST");
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, g_bytes_get_data(fw, NULL)); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, g_bytes_get_data(fw, NULL));
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)g_bytes_get_size(fw)); 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, if (!fu_redfish_request_perform(request,
fu_redfish_backend_get_push_uri_path(backend), fu_redfish_backend_get_push_uri_path(backend),
FU_REDFISH_REQUEST_PERFORM_FLAG_LOAD_JSON, FU_REDFISH_REQUEST_PERFORM_FLAG_LOAD_JSON,
@ -111,7 +112,17 @@ fu_redfish_legacy_device_write_firmware(FuDevice *device,
return FALSE; return FALSE;
} }
location = json_object_get_string_member(json_obj, "@odata.id"); 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 static void
@ -127,4 +138,5 @@ fu_redfish_legacy_device_class_init(FuRedfishLegacyDeviceClass *klass)
klass_device->attach = fu_redfish_legacy_device_attach; klass_device->attach = fu_redfish_legacy_device_attach;
klass_device->detach = fu_redfish_legacy_device_detach; klass_device->detach = fu_redfish_legacy_device_detach;
klass_device->write_firmware = fu_redfish_legacy_device_write_firmware; 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 static gboolean
fu_redfish_multipart_device_write_firmware(FuDevice *device, fu_redfish_multipart_device_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -94,7 +95,7 @@ fu_redfish_multipart_device_write_firmware(FuDevice *device,
curl_mime_filedata(part, filename); curl_mime_filedata(part, filename);
curl_mime_data(part, g_bytes_get_data(fw, NULL), g_bytes_get_size(fw)); 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, if (!fu_redfish_request_perform(request,
fu_redfish_backend_get_push_uri_path(backend), fu_redfish_backend_get_push_uri_path(backend),
FU_REDFISH_REQUEST_PERFORM_FLAG_LOAD_JSON, FU_REDFISH_REQUEST_PERFORM_FLAG_LOAD_JSON,
@ -127,7 +128,17 @@ fu_redfish_multipart_device_write_firmware(FuDevice *device,
return FALSE; return FALSE;
} }
location = json_object_get_string_member(json_obj, "@odata.id"); 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 static void
@ -141,4 +152,5 @@ fu_redfish_multipart_device_class_init(FuRedfishMultipartDeviceClass *klass)
{ {
FuDeviceClass *klass_device = FU_DEVICE_CLASS(klass); FuDeviceClass *klass_device = FU_DEVICE_CLASS(klass);
klass_device->write_firmware = fu_redfish_multipart_device_write_firmware; 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; gboolean ret;
g_autoptr(GError) error = NULL; g_autoptr(GError) error = NULL;
g_autoptr(GBytes) blob_fw = NULL; g_autoptr(GBytes) blob_fw = NULL;
g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC);
devices = fu_plugin_get_devices(self->plugin); devices = fu_plugin_get_devices(self->plugin);
g_assert_nonnull(devices); g_assert_nonnull(devices);
@ -311,6 +312,7 @@ fu_test_redfish_update_func(gconstpointer user_data)
ret = fu_plugin_runner_write_firmware(self->plugin, ret = fu_plugin_runner_write_firmware(self->plugin,
dev, dev,
blob_fw, blob_fw,
progress,
FWUPD_INSTALL_FLAG_NONE, FWUPD_INSTALL_FLAG_NONE,
&error); &error);
g_assert_no_error(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, ret = fu_plugin_runner_write_firmware(self->plugin,
dev, dev,
blob_fw, blob_fw,
progress,
FWUPD_INSTALL_FLAG_NONE, FWUPD_INSTALL_FLAG_NONE,
&error); &error);
g_assert_error(error, FWUPD_ERROR, FWUPD_ERROR_WRITE); g_assert_error(error, FWUPD_ERROR, FWUPD_ERROR_WRITE);

View File

@ -126,7 +126,7 @@ fu_rts54hid_device_write_flash(FuRts54HidDevice *self,
} }
static gboolean 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 = { const FuRts54HidCmdBuffer cmd_buffer = {
.cmd = FU_RTS54HID_CMD_WRITE_DATA, .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, FU_HID_DEVICE_FLAG_NONE,
error)) error))
return FALSE; 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), if (!fu_hid_device_get_report(FU_HID_DEVICE(self),
0x0, 0x0,
buf, buf,
@ -285,6 +285,7 @@ fu_rts54hid_device_close(FuDevice *device, GError **error)
static gboolean static gboolean
fu_rts54hid_device_write_firmware(FuDevice *device, fu_rts54hid_device_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -292,6 +293,13 @@ fu_rts54hid_device_write_firmware(FuDevice *device,
g_autoptr(GBytes) fw = NULL; g_autoptr(GBytes) fw = NULL;
g_autoptr(GPtrArray) chunks = 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 */ /* get default image */
fw = fu_firmware_get_bytes(firmware, error); fw = fu_firmware_get_bytes(firmware, error);
if (fw == NULL) if (fw == NULL)
@ -302,18 +310,15 @@ fu_rts54hid_device_write_firmware(FuDevice *device,
return FALSE; return FALSE;
/* erase spare flash bank only if it is not empty */ /* 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)) if (!fu_rts54hid_device_erase_spare_bank(self, error))
return FALSE; return FALSE;
fu_progress_step_done(progress);
/* build packets */ /* write each block */
chunks = fu_chunk_array_new_from_bytes(fw, chunks = fu_chunk_array_new_from_bytes(fw,
0x00, /* start addr */ 0x00, /* start addr */
0x00, /* page_sz */ 0x00, /* page_sz */
FU_RTS54HID_TRANSFER_BLOCK_SIZE); 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++) { for (guint i = 0; i < chunks->len; i++) {
FuChunk *chk = g_ptr_array_index(chunks, i); FuChunk *chk = g_ptr_array_index(chunks, i);
/* write chunk */ /* write chunk */
@ -325,21 +330,37 @@ fu_rts54hid_device_write_firmware(FuDevice *device,
return FALSE; return FALSE;
/* update progress */ /* 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 */ /* 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; return FALSE;
fu_progress_step_done(progress);
/* send software reset to run available flash code */ /* send software reset to run available flash code */
if (!fu_rts54hid_device_reset_to_flash(self, error)) if (!fu_rts54hid_device_reset_to_flash(self, error))
return FALSE; return FALSE;
fu_progress_step_done(progress);
/* success! */ /* success! */
return TRUE; 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 static void
fu_rts54hid_device_init(FuRts54HidDevice *self) 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->to_string = fu_rts54hid_device_to_string;
klass_device->setup = fu_rts54hid_device_setup; klass_device->setup = fu_rts54hid_device_setup;
klass_device->close = fu_rts54hid_device_close; 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 static gboolean
fu_rts54hid_module_write_firmware(FuDevice *module, fu_rts54hid_module_write_firmware(FuDevice *module,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -235,7 +236,7 @@ fu_rts54hid_module_write_firmware(FuDevice *module,
} }
/* write each block */ /* 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++) { for (guint i = 0; i < chunks->len; i++) {
FuChunk *chk = g_ptr_array_index(chunks, i); FuChunk *chk = g_ptr_array_index(chunks, i);
@ -247,7 +248,7 @@ fu_rts54hid_module_write_firmware(FuDevice *module,
return FALSE; return FALSE;
/* update progress */ /* 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! */ /* success! */

View File

@ -427,6 +427,7 @@ fu_rts54hub_device_close(FuDevice *device, GError **error)
static gboolean static gboolean
fu_rts54hub_device_write_firmware(FuDevice *device, fu_rts54hub_device_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -434,6 +435,13 @@ fu_rts54hub_device_write_firmware(FuDevice *device,
g_autoptr(GBytes) fw = NULL; g_autoptr(GBytes) fw = NULL;
g_autoptr(GPtrArray) chunks = 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 */ /* get default image */
fw = fu_firmware_get_bytes(firmware, error); fw = fu_firmware_get_bytes(firmware, error);
if (fw == NULL) if (fw == NULL)
@ -449,9 +457,9 @@ fu_rts54hub_device_write_firmware(FuDevice *device,
} }
/* erase spare flash bank only if it is not empty */ /* 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)) if (!fu_rts54hub_device_erase_flash(self, 1, error))
return FALSE; return FALSE;
fu_progress_step_done(progress);
/* set MCU clock to high clock mode */ /* set MCU clock to high clock mode */
if (!fu_rts54hub_device_highclockmode(self, 0x0001, error)) { if (!fu_rts54hub_device_highclockmode(self, 0x0001, error)) {
@ -465,14 +473,11 @@ fu_rts54hub_device_write_firmware(FuDevice *device,
return FALSE; return FALSE;
} }
/* build packets */ /* write each block */
chunks = fu_chunk_array_new_from_bytes(fw, chunks = fu_chunk_array_new_from_bytes(fw,
0x00, /* start addr */ 0x00, /* start addr */
0x00, /* page_sz */ 0x00, /* page_sz */
FU_RTS54HUB_DEVICE_BLOCK_SIZE); 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++) { for (guint i = 0; i < chunks->len; i++) {
FuChunk *chk = g_ptr_array_index(chunks, i); FuChunk *chk = g_ptr_array_index(chunks, i);
@ -485,18 +490,21 @@ fu_rts54hub_device_write_firmware(FuDevice *device,
return FALSE; return FALSE;
/* update progress */ /* 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 */ /* get device to authenticate the firmware */
fu_device_set_status(device, FWUPD_STATUS_DEVICE_VERIFY);
if (!fu_rts54hub_device_flash_authentication(self, error)) if (!fu_rts54hub_device_flash_authentication(self, error))
return FALSE; return FALSE;
fu_progress_step_done(progress);
/* send software reset to run available flash code */ /* 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)) if (!fu_rts54hub_device_reset_flash(self, error))
return FALSE; return FALSE;
fu_progress_step_done(progress);
/* don't reset the vendor command enable, the device will be rebooted */ /* don't reset the vendor command enable, the device will be rebooted */
self->vendor_cmd = FU_RTS54HUB_VENDOR_CMD_NONE; 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); 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 static void
fu_rts54hub_device_init(FuRts54HubDevice *self) 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->to_string = fu_rts54hub_device_to_string;
klass_device->prepare_firmware = fu_rts54hub_device_prepare_firmware; klass_device->prepare_firmware = fu_rts54hub_device_prepare_firmware;
klass_device->close = fu_rts54hub_device_close; 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 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)); FuRts54HubDevice *parent = FU_RTS54HUB_DEVICE(fu_device_get_parent(device));
g_autoptr(FuDeviceLocker) locker = NULL; g_autoptr(FuDeviceLocker) locker = NULL;
@ -127,7 +127,7 @@ fu_rts54hub_rtd21xx_background_detach(FuDevice *device, GError **error)
} }
static gboolean 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)); FuRts54HubDevice *parent = FU_RTS54HUB_DEVICE(fu_device_get_parent(device));
FuRts54hubRtd21xxDevice *self = FU_RTS54HUB_RTD21XX_DEVICE(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: "); g_prefix_error(error, "failed to attach: ");
return FALSE; return FALSE;
} }
fu_device_sleep_with_progress(device, 1); fu_progress_sleep(progress, 1000);
/* success */ /* success */
fu_device_remove_flag(device, FWUPD_DEVICE_FLAG_IS_BOOTLOADER); 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 static gboolean
fu_rts54hub_rtd21xx_background_write_firmware(FuDevice *device, fu_rts54hub_rtd21xx_background_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -204,6 +205,13 @@ fu_rts54hub_rtd21xx_background_write_firmware(FuDevice *device,
g_autoptr(GBytes) fw = NULL; g_autoptr(GBytes) fw = NULL;
g_autoptr(GPtrArray) chunks = 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 */ /* open device */
locker = fu_device_locker_new(self, error); locker = fu_device_locker_new(self, error);
if (locker == NULL) if (locker == NULL)
@ -217,7 +225,6 @@ fu_rts54hub_rtd21xx_background_write_firmware(FuDevice *device,
/* get project ID address */ /* get project ID address */
write_buf[0] = ISP_CMD_GET_PROJECT_ID_ADDR; 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), if (!fu_rts54hub_rtd21xx_device_i2c_write(FU_RTS54HUB_RTD21XX_DEVICE(self),
UC_ISP_SLAVE_ADDR, UC_ISP_SLAVE_ADDR,
UC_BACKGROUND_OPCODE, 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); g_prefix_error(error, "failed to write project ID from 0x%04x: ", project_addr);
return FALSE; return FALSE;
} }
fu_device_set_status(device, FWUPD_STATUS_DEVICE_BUSY);
if (!fu_rts54hub_rtd21xx_device_i2c_write(FU_RTS54HUB_RTD21XX_DEVICE(self), if (!fu_rts54hub_rtd21xx_device_i2c_write(FU_RTS54HUB_RTD21XX_DEVICE(self),
UC_ISP_SLAVE_ADDR, UC_ISP_SLAVE_ADDR,
UC_BACKGROUND_OPCODE, 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: "); g_prefix_error(error, "failed to send fw update start cmd: ");
return FALSE; return FALSE;
} }
fu_progress_step_done(progress);
/* send data */ /* send data */
fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE);
chunks = fu_chunk_array_new_from_bytes(fw, chunks = fu_chunk_array_new_from_bytes(fw,
0x00, /* start addr */ 0x00, /* start addr */
0x00, /* page_sz */ 0x00, /* page_sz */
@ -314,11 +320,13 @@ fu_rts54hub_rtd21xx_background_write_firmware(FuDevice *device,
} }
/* update progress */ /* 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 */ /* 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)) if (!fu_rts54hub_rtd21xx_device_read_status(FU_RTS54HUB_RTD21XX_DEVICE(self), NULL, error))
return FALSE; return FALSE;
write_buf[0] = ISP_CMD_FW_UPDATE_ISP_DONE; write_buf[0] = ISP_CMD_FW_UPDATE_ISP_DONE;
@ -333,10 +341,9 @@ fu_rts54hub_rtd21xx_background_write_firmware(FuDevice *device,
} }
/* exit fw mode */ /* 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)) if (!fu_rts54hub_rtd21xx_device_read_status(FU_RTS54HUB_RTD21XX_DEVICE(self), NULL, error))
return FALSE; return FALSE;
fu_progress_step_done(progress);
/* success */ /* success */
return TRUE; return TRUE;

View File

@ -113,7 +113,7 @@ fu_rts54hub_rtd21xx_foreground_detach_cb(FuDevice *device, gpointer user_data, G
} }
static gboolean 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)); FuRts54HubDevice *parent = FU_RTS54HUB_DEVICE(fu_device_get_parent(device));
g_autoptr(FuDeviceLocker) locker = NULL; g_autoptr(FuDeviceLocker) locker = NULL;
@ -126,7 +126,7 @@ fu_rts54hub_rtd21xx_foreground_detach(FuDevice *device, GError **error)
} }
static gboolean 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)); FuRts54HubDevice *parent = FU_RTS54HUB_DEVICE(fu_device_get_parent(device));
FuRts54hubRtd21xxForeground *self = FU_RTS54HUB_RTD21XX_FOREGROUND(device); FuRts54hubRtd21xxForeground *self = FU_RTS54HUB_RTD21XX_FOREGROUND(device);
@ -139,8 +139,6 @@ fu_rts54hub_rtd21xx_foreground_attach(FuDevice *device, GError **error)
return FALSE; return FALSE;
/* exit fw mode */ /* 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)) if (!fu_rts54hub_rtd21xx_device_read_status(FU_RTS54HUB_RTD21XX_DEVICE(self), NULL, error))
return FALSE; return FALSE;
if (!fu_rts54hub_rtd21xx_device_i2c_write(FU_RTS54HUB_RTD21XX_DEVICE(self), 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 /* the device needs some time to restart with the new firmware before
* it can be queried again */ * it can be queried again */
fu_device_sleep_with_progress(device, 60); fu_progress_sleep(progress, 60000);
/* success */ /* success */
return TRUE; return TRUE;
@ -224,6 +222,7 @@ fu_rts54hub_rtd21xx_foreground_reload(FuDevice *device, GError **error)
static gboolean static gboolean
fu_rts54hub_rtd21xx_foreground_write_firmware(FuDevice *device, fu_rts54hub_rtd21xx_foreground_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -238,6 +237,13 @@ fu_rts54hub_rtd21xx_foreground_write_firmware(FuDevice *device,
g_autoptr(GBytes) fw = NULL; g_autoptr(GBytes) fw = NULL;
g_autoptr(GPtrArray) chunks = 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 */ /* open device */
locker = fu_device_locker_new(self, error); locker = fu_device_locker_new(self, error);
if (locker == NULL) if (locker == NULL)
@ -252,7 +258,6 @@ fu_rts54hub_rtd21xx_foreground_write_firmware(FuDevice *device,
/* enable ISP high priority */ /* enable ISP high priority */
write_buf[0] = ISP_CMD_ENTER_FW_UPDATE; write_buf[0] = ISP_CMD_ENTER_FW_UPDATE;
write_buf[1] = 0x01; 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), if (!fu_rts54hub_rtd21xx_device_i2c_write(FU_RTS54HUB_RTD21XX_DEVICE(self),
UC_ISP_SLAVE_ADDR, UC_ISP_SLAVE_ADDR,
UC_FOREGROUND_OPCODE, UC_FOREGROUND_OPCODE,
@ -267,7 +272,6 @@ fu_rts54hub_rtd21xx_foreground_write_firmware(FuDevice *device,
/* get project ID address */ /* get project ID address */
write_buf[0] = ISP_CMD_GET_PROJECT_ID_ADDR; 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), if (!fu_rts54hub_rtd21xx_device_i2c_write(FU_RTS54HUB_RTD21XX_DEVICE(self),
UC_ISP_SLAVE_ADDR, UC_ISP_SLAVE_ADDR,
UC_FOREGROUND_OPCODE, 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); g_prefix_error(error, "failed to write project ID from 0x%04x: ", project_addr);
return FALSE; return FALSE;
} }
fu_device_set_status(device, FWUPD_STATUS_DEVICE_BUSY);
if (!fu_rts54hub_rtd21xx_device_i2c_write(FU_RTS54HUB_RTD21XX_DEVICE(self), if (!fu_rts54hub_rtd21xx_device_i2c_write(FU_RTS54HUB_RTD21XX_DEVICE(self),
UC_ISP_SLAVE_ADDR, UC_ISP_SLAVE_ADDR,
UC_FOREGROUND_OPCODE, 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: "); g_prefix_error(error, "failed to send fw update start cmd: ");
return FALSE; return FALSE;
} }
fu_progress_step_done(progress);
/* send data */ /* send data */
fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE);
chunks = fu_chunk_array_new_from_bytes(fw, chunks = fu_chunk_array_new_from_bytes(fw,
0x00, /* start addr */ 0x00, /* start addr */
0x00, /* page_sz */ 0x00, /* page_sz */
@ -364,11 +367,13 @@ fu_rts54hub_rtd21xx_foreground_write_firmware(FuDevice *device,
} }
/* update progress */ /* 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 */ /* 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)) if (!fu_rts54hub_rtd21xx_device_read_status(FU_RTS54HUB_RTD21XX_DEVICE(self), NULL, error))
return FALSE; return FALSE;
write_buf[0] = ISP_CMD_FW_UPDATE_ISP_DONE; 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: "); g_prefix_error(error, "failed update finish cmd: ");
return FALSE; return FALSE;
} }
fu_progress_step_done(progress);
/* success */ /* success */
return TRUE; 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) res = NULL;
g_autoptr(GByteArray) sig = g_byte_array_new(); 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_byte_array_append_bytes(sig, fw_sig);
fu_solokey_device_exchange(req, SOLO_BOOTLOADER_DONE, 0x00, sig); fu_solokey_device_exchange(req, SOLO_BOOTLOADER_DONE, 0x00, sig);
res = fu_solokey_device_packet(self, SOLO_BOOTLOADER_HID_CMD_BOOT, req, error); 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 static gboolean
fu_solokey_device_write_firmware(FuDevice *device, fu_solokey_device_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -455,6 +455,12 @@ fu_solokey_device_write_firmware(FuDevice *device,
g_autoptr(GBytes) fw_sig = NULL; g_autoptr(GBytes) fw_sig = NULL;
g_autoptr(GPtrArray) chunks = 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 */ /* build packets */
fw = fu_firmware_get_bytes(firmware, error); fw = fu_firmware_get_bytes(firmware, error);
if (fw == NULL) if (fw == NULL)
@ -465,7 +471,6 @@ fu_solokey_device_write_firmware(FuDevice *device,
2048); 2048);
/* write each block */ /* write each block */
fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE);
for (guint i = 0; i < chunks->len; i++) { for (guint i = 0; i < chunks->len; i++) {
FuChunk *chk = g_ptr_array_index(chunks, i); FuChunk *chk = g_ptr_array_index(chunks, i);
g_autoptr(GByteArray) buf = g_byte_array_new(); g_autoptr(GByteArray) buf = g_byte_array_new();
@ -490,14 +495,33 @@ fu_solokey_device_write_firmware(FuDevice *device,
} }
/* update progress */ /* 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 */ /* verify the signature and reboot back to runtime */
fw_sig = fu_firmware_get_image_by_id_bytes(firmware, FU_FIRMWARE_ID_SIGNATURE, error); fw_sig = fu_firmware_get_image_by_id_bytes(firmware, FU_FIRMWARE_ID_SIGNATURE, error);
if (fw_sig == NULL) if (fw_sig == NULL)
return FALSE; 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 static void
@ -522,4 +546,5 @@ fu_solokey_device_class_init(FuSolokeyDeviceClass *klass)
klass_device->setup = fu_solokey_device_setup; klass_device->setup = fu_solokey_device_setup;
klass_device->open = fu_solokey_device_open; klass_device->open = fu_solokey_device_open;
klass_device->close = fu_solokey_device_close; 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; 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 static void
fu_superio_device_init(FuSuperioDevice *self) 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->probe = fu_superio_device_probe;
klass_device->setup = fu_superio_device_setup; klass_device->setup = fu_superio_device_setup;
klass_device->prepare_firmware = fu_superio_device_prepare_firmware; 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; 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 * static GBytes *
fu_plugin_superio_patch_autoload(FuDevice *device, GBytes *fw, GError **error) 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 /* progress callback is optional to not affect device progress during writing
* firmware */ * firmware */
static GBytes * static GBytes *
fu_superio_it55_device_get_firmware(FuDevice *device, fu_superio_it55_device_get_firmware(FuDevice *device, FuProgress *progress, GError **error)
GFileProgressCallback progress_cb,
GError **error)
{ {
FuSuperioDevice *self = FU_SUPERIO_DEVICE(device); FuSuperioDevice *self = FU_SUPERIO_DEVICE(device);
guint64 fwsize = fu_device_get_firmware_size_min(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)) if (!fu_superio_device_ec_read_data(self, &buf[offset], error))
return NULL; return NULL;
if (progress_cb != NULL) fu_progress_set_percentage_full(progress, (gsize)i + 1, (gsize)block_count);
progress_cb(offset, (goffset)fwsize, self);
} }
} }
@ -263,7 +253,7 @@ fu_superio_it55_device_get_firmware(FuDevice *device,
} }
static GBytes * 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; g_autoptr(FuDeviceLocker) locker = NULL;
@ -275,14 +265,12 @@ fu_superio_it55_device_dump_firmware(FuDevice *device, GError **error)
if (locker == NULL) if (locker == NULL)
return NULL; return NULL;
fu_device_set_status(device, FWUPD_STATUS_DEVICE_READ); fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_READ);
return fu_superio_it55_device_get_firmware(device, return fu_superio_it55_device_get_firmware(device, progress, error);
fu_superio_it55_device_progress_cb,
error);
} }
static gboolean 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); FuSuperioDevice *self = FU_SUPERIO_DEVICE(device);
@ -299,7 +287,7 @@ fu_superio_it55_device_attach(FuDevice *device, GError **error)
} }
static gboolean 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); FuSuperioDevice *self = FU_SUPERIO_DEVICE(device);
@ -338,20 +326,30 @@ fu_superio_it55_device_erase(FuDevice *device, GError **error)
} }
static gboolean 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); 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; const guint8 *fw_data = NULL;
g_autoptr(GBytes) erased_fw = NULL; g_autoptr(GBytes) erased_fw = NULL;
g_autoptr(GBytes) written_fw = NULL; g_autoptr(GBytes) written_fw = NULL;
g_autoptr(GPtrArray) blocks = 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)) if (!fu_superio_it55_device_erase(device, error))
return FALSE; 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) { if (erased_fw == NULL) {
g_prefix_error(error, "failed to read erased firmware"); g_prefix_error(error, "failed to read erased firmware");
return FALSE; return FALSE;
@ -363,6 +361,7 @@ fu_superio_it55_device_write_attempt(FuDevice *device, GBytes *firmware, GError
"firmware was not erased"); "firmware was not erased");
return FALSE; return FALSE;
} }
fu_progress_step_done(progress);
/* write everything but the first kilobyte */ /* write everything but the first kilobyte */
blocks = fu_chunk_array_new_from_bytes(firmware, 0x00, 0x00, BLOCK_SIZE); 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; return FALSE;
for (guint j = 0; j < CHUNKS_IN_BLOCK; ++j) { for (guint j = 0; j < CHUNKS_IN_BLOCK; ++j) {
gsize progress = i * CHUNKS_IN_BLOCK + j;
if (first && j < CHUNKS_IN_KBYTE) { if (first && j < CHUNKS_IN_KBYTE) {
offset += CHUNK_SIZE; offset += CHUNK_SIZE;
bytes_left -= CHUNK_SIZE; bytes_left -= CHUNK_SIZE;
fu_device_set_progress_full(device, progress, (gsize)total);
continue; continue;
} }
@ -403,10 +399,12 @@ fu_superio_it55_device_write_attempt(FuDevice *device, GBytes *firmware, GError
++offset; ++offset;
--bytes_left; --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 */ /* now write the first kilobyte */
if (!fu_superio_device_ec_write_cmd(self, SIO_CMD_EC_WRITE_1ST_KBYTE, error)) 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) for (guint i = 0; i < CHUNK_SIZE * CHUNKS_IN_KBYTE; ++i)
if (!fu_superio_device_ec_write_data(self, fw_data[i], error)) if (!fu_superio_device_ec_write_data(self, fw_data[i], error))
return FALSE; return FALSE;
fu_progress_step_done(progress);
g_usleep(1000); 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) { if (written_fw == NULL) {
g_prefix_error(error, "failed to read erased firmware"); g_prefix_error(error, "failed to read firmware");
return FALSE; return FALSE;
} }
if (!fu_common_bytes_compare(written_fw, firmware, error)) { if (!fu_common_bytes_compare(written_fw, firmware, error)) {
g_prefix_error(error, "firmware verification"); g_prefix_error(error, "firmware verification");
return FALSE; return FALSE;
} }
fu_progress_step_done(progress);
/* success */ /* success */
fu_device_set_progress(device, 100);
return TRUE; return TRUE;
} }
static gboolean static gboolean
fu_superio_it55_device_write_firmware(FuDevice *device, fu_superio_it55_device_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -444,6 +445,11 @@ fu_superio_it55_device_write_firmware(FuDevice *device,
g_autoptr(GBytes) fw_patched = NULL; g_autoptr(GBytes) fw_patched = NULL;
g_autoptr(FuDeviceLocker) locker = 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 */ /* require detach -> attach */
locker = fu_device_locker_new_full(device, locker = fu_device_locker_new_full(device,
(FuDeviceLockerFunc)fu_device_detach, (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); fw_patched = fu_plugin_superio_patch_autoload(device, fw, error);
if (fw_patched == NULL) if (fw_patched == NULL)
return FALSE; return FALSE;
fu_progress_step_done(progress);
fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE);
/* try this many times; the failure-to-flash case leaves you without a /* try this many times; the failure-to-flash case leaves you without a
* keyboard and future boot may completely fail */ * keyboard and future boot may completely fail */
for (guint i = 1;; ++i) { for (guint i = 1;; ++i) {
g_autoptr(GError) error_chk = NULL; 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; break;
if (i == MAX_FLASHING_ATTEMPTS) { 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); g_warning("failure %u: %s", i, error_chk->message);
} }
fu_progress_step_done(progress);
/* success */ /* success */
return TRUE; return TRUE;

View File

@ -223,7 +223,7 @@ static GBytes *
fu_superio_it89_device_read_addr(FuSuperioDevice *self, fu_superio_it89_device_read_addr(FuSuperioDevice *self,
guint32 addr, guint32 addr,
guint size, guint size,
GFileProgressCallback progress_cb, FuProgress *progress,
GError **error) GError **error)
{ {
g_autofree guint8 *buf = NULL; g_autofree guint8 *buf = NULL;
@ -261,8 +261,7 @@ fu_superio_it89_device_read_addr(FuSuperioDevice *self,
return NULL; return NULL;
/* update progress */ /* update progress */
if (progress_cb != NULL) fu_progress_set_percentage_full(progress, (goffset)i, (goffset)size);
progress_cb((goffset)i, (goffset)size, self);
} }
/* check again... */ /* check again... */
@ -273,13 +272,6 @@ fu_superio_it89_device_read_addr(FuSuperioDevice *self,
return g_bytes_new_take(g_steal_pointer(&buf), size); 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 static gboolean
fu_superio_it89_device_write_addr(FuSuperioDevice *self, guint addr, GBytes *fw, GError **error) 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 * 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); FuSuperioDevice *self = FU_SUPERIO_DEVICE(device);
guint64 fwsize = fu_device_get_firmware_size_min(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) if (locker == NULL)
return NULL; return NULL;
fu_device_set_status(device, FWUPD_STATUS_DEVICE_READ); fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_READ);
return fu_superio_it89_device_read_addr(self, return fu_superio_it89_device_read_addr(self, 0x0, fwsize, progress, error);
0x0,
fwsize,
fu_superio_it89_device_progress_cb,
error);
} }
static FuFirmware * 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); FuSuperioDevice *self = FU_SUPERIO_DEVICE(device);
g_autoptr(GBytes) blob = NULL; g_autoptr(GBytes) blob = NULL;
g_autoptr(GBytes) fw = 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); fw = fu_plugin_superio_fix_signature(self, blob, error);
return fu_firmware_new_from_bytes(fw); return fu_firmware_new_from_bytes(fw);
} }
static gboolean 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); FuSuperioDevice *self = FU_SUPERIO_DEVICE(device);
@ -458,7 +446,7 @@ fu_superio_it89_device_attach(FuDevice *device, GError **error)
} }
static gboolean 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); FuSuperioDevice *self = FU_SUPERIO_DEVICE(device);
guint8 tmp = 0x00; guint8 tmp = 0x00;
@ -483,14 +471,14 @@ fu_superio_it89_device_detach(FuDevice *device, GError **error)
} }
static gboolean 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; g_autoptr(GBytes) fw = NULL;
const guint64 fwsize = fu_device_get_firmware_size_min(FU_DEVICE(self)); const guint64 fwsize = fu_device_get_firmware_size_min(FU_DEVICE(self));
const guint sigsz = 16; const guint sigsz = 16;
/* last 16 bytes of eeprom */ /* 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) { if (fw == NULL) {
g_prefix_error(error, "failed to read signature bytes: "); g_prefix_error(error, "failed to read signature bytes: ");
return FALSE; return FALSE;
@ -518,12 +506,22 @@ fu_superio_it89_device_check_eflash(FuSuperioDevice *self, GError **error)
} }
static gboolean 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) fw1 = NULL;
g_autoptr(GBytes) fw2 = NULL; g_autoptr(GBytes) fw2 = NULL;
g_autoptr(GBytes) fw3 = 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 */ /* erase page */
if (!fu_superio_it89_device_erase_addr(self, fu_chunk_get_address(chk), error)) { if (!fu_superio_it89_device_erase_addr(self, fu_chunk_get_address(chk), error)) {
g_prefix_error(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)); (guint)fu_chunk_get_address(chk));
return FALSE; return FALSE;
} }
fu_progress_step_done(progress);
/* check erased */ /* check erased */
fw1 = fu_superio_it89_device_read_addr(self, fw1 = fu_superio_it89_device_read_addr(self,
fu_chunk_get_address(chk), fu_chunk_get_address(chk),
fu_chunk_get_data_sz(chk), fu_chunk_get_data_sz(chk),
NULL, fu_progress_get_child(progress),
error); error);
if (fw1 == NULL) { if (fw1 == NULL) {
g_prefix_error(error, 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"); g_set_error_literal(error, FWUPD_ERROR, FWUPD_ERROR_READ, "sector was not erased");
return FALSE; return FALSE;
} }
fu_progress_step_done(progress);
/* skip empty page */ /* skip empty page */
fw2 = g_bytes_new_static(fu_chunk_get_data(chk), fu_chunk_get_data_sz(chk)); 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; return TRUE;
}
/* write page */ /* write page */
if (!fu_superio_it89_device_write_addr(self, fu_chunk_get_address(chk), fw2, error)) { 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)); (guint)fu_chunk_get_address(chk));
return FALSE; return FALSE;
} }
fu_progress_step_done(progress);
/* verify page */ /* verify page */
fw3 = fu_superio_it89_device_read_addr(self, fw3 = fu_superio_it89_device_read_addr(self,
fu_chunk_get_address(chk), fu_chunk_get_address(chk),
fu_chunk_get_data_sz(chk), fu_chunk_get_data_sz(chk),
NULL, fu_progress_get_child(progress),
error); error);
if (fw3 == NULL) { if (fw3 == NULL) {
g_prefix_error(error, 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)); (guint)fu_chunk_get_address(chk));
return FALSE; return FALSE;
} }
fu_progress_step_done(progress);
/* success */ /* success */
return TRUE; 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); 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 static gboolean
fu_superio_it89_device_write_firmware(FuDevice *device, fu_superio_it89_device_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -621,6 +663,12 @@ fu_superio_it89_device_write_firmware(FuDevice *device,
g_autoptr(GBytes) fw = NULL; g_autoptr(GBytes) fw = NULL;
g_autoptr(GPtrArray) chunks = 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 */ /* check JEDEC ID */
if (!fu_superio_it89_device_get_jedec_id(self, id, error)) { if (!fu_superio_it89_device_get_jedec_id(self, id, error)) {
g_prefix_error(error, "failed to get JEDEC ID: "); 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 */ /* 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; return FALSE;
fu_progress_step_done(progress);
/* get default image */ /* get default image */
fw = fu_firmware_get_bytes(firmware, error); 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 of 1kB, skipping the final chunk */
chunks = fu_chunk_array_new_from_bytes(fw_fixed, 0x00, 0x00, 0x400); chunks = fu_chunk_array_new_from_bytes(fw_fixed, 0x00, 0x00, 0x400);
fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE); if (!fu_superio_it89_device_write_chunks(self,
for (guint i = 0; i < chunks->len - 1; i++) { chunks,
FuChunk *chk = g_ptr_array_index(chunks, i); fu_progress_get_child(progress),
error))
/* 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; return FALSE;
} fu_progress_step_done(progress);
g_warning("failure %u: %s", j, error_chk->message);
}
/* set progress */
fu_device_set_progress_full(device, (gsize)i, (gsize)chunks->len);
}
/* success */ /* success */
fu_device_set_progress(device, 100);
return TRUE; return TRUE;
} }

View File

@ -612,6 +612,7 @@ fu_synaptics_cxaudio_device_prepare_firmware(FuDevice *device,
static gboolean static gboolean
fu_synaptics_cxaudio_device_write_firmware(FuDevice *device, fu_synaptics_cxaudio_device_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) 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)); GPtrArray *records = fu_srec_firmware_get_records(FU_SREC_FIRMWARE(firmware));
FuSynapticsCxaudioFileKind file_kind; 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 */ /* check if a patch file fits completely into the EEPROM */
for (guint i = 0; i < records->len; i++) { for (guint i = 0; i < records->len; i++) {
FuSrecFirmwareRecord *rcd = g_ptr_array_index(records, i); FuSrecFirmwareRecord *rcd = g_ptr_array_index(records, i);
@ -645,6 +654,7 @@ fu_synaptics_cxaudio_device_write_firmware(FuDevice *device,
error)) error))
return FALSE; return FALSE;
g_usleep(10 * 1000); g_usleep(10 * 1000);
fu_progress_step_done(progress);
/* initialize layout signature and version to 0 if transitioning from /* initialize layout signature and version to 0 if transitioning from
* EEPROM layout version 1 => 0 */ * EEPROM layout version 1 => 0 */
@ -681,9 +691,9 @@ fu_synaptics_cxaudio_device_write_firmware(FuDevice *device,
} }
g_debug("initialized layout signature"); g_debug("initialized layout signature");
} }
fu_progress_step_done(progress);
/* perform the actual write */ /* perform the actual write */
fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE);
for (guint i = 0; i < records->len; i++) { for (guint i = 0; i < records->len; i++) {
FuSrecFirmwareRecord *rcd = g_ptr_array_index(records, i); FuSrecFirmwareRecord *rcd = g_ptr_array_index(records, i);
if (rcd->kind != FU_FIRMWARE_SREC_RECORD_KIND_S3_DATA_32) 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); rcd->buf->len);
return FALSE; 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) /* 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 */ * 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"); g_debug("invalidated old FW patch for CX2070x (RAM) device");
} }
} }
fu_progress_step_done(progress);
/* unpark the FW */ /* unpark the FW */
if (!fu_synaptics_cxaudio_device_register_clear_bit( if (!fu_synaptics_cxaudio_device_register_clear_bit(
@ -748,13 +762,14 @@ fu_synaptics_cxaudio_device_write_firmware(FuDevice *device,
7, 7,
error)) error))
return FALSE; return FALSE;
fu_progress_step_done(progress);
/* success */ /* success */
return TRUE; return TRUE;
} }
static gboolean 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); FuSynapticsCxaudioDevice *self = FU_SYNAPTICS_CXAUDIO_DEVICE(device);
guint8 tmp = 1 << 6; guint8 tmp = 1 << 6;
@ -765,7 +780,6 @@ fu_synaptics_cxaudio_device_attach(FuDevice *device, GError **error)
return TRUE; return TRUE;
/* wait for re-enumeration */ /* wait for re-enumeration */
fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART);
fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG); fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG);
/* this fails on success */ /* this fails on success */
@ -816,6 +830,17 @@ fu_synaptics_cxaudio_device_set_quirk_kv(FuDevice *device,
return FALSE; 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 static void
fu_synaptics_cxaudio_device_init(FuSynapticsCxaudioDevice *self) 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->write_firmware = fu_synaptics_cxaudio_device_write_firmware;
klass_device->attach = fu_synaptics_cxaudio_device_attach; klass_device->attach = fu_synaptics_cxaudio_device_attach;
klass_device->prepare_firmware = fu_synaptics_cxaudio_device_prepare_firmware; 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, fu_plugin_write_firmware(FuPlugin *plugin,
FuDevice *device, FuDevice *device,
GBytes *blob_fw, GBytes *blob_fw,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
g_autoptr(FuDeviceLocker) locker = fu_device_locker_new(device, error); g_autoptr(FuDeviceLocker) locker = fu_device_locker_new(device, error);
if (locker == NULL) if (locker == NULL)
return FALSE; 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; return FALSE;
if (!fu_device_has_flag(device, FWUPD_DEVICE_FLAG_SKIPS_RESTART)) if (!fu_device_has_flag(device, FWUPD_DEVICE_FLAG_SKIPS_RESTART))
fu_plugin_device_remove(plugin, device); fu_plugin_device_remove(plugin, device);

View File

@ -295,6 +295,7 @@ fu_synaptics_mst_device_set_flash_sector_erase(FuSynapticsMstDevice *self,
static gboolean static gboolean
fu_synaptics_mst_device_update_esm(FuSynapticsMstDevice *self, fu_synaptics_mst_device_update_esm(FuSynapticsMstDevice *self,
const guint8 *payload_data, const guint8 *payload_data,
FuProgress *progress,
GError **error) GError **error)
{ {
guint32 checksum = 0; guint32 checksum = 0;
@ -360,9 +361,9 @@ fu_synaptics_mst_device_update_esm(FuSynapticsMstDevice *self,
} }
write_offset += unit_sz; write_offset += unit_sz;
write_idx += unit_sz; write_idx += unit_sz;
fu_device_set_progress_full(FU_DEVICE(self), fu_progress_set_percentage_full(progress,
(goffset)i * 100, (goffset)i + 1,
(goffset)(write_loops - 1) * 100); (goffset)write_loops);
} }
/* check ESM checksum */ /* check ESM checksum */
@ -404,6 +405,7 @@ static gboolean
fu_synaptics_mst_device_update_tesla_leaf_firmware(FuSynapticsMstDevice *self, fu_synaptics_mst_device_update_tesla_leaf_firmware(FuSynapticsMstDevice *self,
guint32 payload_len, guint32 payload_len,
const guint8 *payload_data, const guint8 *payload_data,
FuProgress *progress,
GError **error) GError **error)
{ {
g_autoptr(FuSynapticsMstConnection) connection = NULL; g_autoptr(FuSynapticsMstConnection) connection = NULL;
@ -460,9 +462,9 @@ fu_synaptics_mst_device_update_tesla_leaf_firmware(FuSynapticsMstDevice *self,
} }
offset += length; offset += length;
data_to_write -= length; data_to_write -= length;
fu_device_set_progress_full(FU_DEVICE(self), fu_progress_set_percentage_full(progress,
(goffset)i * 100, (goffset)i + 1,
(goffset)(write_loops - 1) * 100); (goffset)write_loops);
} }
/* check data just written */ /* check data just written */
@ -526,6 +528,7 @@ static gboolean
fu_synaptics_mst_device_update_panamera_firmware(FuSynapticsMstDevice *self, fu_synaptics_mst_device_update_panamera_firmware(FuSynapticsMstDevice *self,
guint32 payload_len, guint32 payload_len,
const guint8 *payload_data, const guint8 *payload_data,
FuProgress *progress,
GError **error) GError **error)
{ {
guint16 crc_tmp = 0; guint16 crc_tmp = 0;
@ -613,9 +616,9 @@ fu_synaptics_mst_device_update_panamera_firmware(FuSynapticsMstDevice *self,
write_offset += unit_sz; write_offset += unit_sz;
write_idx += unit_sz; write_idx += unit_sz;
fu_device_set_progress_full(FU_DEVICE(self), fu_progress_set_percentage_full(progress,
(goffset)i * 100, (goffset)i + 1,
(goffset)(write_loops - 1) * 100); (goffset)write_loops);
} }
/* verify CRC */ /* verify CRC */
@ -853,6 +856,7 @@ static gboolean
fu_synaptics_mst_device_update_cayenne_firmware(FuSynapticsMstDevice *self, fu_synaptics_mst_device_update_cayenne_firmware(FuSynapticsMstDevice *self,
guint32 payload_len, guint32 payload_len,
const guint8 *payload_data, const guint8 *payload_data,
FuProgress *progress,
GError **error) GError **error)
{ {
g_autoptr(FuSynapticsMstConnection) connection = NULL; g_autoptr(FuSynapticsMstConnection) connection = NULL;
@ -910,7 +914,7 @@ fu_synaptics_mst_device_update_cayenne_firmware(FuSynapticsMstDevice *self,
} }
offset += length; offset += length;
data_to_write -= length; data_to_write -= length;
fu_device_set_progress_full(FU_DEVICE(self), fu_progress_set_percentage_full(progress,
(goffset)i * 100, (goffset)i * 100,
(goffset)(write_loops - 1) * 100); (goffset)(write_loops - 1) * 100);
} }
@ -1031,6 +1035,7 @@ fu_synaptics_mst_device_prepare_firmware(FuDevice *device,
static gboolean static gboolean
fu_synaptics_mst_device_write_firmware(FuDevice *device, fu_synaptics_mst_device_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -1040,13 +1045,18 @@ fu_synaptics_mst_device_write_firmware(FuDevice *device,
gsize payload_len; gsize payload_len;
g_autoptr(FuDeviceLocker) locker = NULL; 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); fw = fu_firmware_get_bytes(firmware, error);
if (fw == NULL) if (fw == NULL)
return FALSE; return FALSE;
payload_data = g_bytes_get_data(fw, &payload_len); payload_data = g_bytes_get_data(fw, &payload_len);
/* enable remote control and disable on exit */ /* 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)) { if (!fu_device_has_flag(device, FWUPD_DEVICE_FLAG_SKIPS_RESTART)) {
locker = locker =
fu_device_locker_new_full(self, 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, if (!fu_synaptics_mst_device_update_tesla_leaf_firmware(self,
payload_len, payload_len,
payload_data, payload_data,
progress,
error)) { error)) {
g_prefix_error(error, "Firmware update failed: "); g_prefix_error(error, "Firmware update failed: ");
return FALSE; return FALSE;
@ -1082,13 +1093,14 @@ fu_synaptics_mst_device_write_firmware(FuDevice *device,
g_prefix_error(error, "Failed to prepare for write: "); g_prefix_error(error, "Failed to prepare for write: ");
return FALSE; 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: "); g_prefix_error(error, "ESM update failed: ");
return FALSE; return FALSE;
} }
if (!fu_synaptics_mst_device_update_panamera_firmware(self, if (!fu_synaptics_mst_device_update_panamera_firmware(self,
payload_len, payload_len,
payload_data, payload_data,
progress,
error)) { error)) {
g_prefix_error(error, "Firmware update failed: "); g_prefix_error(error, "Firmware update failed: ");
return FALSE; return FALSE;
@ -1099,6 +1111,7 @@ fu_synaptics_mst_device_write_firmware(FuDevice *device,
if (!fu_synaptics_mst_device_update_cayenne_firmware(self, if (!fu_synaptics_mst_device_update_cayenne_firmware(self,
payload_len, payload_len,
payload_data, payload_data,
progress,
error)) { error)) {
g_prefix_error(error, "Firmware update failed: "); g_prefix_error(error, "Firmware update failed: ");
return FALSE; return FALSE;
@ -1111,10 +1124,11 @@ fu_synaptics_mst_device_write_firmware(FuDevice *device,
"Unsupported chip family"); "Unsupported chip family");
return FALSE; return FALSE;
} }
fu_progress_step_done(progress);
/* wait for flash clear to settle */ /* wait for flash clear to settle */
fu_device_set_status(device, FWUPD_STATUS_DEVICE_RESTART); fu_progress_sleep(fu_progress_get_child(progress), 2000);
fu_device_sleep_with_progress(device, 2); fu_progress_step_done(progress);
return TRUE; return TRUE;
} }
@ -1465,6 +1479,17 @@ fu_synaptics_mst_device_set_quirk_kv(FuDevice *device,
return FALSE; 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 static void
fu_synaptics_mst_device_class_init(FuSynapticsMstDeviceClass *klass) 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->write_firmware = fu_synaptics_mst_device_write_firmware;
klass_device->prepare_firmware = fu_synaptics_mst_device_prepare_firmware; klass_device->prepare_firmware = fu_synaptics_mst_device_prepare_firmware;
klass_device->probe = fu_synaptics_mst_device_probe; 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_autofree gchar *version = NULL;
g_autoptr(GByteArray) reply = NULL; g_autoptr(GByteArray) reply = NULL;
g_autoptr(GByteArray) request = NULL; g_autoptr(GByteArray) request = NULL;
g_autoptr(FuProgress) progress = fu_progress_new(G_STRLOC);
g_autofree gchar *devid = NULL; g_autofree gchar *devid = NULL;
/* get IOTA */ /* 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)); request = fu_synaprom_request_new(FU_SYNAPROM_CMD_IOTA_FIND, &cmd, sizeof(cmd));
reply = fu_synaprom_reply_new(sizeof(FuSynapromReplyIotaFindHdr) + reply = fu_synaprom_reply_new(sizeof(FuSynapromReplyIotaFindHdr) +
FU_SYNAPROM_MAX_IOTA_READ_SIZE); 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; return FALSE;
if (reply->len < sizeof(hdr) + sizeof(cfg)) { if (reply->len < sizeof(hdr) + sizeof(cfg)) {
g_set_error(error, g_set_error(error,
@ -213,6 +219,7 @@ fu_synaprom_config_prepare_firmware(FuDevice *device,
static gboolean static gboolean
fu_synaprom_config_write_firmware(FuDevice *device, fu_synaprom_config_write_firmware(FuDevice *device,
FuFirmware *firmware, FuFirmware *firmware,
FuProgress *progress,
FwupdInstallFlags flags, FwupdInstallFlags flags,
GError **error) GError **error)
{ {
@ -225,7 +232,7 @@ fu_synaprom_config_write_firmware(FuDevice *device,
return FALSE; return FALSE;
/* I assume the CFG/MFW difference is detected in the device...*/ /* 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 static void
@ -259,17 +266,17 @@ fu_synaprom_config_constructed(GObject *obj)
} }
static gboolean 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); FuDevice *parent = fu_device_get_parent(device);
return fu_device_attach(parent, error); return fu_device_attach(parent, progress, error);
} }
static gboolean 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); FuDevice *parent = fu_device_get_parent(device);
return fu_device_detach(parent, error); return fu_device_detach(parent, progress, error);
} }
static void static void

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