summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Mares <mj@ucw.cz>2014-11-01 18:38:08 +0100
committerMartin Mares <mj@ucw.cz>2014-11-01 18:38:08 +0100
commitac357d3bb8342b2fc22980e0914cdce7758ca310 (patch)
tree253ada2707849f4b8c053fa868feb743b653f740
parente59bfc5e661ef01d0b8c613225074386c6a450a2 (diff)
downloadpciutils-ac357d3bb8342b2fc22980e0914cdce7758ca310.tar.gz
Rewritten support for UDEV's HWDB
HWDB is now handled in a way very similar to the DNS resolver. The interface lives in a separate source file (lib/names-hwdb.c), results of lookups are cached. Use of HWDB can be disabled either by passing PCI_LOOKUP_NO_HWDB or by setting the hwdb.disabled configuration parameter. Also, there should be no more leaks of libudev's structures.
-rw-r--r--lib/Makefile5
-rw-r--r--lib/init.c5
-rw-r--r--lib/internal.h2
-rw-r--r--lib/names-hash.c61
-rw-r--r--lib/names-hwdb.c109
-rw-r--r--lib/names-parse.c1
-rw-r--r--lib/names.c12
-rw-r--r--lib/names.h8
-rw-r--r--lib/params.c1
-rw-r--r--lib/pci.h5
-rw-r--r--pcilib.man5
11 files changed, 149 insertions, 65 deletions
diff --git a/lib/Makefile b/lib/Makefile
index 6f6efec..f119b72 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -1,9 +1,9 @@
# Makefile for The PCI Library
-# (c) 1999--2008 Martin Mares <mj@ucw.cz>
+# (c) 1999--2014 Martin Mares <mj@ucw.cz>
# Expects to be invoked from the top-level Makefile and uses lots of its variables.
-OBJS=init access generic dump names filter names-hash names-parse names-net names-cache params caps
+OBJS=init access generic dump names filter names-hash names-parse names-net names-cache names-hwdb params caps
INCL=internal.h pci.h config.h header.h sysdep.h types.h
ifdef PCI_HAVE_PM_LINUX_SYSFS
@@ -88,5 +88,6 @@ names-cache.o: names-cache.c $(INCL) names.h
names-hash.o: names-hash.c $(INCL) names.h
names-net.o: names-net.c $(INCL) names.h
names-parse.o: names-parse.c $(INCL) names.h
+names-hwdb.o: names-hwdb.c $(INCL) names.h
filter.o: filter.c $(INCL)
nbsd-libpci.o: nbsd-libpci.c $(INCL)
diff --git a/lib/init.c b/lib/init.c
index d28271e..064c932 100644
--- a/lib/init.c
+++ b/lib/init.c
@@ -82,7 +82,7 @@ pci_mfree(void *x)
}
char *
-pci_strdup(struct pci_access *a, char *s)
+pci_strdup(struct pci_access *a, const char *s)
{
int len = strlen(s) + 1;
char *t = pci_malloc(a, len);
@@ -163,6 +163,9 @@ pci_alloc(void)
pci_define_param(a, "net.cache_name", "~/.pciids-cache", "Name of the ID cache file");
a->id_lookup_mode = PCI_LOOKUP_CACHE;
#endif
+#ifdef PCI_HAVE_HWDB
+ pci_define_param(a, "hwdb.disable", "0", "Do not look up names in UDEV's HWDB if non-zero");
+#endif
for (i=0; i<PCI_ACCESS_MAX; i++)
if (pci_methods[i] && pci_methods[i]->config)
pci_methods[i]->config(a);
diff --git a/lib/internal.h b/lib/internal.h
index 18a59e2..ea63738 100644
--- a/lib/internal.h
+++ b/lib/internal.h
@@ -59,7 +59,7 @@ int pci_generic_block_write(struct pci_dev *, int pos, byte *buf, int len);
/* init.c */
void *pci_malloc(struct pci_access *, int);
void pci_mfree(void *);
-char *pci_strdup(struct pci_access *a, char *s);
+char *pci_strdup(struct pci_access *a, const char *s);
/* access.c */
struct pci_dev *pci_alloc_dev(struct pci_access *);
diff --git a/lib/names-hash.c b/lib/names-hash.c
index 9661d03..2f5bc3c 100644
--- a/lib/names-hash.c
+++ b/lib/names-hash.c
@@ -11,11 +11,6 @@
#include "internal.h"
#include "names.h"
-#ifdef PCI_HAVE_HWDB
-#include <libudev.h>
-#include <stdio.h>
-#endif
-
struct id_bucket {
struct id_bucket *next;
unsigned int full;
@@ -91,58 +86,8 @@ char
*pci_id_lookup(struct pci_access *a, int flags, int cat, int id1, int id2, int id3, int id4)
{
struct id_entry *n, *best;
- u32 id12, id34;
-
-#ifdef PCI_HAVE_HWDB
- if (!(flags & PCI_LOOKUP_SKIP_LOCAL))
- {
- char modalias[64];
- const char *key = NULL;
- struct udev *udev = udev_new();
- struct udev_hwdb *hwdb = udev_hwdb_new(udev);
- struct udev_list_entry *entry;
-
- switch(cat)
- {
- case ID_VENDOR:
- sprintf(modalias, "pci:v%08X*", id1);
- key = "ID_VENDOR_FROM_DATABASE";
- break;
- case ID_DEVICE:
- sprintf(modalias, "pci:v%08Xd%08X*", id1, id2);
- key = "ID_MODEL_FROM_DATABASE";
- break;
- case ID_SUBSYSTEM:
- sprintf(modalias, "pci:v%08Xd%08Xsv%08Xsd%08X*", id1, id2, id3, id4);
- key = "ID_MODEL_FROM_DATABASE";
- break;
- case ID_GEN_SUBSYSTEM:
- sprintf(modalias, "pci:v*d*sv%08Xsd%08X*", id1, id2);
- key = "ID_MODEL_FROM_DATABASE";
- break;
- case ID_CLASS:
- sprintf(modalias, "pci:v*d*sv*sd*bc%02X*", id1);
- key = "ID_PCI_CLASS_FROM_DATABASE";
- break;
- case ID_SUBCLASS:
- sprintf(modalias, "pci:v*d*sv*sd*bc%02Xsc%02X*", id1, id2);
- key = "ID_PCI_SUBCLASS_FROM_DATABASE";
- break;
- case ID_PROGIF:
- sprintf(modalias, "pci:v*d*sv*sd*bc%02Xsc%02Xi%02X*", id1, id2, id3);
- key = "ID_PCI_INTERFACE_FROM_DATABASE";
- break;
- }
-
- if (key)
- udev_list_entry_foreach(entry, udev_hwdb_get_properties_list_entry(hwdb, modalias, 0))
- if (strcmp(udev_list_entry_get_name(entry), key) == 0)
- return udev_list_entry_get_value(entry);
- }
-#endif
-
- id12 = id_pair(id1, id2);
- id34 = id_pair(id3, id4);
+ u32 id12 = id_pair(id1, id2);
+ u32 id34 = id_pair(id3, id4);
if (a->id_hash)
{
@@ -158,6 +103,8 @@ char
continue;
if (n->src == SRC_CACHE && !(flags & PCI_LOOKUP_CACHE))
continue;
+ if (n->src == SRC_HWDB && (flags & (PCI_LOOKUP_SKIP_LOCAL | PCI_LOOKUP_NO_HWDB)))
+ continue;
if (!best || best->src < n->src)
best = n;
}
diff --git a/lib/names-hwdb.c b/lib/names-hwdb.c
new file mode 100644
index 0000000..07b3499
--- /dev/null
+++ b/lib/names-hwdb.c
@@ -0,0 +1,109 @@
+/*
+ * The PCI Library -- Looking up Names via UDEV and HWDB
+ *
+ * Copyright (c) 2013--2014 Tom Gundersen <teg@jklm.no>
+ * Copyright (c) 2014 Martin Mares <mj@ucw.cz>
+ *
+ * Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+#include <string.h>
+
+#include "internal.h"
+#include "names.h"
+
+#ifdef PCI_HAVE_HWDB
+
+#include <libudev.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+char *
+pci_id_hwdb_lookup(struct pci_access *a, int cat, int id1, int id2, int id3, int id4)
+{
+ char modalias[64];
+ const char *key = NULL;
+
+ const char *disabled = pci_get_param(a, "hwdb.disable");
+ if (disabled && atoi(disabled))
+ return NULL;
+
+ switch (cat)
+ {
+ case ID_VENDOR:
+ sprintf(modalias, "pci:v%08X*", id1);
+ key = "ID_VENDOR_FROM_DATABASE";
+ break;
+ case ID_DEVICE:
+ sprintf(modalias, "pci:v%08Xd%08X*", id1, id2);
+ key = "ID_MODEL_FROM_DATABASE";
+ break;
+ case ID_SUBSYSTEM:
+ sprintf(modalias, "pci:v%08Xd%08Xsv%08Xsd%08X*", id1, id2, id3, id4);
+ key = "ID_MODEL_FROM_DATABASE";
+ break;
+ case ID_GEN_SUBSYSTEM:
+ sprintf(modalias, "pci:v*d*sv%08Xsd%08X*", id1, id2);
+ key = "ID_MODEL_FROM_DATABASE";
+ break;
+ case ID_CLASS:
+ sprintf(modalias, "pci:v*d*sv*sd*bc%02X*", id1);
+ key = "ID_PCI_CLASS_FROM_DATABASE";
+ break;
+ case ID_SUBCLASS:
+ sprintf(modalias, "pci:v*d*sv*sd*bc%02Xsc%02X*", id1, id2);
+ key = "ID_PCI_SUBCLASS_FROM_DATABASE";
+ break;
+ case ID_PROGIF:
+ sprintf(modalias, "pci:v*d*sv*sd*bc%02Xsc%02Xi%02X*", id1, id2, id3);
+ key = "ID_PCI_INTERFACE_FROM_DATABASE";
+ break;
+ }
+
+ if (key)
+ {
+ if (!a->id_udev_hwdb)
+ {
+ a->debug("Initializing UDEV HWDB\n");
+ a->id_udev = udev_new();
+ a->id_udev_hwdb = udev_hwdb_new(a->id_udev);
+ }
+
+ struct udev_list_entry *entry;
+ udev_list_entry_foreach(entry, udev_hwdb_get_properties_list_entry(a->id_udev_hwdb, modalias, 0))
+ if (strcmp(udev_list_entry_get_name(entry), key) == 0)
+ return pci_strdup(a, udev_list_entry_get_value(entry));
+ }
+
+ return NULL;
+}
+
+void
+pci_id_hwdb_free(struct pci_access *a)
+{
+ if (a->id_udev_hwdb)
+ {
+ udev_hwdb_unref(a->id_udev_hwdb);
+ a->id_udev_hwdb = NULL;
+ }
+ if (a->id_udev)
+ {
+ udev_unref(a->id_udev);
+ a->id_udev = NULL;
+ }
+}
+
+#else
+
+char *
+pci_id_hwdb_lookup(struct pci_access *a UNUSED, int cat UNUSED, int id1 UNUSED, int id2 UNUSED, int id3 UNUSED, int id4 UNUSED)
+{
+ return NULL;
+}
+
+void
+pci_id_hwdb_free(struct pci_access *a UNUSED)
+{
+}
+
+#endif
diff --git a/lib/names-parse.c b/lib/names-parse.c
index 4997b58..f3b7da9 100644
--- a/lib/names-parse.c
+++ b/lib/names-parse.c
@@ -238,6 +238,7 @@ pci_free_name_list(struct pci_access *a)
{
pci_id_cache_flush(a);
pci_id_hash_free(a);
+ pci_id_hwdb_free(a);
a->id_load_failed = 0;
}
diff --git a/lib/names.c b/lib/names.c
index bda8c90..d5353a8 100644
--- a/lib/names.c
+++ b/lib/names.c
@@ -1,7 +1,7 @@
/*
* The PCI Library -- ID to Name Translation
*
- * Copyright (c) 1997--2008 Martin Mares <mj@ucw.cz>
+ * Copyright (c) 1997--2014 Martin Mares <mj@ucw.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
@@ -16,6 +16,7 @@
static char *id_lookup(struct pci_access *a, int flags, int cat, int id1, int id2, int id3, int id4)
{
char *name;
+ int tried_hwdb = 0;
while (!(name = pci_id_lookup(a, flags, cat, id1, id2, id3, id4)))
{
@@ -24,6 +25,15 @@ static char *id_lookup(struct pci_access *a, int flags, int cat, int id1, int id
if (pci_id_cache_load(a, flags))
continue;
}
+ if (!tried_hwdb && !(flags & (PCI_LOOKUP_SKIP_LOCAL | PCI_LOOKUP_NO_HWDB)))
+ {
+ tried_hwdb = 1;
+ if (name = pci_id_hwdb_lookup(a, cat, id1, id2, id3, id4))
+ {
+ pci_id_insert(a, cat, id1, id2, id3, id4, name, SRC_HWDB);
+ continue;
+ }
+ }
if (flags & PCI_LOOKUP_NETWORK)
{
if (name = pci_id_net_lookup(a, cat, id1, id2, id3, id4))
diff --git a/lib/names.h b/lib/names.h
index 81c373f..d7e71ff 100644
--- a/lib/names.h
+++ b/lib/names.h
@@ -1,7 +1,7 @@
/*
* The PCI Library -- ID to Name Translation
*
- * Copyright (c) 1997--2008 Martin Mares <mj@ucw.cz>
+ * Copyright (c) 1997--2014 Martin Mares <mj@ucw.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
@@ -33,6 +33,7 @@ enum id_entry_src {
SRC_UNKNOWN,
SRC_CACHE,
SRC_NET,
+ SRC_HWDB,
SRC_LOCAL,
};
@@ -67,3 +68,8 @@ void pci_id_hash_free(struct pci_access *a);
/* names-dns.c */
char *pci_id_net_lookup(struct pci_access *a, int cat, int id1, int id2, int id3, int id4);
+
+/* names-hwdb.c */
+
+char *pci_id_hwdb_lookup(struct pci_access *a, int cat, int id1, int id2, int id3, int id4);
+void pci_id_hwdb_free(struct pci_access *a);
diff --git a/lib/params.c b/lib/params.c
index 0e6edbb..4d48cab 100644
--- a/lib/params.c
+++ b/lib/params.c
@@ -85,4 +85,3 @@ pci_walk_params(struct pci_access *acc, struct pci_param *prev)
else
return prev->next;
}
-
diff --git a/lib/pci.h b/lib/pci.h
index 37f08e6..8b1d024 100644
--- a/lib/pci.h
+++ b/lib/pci.h
@@ -1,7 +1,7 @@
/*
* The PCI Library
*
- * Copyright (c) 1997--2013 Martin Mares <mj@ucw.cz>
+ * Copyright (c) 1997--2014 Martin Mares <mj@ucw.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
@@ -73,6 +73,8 @@ struct pci_access {
struct id_bucket *current_id_bucket;
int id_load_failed;
int id_cache_status; /* 0=not read, 1=read, 2=dirty */
+ struct udev *id_udev; /* names-hwdb.c */
+ struct udev_hwdb *id_udev_hwdb;
int fd; /* proc/sys: fd for config space */
int fd_rw; /* proc/sys: fd opened read-write */
int fd_pos; /* proc/sys: current position */
@@ -240,6 +242,7 @@ enum pci_lookup_mode {
PCI_LOOKUP_SKIP_LOCAL = 0x100000, /* Do not consult local database */
PCI_LOOKUP_CACHE = 0x200000, /* Consult the local cache before using DNS */
PCI_LOOKUP_REFRESH_CACHE = 0x400000, /* Forget all previously cached entries, but still allow updating the cache */
+ PCI_LOOKUP_NO_HWDB = 0x800000, /* Do not ask udev's hwdb */
};
#endif
diff --git a/pcilib.man b/pcilib.man
index 60c0bb1..dde7e2f 100644
--- a/pcilib.man
+++ b/pcilib.man
@@ -104,6 +104,11 @@ DNS domain containing the ID database.
.B net.cache_name
Name of the file used for caching of resolved ID's.
+.SS Parameters for resolving of ID's via UDEV's HWDB
+.TP
+.B hwdb.disable
+Disable use of HWDB if set to a non-zero value.
+
.SH SEE ALSO
.BR lspci (8),