Hi,

Attached below an updated patch that makes the layout a bit more sensible.

Index: usr.sbin/usbdevs/usbdevs.8
===================================================================
RCS file: /cvs/src/usr.sbin/usbdevs/usbdevs.8,v
retrieving revision 1.9
diff -u -p -r1.9 usbdevs.8
--- usr.sbin/usbdevs/usbdevs.8  26 Jun 2008 05:42:21 -0000      1.9
+++ usr.sbin/usbdevs/usbdevs.8  13 Apr 2015 16:46:59 -0000
@@ -54,7 +54,13 @@ Show the device drivers associated with 
 .It Fl f Ar dev
 Only print information for the given USB controller.
 .It Fl v
-Be verbose.
+Verbose mode.  Causes
+.Nm
+to display detailed information about the devices present.
+Multiple
+.Fl v
+options increase verbosity.  At level 1 or above the device
+and configuration descriptors will be shown.
 .El
 .Sh FILES
 .Bl -tag -width Pa
Index: usr.sbin/usbdevs/usbdevs.c
===================================================================
RCS file: /cvs/src/usr.sbin/usbdevs/usbdevs.c,v
retrieving revision 1.24
diff -u -p -r1.24 usbdevs.c
--- usr.sbin/usbdevs/usbdevs.c  31 Mar 2015 13:38:27 -0000      1.24
+++ usr.sbin/usbdevs/usbdevs.c  13 Apr 2015 16:46:59 -0000
@@ -30,14 +30,17 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <sys/types.h>
+
+#include <err.h>
+#include <errno.h>
+#include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/types.h>
 #include <fcntl.h>
 #include <unistd.h>
-#include <err.h>
-#include <errno.h>
+
 #include <dev/usb/usb.h>
 
 #ifndef nitems
@@ -45,15 +48,29 @@
 #endif
 
 #define USBDEV "/dev/usb"
+#define INDENT_LEVEL 3
 
-int verbose = 0;
-int showdevs = 0;
+int verbose;
+int showdevs;
+
+int indent;
+char done[USB_MAX_DEVICES];
 
 void usage(void);
+void pushlevel(void);
+void poplevel(void);
+void printent(const char *, ...);
+int getddesc(int, int, int, struct usb_device_ddesc *);
+int getcdesc(int, int, int, struct usb_device_cdesc *);
+int getfdesc(int, int, int, int, struct usb_device_fdesc *);
+void dumpedesc(usb_endpoint_descriptor_t *);
+void dumpidesc(usb_interface_descriptor_t *);
+void dumpcdesc(usb_config_descriptor_t *);
+void dumpddesc(usb_device_descriptor_t *);
+void dumpdesc(int, int, int);
 void usbdev(int f, int a, int rec);
 void usbdump(int f);
 void dumpone(char *name, int f, int addr);
-int main(int, char **);
 
 extern char *__progname;
 
@@ -64,8 +81,256 @@ usage(void)
        exit(1);
 }
 
