Index: usbdevs.c =================================================================== RCS file: /cvsroot/src/usr.sbin/usbdevs/usbdevs.c,v retrieving revision 1.37 diff -p -u -r1.37 usbdevs.c --- usbdevs.c 21 Sep 2019 16:22:25 -0000 1.37 +++ usbdevs.c 21 Sep 2019 22:45:27 -0000 @@ -34,10 +34,12 @@ __RCSID("$NetBSD: usbdevs.c,v 1.37 2019/09/21 16:22:25 gson Exp $"); #endif +#include +#include + #include #include #include -#include #include #include #include @@ -45,6 +47,8 @@ __RCSID("$NetBSD: usbdevs.c,v 1.37 2019/ #include #include #include +#include + #include #define USBDEV "/dev/usb" @@ -315,6 +319,50 @@ dumpone(char *name, int f, int addr) usbdump(f); } +static int +getusbcount_device(int fd, const char *dev, int depth) +{ + struct devlistargs laa = { + .l_childname = NULL, + .l_children = 0, + }; + size_t i; + size_t children; + int nbusses = 0; + + if (depth && (dev == NULL || *dev == '\0')) + return 0; + + /* + * Look for children that match "usb[0-9]*". Could maybe + * simply return 1 here, but there's always a chance that + * someone has eg, a USB to PCI bridge, with a USB + * controller behind PCI. + */ + if (strncmp(dev, "usb", 3) == 0 && isdigit((int)dev[3])) + nbusses++; + + strlcpy(laa.l_devname, dev, sizeof(laa.l_devname)); + + if (ioctl(fd, DRVLISTDEV, &laa) == -1) + err(EXIT_FAILURE, "DRVLISTDEV"); + children = laa.l_children; + + laa.l_childname = malloc(children * sizeof(laa.l_childname[0])); + if (laa.l_childname == NULL) + err(EXIT_FAILURE, "out of memory"); + if (ioctl(fd, DRVLISTDEV, &laa) == -1) + err(EXIT_FAILURE, "DRVLISTDEV"); + if (laa.l_children > children) + err(EXIT_FAILURE, "DRVLISTDEV: number of children grew"); + + for (i = 0; i < laa.l_children; i++) { + nbusses += getusbcount_device(fd, laa.l_childname[i], depth+1); + } + + return nbusses; +} + int main(int argc, char **argv) { @@ -347,7 +395,17 @@ main(int argc, char **argv) argv += optind; if (dev == NULL) { - for (ncont = 0, i = 0; i < 16; i++) { + int nbusses; + int fd = open(DRVCTLDEV, O_RDONLY, 0); + + /* If no drvctl configured, default to 16. */ + if (fd != -1) + nbusses = getusbcount_device(fd, "", 0); + else + nbusses = 16; + close(fd); + + for (ncont = 0, i = 0; i < nbusses; i++) { snprintf(buf, sizeof(buf), "%s%d", USBDEV, i); f = open(buf, O_RDONLY); if (f >= 0) {