Blame 0342-usb3-superspeed-endpoint-companion.patch

Hans de Goede c8dfc6
From 5a02a74430f4628a78f43242afbb1377deea4c80 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:28:03 +0200
Hans de Goede c8dfc6
Subject: [PATCH 342/366] usb3: superspeed endpoint companion
Hans de Goede c8dfc6
Hans de Goede c8dfc6
Add support for building superspeed endpoint companion descriptors,
Hans de Goede c8dfc6
create them for superspeed usb devices.
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      |  1 +
Hans de Goede c8dfc6
 hw/usb/desc.c | 55 ++++++++++++++++++++++++++++++++++++++++---------------
Hans de Goede c8dfc6
 hw/usb/desc.h | 26 +++++++++++++++++++++-----
Hans de Goede c8dfc6
 3 files changed, 62 insertions(+), 20 deletions(-)
Hans de Goede c8dfc6
Hans de Goede c8dfc6
diff --git a/hw/usb.h b/hw/usb.h
Hans de Goede c8dfc6
index 684e3f4..78ffdf4 100644
Hans de Goede c8dfc6
--- a/hw/usb.h
Hans de Goede c8dfc6
+++ b/hw/usb.h
Hans de Goede c8dfc6
@@ -137,6 +137,7 @@
Hans de Goede c8dfc6
 #define USB_DT_INTERFACE_ASSOC          0x0B
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_ENDPOINT_XFER_CONTROL	0
Hans de Goede c8dfc6
 #define USB_ENDPOINT_XFER_ISOC		1
