vli: Get the new firmware version when updating the PD device

To do this without rebooting the device implement VliUsbhubPdDevice->reload()
like the other FuVliUsbhubDevice child devices.

Fixes half of https://github.com/fwupd/fwupd/issues/2376
This commit is contained in:
Richard Hughes 2020-10-16 15:24:16 +01:00
parent 84781f41cf
commit ae5858ff58
3 changed files with 74 additions and 51 deletions

View File

@ -498,43 +498,22 @@ fu_vli_usbhub_device_probe (FuDevice *device, GError **error)
static gboolean
fu_vli_usbhub_device_pd_setup (FuVliUsbhubDevice *self, GError **error)
{
FuVliPdHdr hdr = { 0x0 };
g_autoptr(FuDevice) dev = NULL;
g_autoptr(GError) error_local = NULL;
/* legacy location */
if (!fu_vli_device_spi_read_block (FU_VLI_DEVICE (self),
VLI_USBHUB_FLASHMAP_ADDR_PD_LEGACY +
VLI_USBHUB_PD_FLASHMAP_ADDR_LEGACY,
(guint8 *) &hdr, sizeof(hdr), error)) {
g_prefix_error (error, "failed to read legacy PD header");
return FALSE;
}
/* new location */
if (GUINT16_FROM_LE (hdr.vid) != 0x2109) {
g_debug ("PD VID was 0x%04x trying new location",
GUINT16_FROM_LE (hdr.vid));
if (!fu_vli_device_spi_read_block (FU_VLI_DEVICE (self),
VLI_USBHUB_FLASHMAP_ADDR_PD +
VLI_USBHUB_PD_FLASHMAP_ADDR,
(guint8 *) &hdr, sizeof(hdr), error)) {
g_prefix_error (error, "failed to read PD header");
return FALSE;
}
}
/* just empty space */
if (hdr.fwver == G_MAXUINT32) {
g_debug ("no PD device header found");
return TRUE;
}
/* add child */
dev = fu_vli_usbhub_pd_device_new (&hdr);
fu_device_set_quirks (dev, fu_device_get_quirks (FU_DEVICE (self)));
if (!fu_device_probe (dev, &error_local)) {
g_warning ("cannot create PD device: %s", error_local->message);
dev = fu_vli_usbhub_pd_device_new (self);
if (!fu_device_probe (dev, error))
return FALSE;
if (!fu_device_setup (dev, &error_local)) {
if (g_error_matches (error_local,
FWUPD_ERROR,
FWUPD_ERROR_NOT_FOUND)) {
g_debug ("%s", error_local->message);
} else {
g_warning ("cannot create PD device: %s",
error_local->message);
}
return TRUE;
}
fu_device_add_child (FU_DEVICE (self), dev);

View File

@ -19,7 +19,6 @@
struct _FuVliUsbhubPdDevice
{
FuDevice parent_instance;
FuVliPdHdr hdr;
FuVliDeviceKind device_kind;
};
@ -38,10 +37,11 @@ fu_vli_usbhub_pd_device_to_string (FuDevice *device, guint idt, GString *str)
}
static gboolean
fu_vli_usbhub_pd_device_probe (FuDevice *device, GError **error)
fu_vli_usbhub_pd_device_setup (FuDevice *device, GError **error)
{
FuVliPdHdr hdr = { 0x0 };
FuVliUsbhubPdDevice *self = FU_VLI_USBHUB_PD_DEVICE (device);
FuVliUsbhubDevice *parent = FU_VLI_USBHUB_DEVICE (fu_device_get_parent (device));
guint32 fwver;
g_autofree gchar *fwver_str = NULL;
g_autofree gchar *instance_id0 = NULL;
@ -49,8 +49,39 @@ fu_vli_usbhub_pd_device_probe (FuDevice *device, GError **error)
g_autofree gchar *instance_id2 = NULL;
g_autofree gchar *instance_id3 = NULL;
/* legacy location */
if (!fu_vli_device_spi_read_block (FU_VLI_DEVICE (parent),
VLI_USBHUB_FLASHMAP_ADDR_PD_LEGACY +
VLI_USBHUB_PD_FLASHMAP_ADDR_LEGACY,
(guint8 *) &hdr, sizeof(hdr), error)) {
g_prefix_error (error, "failed to read legacy PD header");
return FALSE;
}
/* new location */
if (GUINT16_FROM_LE (hdr.vid) != 0x2109) {
g_debug ("PD VID was 0x%04x trying new location",
GUINT16_FROM_LE (hdr.vid));
if (!fu_vli_device_spi_read_block (FU_VLI_DEVICE (parent),
VLI_USBHUB_FLASHMAP_ADDR_PD +
VLI_USBHUB_PD_FLASHMAP_ADDR,
(guint8 *) &hdr, sizeof(hdr), error)) {
g_prefix_error (error, "failed to read PD header");
return FALSE;
}
}
/* just empty space */
if (hdr.fwver == G_MAXUINT32) {
g_set_error (error,
FWUPD_ERROR,
FWUPD_ERROR_NOT_FOUND,
"no PD device header found");
return FALSE;
}
/* get version */
fwver = GUINT32_FROM_BE (self->hdr.fwver);
fwver = GUINT32_FROM_BE (hdr.fwver);
self->device_kind = fu_vli_pd_common_guess_device_kind (fwver);
if (self->device_kind == FU_VLI_DEVICE_KIND_UNKNOWN) {
g_set_error (error,
@ -66,23 +97,23 @@ fu_vli_usbhub_pd_device_probe (FuDevice *device, GError **error)
fwver_str = fu_common_version_from_uint32 (fwver, FWUPD_VERSION_FORMAT_QUAD);
fu_device_set_version (device, fwver_str);
instance_id0 = g_strdup_printf ("USB\\VID_%04X&PID_%04X&APP_%02X",
GUINT16_FROM_LE (self->hdr.vid),
GUINT16_FROM_LE (self->hdr.pid),
GUINT16_FROM_LE (hdr.vid),
GUINT16_FROM_LE (hdr.pid),
fwver & 0xff);
fu_device_add_instance_id (device, instance_id0);
instance_id1 = g_strdup_printf ("USB\\VID_%04X&PID_%04X&DEV_%s",
GUINT16_FROM_LE (self->hdr.vid),
GUINT16_FROM_LE (self->hdr.pid),
GUINT16_FROM_LE (hdr.vid),
GUINT16_FROM_LE (hdr.pid),
fu_vli_common_device_kind_to_string (self->device_kind));
fu_device_add_instance_id (device, instance_id1);
/* add standard GUIDs in order of priority */
instance_id2 = g_strdup_printf ("USB\\VID_%04X&PID_%04X",
GUINT16_FROM_LE (self->hdr.vid),
GUINT16_FROM_LE (self->hdr.pid));
GUINT16_FROM_LE (hdr.vid),
GUINT16_FROM_LE (hdr.pid));
fu_device_add_instance_id (device, instance_id2);
instance_id3 = g_strdup_printf ("USB\\VID_%04X",
GUINT16_FROM_LE (self->hdr.vid));
GUINT16_FROM_LE (hdr.vid));
fu_device_add_instance_id_full (device, instance_id3,
FU_DEVICE_INSTANCE_FLAG_ONLY_QUIRKS);
@ -94,6 +125,19 @@ fu_vli_usbhub_pd_device_probe (FuDevice *device, GError **error)
return TRUE;
}
static gboolean
fu_vli_usbhub_pd_device_reload (FuDevice *device, GError **error)
{
FuVliUsbhubDevice *parent = FU_VLI_USBHUB_DEVICE (fu_device_get_parent (device));
g_autoptr(FuDeviceLocker) locker = NULL;
/* open parent device */
locker = fu_device_locker_new (parent, error);
if (locker == NULL)
return FALSE;
return fu_vli_usbhub_pd_device_setup (device, error);
}
static FuFirmware *
fu_vli_usbhub_pd_device_prepare_firmware (FuDevice *device,
GBytes *fw,
@ -215,7 +259,8 @@ fu_vli_usbhub_pd_device_class_init (FuVliUsbhubPdDeviceClass *klass)
{
FuDeviceClass *klass_device = FU_DEVICE_CLASS (klass);
klass_device->to_string = fu_vli_usbhub_pd_device_to_string;
klass_device->probe = fu_vli_usbhub_pd_device_probe;
klass_device->setup = fu_vli_usbhub_pd_device_setup;
klass_device->reload = fu_vli_usbhub_pd_device_reload;
klass_device->attach = fu_vli_usbhub_pd_device_attach;
klass_device->dump_firmware = fu_vli_usbhub_pd_device_dump_firmware;
klass_device->write_firmware = fu_vli_usbhub_pd_device_write_firmware;
@ -223,9 +268,10 @@ fu_vli_usbhub_pd_device_class_init (FuVliUsbhubPdDeviceClass *klass)
}
FuDevice *
fu_vli_usbhub_pd_device_new (FuVliPdHdr *hdr)
fu_vli_usbhub_pd_device_new (FuVliUsbhubDevice *parent)
{
FuVliUsbhubPdDevice *self = g_object_new (FU_TYPE_VLI_USBHUB_PD_DEVICE, NULL);
memcpy (&self->hdr, hdr, sizeof(self->hdr));
FuVliUsbhubPdDevice *self = g_object_new (FU_TYPE_VLI_USBHUB_PD_DEVICE,
"parent", parent,
NULL);
return FU_DEVICE (self);
}

View File

@ -8,8 +8,6 @@
#include "fu-plugin.h"
#include "fu-vli-pd-common.h"
#define FU_TYPE_VLI_USBHUB_PD_DEVICE (fu_vli_usbhub_pd_device_get_type ())
G_DECLARE_FINAL_TYPE (FuVliUsbhubPdDevice, fu_vli_usbhub_pd_device, FU, VLI_USBHUB_PD_DEVICE, FuDevice)
@ -18,4 +16,4 @@ struct _FuVliUsbhubPdDeviceClass
FuDeviceClass parent_class;
};
FuDevice *fu_vli_usbhub_pd_device_new (FuVliPdHdr *hdr);
FuDevice *fu_vli_usbhub_pd_device_new (FuVliUsbhubDevice *parent);