mirror of
https://git.proxmox.com/git/fwupd
synced 2025-08-14 17:28:20 +00:00
vli: Fix VL103 reboot from ROM mode to FW mode
The logic was wrong; we should have been using command 0xB0 for attach back to FW mode for both VL10x and VL103. Using a generic reset on VL103 always reset the device back into bootloader mode as the ROM signatures were being written by command 0xC0. As now attach and detach have different code paths, there's no point having a `FuVliDevice->reset()` vfunc, and so we can make everything a little simpler at the same time.
This commit is contained in:
parent
df2ae010d5
commit
aebd90baad
@ -73,19 +73,6 @@ fu_vli_device_get_spi_cmd (FuVliDevice *self,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
|
||||||
fu_vli_device_reset (FuVliDevice *self, GError **error)
|
|
||||||
{
|
|
||||||
FuVliDeviceClass *klass = FU_VLI_DEVICE_GET_CLASS (self);
|
|
||||||
if (klass->reset != NULL) {
|
|
||||||
if (!klass->reset (self, error)) {
|
|
||||||
g_prefix_error (error, "failed to reset device: ");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
fu_vli_device_spi_write_enable (FuVliDevice *self, GError **error)
|
fu_vli_device_spi_write_enable (FuVliDevice *self, GError **error)
|
||||||
{
|
{
|
||||||
@ -584,32 +571,6 @@ fu_vli_device_setup (FuDevice *device, GError **error)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
|
||||||
fu_vli_device_attach (FuDevice *device, GError **error)
|
|
||||||
{
|
|
||||||
g_autoptr(GError) error_local = NULL;
|
|
||||||
|
|
||||||
/* replug, and ignore the device going away */
|
|
||||||
fu_device_set_status (device, FWUPD_STATUS_DEVICE_RESTART);
|
|
||||||
fu_device_add_flag (device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG);
|
|
||||||
if (!fu_vli_device_reset (FU_VLI_DEVICE (device), &error_local)) {
|
|
||||||
if (g_error_matches (error_local,
|
|
||||||
G_USB_DEVICE_ERROR,
|
|
||||||
G_USB_DEVICE_ERROR_NO_DEVICE) ||
|
|
||||||
g_error_matches (error_local,
|
|
||||||
G_USB_DEVICE_ERROR,
|
|
||||||
G_USB_DEVICE_ERROR_FAILED)) {
|
|
||||||
g_debug ("ignoring %s", error_local->message);
|
|
||||||
} else {
|
|
||||||
g_propagate_prefixed_error (error,
|
|
||||||
g_steal_pointer (&error_local),
|
|
||||||
"failed to restart device: ");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
fu_vli_device_set_quirk_kv (FuDevice *device,
|
fu_vli_device_set_quirk_kv (FuDevice *device,
|
||||||
const gchar *key,
|
const gchar *key,
|
||||||
@ -682,5 +643,4 @@ fu_vli_device_class_init (FuVliDeviceClass *klass)
|
|||||||
klass_device->to_string = fu_vli_device_to_string;
|
klass_device->to_string = fu_vli_device_to_string;
|
||||||
klass_device->set_quirk_kv = fu_vli_device_set_quirk_kv;
|
klass_device->set_quirk_kv = fu_vli_device_set_quirk_kv;
|
||||||
klass_device->setup = fu_vli_device_setup;
|
klass_device->setup = fu_vli_device_setup;
|
||||||
klass_device->attach = fu_vli_device_attach;
|
|
||||||
}
|
}
|
||||||
|
@ -21,8 +21,6 @@ struct _FuVliDeviceClass
|
|||||||
void (*to_string) (FuVliDevice *self,
|
void (*to_string) (FuVliDevice *self,
|
||||||
guint idt,
|
guint idt,
|
||||||
GString *str);
|
GString *str);
|
||||||
gboolean (*reset) (FuVliDevice *self,
|
|
||||||
GError **error);
|
|
||||||
gboolean (*spi_chip_erase) (FuVliDevice *self,
|
gboolean (*spi_chip_erase) (FuVliDevice *self,
|
||||||
GError **error);
|
GError **error);
|
||||||
gboolean (*spi_sector_erase) (FuVliDevice *self,
|
gboolean (*spi_sector_erase) (FuVliDevice *self,
|
||||||
@ -69,8 +67,6 @@ void fu_vli_device_set_spi_auto_detect (FuVliDevice *self,
|
|||||||
gboolean spi_auto_detect);
|
gboolean spi_auto_detect);
|
||||||
FuVliDeviceKind fu_vli_device_get_kind (FuVliDevice *self);
|
FuVliDeviceKind fu_vli_device_get_kind (FuVliDevice *self);
|
||||||
guint32 fu_vli_device_get_offset (FuVliDevice *self);
|
guint32 fu_vli_device_get_offset (FuVliDevice *self);
|
||||||
gboolean fu_vli_device_reset (FuVliDevice *self,
|
|
||||||
GError **error);
|
|
||||||
gboolean fu_vli_device_get_spi_cmd (FuVliDevice *self,
|
gboolean fu_vli_device_get_spi_cmd (FuVliDevice *self,
|
||||||
FuVliDeviceSpiReq req,
|
FuVliDeviceSpiReq req,
|
||||||
guint8 *cmd,
|
guint8 *cmd,
|
||||||
|
@ -216,32 +216,6 @@ fu_vli_pd_device_spi_write_data (FuVliDevice *self,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
|
||||||
fu_vli_pd_device_reset (FuVliDevice *device, GError **error)
|
|
||||||
{
|
|
||||||
return g_usb_device_control_transfer (fu_usb_device_get_dev (FU_USB_DEVICE (device)),
|
|
||||||
G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE,
|
|
||||||
G_USB_DEVICE_REQUEST_TYPE_VENDOR,
|
|
||||||
G_USB_DEVICE_RECIPIENT_DEVICE,
|
|
||||||
0xb0, 0x0000, 0x0000,
|
|
||||||
NULL, 0x0, NULL,
|
|
||||||
FU_VLI_DEVICE_TIMEOUT,
|
|
||||||
NULL, error);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
fu_vli_pd_device_reset_vl103 (FuVliDevice *device, GError **error)
|
|
||||||
{
|
|
||||||
return g_usb_device_control_transfer (fu_usb_device_get_dev (FU_USB_DEVICE (device)),
|
|
||||||
G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE,
|
|
||||||
G_USB_DEVICE_REQUEST_TYPE_VENDOR,
|
|
||||||
G_USB_DEVICE_RECIPIENT_DEVICE,
|
|
||||||
0xc0, 0x0000, 0x0000,
|
|
||||||
NULL, 0x0, NULL,
|
|
||||||
FU_VLI_DEVICE_TIMEOUT,
|
|
||||||
NULL, error);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
fu_vli_pd_device_parade_setup (FuVliPdDevice *self, GError **error)
|
fu_vli_pd_device_parade_setup (FuVliPdDevice *self, GError **error)
|
||||||
{
|
{
|
||||||
@ -277,7 +251,6 @@ fu_vli_pd_device_setup (FuVliDevice *device, GError **error)
|
|||||||
guint8 verbuf[4] = { 0x0 };
|
guint8 verbuf[4] = { 0x0 };
|
||||||
guint8 tmp = 0;
|
guint8 tmp = 0;
|
||||||
g_autofree gchar *version_str = NULL;
|
g_autofree gchar *version_str = NULL;
|
||||||
FuVliDeviceClass *klass = FU_VLI_DEVICE_GET_CLASS (device);
|
|
||||||
|
|
||||||
/* get version */
|
/* get version */
|
||||||
if (!g_usb_device_control_transfer (fu_usb_device_get_dev (FU_USB_DEVICE (self)),
|
if (!g_usb_device_control_transfer (fu_usb_device_get_dev (FU_USB_DEVICE (self)),
|
||||||
@ -323,10 +296,6 @@ fu_vli_pd_device_setup (FuVliDevice *device, GError **error)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* handle this in a different way */
|
|
||||||
if (fu_vli_device_get_kind (device) == FU_VLI_DEVICE_KIND_VL103)
|
|
||||||
klass->reset = fu_vli_pd_device_reset_vl103;
|
|
||||||
|
|
||||||
/* get bootloader mode */
|
/* get bootloader mode */
|
||||||
if (!fu_vli_pd_device_read_reg (self, 0x00F7, &tmp, error))
|
if (!fu_vli_pd_device_read_reg (self, 0x00F7, &tmp, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -459,11 +428,16 @@ fu_vli_pd_device_write_firmware (FuDevice *device,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define VL10X_CMD1_SET_ROM_SIG 0xa0 /* all VL10x */
|
||||||
|
#define VL10X_CMD2_CHIP_RESET 0xb0 /* all VL10x */
|
||||||
|
#define VL10X_CMD3_SET_ROM_SIG_AND_RESET 0xc0 /* VL103 only */
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
fu_vli_pd_device_detach (FuDevice *device, GError **error)
|
fu_vli_pd_device_detach (FuDevice *device, GError **error)
|
||||||
{
|
{
|
||||||
FuVliPdDevice *self = FU_VLI_PD_DEVICE (device);
|
FuVliPdDevice *self = FU_VLI_PD_DEVICE (device);
|
||||||
guint8 tmp = 0;
|
guint8 tmp = 0;
|
||||||
|
guint8 cmd = VL10X_CMD2_CHIP_RESET;
|
||||||
g_autoptr(GError) error_local = NULL;
|
g_autoptr(GError) error_local = NULL;
|
||||||
|
|
||||||
/* write GPIOs */
|
/* write GPIOs */
|
||||||
@ -482,12 +456,19 @@ fu_vli_pd_device_detach (FuDevice *device, GError **error)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
if (!fu_vli_pd_device_write_reg (self, 0x2AE5, 0x87, error))
|
if (!fu_vli_pd_device_write_reg (self, 0x2AE5, 0x87, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* VL103 CMD1 does not work, so use CMD3 whose function is CMD1+CMD2 */
|
||||||
|
if (fu_vli_device_get_kind (FU_VLI_DEVICE (device)) == FU_VLI_DEVICE_KIND_VL103) {
|
||||||
|
cmd = VL10X_CMD3_SET_ROM_SIG_AND_RESET;
|
||||||
|
} else {
|
||||||
/* set ROM sig */
|
/* set ROM sig */
|
||||||
if (!g_usb_device_control_transfer (fu_usb_device_get_dev (FU_USB_DEVICE (device)),
|
if (!g_usb_device_control_transfer (fu_usb_device_get_dev (FU_USB_DEVICE (device)),
|
||||||
G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE,
|
G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE,
|
||||||
G_USB_DEVICE_REQUEST_TYPE_VENDOR,
|
G_USB_DEVICE_REQUEST_TYPE_VENDOR,
|
||||||
G_USB_DEVICE_RECIPIENT_DEVICE,
|
G_USB_DEVICE_RECIPIENT_DEVICE,
|
||||||
0xa0, 0x0000, 0x0000,
|
VL10X_CMD1_SET_ROM_SIG,
|
||||||
|
0x0000, 0x0000,
|
||||||
NULL, 0x0, NULL,
|
NULL, 0x0, NULL,
|
||||||
FU_VLI_DEVICE_TIMEOUT,
|
FU_VLI_DEVICE_TIMEOUT,
|
||||||
NULL, error))
|
NULL, error))
|
||||||
@ -496,7 +477,14 @@ fu_vli_pd_device_detach (FuDevice *device, GError **error)
|
|||||||
|
|
||||||
/* reset from SPI_Code into ROM_Code */
|
/* reset from SPI_Code into ROM_Code */
|
||||||
fu_device_set_status (device, FWUPD_STATUS_DEVICE_RESTART);
|
fu_device_set_status (device, FWUPD_STATUS_DEVICE_RESTART);
|
||||||
if (!fu_vli_device_reset (FU_VLI_DEVICE (device), &error_local)) {
|
if (!g_usb_device_control_transfer (fu_usb_device_get_dev (FU_USB_DEVICE (device)),
|
||||||
|
G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE,
|
||||||
|
G_USB_DEVICE_REQUEST_TYPE_VENDOR,
|
||||||
|
G_USB_DEVICE_RECIPIENT_DEVICE,
|
||||||
|
cmd, 0x0000, 0x0000,
|
||||||
|
NULL, 0x0, NULL,
|
||||||
|
FU_VLI_DEVICE_TIMEOUT,
|
||||||
|
NULL, &error_local)) {
|
||||||
if (g_error_matches (error_local,
|
if (g_error_matches (error_local,
|
||||||
G_USB_DEVICE_ERROR,
|
G_USB_DEVICE_ERROR,
|
||||||
G_USB_DEVICE_ERROR_FAILED)) {
|
G_USB_DEVICE_ERROR_FAILED)) {
|
||||||
@ -512,6 +500,43 @@ fu_vli_pd_device_detach (FuDevice *device, GError **error)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
fu_vli_pd_device_attach (FuDevice *device, GError **error)
|
||||||
|
{
|
||||||
|
g_autoptr(GError) error_local = NULL;
|
||||||
|
|
||||||
|
/* replug, and ignore the device going away */
|
||||||
|
fu_device_set_status (device, FWUPD_STATUS_DEVICE_RESTART);
|
||||||
|
fu_device_add_flag (device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG);
|
||||||
|
|
||||||
|
/* CMD2 works for VL10x *and* VL103 */
|
||||||
|
if (!g_usb_device_control_transfer (fu_usb_device_get_dev (FU_USB_DEVICE (device)),
|
||||||
|
G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE,
|
||||||
|
G_USB_DEVICE_REQUEST_TYPE_VENDOR,
|
||||||
|
G_USB_DEVICE_RECIPIENT_DEVICE,
|
||||||
|
VL10X_CMD2_CHIP_RESET,
|
||||||
|
0x0000, 0x0000,
|
||||||
|
NULL, 0x0, NULL,
|
||||||
|
FU_VLI_DEVICE_TIMEOUT,
|
||||||
|
NULL, &error_local)) {
|
||||||
|
if (g_error_matches (error_local,
|
||||||
|
G_USB_DEVICE_ERROR,
|
||||||
|
G_USB_DEVICE_ERROR_NO_DEVICE) ||
|
||||||
|
g_error_matches (error_local,
|
||||||
|
G_USB_DEVICE_ERROR,
|
||||||
|
G_USB_DEVICE_ERROR_FAILED)) {
|
||||||
|
g_debug ("ignoring %s", error_local->message);
|
||||||
|
} else {
|
||||||
|
g_propagate_prefixed_error (error,
|
||||||
|
g_steal_pointer (&error_local),
|
||||||
|
"failed to restart device: ");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fu_vli_pd_device_init (FuVliPdDevice *self)
|
fu_vli_pd_device_init (FuVliPdDevice *self)
|
||||||
{
|
{
|
||||||
@ -533,9 +558,9 @@ fu_vli_pd_device_class_init (FuVliPdDeviceClass *klass)
|
|||||||
klass_device->read_firmware = fu_vli_pd_device_read_firmware;
|
klass_device->read_firmware = fu_vli_pd_device_read_firmware;
|
||||||
klass_device->write_firmware = fu_vli_pd_device_write_firmware;
|
klass_device->write_firmware = fu_vli_pd_device_write_firmware;
|
||||||
klass_device->prepare_firmware = fu_vli_pd_device_prepare_firmware;
|
klass_device->prepare_firmware = fu_vli_pd_device_prepare_firmware;
|
||||||
|
klass_device->attach = fu_vli_pd_device_attach;
|
||||||
klass_device->detach = fu_vli_pd_device_detach;
|
klass_device->detach = fu_vli_pd_device_detach;
|
||||||
klass_vli_device->setup = fu_vli_pd_device_setup;
|
klass_vli_device->setup = fu_vli_pd_device_setup;
|
||||||
klass_vli_device->reset = fu_vli_pd_device_reset;
|
|
||||||
klass_vli_device->spi_chip_erase = fu_vli_pd_device_spi_chip_erase;
|
klass_vli_device->spi_chip_erase = fu_vli_pd_device_spi_chip_erase;
|
||||||
klass_vli_device->spi_sector_erase = fu_vli_pd_device_spi_sector_erase;
|
klass_vli_device->spi_sector_erase = fu_vli_pd_device_spi_sector_erase;
|
||||||
klass_vli_device->spi_read_data = fu_vli_pd_device_spi_read_data;
|
klass_vli_device->spi_read_data = fu_vli_pd_device_spi_read_data;
|
||||||
|
@ -325,16 +325,36 @@ fu_vli_usbhub_device_spi_write_data (FuVliDevice *self,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
fu_vli_usbhub_device_reset (FuVliDevice *device, GError **error)
|
fu_vli_usbhub_device_attach (FuDevice *device, GError **error)
|
||||||
{
|
{
|
||||||
return g_usb_device_control_transfer (fu_usb_device_get_dev (FU_USB_DEVICE (device)),
|
g_autoptr(GError) error_local = NULL;
|
||||||
|
|
||||||
|
/* replug, and ignore the device going away */
|
||||||
|
fu_device_set_status (device, FWUPD_STATUS_DEVICE_RESTART);
|
||||||
|
fu_device_add_flag (device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG);
|
||||||
|
if (!g_usb_device_control_transfer (fu_usb_device_get_dev (FU_USB_DEVICE (device)),
|
||||||
G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE,
|
G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE,
|
||||||
G_USB_DEVICE_REQUEST_TYPE_VENDOR,
|
G_USB_DEVICE_REQUEST_TYPE_VENDOR,
|
||||||
G_USB_DEVICE_RECIPIENT_DEVICE,
|
G_USB_DEVICE_RECIPIENT_DEVICE,
|
||||||
0xf6, 0x0040, 0x0002,
|
0xf6, 0x0040, 0x0002,
|
||||||
NULL, 0x0, NULL,
|
NULL, 0x0, NULL,
|
||||||
FU_VLI_DEVICE_TIMEOUT,
|
FU_VLI_DEVICE_TIMEOUT,
|
||||||
NULL, error);
|
NULL, &error_local)) {
|
||||||
|
if (g_error_matches (error_local,
|
||||||
|
G_USB_DEVICE_ERROR,
|
||||||
|
G_USB_DEVICE_ERROR_NO_DEVICE) ||
|
||||||
|
g_error_matches (error_local,
|
||||||
|
G_USB_DEVICE_ERROR,
|
||||||
|
G_USB_DEVICE_ERROR_FAILED)) {
|
||||||
|
g_debug ("ignoring %s", error_local->message);
|
||||||
|
} else {
|
||||||
|
g_propagate_prefixed_error (error,
|
||||||
|
g_steal_pointer (&error_local),
|
||||||
|
"failed to restart device: ");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* disable hub sleep states -- not really required by 815~ hubs */
|
/* disable hub sleep states -- not really required by 815~ hubs */
|
||||||
@ -995,9 +1015,9 @@ fu_vli_usbhub_device_class_init (FuVliUsbhubDeviceClass *klass)
|
|||||||
klass_device->read_firmware = fu_vli_usbhub_device_read_firmware;
|
klass_device->read_firmware = fu_vli_usbhub_device_read_firmware;
|
||||||
klass_device->write_firmware = fu_vli_usbhub_device_write_firmware;
|
klass_device->write_firmware = fu_vli_usbhub_device_write_firmware;
|
||||||
klass_device->prepare_firmware = fu_vli_usbhub_device_prepare_firmware;
|
klass_device->prepare_firmware = fu_vli_usbhub_device_prepare_firmware;
|
||||||
|
klass_device->attach = fu_vli_usbhub_device_attach;
|
||||||
klass_vli_device->to_string = fu_vli_usbhub_device_to_string;
|
klass_vli_device->to_string = fu_vli_usbhub_device_to_string;
|
||||||
klass_vli_device->setup = fu_vli_usbhub_device_setup;
|
klass_vli_device->setup = fu_vli_usbhub_device_setup;
|
||||||
klass_vli_device->reset = fu_vli_usbhub_device_reset;
|
|
||||||
klass_vli_device->spi_chip_erase = fu_vli_usbhub_device_spi_chip_erase;
|
klass_vli_device->spi_chip_erase = fu_vli_usbhub_device_spi_chip_erase;
|
||||||
klass_vli_device->spi_sector_erase = fu_vli_usbhub_device_spi_sector_erase;
|
klass_vli_device->spi_sector_erase = fu_vli_usbhub_device_spi_sector_erase;
|
||||||
klass_vli_device->spi_read_data = fu_vli_usbhub_device_spi_read_data;
|
klass_vli_device->spi_read_data = fu_vli_usbhub_device_spi_read_data;
|
||||||
|
Loading…
Reference in New Issue
Block a user