[systemd-devel] [PATCH][usbutils] lsusb: port to hwdb

Tom Gundersen teg at jklm.no
Sat Jul 20 17:52:09 PDT 2013


Most of the information in usb.ids is now contained in udev's hwdb. First
attempt to query hwdb before falling back on the old file.

This would allow distributions to no longer ship (most of) usb.ids by default,
but rather keep all the usb device information in only one place (the hwdb).

This patch introduces a dependency on libusb >= 196.

Cc: systemd-devel at lists.freedesktop.org
---
 Makefile.am  |  5 +++--
 configure.ac |  2 ++
 names.c      | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 65 insertions(+), 4 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 1e85a1e..70b9de9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -23,11 +23,12 @@ lsusb_SOURCES = \
 	usbmisc.c usbmisc.h
 
 lsusb_CPPFLAGS = \
-	$(AM_CPPFLAGS) $(LIBUSB_CFLAGS) \
+	$(AM_CPPFLAGS) $(LIBUSB_CFLAGS) $(UDEV_CFLAGS) \
 	-DDATADIR=\"$(datadir)\"
 
 lsusb_LDADD = \
-	$(LIBUSB_LIBS)
+	$(LIBUSB_LIBS) \
+	$(UDEV_LIBS)
 
 if HAVE_ZLIB
 lsusb_CPPFLAGS += -DHAVE_LIBZ
diff --git a/configure.ac b/configure.ac
index adfb4b6..b4b0880 100644
--- a/configure.ac
+++ b/configure.ac
@@ -26,6 +26,8 @@ AM_CONDITIONAL([INSTALL_USBIDS], [test "x$enable_usbids" != "xno"])
 
 PKG_CHECK_MODULES(LIBUSB, libusb-1.0 >= 1.0.0)
 
+PKG_CHECK_MODULES(UDEV, libudev >= 196)
+
 AC_CONFIG_HEADERS([config.h])
 AC_CONFIG_FILES([
 	Makefile
diff --git a/names.c b/names.c
index 12cbd60..4b59213 100644
--- a/names.c
+++ b/names.c
@@ -3,6 +3,7 @@
  *      names.c  --  USB name database manipulation routines
  *
  *      Copyright (C) 1999, 2000  Thomas Sailer (sailer at ife.ee.ethz.ch)
+ *      Copyright (C) 2013  Tom Gundersen (teg at jklm.no)
  *
  *      This program is free software; you can redistribute it and/or modify
  *      it under the terms of the GNU General Public License as published by
@@ -34,6 +35,8 @@
 #include <stdio.h>
 #include <ctype.h>
 
+#include <libudev.h>
+
 #ifdef HAVE_LIBZ
 #include <zlib.h>
 #define 	usb_file			gzFile
@@ -118,6 +121,8 @@ static unsigned int hashnum(unsigned int num)
 
 /* ---------------------------------------------------------------------- */
 
+static struct udev *udev = NULL;
+static struct udev_hwdb *hwdb = NULL;
 static struct vendor *vendors[HASHSZ] = { NULL, };
 static struct product *products[HASHSZ] = { NULL, };
 static struct class *classes[HASHSZ] = { NULL, };
@@ -187,9 +192,27 @@ const char *names_countrycode(unsigned int countrycode)
 	return names_genericstrtable(countrycodes, countrycode);
 }
 
+static const char *hwdb_get(const char *modalias, const char *key)
+{
+	struct udev_list_entry *entry;
+
+	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);
+
+	return NULL;
+}
+
 const char *names_vendor(u_int16_t vendorid)
 {
 	struct vendor *v;
+	char modalias[64];
+	const char *name;
+
+	sprintf(modalias, "usb:v%04X*", vendorid);
+	name = hwdb_get(modalias, "ID_VENDOR_FROM_DATABASE");
+	if (name)
+		return name;
 
 	v = vendors[hashnum(vendorid)];
 	for (; v; v = v->next)
@@ -201,6 +224,13 @@ const char *names_vendor(u_int16_t vendorid)
 const char *names_product(u_int16_t vendorid, u_int16_t productid)
 {
 	struct product *p;
+	char modalias[64];
+	const char *name;
+
+	sprintf(modalias, "usb:v%04Xp%04X*", vendorid, productid);
+	name = hwdb_get(modalias, "ID_MODEL_FROM_DATABASE");
+	if (name)
+		return name;
 
 	p = products[hashnum((vendorid << 16) | productid)];
 	for (; p; p = p->next)
@@ -212,6 +242,13 @@ const char *names_product(u_int16_t vendorid, u_int16_t productid)
 const char *names_class(u_int8_t classid)
 {
 	struct class *c;
+	char modalias[64];
+	const char *name;
+
+	sprintf(modalias, "usb:v*p*d*dc%02X*", classid);
+	name = hwdb_get(modalias, "ID_USB_CLASS_FROM_DATABASE");
+	if (name)
+		return name;
 
 	c = classes[hashnum(classid)];
 	for (; c; c = c->next)
@@ -223,6 +260,13 @@ const char *names_class(u_int8_t classid)
 const char *names_subclass(u_int8_t classid, u_int8_t subclassid)
 {
 	struct subclass *s;
+	char modalias[64];
+	const char *name;
+
+	sprintf(modalias, "usb:v*p*d*dc%02Xdsc%02X*", classid, subclassid);
+	name = hwdb_get(modalias, "ID_USB_SUBCLASS_FROM_DATABASE");
+	if (name)
+		return name;
 
 	s = subclasses[hashnum((classid << 8) | subclassid)];
 	for (; s; s = s->next)
@@ -234,6 +278,13 @@ const char *names_subclass(u_int8_t classid, u_int8_t subclassid)
 const char *names_protocol(u_int8_t classid, u_int8_t subclassid, u_int8_t protocolid)
 {
 	struct protocol *p;
+	char modalias[64];
+	const char *name;
+
+	sprintf(modalias, "usb:v*p*d*dc%02Xdsc%02Xdp%02X*", classid, subclassid, protocolid);
+	name = hwdb_get(modalias, "ID_USB_PROTOCOL_FROM_DATABASE");
+	if (name)
+		return name;
 
 	p = protocols[hashnum((classid << 16) | (subclassid << 8) | protocolid)];
 	for (; p; p = p->next)
@@ -994,18 +1045,25 @@ static void parse(usb_file f)
 int names_init(char *n)
 {
 	usb_file f;
+	int r = 0;
 
 	f = usb_fopen(n, "r");
 	if (!f)
-		return errno;
+		r = errno;
 
 	parse(f);
 	usb_close(f);
-	return 0;
+
+	udev = udev_new();
+	hwdb = udev_hwdb_new(udev);
+
+	return r;
 }
 
 void names_exit(void)
 {
+	hwdb = udev_hwdb_unref(hwdb);
+	udev = udev_unref(udev);
 	free_vendor();
 	free_product();
 	free_class();
-- 
1.8.3.3



More information about the systemd-devel mailing list