Hans de Goede c8dfc6
diff --git a/hw/usb/desc.c b/hw/usb/desc.c
Hans de Goede c8dfc6
index 3e8c6cb..8f5a8e5 100644
Hans de Goede c8dfc6
--- a/hw/usb/desc.c
Hans de Goede c8dfc6
+++ b/hw/usb/desc.c
Hans de Goede c8dfc6
@@ -76,7 +76,8 @@ int usb_desc_device_qualifier(const USBDescDevice *dev,
Hans de Goede c8dfc6
     return bLength;
Hans de Goede c8dfc6
 }
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
-int usb_desc_config(const USBDescConfig *conf, uint8_t *dest, size_t len)
Hans de Goede c8dfc6
+int usb_desc_config(const USBDescConfig *conf, int flags,
Hans de Goede c8dfc6
+                    uint8_t *dest, size_t len)
Hans de Goede c8dfc6
 {
Hans de Goede c8dfc6
     uint8_t  bLength = 0x09;
Hans de Goede c8dfc6
     uint16_t wTotalLength = 0;
Hans de Goede c8dfc6
@@ -99,7 +100,7 @@ int usb_desc_config(const USBDescConfig *conf, uint8_t *dest, size_t len)
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
     /* handle grouped interfaces if any */
Hans de Goede c8dfc6
     for (i = 0; i < conf->nif_groups; i++) {
Hans de Goede c8dfc6
-        rc = usb_desc_iface_group(&(conf->if_groups[i]),
Hans de Goede c8dfc6
+        rc = usb_desc_iface_group(&(conf->if_groups[i]), flags,
Hans de Goede c8dfc6
                                   dest + wTotalLength,
Hans de Goede c8dfc6
                                   len - wTotalLength);
Hans de Goede c8dfc6
         if (rc < 0) {
Hans de Goede c8dfc6
@@ -110,7 +111,8 @@ int usb_desc_config(const USBDescConfig *conf, uint8_t *dest, size_t len)
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
     /* handle normal (ungrouped / no IAD) interfaces if any */
Hans de Goede c8dfc6
     for (i = 0; i < conf->nif; i++) {
Hans de Goede c8dfc6
-        rc = usb_desc_iface(conf->ifs + i, dest + wTotalLength, len - wTotalLength);
Hans de Goede c8dfc6
+        rc = usb_desc_iface(conf->ifs + i, flags,
Hans de Goede c8dfc6
+                            dest + wTotalLength, len - wTotalLength);
Hans de Goede c8dfc6
         if (rc < 0) {
Hans de Goede c8dfc6
             return rc;
Hans de Goede c8dfc6
         }
Hans de Goede c8dfc6
@@ -122,8 +124,8 @@ int usb_desc_config(const USBDescConfig *conf, uint8_t *dest, size_t len)
Hans de Goede c8dfc6
     return wTotalLength;
Hans de Goede c8dfc6
 }
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
-int usb_desc_iface_group(const USBDescIfaceAssoc *iad, uint8_t *dest,
Hans de Goede c8dfc6
-                         size_t len)
Hans de Goede c8dfc6
+int usb_desc_iface_group(const USBDescIfaceAssoc *iad, int flags,
Hans de Goede c8dfc6
+                         uint8_t *dest, size_t len)
Hans de Goede c8dfc6
 {
Hans de Goede c8dfc6
     int pos = 0;
Hans de Goede c8dfc6
     int i = 0;
Hans de Goede c8dfc6
@@ -147,7 +149,7 @@ int usb_desc_iface_group(const USBDescIfaceAssoc *iad, uint8_t *dest,
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
     /* handle associated interfaces in this group */
Hans de Goede c8dfc6
     for (i = 0; i < iad->nif; i++) {
Hans de Goede c8dfc6
-        int rc = usb_desc_iface(&(iad->ifs[i]), dest + pos, len - pos);
Hans de Goede c8dfc6
+        int rc = usb_desc_iface(&(iad->ifs[i]), flags, dest + pos, len - pos);
Hans de Goede c8dfc6
         if (rc < 0) {
Hans de Goede c8dfc6
             return rc;
Hans de Goede c8dfc6
         }
Hans de Goede c8dfc6
@@ -157,7 +159,8 @@ int usb_desc_iface_group(const USBDescIfaceAssoc *iad, uint8_t *dest,
Hans de Goede c8dfc6
     return pos;
Hans de Goede c8dfc6
 }
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
-int usb_desc_iface(const USBDescIface *iface, uint8_t *dest, size_t len)
Hans de Goede c8dfc6
+int usb_desc_iface(const USBDescIface *iface, int flags,
Hans de Goede c8dfc6
+                   uint8_t *dest, size_t len)
Hans de Goede c8dfc6
 {
Hans de Goede c8dfc6
     uint8_t bLength = 0x09;
Hans de Goede c8dfc6
     int i, rc, pos = 0;
Hans de Goede c8dfc6
@@ -188,7 +191,7 @@ int usb_desc_iface(const USBDescIface *iface, uint8_t *dest, size_t len)
Hans de Goede c8dfc6
     }
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
     for (i = 0; i < iface->bNumEndpoints; i++) {
Hans de Goede c8dfc6
-        rc = usb_desc_endpoint(iface->eps + i, dest + pos, len - pos);
Hans de Goede c8dfc6
+        rc = usb_desc_endpoint(iface->eps + i, flags, dest + pos, len - pos);
Hans de Goede c8dfc6
         if (rc < 0) {
Hans de Goede c8dfc6
             return rc;
Hans de Goede c8dfc6
         }
Hans de Goede c8dfc6
@@ -198,13 +201,15 @@ int usb_desc_iface(const USBDescIface *iface, uint8_t *dest, size_t len)
Hans de Goede c8dfc6
     return pos;
Hans de Goede c8dfc6
 }
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
-int usb_desc_endpoint(const USBDescEndpoint *ep, uint8_t *dest, size_t len)
Hans de Goede c8dfc6
+int usb_desc_endpoint(const USBDescEndpoint *ep, int flags,
Hans de Goede c8dfc6
+                      uint8_t *dest, size_t len)
Hans de Goede c8dfc6
 {
Hans de Goede c8dfc6
     uint8_t bLength = ep->is_audio ? 0x09 : 0x07;
Hans de Goede c8dfc6
     uint8_t extralen = ep->extra ? ep->extra[0] : 0;
Hans de Goede c8dfc6
+    uint8_t superlen = (flags & USB_DESC_FLAG_SUPER) ? 0x06 : 0;
Hans de Goede c8dfc6
     USBDescriptor *d = (void *)dest;
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
-    if (len < bLength + extralen) {
Hans de Goede c8dfc6
+    if (len < bLength + extralen + superlen) {
Hans de Goede c8dfc6
         return -1;
Hans de Goede c8dfc6
     }
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
@@ -224,7 +229,21 @@ int usb_desc_endpoint(const USBDescEndpoint *ep, uint8_t *dest, size_t len)
Hans de Goede c8dfc6
         memcpy(dest + bLength, ep->extra, extralen);
Hans de Goede c8dfc6
     }
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
-    return bLength + extralen;
Hans de Goede c8dfc6
+    if (superlen) {
Hans de Goede c8dfc6
+        USBDescriptor *d = (void *)(dest + bLength + extralen);
Hans de Goede c8dfc6
+
Hans de Goede c8dfc6
+        d->bLength                       = 0x06;
Hans de Goede c8dfc6
+        d->bDescriptorType               = USB_DT_ENDPOINT_COMPANION;
Hans de Goede c8dfc6
+
Hans de Goede c8dfc6
+        d->u.super_endpoint.bMaxBurst    = ep->bMaxBurst;
Hans de Goede c8dfc6
+        d->u.super_endpoint.bmAttributes = ep->bmAttributes_super;
Hans de Goede c8dfc6
+        d->u.super_endpoint.wBytesPerInterval_lo =
Hans de Goede c8dfc6
+            usb_lo(ep->wBytesPerInterval);
Hans de Goede c8dfc6
+        d->u.super_endpoint.wBytesPerInterval_hi =
Hans de Goede c8dfc6
+            usb_hi(ep->wBytesPerInterval);
Hans de Goede c8dfc6
+    }
Hans de Goede c8dfc6
+
Hans de Goede c8dfc6
+    return bLength + extralen + superlen;
Hans de Goede c8dfc6
 }
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
 int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len)
Hans de Goede c8dfc6
@@ -509,7 +528,7 @@ int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len
Hans de Goede c8dfc6
     uint8_t buf[256];
Hans de Goede c8dfc6
     uint8_t type = value >> 8;
Hans de Goede c8dfc6
     uint8_t index = value & 0xff;
Hans de Goede c8dfc6
-    int ret = -1;
Hans de Goede c8dfc6
+    int flags, ret = -1;
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
     if (dev->speed == USB_SPEED_HIGH) {
Hans de Goede c8dfc6
         other_dev = usb_device_get_usb_desc(dev)->full;
Hans de Goede c8dfc6
@@ -517,6 +536,11 @@ int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len
Hans de Goede c8dfc6
         other_dev = usb_device_get_usb_desc(dev)->high;
Hans de Goede c8dfc6
     }
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
+    flags = 0;
Hans de Goede c8dfc6
+    if (dev->device->bcdUSB >= 0x0300) {
Hans de Goede c8dfc6
+        flags |= USB_DESC_FLAG_SUPER;
Hans de Goede c8dfc6
+    }
Hans de Goede c8dfc6
+
Hans de Goede c8dfc6
     switch(type) {
Hans de Goede c8dfc6
     case USB_DT_DEVICE:
Hans de Goede c8dfc6
         ret = usb_desc_device(&desc->id, dev->device, buf, sizeof(buf));
Hans de Goede c8dfc6
@@ -524,7 +548,8 @@ int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len
Hans de Goede c8dfc6
         break;
Hans de Goede c8dfc6
     case USB_DT_CONFIG:
Hans de Goede c8dfc6
         if (index < dev->device->bNumConfigurations) {
Hans de Goede c8dfc6
-            ret = usb_desc_config(dev->device->confs + index, buf, sizeof(buf));
Hans de Goede c8dfc6
+            ret = usb_desc_config(dev->device->confs + index, flags,
Hans de Goede c8dfc6
+                                  buf, sizeof(buf));
Hans de Goede c8dfc6
         }
Hans de Goede c8dfc6
         trace_usb_desc_config(dev->addr, index, len, ret);
Hans de Goede c8dfc6
         break;
Hans de Goede c8dfc6
@@ -532,7 +557,6 @@ int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len
Hans de Goede c8dfc6
         ret = usb_desc_string(dev, index, buf, sizeof(buf));
Hans de Goede c8dfc6
         trace_usb_desc_string(dev->addr, index, len, ret);
Hans de Goede c8dfc6
         break;
Hans de Goede c8dfc6
-
Hans de Goede c8dfc6
     case USB_DT_DEVICE_QUALIFIER:
Hans de Goede c8dfc6
         if (other_dev != NULL) {
Hans de Goede c8dfc6
             ret = usb_desc_device_qualifier(other_dev, buf, sizeof(buf));
Hans de Goede c8dfc6
@@ -541,7 +565,8 @@ int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len
Hans de Goede c8dfc6
         break;
Hans de Goede c8dfc6
     case USB_DT_OTHER_SPEED_CONFIG:
Hans de Goede c8dfc6
         if (other_dev != NULL && index < other_dev->bNumConfigurations) {
Hans de Goede c8dfc6
-            ret = usb_desc_config(other_dev->confs + index, buf, sizeof(buf));
Hans de Goede c8dfc6
+            ret = usb_desc_config(other_dev->confs + index, flags,
Hans de Goede c8dfc6
+                                  buf, sizeof(buf));
Hans de Goede c8dfc6
             buf[0x01] = USB_DT_OTHER_SPEED_CONFIG;
Hans de Goede c8dfc6
         }
Hans de Goede c8dfc6
         trace_usb_desc_other_speed_config(dev->addr, index, len, ret);
Hans de Goede c8dfc6
diff --git a/hw/usb/desc.h b/hw/usb/desc.h
Hans de Goede c8dfc6
index d89fa41..4b5e88d 100644
Hans de Goede c8dfc6
--- a/hw/usb/desc.h
Hans de Goede c8dfc6
+++ b/hw/usb/desc.h
Hans de Goede c8dfc6
@@ -63,6 +63,12 @@ typedef struct USBDescriptor {
Hans de Goede c8dfc6
             uint8_t           bRefresh;        /* only audio ep */
Hans de Goede c8dfc6
             uint8_t           bSynchAddress;   /* only audio ep */
Hans de Goede c8dfc6
         } endpoint;
Hans de Goede c8dfc6
+        struct {
Hans de Goede c8dfc6
+            uint8_t           bMaxBurst;
Hans de Goede c8dfc6
+            uint8_t           bmAttributes;
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
     } u;
Hans de Goede c8dfc6
 } QEMU_PACKED USBDescriptor;
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
@@ -139,6 +145,11 @@ struct USBDescEndpoint {
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
     uint8_t                   is_audio; /* has bRefresh + bSynchAddress */
Hans de Goede c8dfc6
     uint8_t                   *extra;
Hans de Goede c8dfc6
+
Hans de Goede c8dfc6
+    /* superspeed endpoint companion */
Hans de Goede c8dfc6
+    uint8_t                   bMaxBurst;
Hans de Goede c8dfc6
+    uint8_t                   bmAttributes_super;
Hans de Goede c8dfc6
+    uint16_t                  wBytesPerInterval;
Hans de Goede c8dfc6
 };
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
 struct USBDescOther {
Hans de Goede c8dfc6
@@ -156,16 +167,21 @@ struct USBDesc {
Hans de Goede c8dfc6
     const char* const         *str;
Hans de Goede c8dfc6
 };
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
+#define USB_DESC_FLAG_SUPER (1 << 1)
Hans de Goede c8dfc6
+
Hans de Goede c8dfc6
 /* generate usb packages from structs */
Hans de Goede c8dfc6
 int usb_desc_device(const USBDescID *id, const USBDescDevice *dev,
Hans de Goede c8dfc6
                     uint8_t *dest, size_t len);
Hans de Goede c8dfc6
 int usb_desc_device_qualifier(const USBDescDevice *dev,
Hans de Goede c8dfc6
                               uint8_t *dest, size_t len);
Hans de Goede c8dfc6
-int usb_desc_config(const USBDescConfig *conf, uint8_t *dest, size_t len);
Hans de Goede c8dfc6
-int usb_desc_iface_group(const USBDescIfaceAssoc *iad, uint8_t *dest,
Hans de Goede c8dfc6
-                         size_t len);
Hans de Goede c8dfc6
-int usb_desc_iface(const USBDescIface *iface, uint8_t *dest, size_t len);
Hans de Goede c8dfc6
-int usb_desc_endpoint(const USBDescEndpoint *ep, uint8_t *dest, size_t len);
Hans de Goede c8dfc6
+int usb_desc_config(const USBDescConfig *conf, int flags,
Hans de Goede c8dfc6
+                    uint8_t *dest, size_t len);
Hans de Goede c8dfc6
+int usb_desc_iface_group(const USBDescIfaceAssoc *iad, int flags,
Hans de Goede c8dfc6
+                         uint8_t *dest, size_t len);
Hans de Goede c8dfc6
+int usb_desc_iface(const USBDescIface *iface, int flags,
Hans de Goede c8dfc6
+                   uint8_t *dest, size_t len);
Hans de Goede c8dfc6
+int usb_desc_endpoint(const USBDescEndpoint *ep, int flags,
Hans de Goede c8dfc6
+                      uint8_t *dest, size_t len);
Hans de Goede c8dfc6
 int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len);
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
 /* control message emulation helpers */
Hans de Goede c8dfc6
-- 
Hans de Goede c8dfc6
1.7.12
Hans de Goede c8dfc6