[PATCH 4/4] usbutils: Print Binary Object Store descriptor.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Wireless USB devices and USB 3.0 devices both have Binary Object Store
(BOS) descriptors.  Some USB 2.0 devices also may also have a BOS
descriptor.

Add printing for 3 of the 4 Device Capability descriptors within the BOS
descriptor: USB 2.0 Extension, SuperSpeed USB, and Container ID device
capability descriptors.  I didn't add the Wireless USB case, because I
have no devices to test with.

Here's sample output of the BOS descriptor from lsusb -v:

Binary Object Store Descriptor:
  bLength                 5
  bDescriptorType        15
  wTotalLength           42
  bNumDeviceCaps          3
  USB 2.0 Extension Device Capability:
    bLength                 7
    bDescriptorType        16
    bDevCapabilityType      2
    bmAttributes   0x00000002
      Link Power Management (LPM) Supported
  SuperSpeed USB Device Capability:
    bLength                10
    bDescriptorType        16
    bDevCapabilityType      3
    bmAttributes         0x00
      Latency Tolerance Messages (LTM) Supported
    wSpeedsSupported   0x000f
      Device can operate at Low Speed (1Mbps)
      Device can operate at Full Speed (12Mbps)
      Device can operate at High Speed (480Mbps)
      Device can operate at SuperSpeed (5Gbps)
    bFunctionalitySupport   0
      Lowest fully-functional device speed is Low Speed (1Mbps)
    bU1DevExitLat           0 micro seconds
    bU2DevExitLat        1255 micro seconds
  Container ID Device Capability:
    bLength                20
    bDescriptorType        16
    bDevCapabilityType      4
    bReserved               0
    ContainerID             {00000000-0000-0000-0000-000000000000}

Signed-off-by: Sarah Sharp <sarah.a.sharp@xxxxxxxxxxxxxxx>
---
 lsusb.c |  176 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 176 insertions(+), 0 deletions(-)

diff --git a/lsusb.c b/lsusb.c
index a6c64c5..52c6e79 100644
--- a/lsusb.c
+++ b/lsusb.c
@@ -67,6 +67,12 @@
 #define USB_DT_RC_INTERFACE		0x23
 #define USB_DT_SS_ENDPOINT_COMP		0x30
 
