The branch main has been updated by bapt:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=8fe86d923f83ffdfed44f3b67b55287bf7cf3ce1

commit 8fe86d923f83ffdfed44f3b67b55287bf7cf3ce1
Author:     Baptiste Daroussin <[email protected]>
AuthorDate: 2024-02-27 17:12:38 +0000
Commit:     Baptiste Daroussin <[email protected]>
CommitDate: 2024-02-29 12:01:06 +0000

    usbconfig: allow to get usb vendors and products from the usb.ids database
    
    Reviewed by:            emaste, manu
    Differential Revision:  https://reviews.freebsd.org/D3392
---
 usr.sbin/usbconfig/dump.c      | 150 ++++++++++++++++++++++++++++++++++++++++-
 usr.sbin/usbconfig/pathnames.h |   4 ++
 2 files changed, 153 insertions(+), 1 deletion(-)

diff --git a/usr.sbin/usbconfig/dump.c b/usr.sbin/usbconfig/dump.c
index d7ea8b93011a..36f026bfc2fb 100644
--- a/usr.sbin/usbconfig/dump.c
+++ b/usr.sbin/usbconfig/dump.c
@@ -2,6 +2,7 @@
  * SPDX-License-Identifier: BSD-2-Clause
  *
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
+ * Copyright (c) 2024 Baptiste Daroussin <[email protected]>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -25,6 +26,8 @@
  * SUCH DAMAGE.
  */
 
+#include <sys/queue.h>
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdint.h>
@@ -38,12 +41,28 @@
 #include <libusb20_desc.h>
 
 #include "dump.h"
+#include "pathnames.h"
 
 #define        DUMP0(n,type,field,...) dump_field(pdev, "  ", #field, 
n->field);
 #define        DUMP1(n,type,field,...) dump_field(pdev, "    ", #field, 
n->field);
 #define        DUMP2(n,type,field,...) dump_field(pdev, "      ", #field, 
n->field);
 #define        DUMP3(n,type,field,...) dump_field(pdev, "        ", #field, 
n->field);
 
+struct usb_product_info {
+       STAILQ_ENTRY(usb_product_info)  link;
+       int                             id;
+       char                            *desc;
+};
+
+struct usb_vendor_info {
+       STAILQ_ENTRY(usb_vendor_info)   link;
+       STAILQ_HEAD(,usb_product_info)  devs;
+       int                             id;
+       char                            *desc;
+};
+
+STAILQ_HEAD(usb_vendors, usb_vendor_info);
+
 const char *
 dump_mode(uint8_t value)
 {
@@ -293,22 +312,151 @@ dump_iface(struct libusb20_device *pdev,
        }
 }
 