-char done[USB_MAX_DEVICES];
-int indent;
+void
+pushlevel(void)
+{
+       indent += INDENT_LEVEL;
+}
+
+void
+poplevel(void)
+{
+       indent -= INDENT_LEVEL;
+}
+
+void
+printent(const char *fmt, ...)
+{
+       va_list ap;
+
+       va_start(ap, fmt);
+       printf("%*s", indent, "");
+       vprintf(fmt, ap);
+       va_end(ap);
+}
+
+int
+getddesc(int f, int b, int a, struct usb_device_ddesc *ddesc)
+{
+       int r;
+
+       ddesc->udd_bus = b;
+       ddesc->udd_addr = a;
+       r = ioctl(f, USB_DEVICE_GET_DDESC, ddesc);
+       if (r) {
+               if (errno != ENXIO)
+                       warn("USB_DEVICE_GET_DDESC");
+               return -1;
+       }
+       return 0;
+}
+
+int
+getcdesc(int f, int b, int a, struct usb_device_cdesc *cdesc)
+{
+       int r;
+
+       cdesc->udc_bus = b;
+       cdesc->udc_addr = a;
+       cdesc->udc_config_index = USB_CURRENT_CONFIG_INDEX;
+       r = ioctl(f, USB_DEVICE_GET_CDESC, cdesc);
+       if (r) {
+               warn("USB_DEVICE_GET_CDESC");
+               return -1;
+       }
+       return 0;
+}
+
+int
+getfdesc(int f, int b, int a, int l, struct usb_device_fdesc *fdesc)
+{
+       int r;
+
+       fdesc->udf_bus = b;
+       fdesc->udf_addr = a;
+       fdesc->udf_config_index = USB_CURRENT_CONFIG_INDEX;
+       fdesc->udf_size = l;
+       fdesc->udf_data = malloc(l);
+       if (!fdesc->udf_data)
+               err(1, "malloc");
+       r = ioctl(f, USB_DEVICE_GET_FDESC, fdesc);
+       if (r) {
+               warn("USB_DEVICE_GET_FDESC");
+               free(fdesc->udf_data);
+               return -1;
+       }
+       return 0;
+}
+
+void
+dumpedesc(usb_endpoint_descriptor_t *ed)
+{
+       char *xfertype, *synchtype;
+
+       printent("Endpoint Descriptor:\n");
+       pushlevel();
+       printent("bLength:          %d\n", ed->bLength);
+       printent("bDescriptorType:  %d\n", ed->bDescriptorType);
+       printent("bEndpointAddress: %#x EP %d %s\n", ed->bEndpointAddress,
+              UE_GET_ADDR(ed->bEndpointAddress),
+              UE_GET_DIR(ed->bEndpointAddress) ? "in" : "out");
+       printent("bmAttributes:     %#x\n", ed->bmAttributes);
+
+       switch (UE_GET_XFERTYPE(ed->bmAttributes)) {
+       case UE_CONTROL:
+               xfertype = "Control";
+               break;
+       case UE_ISOCHRONOUS:
+               xfertype = "Isochronous";
+               break;
+       case UE_BULK:
+               xfertype = "Bulk";
+               break;
+       case UE_INTERRUPT:
+               xfertype = "Interrupt";
+               break;
+       default:
+               xfertype = "Unknown";
+               break;
+       }
+
+       switch (UE_GET_ISO_TYPE(ed->bmAttributes)) {
+       case UE_ISO_ASYNC:
+               synchtype = "Asynchronous";
+               break;
+       case UE_ISO_ADAPT:
+               synchtype = "Adaptive";
+               break;
+       case UE_ISO_SYNC:
+               synchtype = "Synchronous";
+               break;
+       default:
+               synchtype = "No Synchronization";
+               break;
+       }
+
+       pushlevel();
+       printent("Transfer type:    %s\n", xfertype);
+       printent("Synch type:       %s\n", synchtype);
+       poplevel();
+
+       printent("wMaxPacketSize:   %d\n", UGETW(ed->wMaxPacketSize));
+       printent("bInterval:        %d\n", ed->bInterval);
+       poplevel();
+}
+
+void
+dumpidesc(usb_interface_descriptor_t *ifd)
+{
+       printent("Interface Descriptor:\n");
+       pushlevel();
+       printent("bLength:            %d\n", ifd->bLength);
+       printent("bDescriptorType:    %d\n", ifd->bDescriptorType);
+       printent("bInterfaceNumber:   %d\n", ifd->bInterfaceNumber);
+       printent("bAlternateSetting:  %d\n", ifd->bAlternateSetting);
+       printent("bNumEndpoints:      %d\n", ifd->bNumEndpoints);
+       printent("bInterfaceClass:    %d\n", ifd->bInterfaceClass);
+       printent("bInterfaceSubClass: %d\n", ifd->bInterfaceSubClass);
+       printent("bInterfaceProtocol: %d\n", ifd->bInterfaceProtocol);
+       printent("iInterface:         %d\n", ifd->iInterface);
+       poplevel();
+}
+
+void
+dumpcdesc(usb_config_descriptor_t *cd)
+{
+       printent("Configuration Descriptor:\n");
+       pushlevel();
+       printent("bLength:             %d\n", cd->bLength);
+       printent("bDescriptorType:     %d\n", cd->bDescriptorType);
+       printent("wTotalLength:        %d\n", UGETW(cd->wTotalLength));
+       printent("bNumInterface:       %d\n", cd->bNumInterface);
+       printent("bConfigurationValue: %d\n", cd->bConfigurationValue);
+       printent("iConfiguration:      %d\n", cd->iConfiguration);
+       printent("bmAttributes:        %#x\n", cd->bmAttributes);
+
+       pushlevel();
+       if (cd->bmAttributes & UC_SELF_POWERED)
+               printent("Self Powered\n");
+       if (cd->bmAttributes & UC_REMOTE_WAKEUP)
+               printent("Remove Wakeup\n");
+       poplevel();
+
+       printent("bMaxPower:           %d mA\n", cd->bMaxPower * 2);
+       poplevel();
+}
+
+void
+dumpddesc(usb_device_descriptor_t *dd)
+{
+       printent("Device Descriptor:\n");
+       pushlevel();
+       printent("bLength:            %d\n", dd->bLength);
+       printent("bDescriptorType:    %d\n", dd->bDescriptorType);
+       printent("bcdUSB:             %#x\n", UGETW(dd->bcdUSB));
+       printent("bDeviceClass:       %d\n", dd->bDeviceClass);
+       printent("bDeviceSubClass:    %d\n", dd->bDeviceSubClass);
+       printent("bDeviceProtocol:    %d\n", dd->bDeviceProtocol);
+       printent("bMaxPacketSize:     %d\n", dd->bMaxPacketSize);
+       printent("idVendor:           %#x\n", UGETW(dd->idVendor));
+       printent("idProduct:          %#x\n", UGETW(dd->idProduct));
+       printent("bcdDevice:          %#x\n", UGETW(dd->bcdDevice));
+       printent("iManufacturer:      %d\n", dd->iManufacturer);
+       printent("iProduct:           %d\n", dd->iProduct);
+       printent("iSerialNumber:      %d\n", dd->iSerialNumber);
+       printent("bNumConfigurations: %d\n", dd->bNumConfigurations);
+       poplevel();
+}
+
+void
+dumpdesc(int f, int b, int a)
+{
+       struct usb_device_ddesc ddesc;
+       struct usb_device_cdesc cdesc;
+       struct usb_device_fdesc fdesc;
+       char *p;
+       int i, j, k, r;
+
+       r = getddesc(f, b, a, &ddesc);
+       if (r < 0)
+               return;
+
+       r = getcdesc(f, b, a, &cdesc);
+       if (r < 0)
+               return;
+
+       r = getfdesc(f, b, a, UGETW(cdesc.udc_desc.wTotalLength), &fdesc);
+       if (r < 0)
+               return;
+
+       pushlevel();
+       dumpddesc(&ddesc.udd_desc);
+       p = fdesc.udf_data;
+       for (i = 0; i < ddesc.udd_desc.bNumConfigurations; i++) {
+               usb_config_descriptor_t *cd;
+
+               cd = (usb_config_descriptor_t *)p;
+               p += cd->bLength;
+               pushlevel();
+               dumpcdesc(cd);
+               for (j = 0; j < cd->bNumInterface; j++) {
+                       usb_interface_descriptor_t *ifd;
+                       
+                       ifd = (usb_interface_descriptor_t *)p;
+                       p += ifd->bLength;
+                       pushlevel();
+                       dumpidesc(ifd);
+                       for (k = 0; k < ifd->bNumEndpoints; k++) {
+                               usb_endpoint_descriptor_t *ed;
+
+                               ed = (usb_endpoint_descriptor_t *)p;
+                               p += ed->bLength;
+                               pushlevel();
+                               dumpedesc(ed);
+                               poplevel();
+                       }
+                       poplevel();
+               }
+               poplevel();
+       }
+       poplevel();
+       free(fdesc.udf_data);
+}
 
 void
 usbdev(int f, int a, int rec)
