Blame 0343-usb3-bos-decriptor.patch

Hans de Goede c8dfc6
From 52666569c1aa34531c101e005feccec0899c14e2 Mon Sep 17 00:00:00 2001
Hans de Goede c8dfc6
From: Gerd Hoffmann <kraxel@redhat.com>
Hans de Goede c8dfc6
Date: Tue, 28 Aug 2012 17:46:29 +0200
Hans de Goede c8dfc6
Subject: [PATCH 343/366] usb3: bos decriptor
Hans de Goede c8dfc6
Hans de Goede c8dfc6
Add support for creating BOS descriptor and
Hans de Goede c8dfc6
device cappability descriptors.
Hans de Goede c8dfc6
Hans de Goede c8dfc6
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Hans de Goede c8dfc6
---
Hans de Goede c8dfc6
 hw/usb.h      |   6 ++++
Hans de Goede c8dfc6
 hw/usb/desc.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Hans de Goede c8dfc6
 hw/usb/desc.h |  25 ++++++++++++++
Hans de Goede c8dfc6
 trace-events  |   1 +
Hans de Goede c8dfc6
 4 files changed, 141 insertions(+)
Hans de Goede c8dfc6
Hans de Goede c8dfc6
diff --git a/hw/usb.h b/hw/usb.h
Hans de Goede c8dfc6
index 78ffdf4..48c8926 100644
Hans de Goede c8dfc6
--- a/hw/usb.h
Hans de Goede c8dfc6
+++ b/hw/usb.h
Hans de Goede c8dfc6
@@ -135,10 +135,16 @@
Hans de Goede c8dfc6
 #define USB_DT_OTHER_SPEED_CONFIG       0x07
Hans de Goede c8dfc6
 #define USB_DT_DEBUG                    0x0A
Hans de Goede c8dfc6
 #define USB_DT_INTERFACE_ASSOC          0x0B
Hans de Goede c8dfc6
+#define USB_DT_BOS                      0x0F
Hans de Goede c8dfc6
+#define USB_DT_DEVICE_CAPABILITY        0x10
Hans de Goede c8dfc6
 #define USB_DT_CS_INTERFACE             0x24
Hans de Goede c8dfc6
 #define USB_DT_CS_ENDPOINT              0x25
Hans de Goede c8dfc6
 #define USB_DT_ENDPOINT_COMPANION       0x30
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
+#define USB_DEV_CAP_WIRELESS            0x01
Hans de Goede c8dfc6
+#define USB_DEV_CAP_USB2_EXT            0x02
Hans de Goede c8dfc6
+#define USB_DEV_CAP_SUPERSPEED          0x03
Hans de Goede c8dfc6
+
Hans de Goede c8dfc6
 #define USB_ENDPOINT_XFER_CONTROL	0
Hans de Goede c8dfc6
 #define USB_ENDPOINT_XFER_ISOC		1
Hans de Goede c8dfc6
 #define USB_ENDPOINT_XFER_BULK		2
Hans de Goede c8dfc6
diff --git a/hw/usb/desc.c b/hw/usb/desc.c
Hans de Goede c8dfc6
index 8f5a8e5..1f12eae 100644
Hans de Goede c8dfc6
--- a/hw/usb/desc.c
Hans de Goede c8dfc6
+++ b/hw/usb/desc.c
Hans de Goede c8dfc6
@@ -258,6 +258,111 @@ int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len)
Hans de Goede c8dfc6
     return bLength;
