diff options
author | Christophe Fergeau <cfergeau@redhat.com> | 2013-03-06 21:43:41 +0100 |
---|---|---|
committer | Christophe Fergeau <cfergeau@redhat.com> | 2013-03-07 16:23:15 +0100 |
commit | bf238728eec8361716a504c3419eb0265e26cd3c (patch) | |
tree | af448eed60f13a085c3da5611d36a3728847df9d | |
parent | 7a4fb6f9bd02fbbc6cb86c97b7078b86c0d22dc8 (diff) |
-rw-r--r-- | configure.ac | 5 | ||||
-rw-r--r-- | osinfo/Makefile.am | 2 | ||||
-rw-r--r-- | osinfo/osinfo_loader.c | 130 |
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: |