[Spice-devel] [PATCH spice-gtk 3/7] usbutil: Add support for getting strings from usb.ids

Hans de Goede hdegoede at redhat.com
Sat Feb 18 15:50:20 PST 2012


Unfortunately not all device makers go to the "trouble" of adding device
identification strings to a device's descriptors. This patch makes spice-gtk
translate vid/pid into strings if the device lacks the strings.

Signed-off-by: Hans de Goede <hdegoede at redhat.com>
---
 configure.ac    |   21 ++++++++
 gtk/Makefile.am |    1 +
 gtk/usbutil.c   |  150 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 172 insertions(+), 0 deletions(-)

diff --git a/configure.ac b/configure.ac
index d8602fd..d2ac883 100644
--- a/configure.ac
+++ b/configure.ac
@@ -426,6 +426,27 @@ AC_ARG_WITH([usb-acl-helper-dir],
   [ACL_HELPER_DIR="${bindir}/"])
 AC_SUBST([ACL_HELPER_DIR])
 
+AC_ARG_WITH([usb-ids-path],
+  AC_HELP_STRING([--with-usb-ids-path],
+                 [Specify the path to usb.ids @<:@default=auto@:>@]),
+  [USB_IDS="$with_usb_ids_path"],
+  [USB_IDS="auto"])
+AC_MSG_CHECKING([for usb.ids])
+if test "x$USB_IDS" = "xauto"; then
+  if test -n "$PKG_CONFIG"; then
+    USB_IDS=$($PKG_CONFIG --variable=usbids usbutils)
+  else
+    USB_IDS=
+  fi
+fi
+if test -n "$USB_IDS"; then
+  AC_MSG_RESULT([$USB_IDS])
+  AC_SUBST(USB_IDS)
+  AC_DEFINE(WITH_USBIDS, [1], [Define if compiling with usb.ids support])
+else
+  AC_MSG_RESULT([not found])
+fi
+
 AC_ARG_WITH([coroutine],
   AS_HELP_STRING([--with-coroutine=@<:@ucontext/gthread/winfiber/auto@:>@],
                  [use ucontext or GThread for coroutines @<:@default=auto@:>@]),
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index 2ad4494..fd2e477 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -60,6 +60,7 @@ SPICE_COMMON_CPPFLAGS = \
 	-DSW_CANVAS_CACHE		\
 	-DSPICE_GTK_LOCALEDIR=\"${SPICE_GTK_LOCALEDIR}\" \
 	-DPNP_IDS=\""$(PNP_IDS)"\"\
+	-DUSB_IDS=\""$(USB_IDS)"\"\
 	\
 	-I$(COMMON_DIR)			\
 	-I$(CLIENT_DIR)			\
diff --git a/gtk/usbutil.c b/gtk/usbutil.c
index 0d1361e..704f973 100644
--- a/gtk/usbutil.c
+++ b/gtk/usbutil.c
@@ -23,6 +23,8 @@
 
 #include <glib-object.h>
 #include <glib/gi18n.h>
+#include <ctype.h>
+#include <stdlib.h>
 
 #include "glib-compat.h"
 
@@ -35,6 +37,27 @@
 #endif
 #include "usbutil.h"
 
+#ifdef WITH_USBIDS
+#define VENDOR_NAME_LEN (122 - sizeof(void *))
+#define PRODUCT_NAME_LEN 126
+
+typedef struct _usb_product_info {
+    guint16 product_id;
+    char name[PRODUCT_NAME_LEN];
+} usb_product_info;
+
+typedef struct _usb_vendor_info {
+    usb_product_info *product_info;
+    int product_count;
+    guint16 vendor_id;
+    char name[VENDOR_NAME_LEN];
+} usb_vendor_info;
+
+GStaticMutex usbids_parse_mutex = G_STATIC_MUTEX_INIT;
+int usbids_vendor_count;
+usb_vendor_info *usbids_vendor_info;
+#endif
+
 G_GNUC_INTERNAL
 const char *spice_usbutil_libusb_strerror(enum libusb_error error_code)
 {
@@ -98,11 +121,112 @@ static gchar *spice_usbutil_get_sysfs_attribute(int bus, int address,
 }
 #endif
 
+#ifdef WITH_USBIDS
+static void spice_usbutil_parse_usbids(void)
+{
+    gchar *contents, *line, **lines;
+    usb_product_info *product_info;
+    int i, j, id, product_count = 0;
+
+    g_static_mutex_lock(&usbids_parse_mutex);
+    if (usbids_vendor_count)
+        goto leave;
+
+    if (!g_file_get_contents(USB_IDS, &contents, NULL, NULL)) {
+        usbids_vendor_count = -1;
+        goto leave;
+    }
+    lines = g_strsplit(contents, "\n", -1);
+
+    for (i = 0; lines[i]; i++) {
+        if (!isxdigit(lines[i][0]) || !isxdigit(lines[i][1]))
+            continue;
+
+        for (j = 1; lines[i + j] &&
+                   (lines[i + j][0] == '\t' ||
+                    lines[i + j][0] == '#'  ||
+                    lines[i + j][0] == '\0'); j++) {
+            if (lines[i + j][0] == '\t' && isxdigit(lines[i + j][1]))
+                product_count++;
+        }
+        i += j - 1;
+
+        usbids_vendor_count++;
+    }
+
+    usbids_vendor_info = g_new(usb_vendor_info, usbids_vendor_count);
+    product_info = g_new(usb_product_info, product_count);
+
+    usbids_vendor_count = 0;
+    for (i = 0; lines[i]; i++) {
+        line = lines[i];
+
+        if (!isxdigit(line[0]) || !isxdigit(line[1]))
+            continue;
+
+        id = strtoul(line, &line, 16);
+        while(isspace(line[0]))
+            line++;
+        usbids_vendor_info[usbids_vendor_count].vendor_id = id;
+        snprintf(usbids_vendor_info[usbids_vendor_count].name,
+                 VENDOR_NAME_LEN, "%s", line);
+
+        product_count = 0;
+        for (j = 1; lines[i + j] &&
+                   (lines[i + j][0] == '\t' ||
+                    lines[i + j][0] == '#'  ||
+                    lines[i + j][0] == '\0'); j++) {
+            line = lines[i + j];
+
+            if (line[0] != '\t' || !isxdigit(line[1]))
+                continue;
+
+            id = strtoul(line + 1, &line, 16);
+            while(isspace(line[0]))
+                line++;
+            product_info[product_count].product_id = id;
+            snprintf(product_info[product_count].name,
+                     PRODUCT_NAME_LEN, "%s", line);
+
+            product_count++;
+        }
+        i += j - 1;
+
+        usbids_vendor_info[usbids_vendor_count].product_count = product_count;
+        usbids_vendor_info[usbids_vendor_count].product_info  = product_info;
+        product_info += product_count;
+        usbids_vendor_count++;
+    }
+
+    g_strfreev(lines);
+    g_free(contents);
+
+#if 0 /* Testing only */
+    for (i = 0; i < usbids_vendor_count; i++) {
+        printf("%04x  %s\n", usbids_vendor_info[i].vendor_id,
+               usbids_vendor_info[i].name);
+        product_info = usbids_vendor_info[i].product_info;
+        for (j = 0; j < usbids_vendor_info[i].product_count; j++) {
+            printf("\t%04x  %s\n", product_info[j].product_id,
+                   product_info[j].name);
+        }
+    }
+#endif
+leave:
+    g_static_mutex_unlock(&usbids_parse_mutex);
+}
+#endif
+
 G_GNUC_INTERNAL
 void spice_usb_util_get_device_strings(int bus, int address,
                                        int vendor_id, int product_id,
                                        gchar **manufacturer, gchar **product)
 {
+#ifdef WITH_USBIDS
+    usb_product_info *product_info;
+    int i, j;
+#endif
+
     g_return_if_fail(manufacturer != NULL);
     g_return_if_fail(product != NULL);
 
@@ -113,6 +237,32 @@ void spice_usb_util_get_device_strings(int bus, int address,
     *manufacturer = spice_usbutil_get_sysfs_attribute(bus, address, "manufacturer");
     *product = spice_usbutil_get_sysfs_attribute(bus, address, "product");
 #endif
+
+#ifdef WITH_USBIDS
+    if (!*manufacturer || !*product) {
+        spice_usbutil_parse_usbids();
+
+        for (i = 0; i < usbids_vendor_count; i++) {
+            if ((int)usbids_vendor_info[i].vendor_id != vendor_id)
+                continue;
+
+            if (!*manufacturer && usbids_vendor_info[i].name[0])
+                *manufacturer = g_strdup(usbids_vendor_info[i].name);
+
+            product_info = usbids_vendor_info[i].product_info;
+            for (j = 0; j < usbids_vendor_info[i].product_count; j++) {
+                if ((int)product_info[j].product_id != product_id)
+                    continue;
+
+                if (!*product && product_info[j].name[0])
+                    *product = g_strdup(product_info[j].name);
+
+                break;
+            }
+            break;
+        }
+    }
+#endif
     if (!*manufacturer)
         *manufacturer = g_strdup(_("USB"));
     if (!*product)
-- 
1.7.7.5



More information about the Spice-devel mailing list