Hans de Goede c8dfc6
 }
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
+static int usb_desc_cap_usb2_ext(const USBDesc *desc, uint8_t *dest, size_t len)
Hans de Goede c8dfc6
+{
Hans de Goede c8dfc6
+    uint8_t  bLength = 0x07;
Hans de Goede c8dfc6
+    USBDescriptor *d = (void *)dest;
Hans de Goede c8dfc6
+
Hans de Goede c8dfc6
+    if (len < bLength) {
Hans de Goede c8dfc6
+        return -1;
Hans de Goede c8dfc6
+    }
Hans de Goede c8dfc6
+
Hans de Goede c8dfc6
+    d->bLength                          = bLength;
Hans de Goede c8dfc6
+    d->bDescriptorType                  = USB_DT_DEVICE_CAPABILITY;
Hans de Goede c8dfc6
+    d->u.cap.bDevCapabilityType         = USB_DEV_CAP_USB2_EXT;
Hans de Goede c8dfc6
+
Hans de Goede c8dfc6
+    d->u.cap.u.usb2_ext.bmAttributes_1  = (1 << 1);  /* LPM */
Hans de Goede c8dfc6
+    d->u.cap.u.usb2_ext.bmAttributes_2  = 0;
Hans de Goede c8dfc6
+    d->u.cap.u.usb2_ext.bmAttributes_3  = 0;
Hans de Goede c8dfc6
+    d->u.cap.u.usb2_ext.bmAttributes_4  = 0;
Hans de Goede c8dfc6
+
Hans de Goede c8dfc6
+    return bLength;
Hans de Goede c8dfc6
+}
Hans de Goede c8dfc6
+
Hans de Goede c8dfc6
+static int usb_desc_cap_super(const USBDesc *desc, uint8_t *dest, size_t len)
Hans de Goede c8dfc6
+{
Hans de Goede c8dfc6
+    uint8_t  bLength = 0x0a;
Hans de Goede c8dfc6
+    USBDescriptor *d = (void *)dest;
Hans de Goede c8dfc6
+
Hans de Goede c8dfc6
+    if (len < bLength) {
Hans de Goede c8dfc6
+        return -1;
Hans de Goede c8dfc6
+    }
Hans de Goede c8dfc6
+
Hans de Goede c8dfc6
+    d->bLength                           = bLength;
Hans de Goede c8dfc6
+    d->bDescriptorType                   = USB_DT_DEVICE_CAPABILITY;
Hans de Goede c8dfc6
+    d->u.cap.bDevCapabilityType          = USB_DEV_CAP_SUPERSPEED;
Hans de Goede c8dfc6
+
Hans de Goede c8dfc6
+    d->u.cap.u.super.bmAttributes        = 0;
Hans de Goede c8dfc6
+    d->u.cap.u.super.wSpeedsSupported_lo = 0;
Hans de Goede c8dfc6
+    d->u.cap.u.super.wSpeedsSupported_hi = 0;
Hans de Goede c8dfc6
+    d->u.cap.u.super.bFunctionalitySupport = 0;
Hans de Goede c8dfc6
+    d->u.cap.u.super.bU1DevExitLat       = 0x0a;
Hans de Goede c8dfc6
+    d->u.cap.u.super.wU2DevExitLat_lo    = 0x20;
Hans de Goede c8dfc6
+    d->u.cap.u.super.wU2DevExitLat_hi    = 0;
Hans de Goede c8dfc6
+
Hans de Goede c8dfc6
+    if (desc->full) {
Hans de Goede c8dfc6
+        d->u.cap.u.super.wSpeedsSupported_lo |= (1 << 1);
Hans de Goede c8dfc6
+        d->u.cap.u.super.bFunctionalitySupport = 1;
Hans de Goede c8dfc6
+    }
Hans de Goede c8dfc6
+    if (desc->high) {
Hans de Goede c8dfc6
+        d->u.cap.u.super.wSpeedsSupported_lo |= (1 << 2);
Hans de Goede c8dfc6
+        if (!d->u.cap.u.super.bFunctionalitySupport) {
Hans de Goede c8dfc6
+            d->u.cap.u.super.bFunctionalitySupport = 2;
Hans de Goede c8dfc6
+        }
Hans de Goede c8dfc6
+    }
Hans de Goede c8dfc6
+    if (desc->super) {
Hans de Goede c8dfc6
+        d->u.cap.u.super.wSpeedsSupported_lo |= (1 << 3);
Hans de Goede c8dfc6
+        if (!d->u.cap.u.super.bFunctionalitySupport) {
Hans de Goede c8dfc6
+            d->u.cap.u.super.bFunctionalitySupport = 3;
Hans de Goede c8dfc6
+        }
Hans de Goede c8dfc6
+    }
Hans de Goede c8dfc6
+
Hans de Goede c8dfc6
+    return bLength;
Hans de Goede c8dfc6
+}
Hans de Goede c8dfc6
+
Hans de Goede c8dfc6
+static int usb_desc_bos(const USBDesc *desc, uint8_t *dest, size_t len)
Hans de Goede c8dfc6
+{
Hans de Goede c8dfc6
+    uint8_t  bLength = 0x05;
Hans de Goede c8dfc6
+    uint16_t wTotalLength = 0;
Hans de Goede c8dfc6
+    uint8_t  bNumDeviceCaps = 0;
Hans de Goede c8dfc6
+    USBDescriptor *d = (void *)dest;
Hans de Goede c8dfc6
+    int rc;
Hans de Goede c8dfc6
+
Hans de Goede c8dfc6
+    if (len < bLength) {
Hans de Goede c8dfc6
+        return -1;
Hans de Goede c8dfc6
+    }
Hans de Goede c8dfc6
+
Hans de Goede c8dfc6
+    d->bLength                      = bLength;
Hans de Goede c8dfc6
+    d->bDescriptorType              = USB_DT_BOS;
Hans de Goede c8dfc6
+
Hans de Goede c8dfc6
+    wTotalLength += bLength;
Hans de Goede c8dfc6
+
Hans de Goede c8dfc6
+    if (desc->high != NULL) {
Hans de Goede c8dfc6
+        rc = usb_desc_cap_usb2_ext(desc, dest + wTotalLength,
Hans de Goede c8dfc6
+                                   len - wTotalLength);
Hans de Goede c8dfc6
+        if (rc < 0) {
Hans de Goede c8dfc6
+            return rc;
Hans de Goede c8dfc6
+        }
Hans de Goede c8dfc6
+        wTotalLength += rc;
Hans de Goede c8dfc6
+        bNumDeviceCaps++;
Hans de Goede c8dfc6
+    }
Hans de Goede c8dfc6
+
Hans de Goede c8dfc6
+    if (desc->super != NULL) {
Hans de Goede c8dfc6
+        rc = usb_desc_cap_super(desc, dest + wTotalLength,
Hans de Goede c8dfc6
+                                len - wTotalLength);
Hans de Goede c8dfc6
+        if (rc < 0) {
Hans de Goede c8dfc6
+            return rc;
Hans de Goede c8dfc6
+        }
Hans de Goede c8dfc6
+        wTotalLength += rc;
Hans de Goede c8dfc6
+        bNumDeviceCaps++;
Hans de Goede c8dfc6
+    }
Hans de Goede c8dfc6
+
Hans de Goede c8dfc6
+    d->u.bos.wTotalLength_lo = usb_lo(wTotalLength);
Hans de Goede c8dfc6
+    d->u.bos.wTotalLength_hi = usb_hi(wTotalLength);
Hans de Goede c8dfc6
+    d->u.bos.bNumDeviceCaps  = bNumDeviceCaps;
Hans de Goede c8dfc6
+    return wTotalLength;
Hans de Goede c8dfc6
+}
Hans de Goede c8dfc6
+
Hans de Goede c8dfc6
 /* ------------------------------------------------------------------ */
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
 static void usb_desc_ep_init(USBDevice *dev)
