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.
# 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
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)
}
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);
pci_define_param(a, "net.domain", PCI_ID_DOMAIN, "DNS domain used for resolving of ID's");
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)
/* 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 *);
#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;
*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)
{
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;
}
--- /dev/null
+/*
+ * 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
{
pci_id_cache_flush(a);
pci_id_hash_free(a);
+ pci_id_hwdb_free(a);
a->id_load_failed = 0;
}
/*
* 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.
*/
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)))
{
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))
/*
* 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.
*/
SRC_UNKNOWN,
SRC_CACHE,
SRC_NET,
+ SRC_HWDB,
SRC_LOCAL,
};
/* 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);
else
return prev->next;
}
-
/*
* 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.
*/
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 */
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
.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),