Hi, prompted by mpi@ i tried simplifying the way we get the vendor/product/serial info from the device. Currently this is done lazily, and sometimes several times. Instead of this, let's query the device in usbd_new_device(), fallback to the global known lists then to the USB IDs, cache the info in struct usbd_device and reuse it where needed instead of pollin the device again.
The comment about vendor/product being possibly NULL in usbdivar.h might need to be amended, since this is no longer the case. As a bonus it allows us to remove the usedev parameter that was being passed around. Looking for testers, working fine here on my x1, with devices providing the information directly, devices gettting the info from the global usb_known_product/usb_known_vendor lists, and devices defaulting to print the USB IDs as a fallback (which is the case within bsd.rd) To look for regressions, compare usbdevs -vd and lsusb -v (from usbutils pkg) outputs with and without the diff. Landry
? usb_subr.c.dbg Index: ugen.c =================================================================== RCS file: /cvs/src/sys/dev/usb/ugen.c,v retrieving revision 1.97 diff -u -r1.97 ugen.c --- ugen.c 30 Dec 2017 23:08:29 -0000 1.97 +++ ugen.c 25 Apr 2018 18:32:36 -0000 @@ -1202,7 +1202,7 @@ } case USB_GET_DEVICEINFO: usbd_fill_deviceinfo(sc->sc_udev, - (struct usb_device_info *)addr, 1); + (struct usb_device_info *)addr); break; default: return (EINVAL); Index: uhid.c =================================================================== RCS file: /cvs/src/sys/dev/usb/uhid.c,v retrieving revision 1.70 diff -u -r1.70 uhid.c --- uhid.c 30 Dec 2017 20:46:59 -0000 1.70 +++ uhid.c 25 Apr 2018 18:32:36 -0000 @@ -364,7 +364,7 @@ case USB_GET_DEVICEINFO: usbd_fill_deviceinfo(sc->sc_hdev.sc_udev, - (struct usb_device_info *)addr, 1); + (struct usb_device_info *)addr); break; case USB_GET_REPORT_DESC: Index: umass_scsi.c =================================================================== RCS file: /cvs/src/sys/dev/usb/umass_scsi.c,v retrieving revision 1.45 diff -u -r1.45 umass_scsi.c --- umass_scsi.c 3 Aug 2016 13:44:49 -0000 1.45 +++ umass_scsi.c 25 Apr 2018 18:32:36 -0000 @@ -160,7 +160,7 @@ if (sc->maxlun > 0) return (0); - usbd_fill_deviceinfo(sc->sc_udev, &udi, 1); + usbd_fill_deviceinfo(sc->sc_udev, &udi); /* * Create a fake devid using the vendor and product ids and the last Index: uoak_subr.c =================================================================== RCS file: /cvs/src/sys/dev/usb/uoak_subr.c,v retrieving revision 1.8 diff -u -r1.8 uoak_subr.c --- uoak_subr.c 9 Jan 2017 14:44:28 -0000 1.8 +++ uoak_subr.c 25 Apr 2018 18:32:36 -0000 @@ -231,7 +231,7 @@ uoak_get_devinfo(struct uoak_softc *sc) { /* get device serial# */ - usbd_fill_deviceinfo(sc->sc_udev, &sc->sc_udi, 1); + usbd_fill_deviceinfo(sc->sc_udev, &sc->sc_udi); } void Index: usb.c =================================================================== RCS file: /cvs/src/sys/dev/usb/usb.c,v retrieving revision 1.118 diff -u -r1.118 usb.c --- usb.c 26 Feb 2018 13:06:49 -0000 1.118 +++ usb.c 25 Apr 2018 18:32:36 -0000 @@ -527,7 +527,7 @@ if (dev == NULL) return; - usbd_fill_deviceinfo(dev, di, 0); + usbd_fill_deviceinfo(dev, di); } void Index: usb_subr.c =================================================================== RCS file: /cvs/src/sys/dev/usb/usb_subr.c,v retrieving revision 1.135 diff -u -r1.135 usb_subr.c --- usb_subr.c 24 Apr 2018 17:22:33 -0000 1.135 +++ usb_subr.c 25 Apr 2018 18:32:37 -0000 @@ -66,6 +66,7 @@ int usbd_getnewaddr(struct usbd_bus *); int usbd_print(void *, const char *); void usbd_free_iface_data(struct usbd_device *, int); +int usbd_cache_devinfo(struct usbd_device *); usbd_status usbd_probe_and_attach(struct device *, struct usbd_device *, int, int); @@ -230,70 +231,70 @@ return (buf); } -void -usbd_devinfo_vp(struct usbd_device *dev, char *v, size_t vl, - char *p, size_t pl, int usedev) +int +usbd_cache_devinfo(struct usbd_device *dev) { usb_device_descriptor_t *udd = &dev->ddesc; - char *vendor = NULL, *product = NULL; -#ifdef USBVERBOSE - const struct usb_known_vendor *ukv; - const struct usb_known_product *ukp; -#endif - if (dev == NULL) { - v[0] = p[0] = '\0'; - return; - } + dev->serial = malloc(USB_MAX_STRING_LEN, M_USB, M_NOWAIT); + if (dev->serial == NULL) + return (ENOMEM); - if (usedev) { - vendor = usbd_get_string(dev, udd->iManufacturer, v, vl); - usbd_trim_spaces(vendor); - product = usbd_get_string(dev, udd->iProduct, p, pl); - usbd_trim_spaces(product); + if (usbd_get_string(dev, udd->iSerialNumber, dev->serial, USB_MAX_STRING_LEN) != NULL) { + usbd_trim_spaces(dev->serial); } else { - if (dev->vendor != NULL) - vendor = dev->vendor; - if (dev->product != NULL) - product = dev->product; + free(dev->serial, M_USB, USB_MAX_STRING_LEN); + dev->serial = NULL; } + + dev->vendor = malloc(USB_MAX_STRING_LEN, M_USB, M_NOWAIT); + if (dev->vendor == NULL) + return (ENOMEM); + + if (usbd_get_string(dev, udd->iManufacturer, dev->vendor, USB_MAX_STRING_LEN) != NULL) { + usbd_trim_spaces(dev->vendor); + } else { #ifdef USBVERBOSE - if (vendor == NULL || product == NULL) { - for (ukv = usb_known_vendors; - ukv->vendorname != NULL; - ukv++) { + const struct usb_known_vendor *ukv; + + for (ukv = usb_known_vendors; ukv->vendorname != NULL; ukv++) { if (ukv->vendor == UGETW(udd->idVendor)) { - vendor = ukv->vendorname; + strlcpy(dev->vendor, ukv->vendorname, + USB_MAX_STRING_LEN); break; } } - if (vendor != NULL) { - for (ukp = usb_known_products; - ukp->productname != NULL; - ukp++) { - if (ukp->vendor == UGETW(udd->idVendor) && - (ukp->product == UGETW(udd->idProduct))) { - product = ukp->productname; - break; - } + if (ukv->vendorname == NULL) +#endif + snprintf(dev->vendor, USB_MAX_STRING_LEN, "vendor 0x%04x", + UGETW(udd->idVendor)); + } + + dev->product = malloc(USB_MAX_STRING_LEN, M_USB, M_NOWAIT); + if (dev->product == NULL) + return (ENOMEM); + + if (usbd_get_string(dev, udd->iProduct, dev->product, USB_MAX_STRING_LEN) != NULL) { + usbd_trim_spaces(dev->product); + } else { +#ifdef USBVERBOSE + const struct usb_known_product *ukp; + + for (ukp = usb_known_products; ukp->productname != NULL; ukp++) { + if (ukp->vendor == UGETW(udd->idVendor) && + (ukp->product == UGETW(udd->idProduct))) { + strlcpy(dev->product, ukp->productname, + USB_MAX_STRING_LEN); + break; } } - } + if (ukp->productname == NULL) #endif + snprintf(dev->product, USB_MAX_STRING_LEN, "product 0x%04x", + UGETW(udd->idProduct)); + } - if (v == vendor) - ; - else if (vendor != NULL && *vendor) - strlcpy(v, vendor, vl); - else - snprintf(v, vl, "vendor 0x%04x", UGETW(udd->idVendor)); - - if (p == product) - ; - else if (product != NULL && *product) - strlcpy(p, product, pl); - else - snprintf(p, pl, "product 0x%04x", UGETW(udd->idProduct)); + return (0); } int @@ -313,13 +314,10 @@ usbd_devinfo(struct usbd_device *dev, int showclass, char *base, size_t len) { usb_device_descriptor_t *udd = &dev->ddesc; - char vendor[USB_MAX_STRING_LEN]; - char product[USB_MAX_STRING_LEN]; char *cp = base; int bcdDevice, bcdUSB; - usbd_devinfo_vp(dev, vendor, sizeof vendor, product, sizeof product, 0); - snprintf(cp, len, "\"%s %s\"", vendor, product); + snprintf(cp, len, "\"%s %s\"", dev->vendor, dev->product); cp += strlen(cp); if (showclass) { snprintf(cp, base + len - cp, ", class %d/%d", @@ -1237,10 +1235,13 @@ DPRINTF(("usbd_new_device: new dev (addr %d), dev=%p, parent=%p\n", addr, dev, parent)); - /* Cache some strings if possible. */ - dev->vendor = usbd_get_device_string(dev, dev->ddesc.iManufacturer); - dev->product = usbd_get_device_string(dev, dev->ddesc.iProduct); - dev->serial = usbd_get_device_string(dev, dev->ddesc.iSerialNumber); + /* Get device info and cache it */ + err = usbd_cache_devinfo(dev); + if (err) { + usb_free_device(dev); + up->device = NULL; + return (err); + } err = usbd_probe_and_attach(parent, dev, port, addr); if (err) { @@ -1300,16 +1301,15 @@ } void -usbd_fill_deviceinfo(struct usbd_device *dev, struct usb_device_info *di, - int usedev) +usbd_fill_deviceinfo(struct usbd_device *dev, struct usb_device_info *di) { struct usbd_port *p; int i, err, s; di->udi_bus = dev->bus->usbctl->dv_unit; di->udi_addr = dev->address; - usbd_devinfo_vp(dev, di->udi_vendor, sizeof(di->udi_vendor), - di->udi_product, sizeof(di->udi_product), usedev); + strlcpy(di->udi_vendor, dev->vendor, sizeof(di->udi_vendor)); + strlcpy(di->udi_product, dev->product, sizeof(di->udi_product)); usbd_printBCD(di->udi_release, sizeof di->udi_release, UGETW(dev->ddesc.bcdDevice)); di->udi_vendorNo = UGETW(dev->ddesc.idVendor); @@ -1358,13 +1358,9 @@ di->udi_nports = 0; bzero(di->udi_serial, sizeof(di->udi_serial)); - if (!usedev && dev->serial != NULL) { + if (dev->serial != NULL) strlcpy(di->udi_serial, dev->serial, sizeof(di->udi_serial)); - } else { - usbd_get_string(dev, dev->ddesc.iSerialNumber, - di->udi_serial, sizeof(di->udi_serial)); - } } /* Retrieve a complete descriptor for a certain device and index. */ Index: usbdi.h =================================================================== RCS file: /cvs/src/sys/dev/usb/usbdi.h,v retrieving revision 1.69 diff -u -r1.69 usbdi.h --- usbdi.h 15 May 2017 11:05:51 -0000 1.69 +++ usbdi.h 25 Apr 2018 18:32:37 -0000 @@ -129,7 +129,7 @@ usb_device_descriptor_t *usbd_get_device_descriptor(struct usbd_device *dev); usbd_status usbd_set_interface(struct usbd_interface *, int); int usbd_get_no_alts(usb_config_descriptor_t *, int); -void usbd_fill_deviceinfo(struct usbd_device *, struct usb_device_info *, int); +void usbd_fill_deviceinfo(struct usbd_device *, struct usb_device_info *); usb_config_descriptor_t *usbd_get_cdesc(struct usbd_device *, int, u_int *); int usbd_get_interface_altindex(struct usbd_interface *iface); Index: usbdivar.h =================================================================== RCS file: /cvs/src/sys/dev/usb/usbdivar.h,v retrieving revision 1.74 diff -u -r1.74 usbdivar.h --- usbdivar.h 24 Apr 2018 17:22:33 -0000 1.74 +++ usbdivar.h 25 Apr 2018 18:32:37 -0000 @@ -257,8 +257,6 @@ usbd_status usb_insert_transfer(struct usbd_xfer *); void usb_transfer_complete(struct usbd_xfer *); int usbd_detach(struct usbd_device *, struct device *); -void usbd_devinfo_vp(struct usbd_device *, char *, size_t, - char *, size_t, int); /* Routines from usb.c */ void usb_needs_explore(struct usbd_device *, int); Index: uvideo.c =================================================================== RCS file: /cvs/src/sys/dev/usb/uvideo.c,v retrieving revision 1.197 diff -u -r1.197 uvideo.c --- uvideo.c 24 Apr 2018 17:22:33 -0000 1.197 +++ uvideo.c 25 Apr 2018 18:32:38 -0000 @@ -2781,14 +2781,10 @@ uvideo_querycap(void *v, struct v4l2_capability *caps) { struct uvideo_softc *sc = v; - char vendor[USB_MAX_STRING_LEN]; - char product[USB_MAX_STRING_LEN]; bzero(caps, sizeof(*caps)); strlcpy(caps->driver, DEVNAME(sc), sizeof(caps->driver)); - usbd_devinfo_vp(sc->sc_udev, vendor, sizeof (vendor), product, - sizeof (product), 0); - strlcpy(caps->card, product, sizeof(caps->card)); + strlcpy(caps->card, sc->sc_udev->product, sizeof(caps->card)); strlcpy(caps->bus_info, "usb", sizeof(caps->bus_info)); caps->version = 1;