Allow specifying a list of subsystems when setting a physical ID

Sometimes we want to fall back to a different subsystem entirely.
This commit is contained in:
Richard Hughes 2020-02-11 10:57:36 +00:00
parent 390fc1ad28
commit 234ee64509
2 changed files with 28 additions and 20 deletions

View File

@ -552,7 +552,7 @@ fu_udev_device_get_revision (FuUdevDevice *self)
}
#ifdef HAVE_GUDEV
static GString *
static gchar *
fu_udev_device_get_parent_subsystems (FuUdevDevice *self)
{
FuUdevDevicePrivate *priv = GET_PRIVATE (self);
@ -574,14 +574,14 @@ fu_udev_device_get_parent_subsystems (FuUdevDevice *self)
}
if (str->len > 0)
g_string_truncate (str, str->len - 1);
return str;
return g_string_free (str, FALSE);
}
#endif
/**
* fu_udev_device_set_physical_id:
* @self: A #FuUdevDevice
* @subsystem: A subsystem string, e.g. `usb`
* @subsystems: A subsystem string, e.g. `pci,usb`
* @error: A #GError, or %NULL
*
* Sets the physical ID from the device subsystem. Plugins should choose the
@ -593,38 +593,46 @@ fu_udev_device_get_parent_subsystems (FuUdevDevice *self)
* Since: 1.1.2
**/
gboolean
fu_udev_device_set_physical_id (FuUdevDevice *self, const gchar *subsystem, GError **error)
fu_udev_device_set_physical_id (FuUdevDevice *self, const gchar *subsystems, GError **error)
{
#ifdef HAVE_GUDEV
FuUdevDevicePrivate *priv = GET_PRIVATE (self);
const gchar *subsystem = NULL;
const gchar *tmp;
g_autofree gchar *physical_id = NULL;
g_auto(GStrv) split = NULL;
g_autoptr(GUdevDevice) udev_device = NULL;
g_return_val_if_fail (FU_IS_UDEV_DEVICE (self), FALSE);
g_return_val_if_fail (subsystem != NULL, FALSE);
g_return_val_if_fail (subsystems != NULL, FALSE);
/* nothing to do */
if (priv->udev_device == NULL)
return TRUE;
/* get the correct device */
if (g_strcmp0 (priv->subsystem, subsystem) == 0) {
udev_device = g_object_ref (priv->udev_device);
} else {
/* look for each subsystem in turn */
split = g_strsplit (subsystems, ",", -1);
for (guint i = 0; split[i] != NULL; i++) {
subsystem = split[i];
if (g_strcmp0 (priv->subsystem, subsystem) == 0) {
udev_device = g_object_ref (priv->udev_device);
break;
}
udev_device = g_udev_device_get_parent_with_subsystem (priv->udev_device,
subsystem, NULL);
if (udev_device == NULL) {
g_autoptr(GString) str = NULL;
str = fu_udev_device_get_parent_subsystems (self);
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_NOT_FOUND,
"failed to find device with subsystem %s, only got %s",
subsystem, str->str);
return FALSE;
}
if (udev_device != NULL)
break;
}
if (udev_device == NULL) {
g_autofree gchar *str = fu_udev_device_get_parent_subsystems (self);
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_NOT_FOUND,
"failed to find device with subsystems %s, only got %s",
subsystems, str);
return FALSE;
}
if (g_strcmp0 (subsystem, "pci") == 0) {
tmp = g_udev_device_get_property (udev_device, "PCI_SLOT_NAME");
if (tmp == NULL) {

View File

@ -61,7 +61,7 @@ guint8 fu_udev_device_get_revision (FuUdevDevice *self);
guint fu_udev_device_get_slot_depth (FuUdevDevice *self,
const gchar *subsystem);
gboolean fu_udev_device_set_physical_id (FuUdevDevice *self,
const gchar *subsystem,
const gchar *subsystems,
GError **error);
void fu_udev_device_set_readonly (FuUdevDevice *self,
gboolean readonly)