fwupd/plugins/udev/fu-plugin-udev.c
Richard Hughes c125ec02ed Clarify what the platform ID actually is by renaming it
It wasn't hugely clear what the platform ID was actually meant to represent. In
some cases it was being used like a physical ID, in others it was a logical ID,
and in others it was both. In some cases it was even used as a sysfs path.

Clear up all the confusion by splitting the platform ID into two parts, an
optional *physical* ID to represent the electrical connection, and an optional
*logical* ID to disambiguate composite devices with the same physical ID.

Also create an explicit sysfs_path getter for FuUdevDevice to make this clear.

This allows WAIT_FOR_REPLUG to always work, rather than depending on the order
that the GUIDs were added, and that the kernel would always return the same
sysfs path (which it doesn't have to do, especially for hidraw devices).
2018-09-06 16:22:46 +01:00

112 lines
3.2 KiB
C

/*
* Copyright (C) 2015-2016 Richard Hughes <richard@hughsie.com>
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#include "config.h"
#include "fu-plugin.h"
#include "fu-rom.h"
#include "fu-plugin-vfuncs.h"
void
fu_plugin_init (FuPlugin *plugin)
{
fu_plugin_add_udev_subsystem (plugin, "pci");
}
gboolean
fu_plugin_verify (FuPlugin *plugin,
FuDevice *device,
FuPluginVerifyFlags flags,
GError **error)
{
GPtrArray *checksums;
const gchar *rom_fn;
g_autoptr(GFile) file = NULL;
g_autoptr(FuRom) rom = NULL;
/* open the file */
rom_fn = fu_device_get_metadata (device, "RomFilename");
if (rom_fn == NULL) {
g_set_error_literal (error,
FWUPD_ERROR,
FWUPD_ERROR_INTERNAL,
"Unable to read firmware from device");
return FALSE;
}
file = g_file_new_for_path (rom_fn);
rom = fu_rom_new ();
if (!fu_rom_load_file (rom, file, FU_ROM_LOAD_FLAG_BLANK_PPID, NULL, error))
return FALSE;
/* update version */
if (g_strcmp0 (fu_device_get_version (device),
fu_rom_get_version (rom)) != 0) {
g_debug ("changing version of %s from %s to %s",
fu_device_get_id (device),
fu_device_get_version (device),
fu_rom_get_version (rom));
fu_device_set_version (device, fu_rom_get_version (rom));
}
/* Also add the GUID from the firmware as the firmware may be more
* generic, which also allows us to match the GUID when doing 'verify'
* on a device with a different PID to the firmware */
fu_device_add_guid (device, fu_rom_get_guid (rom));
/* update checksums */
checksums = fu_rom_get_checksums (rom);
for (guint i = 0; i < checksums->len; i++) {
const gchar *checksum = g_ptr_array_index (checksums, i);
fu_device_add_checksum (device, checksum);
}
return TRUE;
}
gboolean
fu_plugin_udev_device_added (FuPlugin *plugin, FuUdevDevice *device, GError **error)
{
GUdevDevice *udev_device = fu_udev_device_get_dev (FU_UDEV_DEVICE (device));
const gchar *guid = NULL;
const gchar *pci_slot_name;
g_autofree gchar *physical_id = NULL;
g_autofree gchar *rom_fn = NULL;
g_autoptr(AsProfile) profile = as_profile_new ();
g_autoptr(AsProfileTask) ptask = NULL;
/* interesting device? */
if (g_strcmp0 (fu_udev_device_get_subsystem (device), "pci") != 0)
return TRUE;
guid = g_udev_device_get_property (udev_device, "FWUPD_GUID");
if (guid == NULL)
return TRUE;
/* get data */
ptask = as_profile_start (profile, "FuPluginUdev:client-add{%s}", guid);
g_assert (ptask != NULL);
/* get the physical ID */
pci_slot_name = g_udev_device_get_property (udev_device, "PCI_SLOT_NAME");
if (pci_slot_name == NULL) {
g_prefix_error (error, "failed to find PCI_SLOT_NAME: ");
return FALSE;
}
physical_id = g_strdup_printf ("PCI_SLOT_NAME=%s", pci_slot_name);
fu_device_set_physical_id (FU_DEVICE (device), physical_id);
/* did we get enough data */
fu_device_add_flag (device, FWUPD_DEVICE_FLAG_INTERNAL);
fu_device_add_icon (device, "audio-card");
/* get the FW version from the rom when unlocked */
rom_fn = g_build_filename (fu_udev_device_get_sysfs_path (device), "rom", NULL);
if (g_file_test (rom_fn, G_FILE_TEST_EXISTS))
fu_device_set_metadata (FU_DEVICE (device), "RomFilename", rom_fn);
/* insert to hash */
fu_plugin_device_add_delay (plugin, FU_DEVICE (device));
return TRUE;
}