Hans de Goede c8dfc6
@@ -571,6 +676,10 @@ int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len
Hans de Goede c8dfc6
         }
Hans de Goede c8dfc6
         trace_usb_desc_other_speed_config(dev->addr, index, len, ret);
Hans de Goede c8dfc6
         break;
Hans de Goede c8dfc6
+    case USB_DT_BOS:
Hans de Goede c8dfc6
+        ret = usb_desc_bos(desc, buf, sizeof(buf));
Hans de Goede c8dfc6
+        trace_usb_desc_bos(dev->addr, len, ret);
Hans de Goede c8dfc6
+        break;
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
     case USB_DT_DEBUG:
Hans de Goede c8dfc6
         /* ignore silently */
Hans de Goede c8dfc6
diff --git a/hw/usb/desc.h b/hw/usb/desc.h
Hans de Goede c8dfc6
index 4b5e88d..68bb570 100644
Hans de Goede c8dfc6
--- a/hw/usb/desc.h
Hans de Goede c8dfc6
+++ b/hw/usb/desc.h
Hans de Goede c8dfc6
@@ -69,6 +69,31 @@ typedef struct USBDescriptor {
Hans de Goede c8dfc6
             uint8_t           wBytesPerInterval_lo;
Hans de Goede c8dfc6
             uint8_t           wBytesPerInterval_hi;
Hans de Goede c8dfc6
         } super_endpoint;
Hans de Goede c8dfc6
+        struct {
Hans de Goede c8dfc6
+            uint8_t           wTotalLength_lo;
Hans de Goede c8dfc6
+            uint8_t           wTotalLength_hi;
Hans de Goede c8dfc6
+            uint8_t           bNumDeviceCaps;
Hans de Goede c8dfc6
+        } bos;
Hans de Goede c8dfc6
+        struct {
Hans de Goede c8dfc6
+            uint8_t           bDevCapabilityType;
Hans de Goede c8dfc6
+            union {
Hans de Goede c8dfc6
+                struct {
Hans de Goede c8dfc6
+                    uint8_t   bmAttributes_1;
Hans de Goede c8dfc6
+                    uint8_t   bmAttributes_2;
Hans de Goede c8dfc6
+                    uint8_t   bmAttributes_3;
Hans de Goede c8dfc6
+                    uint8_t   bmAttributes_4;
Hans de Goede c8dfc6
+                } usb2_ext;
Hans de Goede c8dfc6
+                struct {
Hans de Goede c8dfc6
+                    uint8_t   bmAttributes;
Hans de Goede c8dfc6
+                    uint8_t   wSpeedsSupported_lo;
Hans de Goede c8dfc6
+                    uint8_t   wSpeedsSupported_hi;
Hans de Goede c8dfc6
+                    uint8_t   bFunctionalitySupport;
Hans de Goede c8dfc6
+                    uint8_t   bU1DevExitLat;
Hans de Goede c8dfc6
+                    uint8_t   wU2DevExitLat_lo;
Hans de Goede c8dfc6
+                    uint8_t   wU2DevExitLat_hi;
Hans de Goede c8dfc6
+                } super;
Hans de Goede c8dfc6
+            } u;
Hans de Goede c8dfc6
+        } cap;
Hans de Goede c8dfc6
     } u;
Hans de Goede c8dfc6
 } QEMU_PACKED USBDescriptor;
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
diff --git a/trace-events b/trace-events
Hans de Goede c8dfc6
index a894689..5bc591a 100644
Hans de Goede c8dfc6
--- a/trace-events
Hans de Goede c8dfc6
+++ b/trace-events
Hans de Goede c8dfc6
@@ -340,6 +340,7 @@ usb_desc_device_qualifier(int addr, int len, int ret) "dev %d query device quali
Hans de Goede c8dfc6
 usb_desc_config(int addr, int index, int len, int ret) "dev %d query config %d, len %d, ret %d"
Hans de Goede c8dfc6
 usb_desc_other_speed_config(int addr, int index, int len, int ret) "dev %d query config %d, len %d, ret %d"
Hans de Goede c8dfc6
 usb_desc_string(int addr, int index, int len, int ret) "dev %d query string %d, len %d, ret %d"
Hans de Goede c8dfc6
+usb_desc_bos(int addr, int len, int ret) "dev %d bos, len %d, ret %d"
Hans de Goede c8dfc6
 usb_set_addr(int addr) "dev %d"
Hans de Goede c8dfc6
 usb_set_config(int addr, int config, int ret) "dev %d, config %d, ret %d"
Hans de Goede c8dfc6
 usb_set_interface(int addr, int iface, int alt, int ret) "dev %d, interface %d, altsetting %d, ret %d"
Hans de Goede c8dfc6
-- 
Hans de Goede c8dfc6
1.7.12
Hans de Goede c8dfc6