mirror of
https://git.proxmox.com/git/fwupd
synced 2025-08-12 01:47:37 +00:00
Add FuUdevDevice as a derivable helper object
There are currently three plugins that use GUdev rather than libusb, and there are several more in the works. Add a helper object so we can make the plugins smaller and simpler, much like we already do with FuUsbDevice.
This commit is contained in:
parent
bb764e99a0
commit
0216d83b71
381
src/fu-udev-device.c
Normal file
381
src/fu-udev-device.c
Normal file
@ -0,0 +1,381 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017-2018 Richard Hughes <richard@hughsie.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <appstream-glib.h>
|
||||||
|
|
||||||
|
#include "fu-udev-device.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SECTION:fu-udev-device
|
||||||
|
* @short_description: a udev device
|
||||||
|
*
|
||||||
|
* An object that represents a udev device.
|
||||||
|
*
|
||||||
|
* See also: #FuDevice
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GUdevDevice *udev_device;
|
||||||
|
guint16 vendor;
|
||||||
|
guint16 model;
|
||||||
|
guint8 revision;
|
||||||
|
} FuUdevDevicePrivate;
|
||||||
|
|
||||||
|
G_DEFINE_TYPE_WITH_PRIVATE (FuUdevDevice, fu_udev_device, FU_TYPE_DEVICE)
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PROP_0,
|
||||||
|
PROP_UDEV_DEVICE,
|
||||||
|
PROP_LAST
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
SIGNAL_CHANGED,
|
||||||
|
SIGNAL_LAST
|
||||||
|
};
|
||||||
|
|
||||||
|
static guint signals[SIGNAL_LAST] = { 0 };
|
||||||
|
|
||||||
|
#define GET_PRIVATE(o) (fu_udev_device_get_instance_private (o))
|
||||||
|
|
||||||
|
static void
|
||||||
|
fu_udev_device_apply_quirks (FuUdevDevice *self)
|
||||||
|
{
|
||||||
|
FuQuirks *quirks = fu_device_get_quirks (FU_DEVICE (self));
|
||||||
|
GUdevDevice *udev_device = fu_udev_device_get_dev (self);
|
||||||
|
const gchar *tmp;
|
||||||
|
|
||||||
|
/* not set */
|
||||||
|
if (quirks == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* flags */
|
||||||
|
tmp = fu_quirks_lookup_by_udev_device (quirks, udev_device, FU_QUIRKS_FLAGS);
|
||||||
|
if (tmp != NULL)
|
||||||
|
fu_device_set_custom_flags (FU_DEVICE (self), tmp);
|
||||||
|
|
||||||
|
/* name */
|
||||||
|
tmp = fu_quirks_lookup_by_udev_device (quirks, udev_device, FU_QUIRKS_NAME);
|
||||||
|
if (tmp != NULL)
|
||||||
|
fu_device_set_name (FU_DEVICE (self), tmp);
|
||||||
|
|
||||||
|
/* summary */
|
||||||
|
tmp = fu_quirks_lookup_by_udev_device (quirks, udev_device, FU_QUIRKS_SUMMARY);
|
||||||
|
if (tmp != NULL)
|
||||||
|
fu_device_set_summary (FU_DEVICE (self), tmp);
|
||||||
|
|
||||||
|
/* vendor */
|
||||||
|
tmp = fu_quirks_lookup_by_udev_device (quirks, udev_device, FU_QUIRKS_VENDOR);
|
||||||
|
if (tmp != NULL)
|
||||||
|
fu_device_set_vendor (FU_DEVICE (self), tmp);
|
||||||
|
|
||||||
|
/* version */
|
||||||
|
tmp = fu_quirks_lookup_by_udev_device (quirks, udev_device, FU_QUIRKS_VERSION);
|
||||||
|
if (tmp != NULL)
|
||||||
|
fu_device_set_version (FU_DEVICE (self), tmp);
|
||||||
|
|
||||||
|
/* icon */
|
||||||
|
tmp = fu_quirks_lookup_by_udev_device (quirks, udev_device, FU_QUIRKS_ICON);
|
||||||
|
if (tmp != NULL)
|
||||||
|
fu_device_add_icon (FU_DEVICE (self), tmp);
|
||||||
|
|
||||||
|
/* GUID */
|
||||||
|
tmp = fu_quirks_lookup_by_udev_device (quirks, udev_device, FU_QUIRKS_GUID);
|
||||||
|
if (tmp != NULL)
|
||||||
|
fu_device_add_guid (FU_DEVICE (self), tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fu_udev_device_notify_quirks_cb (FuUdevDevice *self, GParamSpec *pspec, gpointer user_data)
|
||||||
|
{
|
||||||
|
fu_udev_device_apply_quirks (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fu_udev_device_emit_changed:
|
||||||
|
* @self: A #FuUdevDevice
|
||||||
|
*
|
||||||
|
* Emits the ::changed signal for the object.
|
||||||
|
*
|
||||||
|
* Since: 1.1.2
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
fu_udev_device_emit_changed (FuUdevDevice *self)
|
||||||
|
{
|
||||||
|
g_return_if_fail (FU_IS_UDEV_DEVICE (self));
|
||||||
|
g_debug ("FuUdevDevice emit changed");
|
||||||
|
g_signal_emit (self, signals[SIGNAL_CHANGED], 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static guint64
|
||||||
|
fu_udev_device_get_sysfs_attr_as_uint64 (FuUdevDevice *self, const gchar *name)
|
||||||
|
{
|
||||||
|
FuUdevDevicePrivate *priv = GET_PRIVATE (self);
|
||||||
|
const gchar *str;
|
||||||
|
guint base = 10;
|
||||||
|
|
||||||
|
str = g_udev_device_get_sysfs_attr (priv->udev_device, name);
|
||||||
|
if (str == NULL)
|
||||||
|
return 0;
|
||||||
|
if (g_str_has_prefix (str, "0x")) {
|
||||||
|
str += 2;
|
||||||
|
base = 16;
|
||||||
|
}
|
||||||
|
return (guint16) g_ascii_strtoull (str, NULL, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fu_udev_device_set_dev (FuUdevDevice *self, GUdevDevice *udev_device)
|
||||||
|
{
|
||||||
|
FuUdevDevicePrivate *priv = GET_PRIVATE (self);
|
||||||
|
const gchar *tmp;
|
||||||
|
g_autofree gchar *devid1 = NULL;
|
||||||
|
g_autofree gchar *devid2 = NULL;
|
||||||
|
g_autofree gchar *subsystem = NULL;
|
||||||
|
|
||||||
|
g_return_if_fail (FU_IS_UDEV_DEVICE (self));
|
||||||
|
|
||||||
|
/* set new device */
|
||||||
|
g_set_object (&priv->udev_device, udev_device);
|
||||||
|
if (priv->udev_device == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* set ven:dev:rev */
|
||||||
|
priv->vendor = fu_udev_device_get_sysfs_attr_as_uint64 (self, "vendor");
|
||||||
|
priv->model = fu_udev_device_get_sysfs_attr_as_uint64 (self, "device");
|
||||||
|
priv->revision = fu_udev_device_get_sysfs_attr_as_uint64 (self, "revision");
|
||||||
|
|
||||||
|
/* add both device IDs */
|
||||||
|
subsystem = g_ascii_strup (fu_udev_device_get_subsystem (self), -1);
|
||||||
|
devid1 = g_strdup_printf ("%s\\VEN_%04X&DEV_%04X",
|
||||||
|
subsystem, priv->vendor, priv->model);
|
||||||
|
fu_device_add_guid (FU_DEVICE (self), devid1);
|
||||||
|
devid2 = g_strdup_printf ("%s\\VEN_%04X&DEV_%04X&REV_%02X",
|
||||||
|
subsystem, priv->vendor, priv->model, priv->revision);
|
||||||
|
fu_device_add_guid (FU_DEVICE (self), devid2);
|
||||||
|
|
||||||
|
/* set the version if the revision has been set */
|
||||||
|
if (priv->revision != 0x00) {
|
||||||
|
g_autofree gchar *version = g_strdup_printf ("%02x", priv->revision);
|
||||||
|
fu_device_set_version (FU_DEVICE (self), version);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set model */
|
||||||
|
tmp = g_udev_device_get_property (udev_device, "FWUPD_MODEL");
|
||||||
|
if (tmp == NULL)
|
||||||
|
tmp = g_udev_device_get_property (udev_device, "ID_MODEL_FROM_DATABASE");
|
||||||
|
if (tmp != NULL)
|
||||||
|
fu_device_set_name (FU_DEVICE (self), tmp);
|
||||||
|
|
||||||
|
/* set vendor */
|
||||||
|
tmp = g_udev_device_get_property (udev_device, "FWUPD_VENDOR");
|
||||||
|
if (tmp == NULL)
|
||||||
|
tmp = g_udev_device_get_property (udev_device, "ID_VENDOR_FROM_DATABASE");
|
||||||
|
if (tmp != NULL)
|
||||||
|
fu_device_set_vendor (FU_DEVICE (self), tmp);
|
||||||
|
|
||||||
|
/* set vendor ID */
|
||||||
|
tmp = g_udev_device_get_subsystem (udev_device);
|
||||||
|
if (tmp != NULL) {
|
||||||
|
g_autofree gchar *subsys = g_ascii_strup (tmp, -1);
|
||||||
|
g_autofree gchar *vendor_id = NULL;
|
||||||
|
vendor_id = g_strdup_printf ("%s:0x%04X", subsys, (guint) priv->vendor);
|
||||||
|
fu_device_set_vendor_id (FU_DEVICE (self), vendor_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set udev platform ID automatically */
|
||||||
|
fu_device_set_platform_id (FU_DEVICE (self),
|
||||||
|
g_udev_device_get_sysfs_path (udev_device));
|
||||||
|
|
||||||
|
/* set the quirks again */
|
||||||
|
fu_udev_device_apply_quirks (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fu_udev_device_get_dev:
|
||||||
|
* @self: A #FuUdevDevice
|
||||||
|
*
|
||||||
|
* Gets the #GUdevDevice.
|
||||||
|
*
|
||||||
|
* Returns: (transfer none): a #GUdevDevice, or %NULL
|
||||||
|
*
|
||||||
|
* Since: 1.1.2
|
||||||
|
**/
|
||||||
|
GUdevDevice *
|
||||||
|
fu_udev_device_get_dev (FuUdevDevice *self)
|
||||||
|
{
|
||||||
|
FuUdevDevicePrivate *priv = GET_PRIVATE (self);
|
||||||
|
g_return_val_if_fail (FU_IS_UDEV_DEVICE (self), NULL);
|
||||||
|
return priv->udev_device;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fu_udev_device_get_subsystem:
|
||||||
|
* @udev_device: A #GUdevDevice
|
||||||
|
*
|
||||||
|
* Gets the device subsystem, e.g. "pci".
|
||||||
|
*
|
||||||
|
* Returns: a subsystem, or NULL if unset or invalid
|
||||||
|
*
|
||||||
|
* Since: 1.1.2
|
||||||
|
**/
|
||||||
|
const gchar *
|
||||||
|
fu_udev_device_get_subsystem (FuUdevDevice *self)
|
||||||
|
{
|
||||||
|
FuUdevDevicePrivate *priv = GET_PRIVATE (self);
|
||||||
|
g_return_val_if_fail (FU_IS_UDEV_DEVICE (self), NULL);
|
||||||
|
return g_udev_device_get_subsystem (priv->udev_device);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fu_udev_device_get_vendor:
|
||||||
|
* @udev_device: A #GUdevDevice
|
||||||
|
*
|
||||||
|
* Gets the device vendor code.
|
||||||
|
*
|
||||||
|
* Returns: a vendor code, or 0 if unset or invalid
|
||||||
|
*
|
||||||
|
* Since: 1.1.2
|
||||||
|
**/
|
||||||
|
guint16
|
||||||
|
fu_udev_device_get_vendor (FuUdevDevice *self)
|
||||||
|
{
|
||||||
|
FuUdevDevicePrivate *priv = GET_PRIVATE (self);
|
||||||
|
g_return_val_if_fail (FU_IS_UDEV_DEVICE (self), 0x0000);
|
||||||
|
return priv->vendor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fu_udev_device_get_model:
|
||||||
|
* @udev_device: A #GUdevDevice
|
||||||
|
*
|
||||||
|
* Gets the device device code.
|
||||||
|
*
|
||||||
|
* Returns: a vendor code, or 0 if unset or invalid
|
||||||
|
*
|
||||||
|
* Since: 1.1.2
|
||||||
|
**/
|
||||||
|
guint16
|
||||||
|
fu_udev_device_get_model (FuUdevDevice *self)
|
||||||
|
{
|
||||||
|
FuUdevDevicePrivate *priv = GET_PRIVATE (self);
|
||||||
|
g_return_val_if_fail (FU_IS_UDEV_DEVICE (self), 0x0000);
|
||||||
|
return priv->model;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fu_udev_device_get_revision:
|
||||||
|
* @udev_device: A #GUdevDevice
|
||||||
|
*
|
||||||
|
* Gets the device revision.
|
||||||
|
*
|
||||||
|
* Returns: a vendor code, or 0 if unset or invalid
|
||||||
|
*
|
||||||
|
* Since: 1.1.2
|
||||||
|
**/
|
||||||
|
guint8
|
||||||
|
fu_udev_device_get_revision (FuUdevDevice *self)
|
||||||
|
{
|
||||||
|
FuUdevDevicePrivate *priv = GET_PRIVATE (self);
|
||||||
|
g_return_val_if_fail (FU_IS_UDEV_DEVICE (self), 0x00);
|
||||||
|
return priv->revision;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fu_udev_device_get_property (GObject *object, guint prop_id,
|
||||||
|
GValue *value, GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
FuUdevDevice *self = FU_UDEV_DEVICE (object);
|
||||||
|
FuUdevDevicePrivate *priv = GET_PRIVATE (self);
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_UDEV_DEVICE:
|
||||||
|
g_value_set_object (value, priv->udev_device);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fu_udev_device_set_property (GObject *object, guint prop_id,
|
||||||
|
const GValue *value, GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
FuUdevDevice *self = FU_UDEV_DEVICE (object);
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_UDEV_DEVICE:
|
||||||
|
fu_udev_device_set_dev (self, g_value_get_object (value));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fu_udev_device_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
FuUdevDevice *self = FU_UDEV_DEVICE (object);
|
||||||
|
FuUdevDevicePrivate *priv = GET_PRIVATE (self);
|
||||||
|
|
||||||
|
if (priv->udev_device != NULL)
|
||||||
|
g_object_unref (priv->udev_device);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (fu_udev_device_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fu_udev_device_init (FuUdevDevice *self)
|
||||||
|
{
|
||||||
|
g_signal_connect (self, "notify::quirks",
|
||||||
|
G_CALLBACK (fu_udev_device_notify_quirks_cb), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fu_udev_device_class_init (FuUdevDeviceClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
GParamSpec *pspec;
|
||||||
|
|
||||||
|
object_class->finalize = fu_udev_device_finalize;
|
||||||
|
object_class->get_property = fu_udev_device_get_property;
|
||||||
|
object_class->set_property = fu_udev_device_set_property;
|
||||||
|
|
||||||
|
signals[SIGNAL_CHANGED] =
|
||||||
|
g_signal_new ("changed",
|
||||||
|
G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
|
||||||
|
0, NULL, NULL, g_cclosure_marshal_VOID__VOID,
|
||||||
|
G_TYPE_NONE, 0);
|
||||||
|
|
||||||
|
pspec = g_param_spec_object ("udev-device", NULL, NULL,
|
||||||
|
G_UDEV_TYPE_DEVICE,
|
||||||
|
G_PARAM_READWRITE |
|
||||||
|
G_PARAM_CONSTRUCT |
|
||||||
|
G_PARAM_STATIC_NAME);
|
||||||
|
g_object_class_install_property (object_class, PROP_UDEV_DEVICE, pspec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fu_udev_device_new:
|
||||||
|
* @udev_device: A #GUdevDevice
|
||||||
|
*
|
||||||
|
* Creates a new #FuUdevDevice.
|
||||||
|
*
|
||||||
|
* Returns: (transfer full): a #FuUdevDevice
|
||||||
|
*
|
||||||
|
* Since: 1.1.2
|
||||||
|
**/
|
||||||
|
FuDevice *
|
||||||
|
fu_udev_device_new (GUdevDevice *udev_device)
|
||||||
|
{
|
||||||
|
FuUdevDevice *self = g_object_new (FU_TYPE_UDEV_DEVICE,
|
||||||
|
"udev-device", udev_device,
|
||||||
|
NULL);
|
||||||
|
return FU_DEVICE (self);
|
||||||
|
}
|
36
src/fu-udev-device.h
Normal file
36
src/fu-udev-device.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017-2018 Richard Hughes <richard@hughsie.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __FU_UDEV_DEVICE_H
|
||||||
|
#define __FU_UDEV_DEVICE_H
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <gudev/gudev.h>
|
||||||
|
|
||||||
|
#include "fu-plugin.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define FU_TYPE_UDEV_DEVICE (fu_udev_device_get_type ())
|
||||||
|
G_DECLARE_DERIVABLE_TYPE (FuUdevDevice, fu_udev_device, FU, UDEV_DEVICE, FuDevice)
|
||||||
|
|
||||||
|
struct _FuUdevDeviceClass
|
||||||
|
{
|
||||||
|
FuDeviceClass parent_class;
|
||||||
|
gpointer __reserved[31];
|
||||||
|
};
|
||||||
|
|
||||||
|
FuDevice *fu_udev_device_new (GUdevDevice *udev_device);
|
||||||
|
void fu_udev_device_emit_changed (FuUdevDevice *self);
|
||||||
|
GUdevDevice *fu_udev_device_get_dev (FuUdevDevice *self);
|
||||||
|
const gchar *fu_udev_device_get_subsystem (FuUdevDevice *self);
|
||||||
|
guint16 fu_udev_device_get_vendor (FuUdevDevice *self);
|
||||||
|
guint16 fu_udev_device_get_model (FuUdevDevice *self);
|
||||||
|
guint8 fu_udev_device_get_revision (FuUdevDevice *self);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __FU_UDEV_DEVICE_H */
|
@ -38,6 +38,7 @@ libfwupdprivate = static_library(
|
|||||||
'fu-quirks.c',
|
'fu-quirks.c',
|
||||||
'fu-smbios.c',
|
'fu-smbios.c',
|
||||||
'fu-test.c',
|
'fu-test.c',
|
||||||
|
'fu-udev-device.c',
|
||||||
'fu-usb-device.c',
|
'fu-usb-device.c',
|
||||||
],
|
],
|
||||||
include_directories : [
|
include_directories : [
|
||||||
@ -127,6 +128,7 @@ fwupdtool = executable(
|
|||||||
'fu-plugin-list.c',
|
'fu-plugin-list.c',
|
||||||
'fu-quirks.c',
|
'fu-quirks.c',
|
||||||
'fu-smbios.c',
|
'fu-smbios.c',
|
||||||
|
'fu-udev-device.c',
|
||||||
'fu-usb-device.c',
|
'fu-usb-device.c',
|
||||||
'fu-util-common.c',
|
'fu-util-common.c',
|
||||||
],
|
],
|
||||||
@ -204,6 +206,7 @@ executable(
|
|||||||
'fu-plugin-list.c',
|
'fu-plugin-list.c',
|
||||||
'fu-quirks.c',
|
'fu-quirks.c',
|
||||||
'fu-smbios.c',
|
'fu-smbios.c',
|
||||||
|
'fu-udev-device.c',
|
||||||
'fu-usb-device.c',
|
'fu-usb-device.c',
|
||||||
],
|
],
|
||||||
include_directories : [
|
include_directories : [
|
||||||
@ -270,6 +273,7 @@ if get_option('tests')
|
|||||||
'fu-quirks.c',
|
'fu-quirks.c',
|
||||||
'fu-smbios.c',
|
'fu-smbios.c',
|
||||||
'fu-test.c',
|
'fu-test.c',
|
||||||
|
'fu-udev-device.c',
|
||||||
'fu-usb-device.c',
|
'fu-usb-device.c',
|
||||||
],
|
],
|
||||||
include_directories : [
|
include_directories : [
|
||||||
@ -320,6 +324,7 @@ if get_option('introspection')
|
|||||||
'fu-plugin.h',
|
'fu-plugin.h',
|
||||||
'fu-quirks.c',
|
'fu-quirks.c',
|
||||||
'fu-quirks.h',
|
'fu-quirks.h',
|
||||||
|
'fu-udev-device.c',
|
||||||
'fu-usb-device.c',
|
'fu-usb-device.c',
|
||||||
],
|
],
|
||||||
nsversion : '1.0',
|
nsversion : '1.0',
|
||||||
|
Loading…
Reference in New Issue
Block a user