+/* Device Capability Type Codes (Wireless USB spec and USB 3.0 bus spec) */
+#define USB_DC_WIRELESS_USB		0x01
+#define USB_DC_20_EXTENSION		0x02
+#define USB_DC_SUPERSPEED		0x03
+#define USB_DC_CONTAINER_ID		0x04
+
 /* Conventional codes for class-specific descriptors.  The convention is
  * defined in the USB "Common Class" Spec (3.11).  Individual class specs
  * are authoritative for their usage, not the "common class" writeup.
@@ -3515,6 +3521,175 @@ static int do_wireless(struct usb_dev_handle *fd)
 	return 0;
 }
 
+static void dump_usb2_device_capability_desc(unsigned char *buf)
+{
+	unsigned int wide;
+
+	wide = buf[3] + (buf[4] << 8) +
+		(buf[5] << 8) + (buf[6] << 8);
+	printf("  USB 2.0 Extension Device Capability:\n"
+			"    bLength             %5u\n"
+			"    bDescriptorType     %5u\n"
+			"    bDevCapabilityType  %5u\n"
+			"    bmAttributes   0x%08x\n",
+			buf[0], buf[1], buf[2], wide);
+	if (!(wide & 0x02))
+		printf("      (Missing must-be-set LPM bit!)\n");
+	else
+		printf("      Link Power Management (LPM)"
+				" Supported\n");
+}
+
+static void dump_ss_device_capability_desc(unsigned char *buf)
+{
+	if (buf[0] < 10) {
+		printf("  Bad SuperSpeed USB Device Capability descriptor.\n");
+		return;
+	}
+	printf("  SuperSpeed USB Device Capability:\n"
+			"    bLength             %5u\n"
+			"    bDescriptorType     %5u\n"
+			"    bDevCapabilityType  %5u\n"
+			"    bmAttributes         0x%02x\n",
+			buf[0], buf[1], buf[2], buf[3]);
+	if (!(buf[3] & 0x02))
+		printf("      Latency Tolerance Messages (LTM)"
+				" Supported\n");
+	printf("    wSpeedsSupported   0x%04x\n", buf[4]);
+	if (buf[4] & (1 << 0))
+		printf("      Device can operate at Low Speed (1Mbps)\n");
+	if (buf[4] & (1 << 1))
+		printf("      Device can operate at Full Speed (12Mbps)\n");
+	if (buf[4] & (1 << 2))
+		printf("      Device can operate at High Speed (480Mbps)\n");
+	if (buf[4] & (1 << 3))
+		printf("      Device can operate at SuperSpeed (5Gbps)\n");
+
+	printf("    bFunctionalitySupport %3u\n", buf[5]);
+	switch(buf[5]) {
+	case 0:
+		printf("      Lowest fully-functional device speed is "
+				"Low Speed (1Mbps)\n");
+		break;
+	case 1:
+		printf("      Lowest fully-functional device speed is "
+				"Full Speed (12Mbps)\n");
+		break;
+	case 2:
+		printf("      Lowest fully-functional device speed is "
+				"High Speed (480Mbps)\n");
+		break;
+	case 3:
+		printf("      Lowest fully-functional device speed is "
+				"SuperSpeed (5Gbps)\n");
+		break;
+	default:
+		printf("      Lowest fully-functional device speed is "
+				"at an unknown speed!\n");
+		break;
+	}
+	printf("    bU1DevExitLat        %4u micro seconds\n", buf[6]);
+	printf("    bU2DevExitLat    %8u micro seconds\n", buf[8] + (buf[7] << 8));
+}
+
+static void dump_container_id_device_capability_desc(unsigned char *buf)
+{
+	if (buf[0] < 20) {
+		printf("  Bad Container ID Device Capability descriptor.\n");
+		return;
+	}
+	printf("  Container ID Device Capability:\n"
+			"    bLength             %5u\n"
+			"    bDescriptorType     %5u\n"
+			"    bDevCapabilityType  %5u\n"
+			"    bReserved           %5u\n",
+			buf[0], buf[1], buf[2], buf[3]);
+	printf("    ContainerID             %s\n",
+			get_guid(&buf[4]));
+}
+
+static void dump_bos_descriptor(struct usb_dev_handle *fd)
+{
+	/* Total for all known BOS descriptors is 43 bytes:
+	 * 6 bytes for Wireless USB, 7 bytes for USB 2.0 extension,
+	 * 10 bytes for SuperSpeed, 20 bytes for Container ID.
+	 */
+	unsigned char bos_desc[43];
+	unsigned int bos_desc_size;
+	int size, ret;
+	unsigned char *buf;
+
+	/* Get the first 5 bytes to get the wTotalLength field */
+	ret = usb_control_msg(fd,
+			USB_ENDPOINT_IN | USB_RECIP_DEVICE,
+			USB_REQ_GET_DESCRIPTOR,
+			USB_DT_BOS << 8, 0,
+			bos_desc, 5, CTRL_TIMEOUT);
+	if (ret < 0)
+		return;
+
+	bos_desc_size = bos_desc[2] + (bos_desc[3] << 8);
+	printf("Binary Object Store Descriptor:\n"
+	       "  bLength             %5u\n"
+	       "  bDescriptorType     %5u\n"
+	       "  wTotalLength        %5u\n"
+	       "  bNumDeviceCaps      %5u\n",
+	       bos_desc[0], bos_desc[1],
+	       bos_desc_size, bos_desc[4]);
+
+	if (bos_desc_size <= 5) {
+		if (bos_desc[4] > 0)
+			fprintf(stderr, "Couldn't get "
+					"device capability descriptors\n");
+		return;
+	}
+	if (bos_desc_size > sizeof bos_desc) {
+		fprintf(stderr, "FIXME: alloc bigger buffer for "
+				"device capability descriptors\n");
+		return;
+	}
+
+	ret = usb_control_msg(fd,
+			USB_ENDPOINT_IN | USB_RECIP_DEVICE,
+			USB_REQ_GET_DESCRIPTOR,
+			USB_DT_BOS << 8, 0,
+			bos_desc, bos_desc_size, CTRL_TIMEOUT);
+	if (ret < 0) {
+		fprintf(stderr, "Couldn't get device capability descriptors\n");
+		return;
+	}
+
+	size = bos_desc_size - 5;
+	buf = &bos_desc[5];
+
+	while (size >= 3) {
+		if (buf[0] < 3) {
+			printf("buf[0] = %u\n", buf[0]);
+			return;
+		}
+		switch (buf[2]) {
+		case USB_DC_WIRELESS_USB:
+			/* FIXME */
+			break;
+		case USB_DC_20_EXTENSION:
+			dump_usb2_device_capability_desc(buf);
+			break;
+		case USB_DC_SUPERSPEED:
+			dump_ss_device_capability_desc(buf);
+			break;
+		case USB_DC_CONTAINER_ID:
+			dump_container_id_device_capability_desc(buf);
+			break;
+		default:
+			printf("  ** UNRECOGNIZED: ");
+			dump_bytes(buf, buf[0]);
+			break;
+		}
+		size -= buf[0];
+		buf += buf[0];
+	}
+}
+
 static void dumpdev(struct usb_device *dev)
 {
 	struct usb_dev_handle *udev;
@@ -3547,6 +3722,7 @@ static void dumpdev(struct usb_device *dev)
 		do_debug(udev);
 	}
 	dump_device_status(udev, otg, wireless);
+	dump_bos_descriptor(udev);
 	usb_close(udev);
 }
 
-- 
1.6.3.3

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux