mirror of
https://git.proxmox.com/git/fwupd
synced 2025-07-27 04:04:05 +00:00
Move the generic Intel Goshen Ridge code out to a new plugin
The original code was written by Dell for the dell-dock plugin, but it's exactly the same code and NVM format for Intel reference hardware.
This commit is contained in:
parent
fc3ac81978
commit
5ebc3b6ad9
@ -468,6 +468,7 @@ done
|
|||||||
%{_libdir}/fwupd-plugins-%{fwupdplugin_version}/libfu_plugin_gpio.so
|
%{_libdir}/fwupd-plugins-%{fwupdplugin_version}/libfu_plugin_gpio.so
|
||||||
%endif
|
%endif
|
||||||
%{_libdir}/fwupd-plugins-%{fwupdplugin_version}/libfu_plugin_hailuck.so
|
%{_libdir}/fwupd-plugins-%{fwupdplugin_version}/libfu_plugin_hailuck.so
|
||||||
|
%{_libdir}/fwupd-plugins-%{fwupdplugin_version}/libfu_plugin_intel_usb4.so
|
||||||
%ifarch i686 x86_64
|
%ifarch i686 x86_64
|
||||||
%{_libdir}/fwupd-plugins-%{fwupdplugin_version}/libfu_plugin_iommu.so
|
%{_libdir}/fwupd-plugins-%{fwupdplugin_version}/libfu_plugin_iommu.so
|
||||||
%endif
|
%endif
|
||||||
|
@ -21,9 +21,6 @@ Plugin = dell_dock
|
|||||||
Name = Unprobed Dell accessory endpoint
|
Name = Unprobed Dell accessory endpoint
|
||||||
Plugin = dell_dock
|
Plugin = dell_dock
|
||||||
Flags = has-bridge
|
Flags = has-bridge
|
||||||
[USB\VID_8087&PID_0B40]
|
|
||||||
Name = Unprobed USB3 endpoint for USB4 hub
|
|
||||||
Plugin = dell_dock
|
|
||||||
|
|
||||||
# USB hub1
|
# USB hub1
|
||||||
[USB\VID_413C&PID_B06F&hub]
|
[USB\VID_413C&PID_B06F&hub]
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
#include "fu-dell-dock-i2c-mst.h"
|
#include "fu-dell-dock-i2c-mst.h"
|
||||||
#include "fu-dell-dock-i2c-tbt.h"
|
#include "fu-dell-dock-i2c-tbt.h"
|
||||||
#include "fu-dell-dock-status.h"
|
#include "fu-dell-dock-status.h"
|
||||||
#include "fu-dell-dock-usb-usb4.h"
|
|
||||||
|
|
||||||
#define DELL_DOCK_DOCK1_INSTANCE_ID "USB\\VID_413C&PID_B06E&hub&status"
|
#define DELL_DOCK_DOCK1_INSTANCE_ID "USB\\VID_413C&PID_B06E&hub&status"
|
||||||
#define DELL_DOCK_DOCK2_INSTANCE_ID "USB\\VID_413C&PID_B06E&hub&salomon_mlk_status"
|
#define DELL_DOCK_DOCK2_INSTANCE_ID "USB\\VID_413C&PID_B06E&hub&salomon_mlk_status"
|
||||||
|
@ -148,32 +148,12 @@ fu_plugin_dell_dock_backend_device_added(FuPlugin *plugin, FuDevice *device, GEr
|
|||||||
GPtrArray *devices;
|
GPtrArray *devices;
|
||||||
FuDevice *ec_device;
|
FuDevice *ec_device;
|
||||||
FuDevice *hub_dev;
|
FuDevice *hub_dev;
|
||||||
guint device_vid;
|
|
||||||
guint device_pid;
|
|
||||||
guint8 dock_type;
|
guint8 dock_type;
|
||||||
|
|
||||||
/* not interesting */
|
/* not interesting */
|
||||||
if (!FU_IS_USB_DEVICE(device))
|
if (!FU_IS_USB_DEVICE(device))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
device_vid = (guint)fu_usb_device_get_vid(FU_USB_DEVICE(device));
|
|
||||||
device_pid = (guint)fu_usb_device_get_pid(FU_USB_DEVICE(device));
|
|
||||||
g_debug("%s: processing usb device, vid: 0x%x, pid: 0x%x",
|
|
||||||
fu_plugin_get_name(plugin),
|
|
||||||
device_vid,
|
|
||||||
device_pid);
|
|
||||||
|
|
||||||
/* GR controller internal USB HUB */
|
|
||||||
if (device_vid == GR_USB_VID && device_pid == GR_USB_PID) {
|
|
||||||
g_autoptr(FuDellDockUsb4) usb4_dev = NULL;
|
|
||||||
usb4_dev = fu_dell_dock_usb4_new(FU_USB_DEVICE(device));
|
|
||||||
locker = fu_device_locker_new(FU_DEVICE(usb4_dev), error);
|
|
||||||
if (locker == NULL)
|
|
||||||
return FALSE;
|
|
||||||
fu_plugin_device_add(plugin, FU_DEVICE(usb4_dev));
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
hub = fu_dell_dock_hub_new(FU_USB_DEVICE(device));
|
hub = fu_dell_dock_hub_new(FU_USB_DEVICE(device));
|
||||||
locker = fu_device_locker_new(FU_DEVICE(hub), error);
|
locker = fu_device_locker_new(FU_DEVICE(hub), error);
|
||||||
if (locker == NULL)
|
if (locker == NULL)
|
||||||
@ -218,17 +198,9 @@ fu_plugin_dell_dock_backend_device_added(FuPlugin *plugin, FuDevice *device, GEr
|
|||||||
static void
|
static void
|
||||||
fu_plugin_dell_dock_separate_activation(FuPlugin *plugin)
|
fu_plugin_dell_dock_separate_activation(FuPlugin *plugin)
|
||||||
{
|
{
|
||||||
GPtrArray *devices = fu_plugin_get_devices(plugin);
|
FuDevice *device_ec = fu_plugin_cache_lookup(plugin, "ec");
|
||||||
FuDevice *device_ec = NULL;
|
FuDevice *device_usb4 = fu_plugin_cache_lookup(plugin, "usb4");
|
||||||
FuDevice *device_usb4 = NULL;
|
|
||||||
|
|
||||||
for (guint i = 0; i < devices->len; i++) {
|
|
||||||
FuDevice *device_tmp = g_ptr_array_index(devices, i);
|
|
||||||
if (FU_IS_DELL_DOCK_EC(device_tmp))
|
|
||||||
device_ec = device_tmp;
|
|
||||||
else if (FU_IS_DELL_DOCK_USB4(device_tmp))
|
|
||||||
device_usb4 = device_tmp;
|
|
||||||
}
|
|
||||||
/* both usb4 and ec device are found */
|
/* both usb4 and ec device are found */
|
||||||
if (device_usb4 && device_ec) {
|
if (device_usb4 && device_ec) {
|
||||||
if (fu_device_has_flag(device_usb4, FWUPD_DEVICE_FLAG_NEEDS_ACTIVATION) &&
|
if (fu_device_has_flag(device_usb4, FWUPD_DEVICE_FLAG_NEEDS_ACTIVATION) &&
|
||||||
@ -246,8 +218,16 @@ static void
|
|||||||
fu_plugin_dell_dock_device_registered(FuPlugin *plugin, FuDevice *device)
|
fu_plugin_dell_dock_device_registered(FuPlugin *plugin, FuDevice *device)
|
||||||
{
|
{
|
||||||
/* dell dock delays the activation so skips device restart */
|
/* dell dock delays the activation so skips device restart */
|
||||||
if (fu_device_has_guid(device, DELL_DOCK_TBT_INSTANCE_ID))
|
if (fu_device_has_guid(device, DELL_DOCK_TBT_INSTANCE_ID)) {
|
||||||
fu_device_add_flag(device, FWUPD_DEVICE_FLAG_SKIPS_RESTART);
|
fu_device_add_flag(device, FWUPD_DEVICE_FLAG_SKIPS_RESTART);
|
||||||
|
fu_plugin_cache_add(plugin, "tbt", device);
|
||||||
|
}
|
||||||
|
if (fu_device_has_guid(device, DELL_DOCK_USB4_INSTANCE_ID)) {
|
||||||
|
fu_device_add_flag(device, FWUPD_DEVICE_FLAG_SKIPS_RESTART);
|
||||||
|
fu_plugin_cache_add(plugin, "usb4", device);
|
||||||
|
}
|
||||||
|
if (FU_IS_DELL_DOCK_EC(device))
|
||||||
|
fu_plugin_cache_add(plugin, "ec", device);
|
||||||
|
|
||||||
/* usb4 device from thunderbolt plugin */
|
/* usb4 device from thunderbolt plugin */
|
||||||
if (g_strcmp0(fu_device_get_plugin(device), "thunderbolt") == 0 &&
|
if (g_strcmp0(fu_device_get_plugin(device), "thunderbolt") == 0 &&
|
||||||
@ -260,9 +240,7 @@ fu_plugin_dell_dock_device_registered(FuPlugin *plugin, FuDevice *device)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* online activation is mutually exclusive between usb4 and ec */
|
/* online activation is mutually exclusive between usb4 and ec */
|
||||||
if (g_strcmp0(fu_device_get_plugin(device), "dell_dock") == 0 &&
|
fu_plugin_dell_dock_separate_activation(plugin);
|
||||||
(FU_IS_DELL_DOCK_EC(device) || FU_IS_DELL_DOCK_USB4(device)))
|
|
||||||
fu_plugin_dell_dock_separate_activation(plugin);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -14,7 +14,6 @@ shared_module('fu_plugin_dell_dock',
|
|||||||
'fu-dell-dock-hub.c',
|
'fu-dell-dock-hub.c',
|
||||||
'fu-dell-dock-i2c-tbt.c',
|
'fu-dell-dock-i2c-tbt.c',
|
||||||
'fu-dell-dock-i2c-mst.c',
|
'fu-dell-dock-i2c-mst.c',
|
||||||
'fu-dell-dock-usb-usb4.c'
|
|
||||||
],
|
],
|
||||||
include_directories: [
|
include_directories: [
|
||||||
root_incdir,
|
root_incdir,
|
||||||
|
37
plugins/intel-usb4/README.md
Normal file
37
plugins/intel-usb4/README.md
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
# Intel USB4
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
This plugin supports the Goshen Ridge hardware which is a USB-4 controller from Intel.
|
||||||
|
These devices can updated using multiple interfaces, but this plugin only uses the XHCI interface.
|
||||||
|
|
||||||
|
## Firmware Format
|
||||||
|
|
||||||
|
The daemon will decompress the cabinet archive and extract a firmware blob in
|
||||||
|
an unspecified binary file format, with vendor specific header.
|
||||||
|
|
||||||
|
This plugin supports the following protocol ID:
|
||||||
|
|
||||||
|
* com.intel.thunderbolt
|
||||||
|
|
||||||
|
## GUID Generation
|
||||||
|
|
||||||
|
These devices use a custom generation scheme, which is quite intentionally identical to thunderbolt
|
||||||
|
plugin:
|
||||||
|
|
||||||
|
* `TBT-{nvm_vendor_id}{nvm_product_id}`
|
||||||
|
|
||||||
|
## Update Behavior
|
||||||
|
|
||||||
|
By default the USB4 controller will reboot at the end of the update.
|
||||||
|
|
||||||
|
Some devices (e.g. inside some Dell docks) will instead be updated the next time the USB-C plug
|
||||||
|
from the dock is unplugged from the host, or when activated manually.
|
||||||
|
|
||||||
|
## Vendor ID Security
|
||||||
|
|
||||||
|
The vendor ID is set from the USB vendor, in this instance set to `USB:0x8087`
|
||||||
|
|
||||||
|
## External Interface Access
|
||||||
|
|
||||||
|
This plugin requires read/write access to `/dev/bus/usb`.
|
@ -1,4 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
|
* Copyright (C) 2022 Richard Hughes <richard@hughsie.com>
|
||||||
* Copyright (C) 2021 Intel Corporation.
|
* Copyright (C) 2021 Intel Corporation.
|
||||||
* Copyright (C) 2021 Dell Inc.
|
* Copyright (C) 2021 Dell Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
@ -16,7 +17,7 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include "fu-dell-dock-common.h"
|
#include "fu-intel-usb4-device.h"
|
||||||
|
|
||||||
#define GR_USB_INTERFACE_NUMBER 0x0
|
#define GR_USB_INTERFACE_NUMBER 0x0
|
||||||
#define GR_USB_BLOCK_SIZE 64
|
#define GR_USB_BLOCK_SIZE 64
|
||||||
@ -58,32 +59,26 @@
|
|||||||
/* Default length for NVM READ */
|
/* Default length for NVM READ */
|
||||||
#define NVM_READ_LENGTH 0x224
|
#define NVM_READ_LENGTH 0x224
|
||||||
|
|
||||||
/* NVM offset */
|
|
||||||
#define NVM_VER_OFFSET_MAJOR 0xa
|
|
||||||
#define NVM_VER_OFFSET_MINOR 0x9
|
|
||||||
#define NVM_VID_OFFSET_MAJOR 0x221
|
|
||||||
#define NVM_VID_OFFSET_MINOR 0x220
|
|
||||||
#define NVM_PID_OFFSET_MAJOR 0x223
|
|
||||||
#define NVM_PID_OFFSET_MINOR 0x222
|
|
||||||
|
|
||||||
struct mbox_regx {
|
struct mbox_regx {
|
||||||
guint16 opcode;
|
guint16 opcode;
|
||||||
guint8 rsvd;
|
guint8 rsvd;
|
||||||
guint8 status;
|
guint8 status;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
struct _FuDellDockUsb4 {
|
struct _FuIntelUsb4Device {
|
||||||
FuUsbDevice parent_instance;
|
FuUsbDevice parent_instance;
|
||||||
guint blocksz;
|
guint blocksz;
|
||||||
guint8 intf_nr;
|
guint8 intf_nr;
|
||||||
|
guint16 nvm_product_id;
|
||||||
|
guint16 nvm_vendor_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE(FuDellDockUsb4, fu_dell_dock_usb4, FU_TYPE_USB_DEVICE)
|
G_DEFINE_TYPE(FuIntelUsb4Device, fu_intel_usb4_device, FU_TYPE_USB_DEVICE)
|
||||||
|
|
||||||
/* wIndex contains the hub register offset, value BIT[10] is "access to
|
/* wIndex contains the hub register offset, value BIT[10] is "access to
|
||||||
* mailbox", rest of values are vendor specific or rsvd */
|
* mailbox", rest of values are vendor specific or rsvd */
|
||||||
static gboolean
|
static gboolean
|
||||||
fu_dell_dock_usb4_hub_get_mmio(FuDevice *device, guint16 mbox_reg, guchar *buf, GError **error)
|
fu_intel_usb4_device_get_mmio(FuDevice *device, guint16 mbox_reg, guint8 *buf, 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));
|
||||||
struct mbox_regx *regx;
|
struct mbox_regx *regx;
|
||||||
@ -95,7 +90,7 @@ fu_dell_dock_usb4_hub_get_mmio(FuDevice *device, guint16 mbox_reg, guchar *buf,
|
|||||||
REQ_HUB_GET_MMIO, /* request */
|
REQ_HUB_GET_MMIO, /* request */
|
||||||
MBOX_ACCESS, /* value */
|
MBOX_ACCESS, /* value */
|
||||||
mbox_reg, /* index */
|
mbox_reg, /* index */
|
||||||
(guchar *)buf, /* data */
|
(guint8 *)buf, /* data */
|
||||||
4, /* length */
|
4, /* length */
|
||||||
NULL, /* actual length */
|
NULL, /* actual length */
|
||||||
MBOX_TIMEOUT,
|
MBOX_TIMEOUT,
|
||||||
@ -136,7 +131,7 @@ fu_dell_dock_usb4_hub_get_mmio(FuDevice *device, guint16 mbox_reg, guchar *buf,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
fu_dell_dock_usb4_hub_set_mmio(FuDevice *device, guint16 mbox_reg, guchar *buf, GError **error)
|
fu_intel_usb4_device_set_mmio(FuDevice *device, guint16 mbox_reg, guint8 *buf, 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));
|
||||||
|
|
||||||
@ -147,7 +142,7 @@ fu_dell_dock_usb4_hub_set_mmio(FuDevice *device, guint16 mbox_reg, guchar *buf,
|
|||||||
REQ_HUB_SET_MMIO, /* request */
|
REQ_HUB_SET_MMIO, /* request */
|
||||||
MBOX_ACCESS, /* value */
|
MBOX_ACCESS, /* value */
|
||||||
mbox_reg, /* index */
|
mbox_reg, /* index */
|
||||||
(guchar *)buf, /* data */
|
(guint8 *)buf, /* data */
|
||||||
4, /* length */
|
4, /* length */
|
||||||
NULL, /* actual length */
|
NULL, /* actual length */
|
||||||
MBOX_TIMEOUT,
|
MBOX_TIMEOUT,
|
||||||
@ -166,9 +161,9 @@ fu_dell_dock_usb4_hub_set_mmio(FuDevice *device, guint16 mbox_reg, guchar *buf,
|
|||||||
* read operation before reading the mbox data registers.
|
* read operation before reading the mbox data registers.
|
||||||
*/
|
*/
|
||||||
static gboolean
|
static gboolean
|
||||||
fu_dell_dock_usb4_mbox_data_read(FuDevice *device, guchar *data, guint8 length, GError **error)
|
fu_intel_usb4_device_mbox_data_read(FuDevice *device, guint8 *data, guint8 length, GError **error)
|
||||||
{
|
{
|
||||||
guchar *ptr = data;
|
guint8 *ptr = data;
|
||||||
|
|
||||||
if (length > 64 || length % 4) {
|
if (length > 64 || length % 4) {
|
||||||
g_set_error(error,
|
g_set_error(error,
|
||||||
@ -180,7 +175,7 @@ fu_dell_dock_usb4_mbox_data_read(FuDevice *device, guchar *data, guint8 length,
|
|||||||
}
|
}
|
||||||
/* read 4 bytes per iteration */
|
/* read 4 bytes per iteration */
|
||||||
for (gint i = 0; i < length / 4; i++) {
|
for (gint i = 0; i < length / 4; i++) {
|
||||||
if (!fu_dell_dock_usb4_hub_get_mmio(device, i, ptr, error)) {
|
if (!fu_intel_usb4_device_get_mmio(device, i, ptr, error)) {
|
||||||
g_prefix_error(error, "failed to read mbox data registers: ");
|
g_prefix_error(error, "failed to read mbox data registers: ");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@ -195,12 +190,12 @@ fu_dell_dock_usb4_mbox_data_read(FuDevice *device, guchar *data, guint8 length,
|
|||||||
* at the set offset
|
* at the set offset
|
||||||
*/
|
*/
|
||||||
static gboolean
|
static gboolean
|
||||||
fu_dell_dock_usb4_mbox_data_write(FuDevice *device,
|
fu_intel_usb4_device_mbox_data_write(FuDevice *device,
|
||||||
const guchar *data,
|
const guint8 *data,
|
||||||
guint8 length,
|
guint8 length,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
guchar *ptr = (guchar *)data;
|
guint8 *ptr = (guint8 *)data;
|
||||||
|
|
||||||
if (length > 64 || length % 4) {
|
if (length > 64 || length % 4) {
|
||||||
g_set_error(error,
|
g_set_error(error,
|
||||||
@ -213,7 +208,7 @@ fu_dell_dock_usb4_mbox_data_write(FuDevice *device,
|
|||||||
|
|
||||||
/* writes 4 bytes per iteration */
|
/* writes 4 bytes per iteration */
|
||||||
for (gint i = 0; i < length / 4; i++) {
|
for (gint i = 0; i < length / 4; i++) {
|
||||||
if (!fu_dell_dock_usb4_hub_set_mmio(device, i, ptr, error))
|
if (!fu_intel_usb4_device_set_mmio(device, i, ptr, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
ptr += 4;
|
ptr += 4;
|
||||||
}
|
}
|
||||||
@ -221,11 +216,11 @@ fu_dell_dock_usb4_mbox_data_write(FuDevice *device,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
fu_dell_dock_usb4_hub_operation(FuDevice *device, guint16 opcode, guchar *metadata, GError **error)
|
fu_intel_usb4_device_operation(FuDevice *device, guint16 opcode, guint8 *metadata, GError **error)
|
||||||
{
|
{
|
||||||
struct mbox_regx *regx;
|
struct mbox_regx *regx;
|
||||||
gint max_tries = 100;
|
gint max_tries = 100;
|
||||||
guchar buf[4] = {0x0};
|
guint8 buf[4] = {0x0};
|
||||||
|
|
||||||
regx = (struct mbox_regx *)buf;
|
regx = (struct mbox_regx *)buf;
|
||||||
regx->opcode = GUINT16_TO_LE(opcode);
|
regx->opcode = GUINT16_TO_LE(opcode);
|
||||||
@ -247,7 +242,7 @@ fu_dell_dock_usb4_hub_operation(FuDevice *device, guint16 opcode, guchar *metada
|
|||||||
opcode);
|
opcode);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
if (!fu_dell_dock_usb4_hub_set_mmio(device, MBOX_REG_METADATA, metadata, error)) {
|
if (!fu_intel_usb4_device_set_mmio(device, MBOX_REG_METADATA, metadata, error)) {
|
||||||
g_prefix_error(error, "failed to write metadata %s: ", metadata);
|
g_prefix_error(error, "failed to write metadata %s: ", metadata);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@ -262,7 +257,7 @@ fu_dell_dock_usb4_hub_operation(FuDevice *device, guint16 opcode, guchar *metada
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* write the operation and poll completion or error */
|
/* write the operation and poll completion or error */
|
||||||
if (!fu_dell_dock_usb4_hub_set_mmio(device, MBOX_REG, buf, error))
|
if (!fu_intel_usb4_device_set_mmio(device, MBOX_REG, buf, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* leave early as successful USB4 AUTH resets the device immediately */
|
/* leave early as successful USB4 AUTH resets the device immediately */
|
||||||
@ -271,7 +266,7 @@ fu_dell_dock_usb4_hub_operation(FuDevice *device, guint16 opcode, guchar *metada
|
|||||||
|
|
||||||
for (gint i = 0; i <= max_tries; i++) {
|
for (gint i = 0; i <= max_tries; i++) {
|
||||||
g_autoptr(GError) error_local = NULL;
|
g_autoptr(GError) error_local = NULL;
|
||||||
if (fu_dell_dock_usb4_hub_get_mmio(device, MBOX_REG, buf, &error_local))
|
if (fu_intel_usb4_device_get_mmio(device, MBOX_REG, buf, &error_local))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
if (i == max_tries) {
|
if (i == max_tries) {
|
||||||
g_propagate_prefixed_error(error,
|
g_propagate_prefixed_error(error,
|
||||||
@ -283,22 +278,12 @@ fu_dell_dock_usb4_hub_operation(FuDevice *device, guint16 opcode, guchar *metada
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* fu_dell_dock_usb4_hub_nvm_read:
|
|
||||||
* @device: a #FuDevice
|
|
||||||
* @buf: array of bytes to store the read from registers
|
|
||||||
* @length: length of buf array
|
|
||||||
* @nvm_addr: nvm read offset, e.g. `0`
|
|
||||||
* @error: (nullable): optional return location for an error
|
|
||||||
*
|
|
||||||
* Read NVM over USB interface
|
|
||||||
**/
|
|
||||||
static gboolean
|
static gboolean
|
||||||
fu_dell_dock_usb4_hub_nvm_read(FuDevice *device,
|
fu_intel_usb4_device_nvm_read(FuDevice *device,
|
||||||
guint8 *buf,
|
guint8 *buf,
|
||||||
guint32 length,
|
guint32 length,
|
||||||
guint32 nvm_addr,
|
guint32 nvm_addr,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
guint8 tmpbuf[64] = {0x0};
|
guint8 tmpbuf[64] = {0x0};
|
||||||
|
|
||||||
@ -327,12 +312,12 @@ fu_dell_dock_usb4_hub_nvm_read(FuDevice *device,
|
|||||||
metadata[3] = (padded_len / 4) & 0xf;
|
metadata[3] = (padded_len / 4) & 0xf;
|
||||||
|
|
||||||
/* ask hub to read up to 64 bytes from NVM to mbox data regs */
|
/* ask hub to read up to 64 bytes from NVM to mbox data regs */
|
||||||
if (!fu_dell_dock_usb4_hub_operation(device, OP_NVM_READ, metadata, error)) {
|
if (!fu_intel_usb4_device_operation(device, OP_NVM_READ, metadata, error)) {
|
||||||
g_prefix_error(error, "hub NVM read error: ");
|
g_prefix_error(error, "hub NVM read error: ");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
/* read the data from mbox data regs into our buffer */
|
/* read the data from mbox data regs into our buffer */
|
||||||
if (!fu_dell_dock_usb4_mbox_data_read(device, tmpbuf, padded_len, error)) {
|
if (!fu_intel_usb4_device_mbox_data_read(device, tmpbuf, padded_len, error)) {
|
||||||
g_prefix_error(error, "hub firmware mbox data read error: ");
|
g_prefix_error(error, "hub firmware mbox data read error: ");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@ -355,18 +340,16 @@ fu_dell_dock_usb4_hub_nvm_read(FuDevice *device,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
fu_dell_dock_usb4_hub_nvm_write(FuDevice *device,
|
fu_intel_usb4_device_nvm_write(FuDevice *device,
|
||||||
const guint8 *buf,
|
GBytes *blob,
|
||||||
guint32 length,
|
guint32 nvm_addr,
|
||||||
guint32 nvm_addr,
|
FuProgress *progress,
|
||||||
FuProgress *progress,
|
GError **error)
|
||||||
GError **error)
|
|
||||||
{
|
{
|
||||||
guint8 metadata[4];
|
guint8 metadata[4];
|
||||||
guint32 bytes_done = 0;
|
g_autoptr(GPtrArray) chunks = NULL;
|
||||||
guint32 bytes_total = length;
|
|
||||||
|
|
||||||
if (nvm_addr % 4) {
|
if (nvm_addr % 4 != 0) {
|
||||||
g_set_error(error,
|
g_set_error(error,
|
||||||
FWUPD_ERROR,
|
FWUPD_ERROR,
|
||||||
FWUPD_ERROR_INVALID_FILE,
|
FWUPD_ERROR_INVALID_FILE,
|
||||||
@ -374,53 +357,61 @@ fu_dell_dock_usb4_hub_nvm_write(FuDevice *device,
|
|||||||
nvm_addr);
|
nvm_addr);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
if (length < 64 || length % 64) {
|
if (g_bytes_get_size(blob) < 64 || g_bytes_get_size(blob) % 64) {
|
||||||
g_set_error(error,
|
g_set_error(error,
|
||||||
FWUPD_ERROR,
|
FWUPD_ERROR,
|
||||||
FWUPD_ERROR_INVALID_FILE,
|
FWUPD_ERROR_INVALID_FILE,
|
||||||
"Invalid NVM length 0x%x, must be 64 byte aligned: ",
|
"Invalid NVM length 0x%x, must be 64 byte aligned: ",
|
||||||
length);
|
(guint)g_bytes_get_size(blob));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 1. Set initial offset, must be DW aligned */
|
/* set initial offset, must be DW aligned */
|
||||||
fu_memwrite_uint32(metadata, NVM_OFFSET_TO_METADATA(nvm_addr), G_LITTLE_ENDIAN);
|
fu_memwrite_uint32(metadata, NVM_OFFSET_TO_METADATA(nvm_addr), G_LITTLE_ENDIAN);
|
||||||
|
if (!fu_intel_usb4_device_operation(device, OP_NVM_SET_OFFSET, metadata, error)) {
|
||||||
if (!fu_dell_dock_usb4_hub_operation(device, OP_NVM_SET_OFFSET, metadata, error)) {
|
|
||||||
g_prefix_error(error, "hub NVM set offset error: ");
|
g_prefix_error(error, "hub NVM set offset error: ");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 2 Write data in 64 byte blocks */
|
/* write data in 64 byte blocks */
|
||||||
fu_progress_set_percentage_full(progress, bytes_done, bytes_total);
|
chunks = fu_chunk_array_new_from_bytes(blob, 0x0, 0x0, 64);
|
||||||
|
fu_progress_set_id(progress, G_STRLOC);
|
||||||
|
fu_progress_set_steps(progress, chunks->len);
|
||||||
fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_WRITE);
|
fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_WRITE);
|
||||||
while (length > 0) {
|
for (guint i = 0; i < chunks->len; i++) {
|
||||||
|
FuChunk *chk = g_ptr_array_index(chunks, i);
|
||||||
|
|
||||||
/* 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_intel_usb4_device_mbox_data_write(device,
|
||||||
|
fu_chunk_get_data(chk),
|
||||||
|
fu_chunk_get_data_sz(chk),
|
||||||
|
error)) {
|
||||||
g_prefix_error(error, "hub mbox data write error: ");
|
g_prefix_error(error, "hub mbox data write error: ");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
/* ask hub to write 64 bytes from data regs to NVM */
|
/* ask hub to write 64 bytes from data regs to NVM */
|
||||||
if (!fu_dell_dock_usb4_hub_operation(device, OP_NVM_WRITE, NULL, error)) {
|
if (!fu_intel_usb4_device_operation(device, OP_NVM_WRITE, NULL, error)) {
|
||||||
g_prefix_error(error, "hub NVM write operation error: ");
|
g_prefix_error(error, "hub NVM write operation error: ");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
buf += 64;
|
|
||||||
length -= 64;
|
/* done */
|
||||||
fu_progress_set_percentage_full(progress, bytes_done += 64, bytes_total);
|
fu_progress_step_done(progress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* success */
|
||||||
fu_progress_set_status(progress, 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, FuProgress *progress, GError **error)
|
fu_intel_usb4_device_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)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (!fu_dell_dock_usb4_hub_operation(device, OP_NVM_AUTH_WRITE, NULL, error)) {
|
if (!fu_intel_usb4_device_operation(device, OP_NVM_AUTH_WRITE, NULL, error)) {
|
||||||
g_prefix_error(error, "NVM authenticate failed: ");
|
g_prefix_error(error, "NVM authenticate failed: ");
|
||||||
fu_device_set_update_state(device, FWUPD_UPDATE_STATE_FAILED);
|
fu_device_set_update_state(device, FWUPD_UPDATE_STATE_FAILED);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -429,196 +420,141 @@ fu_dell_dock_usb4_activate(FuDevice *device, FuProgress *progress, GError **erro
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static FuFirmware *
|
||||||
fu_dell_dock_usb4_write_fw(FuDevice *device,
|
fu_intel_usb4_device_prepare_firmware(FuDevice *device,
|
||||||
FuFirmware *firmware,
|
GBytes *fw,
|
||||||
FuProgress *progress,
|
FwupdInstallFlags flags,
|
||||||
FwupdInstallFlags flags,
|
GError **error)
|
||||||
GError **error)
|
{
|
||||||
|
FuIntelUsb4Device *self = FU_INTEL_USB4_DEVICE(device);
|
||||||
|
guint16 fw_vendor_id;
|
||||||
|
guint16 fw_product_id;
|
||||||
|
g_autoptr(FuFirmware) firmware = fu_intel_thunderbolt_firmware_new();
|
||||||
|
|
||||||
|
/* get vid:pid:rev */
|
||||||
|
if (!fu_firmware_parse(firmware, fw, flags, error))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* check is compatible */
|
||||||
|
fw_vendor_id = fu_intel_thunderbolt_nvm_get_vendor_id(FU_INTEL_THUNDERBOLT_NVM(firmware));
|
||||||
|
fw_product_id = fu_intel_thunderbolt_nvm_get_model_id(FU_INTEL_THUNDERBOLT_NVM(firmware));
|
||||||
|
if (self->nvm_vendor_id != fw_vendor_id || self->nvm_product_id != fw_product_id) {
|
||||||
|
if ((flags & FWUPD_INSTALL_FLAG_FORCE) == 0) {
|
||||||
|
g_set_error(error,
|
||||||
|
FWUPD_ERROR,
|
||||||
|
FWUPD_ERROR_NOT_SUPPORTED,
|
||||||
|
"firmware 0x%04x:0x%04x does not match device 0x%04x:0x%04x",
|
||||||
|
fw_vendor_id,
|
||||||
|
fw_product_id,
|
||||||
|
self->nvm_vendor_id,
|
||||||
|
self->nvm_product_id);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
g_warning("firmware 0x%04x:0x%04x does not match device 0x%04x:0x%04x",
|
||||||
|
fw_vendor_id,
|
||||||
|
fw_product_id,
|
||||||
|
self->nvm_vendor_id,
|
||||||
|
self->nvm_product_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* success */
|
||||||
|
return g_steal_pointer(&firmware);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
fu_intel_usb4_device_write_firmware(FuDevice *device,
|
||||||
|
FuFirmware *firmware,
|
||||||
|
FuProgress *progress,
|
||||||
|
FwupdInstallFlags flags,
|
||||||
|
GError **error)
|
||||||
{
|
{
|
||||||
const guint8 *fw_buf;
|
|
||||||
gsize fw_blob_size = 0;
|
|
||||||
guchar nvm_buf[NVM_READ_LENGTH] = {0x0};
|
|
||||||
guint32 fw_header_offset = 0;
|
|
||||||
guint8 *tmp_header = NULL;
|
|
||||||
g_autofree gchar *fw_product_id = NULL;
|
|
||||||
g_autofree gchar *fw_vendor_id = NULL;
|
|
||||||
g_autofree gchar *fw_version = NULL;
|
|
||||||
g_autofree gchar *nvm_product_id = NULL;
|
|
||||||
g_autofree gchar *nvm_vendor_id = NULL;
|
|
||||||
g_autoptr(GBytes) fw_image = NULL;
|
g_autoptr(GBytes) fw_image = NULL;
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
/* get default image */
|
/* get payload */
|
||||||
fw_image = fu_firmware_get_bytes(firmware, error);
|
fw_image = fu_firmware_get_image_by_id_bytes(firmware, FU_FIRMWARE_ID_PAYLOAD, error);
|
||||||
if (fw_image == NULL)
|
if (fw_image == NULL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
fw_buf = g_bytes_get_data(fw_image, &fw_blob_size);
|
|
||||||
g_debug("total image size: %" G_GSIZE_FORMAT, fw_blob_size);
|
|
||||||
|
|
||||||
/* get header offset */
|
|
||||||
tmp_header = (guint8 *)&fw_header_offset;
|
|
||||||
if (!fu_memcpy_safe(tmp_header,
|
|
||||||
sizeof(guint32),
|
|
||||||
0x0,
|
|
||||||
fw_buf,
|
|
||||||
fw_blob_size,
|
|
||||||
0x0,
|
|
||||||
sizeof(guint32),
|
|
||||||
error))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
g_debug("image header size: %" G_GUINT32_FORMAT, fw_header_offset);
|
|
||||||
if (fw_header_offset > fw_blob_size) {
|
|
||||||
g_set_error(error,
|
|
||||||
FWUPD_ERROR,
|
|
||||||
FWUPD_ERROR_INVALID_FILE,
|
|
||||||
"image header is too big: %" G_GUINT32_FORMAT,
|
|
||||||
fw_header_offset);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get firmware version, vendor-id, product-id */
|
|
||||||
fw_version = g_strdup_printf("%02x.%02x",
|
|
||||||
fw_buf[fw_header_offset + NVM_VER_OFFSET_MAJOR],
|
|
||||||
fw_buf[fw_header_offset + NVM_VER_OFFSET_MINOR]);
|
|
||||||
fw_vendor_id = g_strdup_printf("%02x%02x",
|
|
||||||
fw_buf[fw_header_offset + NVM_VID_OFFSET_MAJOR],
|
|
||||||
fw_buf[fw_header_offset + NVM_VID_OFFSET_MINOR]);
|
|
||||||
fw_product_id = g_strdup_printf("%02x%02x",
|
|
||||||
fw_buf[fw_header_offset + NVM_PID_OFFSET_MAJOR],
|
|
||||||
fw_buf[fw_header_offset + NVM_PID_OFFSET_MINOR]);
|
|
||||||
|
|
||||||
g_debug("writing Thunderbolt firmware version %s", fw_version);
|
|
||||||
g_debug("writing Thunderbolt product-id %s", fw_product_id);
|
|
||||||
g_debug("writing Thunderbolt vendor-id %s", fw_vendor_id);
|
|
||||||
|
|
||||||
/* compare vendor-id, product-id between firmware blob and NVM */
|
|
||||||
if (!fu_dell_dock_usb4_hub_nvm_read(device, nvm_buf, NVM_READ_LENGTH, 0, error)) {
|
|
||||||
g_prefix_error(error, "NVM READ error: ");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
nvm_vendor_id = g_strdup_printf("%02x%02x",
|
|
||||||
nvm_buf[NVM_VID_OFFSET_MAJOR],
|
|
||||||
nvm_buf[NVM_VID_OFFSET_MINOR]);
|
|
||||||
nvm_product_id = g_strdup_printf("%02x%02x",
|
|
||||||
nvm_buf[NVM_PID_OFFSET_MAJOR],
|
|
||||||
nvm_buf[NVM_PID_OFFSET_MINOR]);
|
|
||||||
|
|
||||||
if (((flags & FWUPD_INSTALL_FLAG_FORCE) == 0) &&
|
|
||||||
(g_strcmp0(nvm_vendor_id, fw_vendor_id) != 0 ||
|
|
||||||
g_strcmp0(nvm_product_id, fw_product_id) != 0)) {
|
|
||||||
g_set_error(error,
|
|
||||||
FWUPD_ERROR,
|
|
||||||
FWUPD_ERROR_NOT_SUPPORTED,
|
|
||||||
"Thunderbolt firmware vendor_id %s, product_id %s"
|
|
||||||
"doesn't match NVM vendor_id %s, product_id %s",
|
|
||||||
fw_vendor_id,
|
|
||||||
fw_product_id,
|
|
||||||
nvm_vendor_id,
|
|
||||||
nvm_product_id);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* firmware install */
|
/* firmware install */
|
||||||
fw_buf += fw_header_offset;
|
if (!fu_intel_usb4_device_nvm_write(device, fw_image, 0, progress, error))
|
||||||
fw_blob_size -= fw_header_offset;
|
|
||||||
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);
|
/* success, but needs activation */
|
||||||
fu_device_set_version(device, fw_version);
|
if (fu_device_has_flag(device, FWUPD_DEVICE_FLAG_SKIPS_RESTART)) {
|
||||||
|
fu_device_add_flag(device, FWUPD_DEVICE_FLAG_NEEDS_ACTIVATION);
|
||||||
|
fu_device_set_version(device, fu_firmware_get_version(firmware));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* activate, wait for replug */
|
||||||
|
if (!fu_intel_usb4_device_operation(device, OP_NVM_AUTH_WRITE, NULL, error)) {
|
||||||
|
g_prefix_error(error, "NVM authenticate failed: ");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
fu_device_add_flag(device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG);
|
||||||
|
|
||||||
|
/* success */
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
fu_dell_dock_usb4_setup(FuDevice *device, GError **error)
|
fu_intel_usb4_device_setup(FuDevice *device, GError **error)
|
||||||
{
|
{
|
||||||
guchar buf[NVM_READ_LENGTH] = {0x0};
|
FuIntelUsb4Device *self = FU_INTEL_USB4_DEVICE(device);
|
||||||
|
guint8 buf[NVM_READ_LENGTH] = {0x0};
|
||||||
g_autofree gchar *name = NULL;
|
g_autofree gchar *name = NULL;
|
||||||
g_autofree gchar *nvm_product_id = NULL;
|
g_autoptr(FuFirmware) fw = fu_intel_thunderbolt_nvm_new();
|
||||||
g_autofree gchar *nvm_vendor_id = NULL;
|
g_autoptr(GBytes) blob = NULL;
|
||||||
g_autofree gchar *nvm_version = NULL;
|
|
||||||
|
|
||||||
if (!fu_dell_dock_usb4_hub_nvm_read(device, buf, NVM_READ_LENGTH, 0, error)) {
|
/* read from device and parse firmware */
|
||||||
g_prefix_error(error, "NVM READ error: ");
|
if (!fu_intel_usb4_device_nvm_read(device, buf, sizeof(buf), 0, error)) {
|
||||||
|
g_prefix_error(error, "NVM read error: ");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
nvm_version =
|
blob = g_bytes_new(buf, sizeof(buf));
|
||||||
g_strdup_printf("%02x.%02x", buf[NVM_VER_OFFSET_MAJOR], buf[NVM_VER_OFFSET_MINOR]),
|
if (!fu_firmware_parse(fw, blob, FWUPD_INSTALL_FLAG_NONE, error)) {
|
||||||
nvm_vendor_id =
|
g_prefix_error(error, "NVM parse error: ");
|
||||||
g_strdup_printf("%02x%02x", buf[NVM_VID_OFFSET_MAJOR], buf[NVM_VID_OFFSET_MINOR]);
|
|
||||||
nvm_product_id =
|
|
||||||
g_strdup_printf("%02x%02x", buf[NVM_PID_OFFSET_MAJOR], buf[NVM_PID_OFFSET_MINOR]);
|
|
||||||
|
|
||||||
/* only add known supported thunderbolt devices */
|
|
||||||
name = g_strdup_printf("TBT-%s%s", nvm_vendor_id, nvm_product_id);
|
|
||||||
if (g_strcmp0(name, DELL_DOCK_USB4_INSTANCE_ID) != 0) {
|
|
||||||
g_set_error_literal(error,
|
|
||||||
FWUPD_ERROR,
|
|
||||||
FWUPD_ERROR_NOT_SUPPORTED,
|
|
||||||
"no supported device found");
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
self->nvm_vendor_id = fu_intel_thunderbolt_nvm_get_vendor_id(FU_INTEL_THUNDERBOLT_NVM(fw));
|
||||||
|
self->nvm_product_id = fu_intel_thunderbolt_nvm_get_model_id(FU_INTEL_THUNDERBOLT_NVM(fw));
|
||||||
|
|
||||||
|
name = g_strdup_printf("TBT-%04x%04x", self->nvm_vendor_id, self->nvm_product_id);
|
||||||
fu_device_add_instance_id(device, name);
|
fu_device_add_instance_id(device, name);
|
||||||
fu_device_set_version_format(device, FWUPD_VERSION_FORMAT_PAIR);
|
fu_device_set_version(device, fu_firmware_get_version(fw));
|
||||||
fu_device_set_version(device, nvm_version);
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static void
|
||||||
fu_dell_dock_usb4_probe(FuDevice *device, GError **error)
|
fu_intel_usb4_device_to_string(FuDevice *device, guint idt, GString *str)
|
||||||
{
|
{
|
||||||
FuDellDockUsb4 *self = FU_DELL_DOCK_USB4(device);
|
FuIntelUsb4Device *self = FU_INTEL_USB4_DEVICE(device);
|
||||||
|
fu_string_append_kx(str, idt, "NvmVendorId", self->nvm_vendor_id);
|
||||||
|
fu_string_append_kx(str, idt, "NvmProductId", self->nvm_product_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fu_intel_usb4_device_init(FuIntelUsb4Device *self)
|
||||||
|
{
|
||||||
self->intf_nr = GR_USB_INTERFACE_NUMBER;
|
self->intf_nr = GR_USB_INTERFACE_NUMBER;
|
||||||
self->blocksz = GR_USB_BLOCK_SIZE;
|
self->blocksz = GR_USB_BLOCK_SIZE;
|
||||||
fu_device_set_logical_id(FU_DEVICE(device), "usb4");
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
fu_dell_dock_usb4_finalize(GObject *object)
|
|
||||||
{
|
|
||||||
G_OBJECT_CLASS(fu_dell_dock_usb4_parent_class)->finalize(object);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
fu_dell_dock_usb4_init(FuDellDockUsb4 *self)
|
|
||||||
{
|
|
||||||
fu_device_add_protocol(FU_DEVICE(self), "com.intel.thunderbolt");
|
fu_device_add_protocol(FU_DEVICE(self), "com.intel.thunderbolt");
|
||||||
fu_device_add_flag(FU_DEVICE(self), FWUPD_DEVICE_FLAG_USABLE_DURING_UPDATE);
|
|
||||||
fu_device_add_flag(FU_DEVICE(self), FWUPD_DEVICE_FLAG_UPDATABLE);
|
fu_device_add_flag(FU_DEVICE(self), FWUPD_DEVICE_FLAG_UPDATABLE);
|
||||||
fu_device_add_flag(FU_DEVICE(self), FWUPD_DEVICE_FLAG_SIGNED_PAYLOAD);
|
fu_device_add_flag(FU_DEVICE(self), FWUPD_DEVICE_FLAG_SIGNED_PAYLOAD);
|
||||||
|
fu_device_set_version_format(FU_DEVICE(self), FWUPD_VERSION_FORMAT_PAIR);
|
||||||
fu_device_add_internal_flag(FU_DEVICE(self), FU_DEVICE_INTERNAL_FLAG_INHERIT_ACTIVATION);
|
fu_device_add_internal_flag(FU_DEVICE(self), FU_DEVICE_INTERNAL_FLAG_INHERIT_ACTIVATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fu_dell_dock_usb4_class_init(FuDellDockUsb4Class *klass)
|
fu_intel_usb4_device_class_init(FuIntelUsb4DeviceClass *klass)
|
||||||
{
|
{
|
||||||
GObjectClass *object_class = G_OBJECT_CLASS(klass);
|
|
||||||
FuDeviceClass *klass_device = FU_DEVICE_CLASS(klass);
|
FuDeviceClass *klass_device = FU_DEVICE_CLASS(klass);
|
||||||
object_class->finalize = fu_dell_dock_usb4_finalize;
|
klass_device->to_string = fu_intel_usb4_device_to_string;
|
||||||
klass_device->probe = fu_dell_dock_usb4_probe;
|
klass_device->setup = fu_intel_usb4_device_setup;
|
||||||
klass_device->setup = fu_dell_dock_usb4_setup;
|
klass_device->prepare_firmware = fu_intel_usb4_device_prepare_firmware;
|
||||||
klass_device->write_firmware = fu_dell_dock_usb4_write_fw;
|
klass_device->write_firmware = fu_intel_usb4_device_write_firmware;
|
||||||
klass_device->activate = fu_dell_dock_usb4_activate;
|
klass_device->activate = fu_intel_usb4_device_activate;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* fu_dell_dock_usb4_new:
|
|
||||||
*
|
|
||||||
* Creates a new USB4 device object.
|
|
||||||
*
|
|
||||||
* Returns: a new #FuDellDockUsb4
|
|
||||||
**/
|
|
||||||
FuDellDockUsb4 *
|
|
||||||
fu_dell_dock_usb4_new(FuUsbDevice *device)
|
|
||||||
{
|
|
||||||
FuDellDockUsb4 *self = g_object_new(FU_TYPE_DELL_DOCK_USB4, NULL);
|
|
||||||
fu_device_incorporate(FU_DEVICE(self), FU_DEVICE(device));
|
|
||||||
return FU_DELL_DOCK_USB4(self);
|
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
|
* Copyright (C) 2022 Richard Hughes <richard@hughsie.com>
|
||||||
* Copyright (C) 2021 Intel Corporation.
|
* Copyright (C) 2021 Intel Corporation.
|
||||||
* Copyright (C) 2021 Dell Inc.
|
* Copyright (C) 2021 Dell Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
@ -20,8 +21,5 @@
|
|||||||
|
|
||||||
#include <fwupdplugin.h>
|
#include <fwupdplugin.h>
|
||||||
|
|
||||||
#define FU_TYPE_DELL_DOCK_USB4 (fu_dell_dock_usb4_get_type())
|
#define FU_TYPE_INTEL_USB4_DEVICE (fu_intel_usb4_device_get_type())
|
||||||
G_DECLARE_FINAL_TYPE(FuDellDockUsb4, fu_dell_dock_usb4, FU, DELL_DOCK_USB4, FuUsbDevice)
|
G_DECLARE_FINAL_TYPE(FuIntelUsb4Device, fu_intel_usb4_device, FU, INTEL_USB4_DEVICE, FuUsbDevice)
|
||||||
|
|
||||||
FuDellDockUsb4 *
|
|
||||||
fu_dell_dock_usb4_new(FuUsbDevice *device);
|
|
22
plugins/intel-usb4/fu-plugin-intel-usb4.c
Normal file
22
plugins/intel-usb4/fu-plugin-intel-usb4.c
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 Richard Hughes <richard@hughsie.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "fu-intel-usb4-device.h"
|
||||||
|
|
||||||
|
static void
|
||||||
|
fu_plugin_intel_usb4_init(FuPlugin *plugin)
|
||||||
|
{
|
||||||
|
fu_plugin_add_device_gtype(plugin, FU_TYPE_INTEL_USB4_DEVICE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
fu_plugin_init_vfuncs(FuPluginVfuncs *vfuncs)
|
||||||
|
{
|
||||||
|
vfuncs->build_hash = FU_BUILD_HASH;
|
||||||
|
vfuncs->init = fu_plugin_intel_usb4_init;
|
||||||
|
}
|
2
plugins/intel-usb4/intel-usb4.quirk
Normal file
2
plugins/intel-usb4/intel-usb4.quirk
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
[USB\VID_8087&PID_0B40]
|
||||||
|
Plugin = intel_usb4
|
29
plugins/intel-usb4/meson.build
Normal file
29
plugins/intel-usb4/meson.build
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
if gusb.found()
|
||||||
|
cargs = ['-DG_LOG_DOMAIN="FuPluginIntelUsb4"']
|
||||||
|
|
||||||
|
plugin_quirks += join_paths(meson.current_source_dir(), 'intel-usb4.quirk')
|
||||||
|
|
||||||
|
shared_module('fu_plugin_intel_usb4',
|
||||||
|
fu_hash,
|
||||||
|
sources: [
|
||||||
|
'fu-intel-usb4-device.c',
|
||||||
|
'fu-plugin-intel-usb4.c',
|
||||||
|
],
|
||||||
|
include_directories: [
|
||||||
|
root_incdir,
|
||||||
|
fwupd_incdir,
|
||||||
|
fwupdplugin_incdir,
|
||||||
|
],
|
||||||
|
install: true,
|
||||||
|
install_dir: plugin_dir,
|
||||||
|
link_with: [
|
||||||
|
fwupd,
|
||||||
|
fwupdplugin,
|
||||||
|
],
|
||||||
|
c_args: cargs,
|
||||||
|
dependencies: [
|
||||||
|
plugin_deps,
|
||||||
|
gudev,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
endif
|
@ -47,6 +47,7 @@ subdir('goodix-moc')
|
|||||||
subdir('gpio')
|
subdir('gpio')
|
||||||
subdir('hailuck')
|
subdir('hailuck')
|
||||||
subdir('intel-spi')
|
subdir('intel-spi')
|
||||||
|
subdir('intel-usb4')
|
||||||
subdir('iommu')
|
subdir('iommu')
|
||||||
subdir('jabra')
|
subdir('jabra')
|
||||||
subdir('lenovo-thinklmi')
|
subdir('lenovo-thinklmi')
|
||||||
|
Loading…
Reference in New Issue
Block a user