+static struct usb_vendors *
+load_vendors(void)
+{
+       const char *dbf;
+       FILE *db = NULL;
+       struct usb_vendor_info *cv;
+       struct usb_product_info *cd;
+       struct usb_vendors *usb_vendors;
+       char buf[1024], str[1024];
+       char *ch;
+       int id;
+
+       usb_vendors = malloc(sizeof(*usb_vendors));
+       if (usb_vendors == NULL)
+               err(1, "out of memory");
+       STAILQ_INIT(usb_vendors);
+       if ((dbf = getenv("USB_VENDOR_DATABASE")) != NULL)
+               db = fopen(dbf, "r");
+       if (db == NULL) {
+               dbf = _PATH_LUSBVDB;
+               if ((db = fopen(dbf, "r")) == NULL) {
+                       dbf = _PATH_USBVDB;
+                       if ((db = fopen(dbf, "r")) == NULL)
+                               return (usb_vendors);
+               }
+       }
+       cv = NULL;
+       cd = NULL;
+
+       for (;;) {
+               if (fgets(buf, sizeof(buf), db) == NULL)
+                       break;
+
+               if ((ch = strchr(buf, '#')) != NULL)
+                       *ch = '\0';
+               if (ch == buf)
+                       continue;
+               ch = strchr(buf, '\0') - 1;
+               while (ch > buf && isspace(*ch))
+                       *ch-- = '\0';
+               if (ch <= buf)
+                       continue;
+
+               /* Can't handle subvendor / subdevice entries yet */
+               if (buf[0] == '\t' && buf[1] == '\t')
+                       continue;
+
+               /* Check for vendor entry */
+               if (buf[0] != '\t' && sscanf(buf, "%04x %[^\n]", &id, str) == 
2) {
+                       if ((id == 0) || (strlen(str) < 1))
+                               continue;
+                       if ((cv = malloc(sizeof(struct usb_vendor_info))) == 
NULL)
+                               err(1, "out of memory");
+                       if ((cv->desc = strdup(str)) == NULL)
+                               err(1, "out of memory");
+                       cv->id = id;
+                       STAILQ_INIT(&cv->devs);
+                       STAILQ_INSERT_TAIL(usb_vendors, cv, link);
+                       continue;
+               }
+
+               /* Check for device entry */
+               if (buf[0] == '\t' && sscanf(buf + 1, "%04x %[^\n]", &id, str) 
== 2) {
+                       if ((id == 0) || (strlen(str) < 1))
+                               continue;
+                       if (cv == NULL)
+                               continue;
+                       if ((cd = malloc(sizeof(struct usb_product_info))) == 
NULL)
+                               err(1, "out of memory");
+                       if ((cd->desc = strdup(str)) == NULL)
+                               err(1, "out of memory");
+                       cd->id = id;
+                       STAILQ_INSERT_TAIL(&cv->devs, cd, link);
+                       continue;
+               }
+       }
+       if (ferror(db))
+               err(1, "error reading the usb id db");
+
+       fclose(db);
+       /* cleanup */
+       return (usb_vendors);
+}
+
+static char *
+_device_desc(struct libusb20_device *pdev)
+{
+       static struct usb_vendors *usb_vendors = NULL;
+       char *desc = NULL;
+       const char *vendor = NULL, *product = NULL;
+       uint16_t vid = libusb20_dev_get_device_desc(pdev)->idVendor;
+       uint16_t pid = libusb20_dev_get_device_desc(pdev)->idProduct;
+       struct usb_vendor_info *vi;
+       struct usb_product_info *pi;
+
+       if (usb_vendors == NULL)
+               usb_vendors = load_vendors();
+
+       STAILQ_FOREACH(vi, usb_vendors, link) {
+               if (vi->id == vid) {
+                       vendor = vi->desc;
+                       break;
+               }
+       }
+       if (vi != NULL) {
+               STAILQ_FOREACH(pi, &vi->devs, link) {
+                       if (pi->id == pid) {
+                               product = pi->desc;
+                               break;
+                       }
+               }
+       }
+       if (vendor == NULL || product == NULL)
+               return (NULL);
+
+       asprintf(&desc, "ugen%u.%u: <%s %s> at usbus%u",
+                       libusb20_dev_get_bus_number(pdev),
+                       libusb20_dev_get_address(pdev),
+                       product, vendor,
+                       libusb20_dev_get_bus_number(pdev));
+
+
+       return (desc);
+}
+
 void
 dump_device_info(struct libusb20_device *pdev, uint8_t show_ifdrv)
 {
        char buf[128];
        uint8_t n;
        unsigned int usage;
+       char *desc;
 
        usage = libusb20_dev_get_power_usage(pdev);
 
+       desc = _device_desc(pdev);
+
        printf("%s, cfg=%u md=%s spd=%s pwr=%s (%umA)\n",
-           libusb20_dev_get_desc(pdev),
+           desc ? desc : libusb20_dev_get_desc(pdev),
            libusb20_dev_get_config_index(pdev),
            dump_mode(libusb20_dev_get_mode(pdev)),
            dump_speed(libusb20_dev_get_speed(pdev)),
            dump_power_mode(libusb20_dev_get_power_mode(pdev)),
            usage);
+       free(desc);
 
        if (!show_ifdrv)
                return;
diff --git a/usr.sbin/usbconfig/pathnames.h b/usr.sbin/usbconfig/pathnames.h
new file mode 100644
index 000000000000..66053a9a87c5
--- /dev/null
+++ b/usr.sbin/usbconfig/pathnames.h
@@ -0,0 +1,4 @@
+#include <paths.h>
+
+#define        _PATH_USBVDB    "/usr/share/misc/usb_vendors"
+#define        _PATH_LUSBVDB   _PATH_LOCALBASE "/share/usbids/usb.ids"

Reply via email to