mvadkert / rpms / qemu

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