mirror of
https://git.proxmox.com/git/fwupd
synced 2025-06-03 13:41:12 +00:00

Now incorporate is fixed to copy across the properties we need in the superclass, we don't need to do the subclass ->probe(). Note, we still need to do the subclassed ->probe() when using FU_UDEV_DEVICE_FLAG_VENDOR_FROM_PARENT or when looking at properties on the parent device. This also removes the spurious 'already set GType to FuVliUsbhubDevice, ignoring FuVliUsbhubDevice' messages when running the daemon.
157 lines
4.5 KiB
C
157 lines
4.5 KiB
C
/*
|
|
* Copyright (C) 2021 Richard Hughes <richard@hughsie.com>
|
|
* Copyright (C) 2017 Christian J. Kellner <christian@kellner.me>
|
|
* Copyright (C) 2020 Mario Limonciello <mario.limonciello@dell.com>
|
|
*
|
|
* SPDX-License-Identifier: LGPL-2.1+
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <fwupdplugin.h>
|
|
|
|
#include "fu-thunderbolt-common.h"
|
|
#include "fu-thunderbolt-retimer.h"
|
|
|
|
struct _FuThunderboltRetimer {
|
|
FuThunderboltDevice parent_instance;
|
|
};
|
|
|
|
G_DEFINE_TYPE(FuThunderboltRetimer, fu_thunderbolt_retimer, FU_TYPE_THUNDERBOLT_DEVICE)
|
|
|
|
static FuUdevDevice *
|
|
fu_thunderbolt_retimer_get_udev_grandparent(FuDevice *device, GError **error)
|
|
{
|
|
g_autoptr(GUdevDevice) udev_parent1 = NULL;
|
|
g_autoptr(GUdevDevice) udev_parent2 = NULL;
|
|
GUdevDevice *udev_device = NULL;
|
|
FuThunderboltRetimer *self = FU_THUNDERBOLT_RETIMER(device);
|
|
|
|
udev_device = fu_udev_device_get_dev(FU_UDEV_DEVICE(device));
|
|
if (udev_device == NULL) {
|
|
g_set_error_literal(error,
|
|
FWUPD_ERROR,
|
|
FWUPD_ERROR_INTERNAL,
|
|
"failed to get udev device for retimer");
|
|
return NULL;
|
|
}
|
|
udev_parent1 = g_udev_device_get_parent(udev_device);
|
|
if (udev_parent1 == NULL) {
|
|
g_set_error_literal(error,
|
|
FWUPD_ERROR,
|
|
FWUPD_ERROR_INTERNAL,
|
|
"failed to get parent device for retimer");
|
|
return NULL;
|
|
}
|
|
udev_parent2 = g_udev_device_get_parent(udev_parent1);
|
|
if (udev_parent2 == NULL) {
|
|
g_set_error_literal(error,
|
|
FWUPD_ERROR,
|
|
FWUPD_ERROR_INTERNAL,
|
|
"failed to get host router device for retimer");
|
|
return NULL;
|
|
}
|
|
return fu_udev_device_new(fu_device_get_context(FU_DEVICE(self)),
|
|
g_steal_pointer(&udev_parent2));
|
|
}
|
|
|
|
gboolean
|
|
fu_thunderbolt_retimer_set_parent_port_offline(FuDevice *device, GError **error)
|
|
{
|
|
g_autoptr(FuUdevDevice) parent = fu_thunderbolt_retimer_get_udev_grandparent(device, error);
|
|
if (parent == NULL)
|
|
return FALSE;
|
|
return fu_thunderbolt_udev_set_port_offline(parent, error);
|
|
}
|
|
|
|
gboolean
|
|
fu_thunderbolt_retimer_set_parent_port_online(FuDevice *device, GError **error)
|
|
{
|
|
g_autoptr(FuUdevDevice) parent = fu_thunderbolt_retimer_get_udev_grandparent(device, error);
|
|
if (parent == NULL)
|
|
return FALSE;
|
|
return fu_thunderbolt_udev_set_port_online(parent, error);
|
|
}
|
|
|
|
static gboolean
|
|
fu_thunderbolt_retimer_probe(FuDevice *device, GError **error)
|
|
{
|
|
const gchar *devpath = fu_udev_device_get_sysfs_path(FU_UDEV_DEVICE(device));
|
|
g_autofree gchar *physical_id = g_path_get_basename(devpath);
|
|
|
|
/* device */
|
|
if (physical_id != NULL)
|
|
fu_device_set_physical_id(device, physical_id);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
fu_thunderbolt_retimer_setup(FuDevice *device, GError **error)
|
|
{
|
|
FuThunderboltRetimer *self = FU_THUNDERBOLT_RETIMER(device);
|
|
guint16 did;
|
|
guint16 vid;
|
|
g_autofree gchar *instance = NULL;
|
|
|
|
/* get version */
|
|
if (!fu_thunderbolt_device_get_version(FU_THUNDERBOLT_DEVICE(self), error))
|
|
return FALSE;
|
|
|
|
/* as defined in PCIe 4.0 spec */
|
|
vid = fu_udev_device_get_vendor(FU_UDEV_DEVICE(self));
|
|
if (vid == 0x0) {
|
|
g_set_error_literal(error,
|
|
FWUPD_ERROR,
|
|
FWUPD_ERROR_NOT_SUPPORTED,
|
|
"missing vendor id");
|
|
return FALSE;
|
|
}
|
|
did = fu_udev_device_get_model(FU_UDEV_DEVICE(self));
|
|
if (did == 0x0) {
|
|
g_set_error_literal(error,
|
|
FWUPD_ERROR,
|
|
FWUPD_ERROR_NOT_SUPPORTED,
|
|
"missing device id");
|
|
return FALSE;
|
|
}
|
|
|
|
instance = g_strdup_printf("TBT-%04x%04x-retimer%s",
|
|
(guint)vid,
|
|
(guint)did,
|
|
fu_device_get_physical_id(device));
|
|
fu_device_add_instance_id(device, instance);
|
|
|
|
/* hardcoded for now:
|
|
* 1. unsure if ID_VENDOR_FROM_DATABASE works in this instance
|
|
* 2. we don't recognize anyone else yet
|
|
*/
|
|
if (fu_device_get_vendor(device) == NULL)
|
|
fu_device_set_vendor(device, "Intel");
|
|
|
|
/* success */
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
fu_thunderbolt_retimer_init(FuThunderboltRetimer *self)
|
|
{
|
|
fu_device_set_name(FU_DEVICE(self), "USB4 Retimer");
|
|
fu_device_set_summary(
|
|
FU_DEVICE(self),
|
|
"A physical layer protocol-aware, software-transparent extension device "
|
|
"that forms two separate electrical link segments");
|
|
fu_device_add_flag(FU_DEVICE(self), FWUPD_DEVICE_FLAG_DUAL_IMAGE);
|
|
fu_device_add_flag(FU_DEVICE(self), FWUPD_DEVICE_FLAG_INTERNAL);
|
|
fu_device_add_flag(FU_DEVICE(self), FWUPD_DEVICE_FLAG_UPDATABLE);
|
|
fu_device_add_internal_flag(FU_DEVICE(self), FU_DEVICE_INTERNAL_FLAG_NO_AUTO_REMOVE);
|
|
}
|
|
|
|
static void
|
|
fu_thunderbolt_retimer_class_init(FuThunderboltRetimerClass *klass)
|
|
{
|
|
FuDeviceClass *klass_device = FU_DEVICE_CLASS(klass);
|
|
klass_device->setup = fu_thunderbolt_retimer_setup;
|
|
klass_device->probe = fu_thunderbolt_retimer_probe;
|
|
}
|