summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristophe Fergeau <cfergeau@redhat.com>2013-03-06 21:43:41 +0100
committerChristophe Fergeau <cfergeau@redhat.com>2013-03-07 16:23:15 +0100
commitbf238728eec8361716a504c3419eb0265e26cd3c (patch)
treeaf448eed60f13a085c3da5611d36a3728847df9d
parent7a4fb6f9bd02fbbc6cb86c97b7078b86c0d22dc8 (diff)
Use udev hwdb API to get device informationHEADmaster
-rw-r--r--configure.ac5
-rw-r--r--osinfo/Makefile.am2
-rw-r--r--osinfo/osinfo_loader.c130
3 files changed, 134 insertions, 3 deletions
diff --git a/configure.ac b/configure.ac
index 5ad9b6d..054f762 100644
--- a/configure.ac
+++ b/configure.ac
@@ -138,6 +138,11 @@ if test "x$enable_introspection" = "xyes" ; then
fi
AM_CONDITIONAL([WITH_VALA], [test "x$enable_vala" = "xyes"])
+PKG_CHECK_MODULES([UDEV], [libudev > 196], [have_udev=yes], [have_udev=no])
+if test "x$have_udev"="xyes"; then
+ AC_DEFINE([HAVE_UDEV],[1],[Whether to compile with udev support])
+fi
+
AC_ARG_ENABLE([udev],
AS_HELP_STRING([--enable-udev], [enable Udev support]),
[], [enable_udev=no])
diff --git a/osinfo/Makefile.am b/osinfo/Makefile.am
index 5e9a761..ac4d704 100644
--- a/osinfo/Makefile.am
+++ b/osinfo/Makefile.am
@@ -34,6 +34,7 @@ libosinfo_1_0_la_CFLAGS = \
$(LIBXSLT_CFLAGS) \
$(GOBJECT_CFLAGS) \
$(GIO_CFLAGS) \
+ $(UDEV_CFLAGS) \
-DPKG_DATA_DIR='"$(pkgdatadir)"' \
-DSYS_CONF_DIR='"$(sysconfdir)"' \
-DLOCALEDIR="\"$(datadir)/locale\"" \
@@ -45,6 +46,7 @@ libosinfo_1_0_la_LDFLAGS = \
$(LIBXSLT_LIBS) \
$(GOBJECT_LIBS) \
$(GIO_LIBS) \
+ $(UDEV_LIBS) \
$(VERSION_SCRIPT_FLAGS)$(LIBOSINFO_VERSION_FILE) \
-version-info $(LIBOSINFO_VERSION_INFO) \
$(NO_UNDEFINED_FLAGS)
diff --git a/osinfo/osinfo_loader.c b/osinfo/osinfo_loader.c
index 76e9bc2..491e60b 100644
--- a/osinfo/osinfo_loader.c
+++ b/osinfo/osinfo_loader.c
@@ -29,6 +29,10 @@
#include <gio/gio.h>
+#if HAVE_UDEV
+#include <libudev.h>
+#endif
+
#include <string.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
@@ -55,6 +59,10 @@ G_DEFINE_TYPE (OsinfoLoader, osinfo_loader, G_TYPE_OBJECT);
struct _OsinfoLoaderPrivate
{
OsinfoDb *db;
+#ifdef HAVE_UDEV
+ struct udev *udev;
+ struct udev_hwdb *hwdb;
+#endif
};
static void
@@ -63,6 +71,10 @@ osinfo_loader_finalize (GObject *object)
OsinfoLoader *loader = OSINFO_LOADER (object);
g_object_unref(loader->priv->db);
+#ifdef HAVE_UDEV
+ udev_hwdb_unref(loader->priv->hwdb);
+ udev_unref(loader->priv->udev);
+#endif
/* Chain up to the parent class */
G_OBJECT_CLASS (osinfo_loader_parent_class)->finalize (object);
@@ -87,6 +99,12 @@ osinfo_loader_init (OsinfoLoader *loader)
{
loader->priv = OSINFO_LOADER_GET_PRIVATE(loader);
loader->priv->db = osinfo_db_new();
+#ifdef HAVE_UDEV
+ loader->priv->udev = udev_new();
+ if (loader->priv->udev != NULL) {
+ loader->priv->hwdb = udev_hwdb_new(loader->priv->udev);
+ }
+#endif
}
/** PUBLIC METHODS */
@@ -298,14 +316,116 @@ static OsinfoDatamap *osinfo_loader_get_datamap(OsinfoLoader *loader,
return datamap;
}
+#if HAVE_UDEV
+static gboolean osinfo_loader_parse_device_id(const char *id, gchar **out_bus,
+ gchar **out_vid, gchar **out_pid)
+{
+ GStrv ids;
+ const gchar *bus;
+
+ if (g_str_has_prefix(id, "http://pciids.sourceforge.net/v2.2/pci.ids/")) {
+ bus = "pci";
+ id += strlen("http://pciids.sourceforge.net/v2.2/pci.ids/");
+ } else if (g_str_has_prefix(id, "http://www.linux-usb.org/usb.ids/")) {
+ bus = "usb";
+ id += strlen("http://www.linux-usb.org/usb.ids/");
+ } else {
+ bus = NULL; /* silence gcc warning */
+ g_warning("Unknown bus type for id: %s", id);
+ return FALSE;
+ }
+ ids = g_strsplit(id, "/", 2);
+ if (g_strv_length(ids) != 2) {
+ return FALSE;
+ }
+ *out_bus = g_strdup(bus);
+ *out_vid = g_ascii_strup(ids[0], -1);
+ *out_pid = g_ascii_strup(ids[1], -1);
+ /* TODO: Add leading 0s to pci vid/pid */
+ g_strfreev(ids);
+
+ return TRUE;
+}
+#endif
+
+static OsinfoDevice *osinfo_loader_device_new(OsinfoLoader *loader,
+ const gchar *id)
+{
+ OsinfoDevice *dev;
+
+#if HAVE_UDEV
+ struct udev_list_entry *props;
+ char *bus = NULL;
+ char *vid = NULL;
+ char *pid = NULL;
+ char *modalias = NULL;
+#endif
+
+ dev = osinfo_device_new(id);
+ osinfo_db_add_device(loader->priv->db, dev);
+ g_object_unref(dev);
+
+#if HAVE_UDEV
+ if (!osinfo_loader_parse_device_id(id, &bus, &vid, &pid))
+ goto end;
+
+ osinfo_entity_set_param(OSINFO_ENTITY(dev),
+ OSINFO_DEVICE_PROP_BUS_TYPE,
+ bus);
+
+ if (strcmp(bus, "pci") == 0) {
+ modalias = g_strdup_printf("%s:v0000%sd0000%s*", bus, vid, pid);
+ } else if (strcmp(bus, "usb") == 0) {
+ modalias = g_strdup_printf("%s:v%sp%s*", bus, vid, pid);
+ } else {
+ g_warn_if_reached();
+ goto end;
+ }
+
+ if (loader->priv->hwdb == NULL) {
+ goto end;
+ }
+ g_warning("looking up %s", modalias);
+ props = udev_hwdb_get_properties_list_entry(loader->priv->hwdb,
+ modalias, 0);
+ g_free(modalias);
+
+ udev_list_entry_foreach(props, props) {
+ const char *name;
+ const char *value;
+
+ name = udev_list_entry_get_name(props);
+ value = udev_list_entry_get_value(props);
+ if (strcmp(name, "ID_PRODUCT_FROM_DATABASE") == 0) {
+ g_warning("setting product %s", value);
+ osinfo_entity_set_param(OSINFO_ENTITY(dev),
+ OSINFO_DEVICE_PROP_PRODUCT_ID,
+ value);
+ } else if (strcmp(name, "ID_VENDOR_FROM_DATABASE") == 0) {
+ g_warning("setting vendor %s", value);
+ osinfo_entity_set_param(OSINFO_ENTITY(dev),
+ OSINFO_DEVICE_PROP_VENDOR_ID,
+ value);
+ } else {
+ g_warning("unknown hwdb attribute: %s", name);
+ }
+ }
+
+end:
+ g_free(bus);
+ g_free(vid);
+ g_free(pid);
+#endif
+
+ return dev;
+}
+
static OsinfoDevice *osinfo_loader_get_device(OsinfoLoader *loader,
const gchar *id)
{
OsinfoDevice *dev = osinfo_db_get_device(loader->priv->db, id);
if (!dev) {
- dev = osinfo_device_new(id);
- osinfo_db_add_device(loader->priv->db, dev);
- g_object_unref(dev);
+ dev = osinfo_loader_device_new(loader, id);
}
return dev;
}
@@ -1412,6 +1532,7 @@ static void osinfo_loader_process_xml(OsinfoLoader *loader,
xmlFreeParserCtxt(pctxt);
}
+#ifndef HAVE_UDEV
static void
osinfo_loader_process_file_reg_ids(OsinfoLoader *loader,
GFile *file,
@@ -1561,6 +1682,7 @@ osinfo_loader_process_file_reg_pci(OsinfoLoader *loader,
"pci",
err);
}
+#endif
static void
osinfo_loader_process_file(OsinfoLoader *loader,
@@ -1653,10 +1775,12 @@ osinfo_loader_process_file(OsinfoLoader *loader,
case G_FILE_TYPE_REGULAR:
if (g_str_has_suffix(name, ".xml"))
osinfo_loader_process_file_reg_xml(loader, file, info, &error);
+#ifndef HAVE_UDEV
else if (strcmp(name, "usb.ids") == 0)
osinfo_loader_process_file_reg_usb(loader, file, info, &error);
else if (strcmp(name, "pci.ids") == 0)
osinfo_loader_process_file_reg_pci(loader, file, info, &error);
+#endif
break;
case G_FILE_TYPE_DIRECTORY: