Hi everyone,

This is a preliminary patch that adds descriptor dumping support
to usbdevs(8).  I have attempted to keep any unnecessary changes to
a minimum.  I will do some cleanup work incrementally on top of
this patch.

I've tested this on a single machine running -current so more testing
would be nice.

Let me know what you think and I will rework my patch.

Cheers,
Dimitris

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 13:57:27 -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 13:57:27 -0000
@@ -50,6 +50,14 @@ int verbose = 0;
 int showdevs = 0;
 
 void usage(void);
+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);
@@ -67,6 +75,236 @@ usage(void)
 char done[USB_MAX_DEVICES];
 int indent;
 
+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) {
+               if (errno != ENXIO)
+                       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) {
+               if (errno != ENXIO)
+                       warn("USB_DEVICE_GET_FDESC");
+               free(fdesc->udf_data);
+               return -1;
+       }
+       return 0;
+}
+
+void
+dumpedesc(usb_endpoint_descriptor_t *ed)
+{
+       char *xfertype, *synchtype;
+
+       printf("%*sEndpoint Descriptor:\n", indent, "");
+       indent++;
+       printf("%*sbLength: %d\n", indent, "", ed->bLength);
+       printf("%*sbDescriptorType: %d\n", indent, "", ed->bDescriptorType);
+       printf("%*sbEndpointAddress: %#x EP %d %s\n", indent, "", 
ed->bEndpointAddress,
+              UE_GET_ADDR(ed->bEndpointAddress),
+              UE_GET_DIR(ed->bEndpointAddress) ? "in" : "out");
+       printf("%*sbmAttributes: %#x\n", indent, "", 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;
+       }
+
+       indent++;
+       printf("%*sTransfer type: %s\n", indent, "", xfertype);
+       printf("%*sSynch type: %s\n", indent, "", synchtype);
+       indent--;
+
+       printf("%*swMaxPacketSize: %#x\n", indent, "", 
UGETW(ed->wMaxPacketSize));
+       printf("%*sbInterval: %d\n", indent, "", ed->bInterval);
+       indent--;
+}
+
+void
+dumpidesc(usb_interface_descriptor_t *ifd)
+{
+       printf("%*sInterface Descriptor:\n", indent, "");
+       indent++;
+       printf("%*sbLength: %d\n", indent, "", ifd->bLength);
+       printf("%*sbDescriptorType: %d\n", indent, "", ifd->bDescriptorType);
+       printf("%*sbInterfaceNumber: %d\n", indent, "", ifd->bInterfaceNumber);
+       printf("%*sbAlternateSetting: %d\n", indent, "", 
ifd->bAlternateSetting);
+       printf("%*sbNumEndpoints: %d\n", indent, "", ifd->bNumEndpoints);
+       printf("%*sbInterfaceClass: %d\n", indent, "", ifd->bInterfaceClass);
+       printf("%*sbInterfaceSubClass: %d\n", indent, "", 
ifd->bInterfaceSubClass);
+       printf("%*sbInterfaceProtocol: %d\n", indent, "", 
ifd->bInterfaceProtocol);
+       printf("%*siInterface: %d\n", indent, "", ifd->iInterface);
+       indent--;
+}
+
+void
+dumpcdesc(usb_config_descriptor_t *cd)
+{
+       printf("%*sConfiguration Descriptor:\n", indent, "");
+       indent++;
+       printf("%*sbLength: %d\n", indent, "", cd->bLength);
+       printf("%*sbDescriptorType: %d\n", indent, "", cd->bDescriptorType);
+       printf("%*swTotalLength: %d\n", indent, "", UGETW(cd->wTotalLength));
+       printf("%*sbNumInterface: %d\n", indent, "", cd->bNumInterface);
+       printf("%*sbConfigurationValue: %d\n", indent, "", 
cd->bConfigurationValue);
+       printf("%*siConfiguration: %d\n", indent, "", cd->iConfiguration);
+       printf("%*sbmAttributes: %#x\n", indent, "", cd->bmAttributes);
+       indent++;
+       if (cd->bmAttributes & UC_BUS_POWERED)
+               printf("%*sBus Powered\n", indent, "");
+       else if (cd->bmAttributes & UC_SELF_POWERED)
+               printf("%*sSelf Powered\n", indent, "");
+       else if (cd->bmAttributes & UC_REMOTE_WAKEUP)
+               printf("%*sRemove Wakeup\n", indent, "");
+       indent--;
+       printf("%*sbMaxPower: %dmA\n", indent, "", cd->bMaxPower * 2);
+       indent--;
+}
+
+void
+dumpddesc(usb_device_descriptor_t *dd)
+{
+       printf("%*sDevice Descriptor:\n", indent, "");
+       indent++;
+       printf("%*sbLength: %d\n", indent, "", dd->bLength);
+       printf("%*sbDescriptorType: %d\n", indent, "", dd->bDescriptorType);
+       printf("%*sbcdUSB: %#x\n", indent, "", UGETW(dd->bcdUSB));
+       printf("%*sbDeviceClass: %d\n", indent, "", dd->bDeviceClass);
+       printf("%*sbDeviceSubClass: %d\n", indent, "", dd->bDeviceSubClass);
+       printf("%*sbDeviceProtocol: %d\n", indent, "", dd->bDeviceProtocol);
+       printf("%*sbMaxPacketSize: %#x\n", indent, "", dd->bMaxPacketSize);
+       printf("%*sidVendor: %#x\n", indent, "", UGETW(dd->idVendor));
+       printf("%*sidProduct: %#x\n", indent, "", UGETW(dd->idProduct));
+       printf("%*sbcdDevice: %#x\n", indent, "", UGETW(dd->bcdDevice));
+       printf("%*siManufacturer: %d\n", indent, "", dd->iManufacturer);
+       printf("%*siProduct: %d\n", indent, "", dd->iProduct);
+       printf("%*siSerialNumber: %d\n", indent, "", dd->iSerialNumber);
+       printf("%*sbNumConfigurations: %d\n", indent, "", 
dd->bNumConfigurations);
+       indent--;
+}
+
+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;
+
+       indent++;
+       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;
+               indent++;
+               dumpcdesc(cd);
+               for (j = 0; j < cd->bNumInterface; j++) {
+                       usb_interface_descriptor_t *ifd;
+                       
+                       ifd = (usb_interface_descriptor_t *)p;
+                       p += ifd->bLength;
+                       indent++;
+                       dumpidesc(ifd);
+                       for (k = 0; k < ifd->bNumEndpoints; k++) {
+                               usb_endpoint_descriptor_t *ed;
+
+                               ed = (usb_endpoint_descriptor_t *)p;
+                               p += ed->bLength;
+                               indent++;
+                               dumpedesc(ed);
+                               indent--;
+                       }
+                       indent--;
+               }
+               indent--;
+       }
+       indent--;
+       free(fdesc.udf_data);
+}
+
 void
 usbdev(int f, int a, int rec)
 {
@@ -122,9 +360,11 @@ usbdev(int f, int a, int rec)
        if (showdevs) {
                for (i = 0; i < USB_MAX_DEVNAMES; i++)
                        if (di.udi_devnames[i][0])
-                               printf("%*s  %s\n", indent, "",
+                               printf("%*s %s\n", indent, "",
                                    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++) {
@@ -201,7 +441,7 @@ main(int argc, char **argv)
                        dev = optarg;
                        break;
                case 'v':
-                       verbose = 1;
+                       verbose++;
                        break;
                default:
                        usage();

Reply via email to