diff options
author | Martin Mares <mj@ucw.cz> | 2014-11-01 18:38:08 +0100 |
---|---|---|
committer | Martin Mares <mj@ucw.cz> | 2014-11-01 18:38:08 +0100 |
commit | ac357d3bb8342b2fc22980e0914cdce7758ca310 (patch) | |
tree | 253ada2707849f4b8c053fa868feb743b653f740 | |
parent | e59bfc5e661ef01d0b8c613225074386c6a450a2 (diff) | |
download | pciutils-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/Makefile | 5 | ||||
-rw-r--r-- | lib/init.c | 5 | ||||
-rw-r--r-- | lib/internal.h | 2 | ||||
-rw-r--r-- | lib/names-hash.c | 61 | ||||
-rw-r--r-- | lib/names-hwdb.c | 109 | ||||
-rw-r--r-- | lib/names-parse.c | 1 | ||||
-rw-r--r-- | lib/names.c | 12 | ||||
-rw-r--r-- | lib/names.h | 8 | ||||
-rw-r--r-- | lib/params.c | 1 | ||||
-rw-r--r-- | lib/pci.h | 5 | ||||
-rw-r--r-- | pcilib.man | 5 |
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) @@ -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; } - @@ -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 @@ -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), |