@@ -118,13 +383,14 @@ usbdev(int f, int a, int rec)
                        printf(", iSerialNumber %s", di.udi_serial);
        } else
                printf("%s, %s", di.udi_product, di.udi_vendor);
-       printf("\n");
+       putchar('\n');
        if (showdevs) {
                for (i = 0; i < USB_MAX_DEVNAMES; i++)
                        if (di.udi_devnames[i][0])
-                               printf("%*s  %s\n", indent, "",
-                                   di.udi_devnames[i]);
+                               printent("%s\n", di.udi_devnames[i]);
        }
+       if (verbose > 1)
+               dumpdesc(f, di.udi_bus, di.udi_addr);
        if (!rec)
                return;
        for (p = 0; p < di.udi_nports && p < nitems(di.udi_ports); p++) {
@@ -132,24 +398,26 @@ usbdev(int f, int a, int rec)
 
                if (s >= USB_MAX_DEVICES) {
                        if (verbose) {
-                               printf("%*sport %d %s\n", indent+1, "", p+1,
+                               pushlevel();
+                               printent("port %d %s\n", p+1,
                                    s == USB_PORT_ENABLED ? "enabled" :
                                    s == USB_PORT_SUSPENDED ? "suspended" :
                                    s == USB_PORT_POWERED ? "powered" :
                                    s == USB_PORT_DISABLED ? "disabled" :
                                    "???");
+                               poplevel();
                        }
                        continue;
                }
-               indent++;
-               printf("%*s", indent, "");
+               pushlevel();
+               printent("");
                if (verbose)
                        printf("port %d ", p+1);
                if (s == 0)
                        printf("addr 0 should never happen!\n");
                else
                        usbdev(f, s, 1);
-               indent--;
+               poplevel();
        }
 }
 
@@ -201,7 +469,7 @@ main(int argc, char **argv)
                        dev = optarg;
                        break;
                case 'v':
-                       verbose = 1;
+                       verbose++;
                        break;
                default:
                        usage();

Reply via email to