All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v4 00/32] usb descriptor overhaul + more
@ 2011-01-12 11:19 Gerd Hoffmann
  2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 01/32] usb: update MAINTAINERS Gerd Hoffmann
                   ` (32 more replies)
  0 siblings, 33 replies; 37+ messages in thread
From: Gerd Hoffmann @ 2011-01-12 11:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

  Hi,

Here is a update of the usb descriptor patches and a bunch of
improvements on top of that.  This patch series features:

  * Update USB section in MAINTAINERS
  * A major overhaul for the usb descriptor handling for
    emulated devices.  This is in preparation for USB 2.0
    support entering qemu which will need a bit more
    sophisticated descriptor handling.  This is also for
    moving descriptor handling to common code instead of
    having each driver duplicate it.
  * Improved usb port management.
  * Remote wakeup support, which allows guests to suspend
    the usb bus when all devices are idle, so qemu will
    not wakeup at usb frame rate (1000 Hz).
  * A bunch of improvements and fixes for the usb-storage
    emulation.  It features full USB 2.0 support now, although
    due to the lack of a EHCI controller the only thing you'll
    notice is that the linux kernel logs a message which suggests
    to connect the device to a high-speed port.

New in v4:
  * rebased to latest master
  * solved conflicts with glebs fw_path bits
  * rewrote anf fixed the fw_path support for usb to use the
    new port management support (check last two patches).

cheers,
  Gerd

The following changes since commit 05bf441eb69a813d3893174d54faa6afa8c0d39b:

  cris: Remove unused orig_flags (2011-01-10 23:28:08 +0100)

are available in the git repository at:
  git://anongit.freedesktop.org/spice/qemu usb.4

Gerd Hoffmann (32):
      usb: update MAINTAINERS
      usb: data structs and helpers for usb descriptors.
      usb hid: use new descriptor infrastructure.
      usb serial: use new descriptor infrastructure.
      usb storage: use new descriptor infrastructure.
      usb wacom: use new descriptor infrastructure.
      usb bluetooth: use new descriptor infrastructure.
      usb hub: use new descriptor infrastructure.
      usb descriptors: add settable strings.
      usb storage: serial number support
      usb network: use new descriptor infrastructure.
      usb: move USB_REQ_SET_ADDRESS handling to common code
      usb: move USB_REQ_{GET,SET}_CONFIGURATION handling to common code
      usb: move remote wakeup handling to common code
      usb: create USBPortOps, move attach there.
      usb: rework attach/detach workflow
      usb: add usb_wakeup() + wakeup callback to port ops
      usb: uhci: remote wakeup support.
      usb: hub: remote wakeup support.
      usb: hid: remote wakeup support.
      usb: hid: change serial number to "42".
      usb: add speed mask to ports
      usb: add attach callback
      usb: add usb_desc_attach
      usb: add device qualifier support
      usb storage: high speed support
      usb storage: fix status reporting
      usb storage: handle long responses
      usb: keep track of physical port address.
      usb: add port property.
      usb: rewrite fw path, fix numbering
      usb: zap pdev from usbport

 MAINTAINERS     |    4 +-
 Makefile.objs   |    2 +-
 hw/usb-bt.c     |  525 ++++++++++++++++++++++--------------------------------
 hw/usb-bus.c    |  129 ++++++++------
 hw/usb-desc.c   |  406 ++++++++++++++++++++++++++++++++++++++++++
 hw/usb-desc.h   |   92 ++++++++++
 hw/usb-hid.c    |  486 ++++++++++++++++++++++-----------------------------
 hw/usb-hub.c    |  250 +++++++++++++-------------
 hw/usb-msd.c    |  267 +++++++++++++---------------
 hw/usb-musb.c   |   44 ++---
 hw/usb-net.c    |  528 +++++++++++++++++++++++--------------------------------
 hw/usb-ohci.c   |   88 +++++-----
 hw/usb-serial.c |  236 +++++++++----------------
 hw/usb-uhci.c   |   98 ++++++-----
 hw/usb-wacom.c  |  214 ++++++++---------------
 hw/usb.c        |   34 ++++-
 hw/usb.h        |   50 +++++-
 trace-events    |   11 ++
 18 files changed, 1842 insertions(+), 1622 deletions(-)
 create mode 100644 hw/usb-desc.c
 create mode 100644 hw/usb-desc.h

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v4 01/32] usb: update MAINTAINERS
  2011-01-12 11:19 [Qemu-devel] [PATCH v4 00/32] usb descriptor overhaul + more Gerd Hoffmann
@ 2011-01-12 11:19 ` Gerd Hoffmann
  2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 02/32] usb: data structs and helpers for usb descriptors Gerd Hoffmann
                   ` (31 subsequent siblings)
  32 siblings, 0 replies; 37+ messages in thread
From: Gerd Hoffmann @ 2011-01-12 11:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 MAINTAINERS |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 59effc7..4b07192 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -329,8 +329,8 @@ F: hw/lsi53c895a.c
 F: hw/scsi*
 
 USB
-M: qemu-devel@nongnu.org
-S: Odd Fixes
+M: Gerd Hoffmann <kraxel@redhat.com>
+S: Maintained
 F: hw/usb*
 
 vhost
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v4 02/32] usb: data structs and helpers for usb descriptors.
  2011-01-12 11:19 [Qemu-devel] [PATCH v4 00/32] usb descriptor overhaul + more Gerd Hoffmann
  2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 01/32] usb: update MAINTAINERS Gerd Hoffmann
@ 2011-01-12 11:19 ` Gerd Hoffmann
  2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 03/32] usb hid: use new descriptor infrastructure Gerd Hoffmann
                   ` (30 subsequent siblings)
  32 siblings, 0 replies; 37+ messages in thread
From: Gerd Hoffmann @ 2011-01-12 11:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

This patch adds hw/usb-desc.[ch] files.  They carry data structures
for various usb descriptors and helper functions to generate usb
packets from the structures.

The intention is to have a internal representation of the device
desription which is more usable than the current char array blobs,
so we can have common code handle common usb device emulation using
the device description.

The usage of this infrastructure is optional for usb drivers as there
are cases such as pass-through where it probably isn't very useful.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 Makefile.objs |    2 +-
 hw/usb-desc.c |  238 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/usb-desc.h |   86 +++++++++++++++++++++
 hw/usb.h      |    9 ++
 trace-events  |    5 +
 5 files changed, 339 insertions(+), 1 deletions(-)
 create mode 100644 hw/usb-desc.c
 create mode 100644 hw/usb-desc.h

diff --git a/Makefile.objs b/Makefile.objs
index c3e52c5..fda366d 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -88,7 +88,7 @@ common-obj-y += eeprom93xx.o
 common-obj-y += scsi-disk.o cdrom.o
 common-obj-y += scsi-generic.o scsi-bus.o
 common-obj-y += usb.o usb-hub.o usb-$(HOST_USB).o usb-hid.o usb-msd.o usb-wacom.o
-common-obj-y += usb-serial.o usb-net.o usb-bus.o
+common-obj-y += usb-serial.o usb-net.o usb-bus.o usb-desc.o
 common-obj-$(CONFIG_SSI) += ssi.o
 common-obj-$(CONFIG_SSI_SD) += ssi-sd.o
 common-obj-$(CONFIG_SD) += sd.o
diff --git a/hw/usb-desc.c b/hw/usb-desc.c
new file mode 100644
index 0000000..559ced7
--- /dev/null
+++ b/hw/usb-desc.c
@@ -0,0 +1,238 @@
+#include "usb.h"
+#include "usb-desc.h"
+#include "trace.h"
+
+/* ------------------------------------------------------------------ */
+
+static uint8_t usb_lo(uint16_t val)
+{
+    return val & 0xff;
+}
+
+static uint8_t usb_hi(uint16_t val)
+{
+    return (val >> 8) & 0xff;
+}
+
+int usb_desc_device(const USBDescID *id, const USBDescDevice *dev,
+                    uint8_t *dest, size_t len)
+{
+    uint8_t bLength = 0x12;
+
+    if (len < bLength) {
+        return -1;
+    }
+
+    dest[0x00] = bLength;
+    dest[0x01] = USB_DT_DEVICE;
+
+    dest[0x02] = usb_lo(dev->bcdUSB);
+    dest[0x03] = usb_hi(dev->bcdUSB);
+    dest[0x04] = dev->bDeviceClass;
+    dest[0x05] = dev->bDeviceSubClass;
+    dest[0x06] = dev->bDeviceProtocol;
+    dest[0x07] = dev->bMaxPacketSize0;
+
+    dest[0x08] = usb_lo(id->idVendor);
+    dest[0x09] = usb_hi(id->idVendor);
+    dest[0x0a] = usb_lo(id->idProduct);
+    dest[0x0b] = usb_hi(id->idProduct);
+    dest[0x0c] = usb_lo(id->bcdDevice);
+    dest[0x0d] = usb_hi(id->bcdDevice);
+    dest[0x0e] = id->iManufacturer;
+    dest[0x0f] = id->iProduct;
+    dest[0x10] = id->iSerialNumber;
+
+    dest[0x11] = dev->bNumConfigurations;
+
+    return bLength;
+}
+
+int usb_desc_config(const USBDescConfig *conf, uint8_t *dest, size_t len)
+{
+    uint8_t  bLength = 0x09;
+    uint16_t wTotalLength = 0;
+    int i, rc, count;
+
+    if (len < bLength) {
+        return -1;
+    }
+
+    dest[0x00] = bLength;
+    dest[0x01] = USB_DT_CONFIG;
+    dest[0x04] = conf->bNumInterfaces;
+    dest[0x05] = conf->bConfigurationValue;
+    dest[0x06] = conf->iConfiguration;
+    dest[0x07] = conf->bmAttributes;
+    dest[0x08] = conf->bMaxPower;
+    wTotalLength += bLength;
+
+    count = conf->nif ? conf->nif : conf->bNumInterfaces;
+    for (i = 0; i < count; i++) {
+        rc = usb_desc_iface(conf->ifs + i, dest + wTotalLength, len - wTotalLength);
+        if (rc < 0) {
+            return rc;
+        }
+        wTotalLength += rc;
+    }
+
+    dest[0x02] = usb_lo(wTotalLength);
+    dest[0x03] = usb_hi(wTotalLength);
+    return wTotalLength;
+}
+
+int usb_desc_iface(const USBDescIface *iface, uint8_t *dest, size_t len)
+{
+    uint8_t bLength = 0x09;
+    int i, rc, pos = 0;
+
+    if (len < bLength) {
+        return -1;
+    }
+
+    dest[0x00] = bLength;
+    dest[0x01] = USB_DT_INTERFACE;
+    dest[0x02] = iface->bInterfaceNumber;
+    dest[0x03] = iface->bAlternateSetting;
+    dest[0x04] = iface->bNumEndpoints;
+    dest[0x05] = iface->bInterfaceClass;
+    dest[0x06] = iface->bInterfaceSubClass;
+    dest[0x07] = iface->bInterfaceProtocol;
+    dest[0x08] = iface->iInterface;
+    pos += bLength;
+
+    for (i = 0; i < iface->ndesc; i++) {
+        rc = usb_desc_other(iface->descs + i, dest + pos, len - pos);
+        if (rc < 0) {
+            return rc;
+        }
+        pos += rc;
+    }
+
+    for (i = 0; i < iface->bNumEndpoints; i++) {
+        rc = usb_desc_endpoint(iface->eps + i, dest + pos, len - pos);
+        if (rc < 0) {
+            return rc;
+        }
+        pos += rc;
+    }
+
+    return pos;
+}
+
+int usb_desc_endpoint(const USBDescEndpoint *ep, uint8_t *dest, size_t len)
+{
+    uint8_t bLength = 0x07;
+
+    if (len < bLength) {
+        return -1;
+    }
+
+    dest[0x00] = bLength;
+    dest[0x01] = USB_DT_ENDPOINT;
+    dest[0x02] = ep->bEndpointAddress;
+    dest[0x03] = ep->bmAttributes;
+    dest[0x04] = usb_lo(ep->wMaxPacketSize);
+    dest[0x05] = usb_hi(ep->wMaxPacketSize);
+    dest[0x06] = ep->bInterval;
+
+    return bLength;
+}
+
+int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len)
+{
+    int bLength = desc->length ? desc->length : desc->data[0];
+
+    if (len < bLength) {
+        return -1;
+    }
+
+    memcpy(dest, desc->data, bLength);
+    return bLength;
+}
+
+int usb_desc_string(const char* const *str, int index, uint8_t *dest, size_t len)
+{
+    uint8_t bLength, pos, i;
+
+    if (len < 4) {
+        return -1;
+    }
+
+    if (index == 0) {
+        /* language ids */
+        dest[0] = 4;
+        dest[1] = USB_DT_STRING;
+        dest[2] = 0x09;
+        dest[3] = 0x04;
+        return 4;
+    }
+
+    if (str[index] == NULL) {
+        return 0;
+    }
+    bLength = strlen(str[index]) * 2 + 2;
+    dest[0] = bLength;
+    dest[1] = USB_DT_STRING;
+    i = 0; pos = 2;
+    while (pos+1 < bLength && pos+1 < len) {
+        dest[pos++] = str[index][i++];
+        dest[pos++] = 0;
+    }
+    return pos;
+}
+
+/* ------------------------------------------------------------------ */
+
+int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len)
+{
+    const USBDesc *desc = dev->info->usb_desc;
+    uint8_t buf[256];
+    uint8_t type = value >> 8;
+    uint8_t index = value & 0xff;
+    int ret = -1;
+
+    switch(type) {
+    case USB_DT_DEVICE:
+        ret = usb_desc_device(&desc->id, desc->full, buf, sizeof(buf));
+        trace_usb_desc_device(dev->addr, len, ret);
+        break;
+    case USB_DT_CONFIG:
+        if (index < desc->full->bNumConfigurations) {
+            ret = usb_desc_config(desc->full->confs + index, buf, sizeof(buf));
+        }
+        trace_usb_desc_config(dev->addr, index, len, ret);
+        break;
+    case USB_DT_STRING:
+        ret = usb_desc_string(desc->str, index, buf, sizeof(buf));
+        trace_usb_desc_string(dev->addr, index, len, ret);
+        break;
+    default:
+        fprintf(stderr, "%s: %d unknown type %d (len %zd)\n", __FUNCTION__,
+                dev->addr, type, len);
+        break;
+    }
+
+    if (ret > 0) {
+        if (ret > len) {
+            ret = len;
+        }
+        memcpy(dest, buf, ret);
+    }
+    return ret;
+}
+
+int usb_desc_handle_control(USBDevice *dev, int request, int value,
+                            int index, int length, uint8_t *data)
+{
+    const USBDesc *desc = dev->info->usb_desc;
+    int ret = -1;
+
+    assert(desc != NULL);
+    switch(request) {
+    case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
+        ret = usb_desc_get_descriptor(dev, value, data, length);
+        break;
+    }
+    return ret;
+}
diff --git a/hw/usb-desc.h b/hw/usb-desc.h
new file mode 100644
index 0000000..d80efdb
--- /dev/null
+++ b/hw/usb-desc.h
@@ -0,0 +1,86 @@
+#ifndef QEMU_HW_USB_DESC_H
+#define QEMU_HW_USB_DESC_H
+
+#include <inttypes.h>
+
+struct USBDescID {
+    uint16_t                  idVendor;
+    uint16_t                  idProduct;
+    uint16_t                  bcdDevice;
+    uint8_t                   iManufacturer;
+    uint8_t                   iProduct;
+    uint8_t                   iSerialNumber;
+};
+
+struct USBDescDevice {
+    uint16_t                  bcdUSB;
+    uint8_t                   bDeviceClass;
+    uint8_t                   bDeviceSubClass;
+    uint8_t                   bDeviceProtocol;
+    uint8_t                   bMaxPacketSize0;
+    uint8_t                   bNumConfigurations;
+
+    const USBDescConfig       *confs;
+};
+
+struct USBDescConfig {
+    uint8_t                   bNumInterfaces;
+    uint8_t                   bConfigurationValue;
+    uint8_t                   iConfiguration;
+    uint8_t                   bmAttributes;
+    uint8_t                   bMaxPower;
+
+    uint8_t                   nif;
+    const USBDescIface        *ifs;
+};
+
+struct USBDescIface {
+    uint8_t                   bInterfaceNumber;
+    uint8_t                   bAlternateSetting;
+    uint8_t                   bNumEndpoints;
+    uint8_t                   bInterfaceClass;
+    uint8_t                   bInterfaceSubClass;
+    uint8_t                   bInterfaceProtocol;
+    uint8_t                   iInterface;
+
+    uint8_t                   ndesc;
+    USBDescOther              *descs;
+    USBDescEndpoint           *eps;
+};
+
+struct USBDescEndpoint {
+    uint8_t                   bEndpointAddress;
+    uint8_t                   bmAttributes;
+    uint16_t                  wMaxPacketSize;
+    uint8_t                   bInterval;
+};
+
+struct USBDescOther {
+    uint8_t                   length;
+    uint8_t                   *data;
+};
+
+typedef const char *USBDescStrings[256];
+
+struct USBDesc {
+    USBDescID                 id;
+    const USBDescDevice       *full;
+    const USBDescDevice       *high;
+    const char* const         *str;
+};
+
+/* generate usb packages from structs */
+int usb_desc_device(const USBDescID *id, const USBDescDevice *dev,
+                    uint8_t *dest, size_t len);
+int usb_desc_config(const USBDescConfig *conf, uint8_t *dest, size_t len);
+int usb_desc_iface(const USBDescIface *iface, uint8_t *dest, size_t len);
+int usb_desc_endpoint(const USBDescEndpoint *ep, uint8_t *dest, size_t len);
+int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len);
+int usb_desc_string(const char* const *str, int index, uint8_t *dest, size_t len);
+
+/* control message emulation helpers */
+int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len);
+int usb_desc_handle_control(USBDevice *dev, int request, int value,
+                            int index, int length, uint8_t *data);
+
+#endif /* QEMU_HW_USB_DESC_H */
diff --git a/hw/usb.h b/hw/usb.h
index 0b32d77..a29b6d6 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -128,6 +128,14 @@ typedef struct USBDevice USBDevice;
 typedef struct USBDeviceInfo USBDeviceInfo;
 typedef struct USBPacket USBPacket;
 
+typedef struct USBDesc USBDesc;
+typedef struct USBDescID USBDescID;
+typedef struct USBDescDevice USBDescDevice;
+typedef struct USBDescConfig USBDescConfig;
+typedef struct USBDescIface USBDescIface;
+typedef struct USBDescEndpoint USBDescEndpoint;
+typedef struct USBDescOther USBDescOther;
+
 /* definition of a USB device */
 struct USBDevice {
     DeviceState qdev;
@@ -190,6 +198,7 @@ struct USBDeviceInfo {
     int (*handle_data)(USBDevice *dev, USBPacket *p);
 
     const char *product_desc;
+    const USBDesc *usb_desc;
 
     /* handle legacy -usbdevice command line options */
     const char *usbdevice_name;
diff --git a/trace-events b/trace-events
index e8fed0f..8264ff0 100644
--- a/trace-events
+++ b/trace-events
@@ -190,6 +190,11 @@ disable sun4m_iommu_page_get_flags(uint64_t pa, uint64_t iopte, uint32_t ret) "g
 disable sun4m_iommu_translate_pa(uint64_t addr, uint64_t pa, uint32_t iopte) "xlate dva %"PRIx64" => pa %"PRIx64" iopte = %x"
 disable sun4m_iommu_bad_addr(uint64_t addr) "bad addr %"PRIx64""
 
+# hw/usb-desc.c
+disable usb_desc_device(int addr, int len, int ret) "dev %d query device, len %d, ret %d"
+disable usb_desc_config(int addr, int index, int len, int ret) "dev %d query config %d, len %d, ret %d"
+disable usb_desc_string(int addr, int index, int len, int ret) "dev %d query string %d, len %d, ret %d"
+
 # vl.c
 disable vm_state_notify(int running, int reason) "running %d reason %d"
 
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v4 03/32] usb hid: use new descriptor infrastructure.
  2011-01-12 11:19 [Qemu-devel] [PATCH v4 00/32] usb descriptor overhaul + more Gerd Hoffmann
  2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 01/32] usb: update MAINTAINERS Gerd Hoffmann
  2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 02/32] usb: data structs and helpers for usb descriptors Gerd Hoffmann
@ 2011-01-12 11:19 ` Gerd Hoffmann
  2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 04/32] usb serial: " Gerd Hoffmann
                   ` (29 subsequent siblings)
  32 siblings, 0 replies; 37+ messages in thread
From: Gerd Hoffmann @ 2011-01-12 11:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Switch the usb hid drivers (keyboard, mouse, tablet) over to the
new descriptor infrastructure.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb-hid.c |  448 +++++++++++++++++++++++++++-------------------------------
 1 files changed, 205 insertions(+), 243 deletions(-)

diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index 882d933..74d17fc 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -25,6 +25,7 @@
 #include "hw.h"
 #include "console.h"
 #include "usb.h"
+#include "usb-desc.h"
 #include "sysemu.h"
 
 /* HID interface requests */
@@ -73,190 +74,206 @@ typedef struct USBHIDState {
     void (*datain)(void *);
 } USBHIDState;
 
-/* mostly the same values as the Bochs USB Mouse device */
-static const uint8_t qemu_mouse_dev_descriptor[] = {
-	0x12,       /*  u8 bLength; */
-	0x01,       /*  u8 bDescriptorType; Device */
-	0x00, 0x01, /*  u16 bcdUSB; v1.0 */
-
-	0x00,	    /*  u8  bDeviceClass; */
-	0x00,	    /*  u8  bDeviceSubClass; */
-	0x00,       /*  u8  bDeviceProtocol; [ low/full speeds only ] */
-	0x08,       /*  u8  bMaxPacketSize0; 8 Bytes */
-
-	0x27, 0x06, /*  u16 idVendor; */
- 	0x01, 0x00, /*  u16 idProduct; */
-	0x00, 0x00, /*  u16 bcdDevice */
-
-	0x03,       /*  u8  iManufacturer; */
-	0x02,       /*  u8  iProduct; */
-	0x01,       /*  u8  iSerialNumber; */
-	0x01        /*  u8  bNumConfigurations; */
+enum {
+    STR_MANUFACTURER = 1,
+    STR_PRODUCT_MOUSE,
+    STR_PRODUCT_TABLET,
+    STR_PRODUCT_KEYBOARD,
+    STR_SERIALNUMBER,
+    STR_CONFIG_MOUSE,
+    STR_CONFIG_TABLET,
+    STR_CONFIG_KEYBOARD,
 };
 
-static const uint8_t qemu_mouse_config_descriptor[] = {
-	/* one configuration */
-	0x09,       /*  u8  bLength; */
-	0x02,       /*  u8  bDescriptorType; Configuration */
-	0x22, 0x00, /*  u16 wTotalLength; */
-	0x01,       /*  u8  bNumInterfaces; (1) */
-	0x01,       /*  u8  bConfigurationValue; */
-	0x04,       /*  u8  iConfiguration; */
-	0xe0,       /*  u8  bmAttributes;
-				 Bit 7: must be set,
-				     6: Self-powered,
-				     5: Remote wakeup,
-				     4..0: resvd */
-	50,         /*  u8  MaxPower; */
-
-	/* USB 1.1:
-	 * USB 2.0, single TT organization (mandatory):
-	 *	one interface, protocol 0
-	 *
-	 * USB 2.0, multiple TT organization (optional):
-	 *	two interfaces, protocols 1 (like single TT)
-	 *	and 2 (multiple TT mode) ... config is
-	 *	sometimes settable
-	 *	NOT IMPLEMENTED
-	 */
-
-	/* one interface */
-	0x09,       /*  u8  if_bLength; */
-	0x04,       /*  u8  if_bDescriptorType; Interface */
-	0x00,       /*  u8  if_bInterfaceNumber; */
-	0x00,       /*  u8  if_bAlternateSetting; */
-	0x01,       /*  u8  if_bNumEndpoints; */
-	0x03,       /*  u8  if_bInterfaceClass; */
-	0x01,       /*  u8  if_bInterfaceSubClass; */
-	0x02,       /*  u8  if_bInterfaceProtocol; [usb1.1 or single tt] */
-	0x07,       /*  u8  if_iInterface; */
-
-        /* HID descriptor */
-        0x09,        /*  u8  bLength; */
-        0x21,        /*  u8 bDescriptorType; */
-        0x01, 0x00,  /*  u16 HID_class */
-        0x00,        /*  u8 country_code */
-        0x01,        /*  u8 num_descriptors */
-        0x22,        /*  u8 type; Report */
-        52, 0,       /*  u16 len */
-
-	/* one endpoint (status change endpoint) */
-	0x07,       /*  u8  ep_bLength; */
-	0x05,       /*  u8  ep_bDescriptorType; Endpoint */
-	0x81,       /*  u8  ep_bEndpointAddress; IN Endpoint 1 */
- 	0x03,       /*  u8  ep_bmAttributes; Interrupt */
- 	0x04, 0x00, /*  u16 ep_wMaxPacketSize; */
-	0x0a,       /*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
+static const USBDescStrings desc_strings = {
+    [STR_MANUFACTURER]     = "QEMU " QEMU_VERSION,
+    [STR_PRODUCT_MOUSE]    = "QEMU USB Mouse",
+    [STR_PRODUCT_TABLET]   = "QEMU USB Tablet",
+    [STR_PRODUCT_KEYBOARD] = "QEMU USB Keyboard",
+    [STR_SERIALNUMBER]     = "1",
+    [STR_CONFIG_MOUSE]     = "HID Mouse",
+    [STR_CONFIG_TABLET]    = "HID Tablet",
+    [STR_CONFIG_KEYBOARD]  = "HID Keyboard",
 };
 
-static const uint8_t qemu_tablet_config_descriptor[] = {
-	/* one configuration */
-	0x09,       /*  u8  bLength; */
-	0x02,       /*  u8  bDescriptorType; Configuration */
-	0x22, 0x00, /*  u16 wTotalLength; */
-	0x01,       /*  u8  bNumInterfaces; (1) */
-	0x01,       /*  u8  bConfigurationValue; */
-	0x05,       /*  u8  iConfiguration; */
-	0xa0,       /*  u8  bmAttributes;
-				 Bit 7: must be set,
-				     6: Self-powered,
-				     5: Remote wakeup,
-				     4..0: resvd */
-	50,         /*  u8  MaxPower; */
-
-	/* USB 1.1:
-	 * USB 2.0, single TT organization (mandatory):
-	 *	one interface, protocol 0
-	 *
-	 * USB 2.0, multiple TT organization (optional):
-	 *	two interfaces, protocols 1 (like single TT)
-	 *	and 2 (multiple TT mode) ... config is
-	 *	sometimes settable
-	 *	NOT IMPLEMENTED
-	 */
-
-	/* one interface */
-	0x09,       /*  u8  if_bLength; */
-	0x04,       /*  u8  if_bDescriptorType; Interface */
-	0x00,       /*  u8  if_bInterfaceNumber; */
-	0x00,       /*  u8  if_bAlternateSetting; */
-	0x01,       /*  u8  if_bNumEndpoints; */
-	0x03,       /*  u8  if_bInterfaceClass; */
-	0x01,       /*  u8  if_bInterfaceSubClass; */
-	0x02,       /*  u8  if_bInterfaceProtocol; [usb1.1 or single tt] */
-	0x07,       /*  u8  if_iInterface; */
-
-        /* HID descriptor */
-        0x09,        /*  u8  bLength; */
-        0x21,        /*  u8 bDescriptorType; */
-        0x01, 0x00,  /*  u16 HID_class */
-        0x00,        /*  u8 country_code */
-        0x01,        /*  u8 num_descriptors */
-        0x22,        /*  u8 type; Report */
-        74, 0,       /*  u16 len */
-
-	/* one endpoint (status change endpoint) */
-	0x07,       /*  u8  ep_bLength; */
-	0x05,       /*  u8  ep_bDescriptorType; Endpoint */
-	0x81,       /*  u8  ep_bEndpointAddress; IN Endpoint 1 */
- 	0x03,       /*  u8  ep_bmAttributes; Interrupt */
- 	0x08, 0x00, /*  u16 ep_wMaxPacketSize; */
-	0x0a,       /*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
+static const USBDescIface desc_iface_mouse = {
+    .bInterfaceNumber              = 0,
+    .bNumEndpoints                 = 1,
+    .bInterfaceClass               = USB_CLASS_HID,
+    .bInterfaceSubClass            = 0x01, /* boot */
+    .bInterfaceProtocol            = 0x02,
+    .ndesc                         = 1,
+    .descs = (USBDescOther[]) {
+        {
+            /* HID descriptor */
+            .data = (uint8_t[]) {
+                0x09,          /*  u8  bLength */
+                USB_DT_HID,    /*  u8  bDescriptorType */
+                0x01, 0x00,    /*  u16 HID_class */
+                0x00,          /*  u8  country_code */
+                0x01,          /*  u8  num_descriptors */
+                USB_DT_REPORT, /*  u8  type: Report */
+                52, 0,         /*  u16 len */
+            },
+        },
+    },
+    .eps = (USBDescEndpoint[]) {
+        {
+            .bEndpointAddress      = USB_DIR_IN | 0x01,
+            .bmAttributes          = USB_ENDPOINT_XFER_INT,
+            .wMaxPacketSize        = 4,
+            .bInterval             = 0x0a,
+        },
+    },
 };
 
-static const uint8_t qemu_keyboard_config_descriptor[] = {
-    /* one configuration */
-    0x09,		/*  u8  bLength; */
-    USB_DT_CONFIG,	/*  u8  bDescriptorType; Configuration */
-    0x22, 0x00,		/*  u16 wTotalLength; */
-    0x01,		/*  u8  bNumInterfaces; (1) */
-    0x01,		/*  u8  bConfigurationValue; */
-    0x06,		/*  u8  iConfiguration; */
-    0xa0,		/*  u8  bmAttributes;
-				Bit 7: must be set,
-				    6: Self-powered,
-				    5: Remote wakeup,
-				    4..0: resvd */
-    0x32,		/*  u8  MaxPower; */
-
-    /* USB 1.1:
-     * USB 2.0, single TT organization (mandatory):
-     *	one interface, protocol 0
-     *
-     * USB 2.0, multiple TT organization (optional):
-     *	two interfaces, protocols 1 (like single TT)
-     *	and 2 (multiple TT mode) ... config is
-     *	sometimes settable
-     *	NOT IMPLEMENTED
-     */
-
-    /* one interface */
-    0x09,		/*  u8  if_bLength; */
-    USB_DT_INTERFACE,	/*  u8  if_bDescriptorType; Interface */
-    0x00,		/*  u8  if_bInterfaceNumber; */
-    0x00,		/*  u8  if_bAlternateSetting; */
-    0x01,		/*  u8  if_bNumEndpoints; */
-    0x03,		/*  u8  if_bInterfaceClass; HID */
-    0x01,		/*  u8  if_bInterfaceSubClass; Boot */
-    0x01,		/*  u8  if_bInterfaceProtocol; Keyboard */
-    0x07,		/*  u8  if_iInterface; */
-
-    /* HID descriptor */
-    0x09,		/*  u8  bLength; */
-    USB_DT_HID,		/*  u8  bDescriptorType; */
-    0x11, 0x01,		/*  u16 HID_class */
-    0x00,		/*  u8  country_code */
-    0x01,		/*  u8  num_descriptors */
-    USB_DT_REPORT,	/*  u8  type; Report */
-    0x3f, 0x00,		/*  u16 len */
-
-    /* one endpoint (status change endpoint) */
-    0x07,		/*  u8  ep_bLength; */
-    USB_DT_ENDPOINT,	/*  u8  ep_bDescriptorType; Endpoint */
-    USB_DIR_IN | 0x01,	/*  u8  ep_bEndpointAddress; IN Endpoint 1 */
-    0x03,		/*  u8  ep_bmAttributes; Interrupt */
-    0x08, 0x00,		/*  u16 ep_wMaxPacketSize; */
-    0x0a,		/*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
+static const USBDescIface desc_iface_tablet = {
+    .bInterfaceNumber              = 0,
+    .bNumEndpoints                 = 1,
+    .bInterfaceClass               = USB_CLASS_HID,
+    .bInterfaceSubClass            = 0x01, /* boot */
+    .bInterfaceProtocol            = 0x02,
+    .ndesc                         = 1,
+    .descs = (USBDescOther[]) {
+        {
+            /* HID descriptor */
+            .data = (uint8_t[]) {
+                0x09,          /*  u8  bLength */
+                USB_DT_HID,    /*  u8  bDescriptorType */
+                0x01, 0x00,    /*  u16 HID_class */
+                0x00,          /*  u8  country_code */
+                0x01,          /*  u8  num_descriptors */
+                USB_DT_REPORT, /*  u8  type: Report */
+                74, 0,         /*  u16 len */
+            },
+        },
+    },
+    .eps = (USBDescEndpoint[]) {
+        {
+            .bEndpointAddress      = USB_DIR_IN | 0x01,
+            .bmAttributes          = USB_ENDPOINT_XFER_INT,
+            .wMaxPacketSize        = 8,
+            .bInterval             = 0x0a,
+        },
+    },
+};
+
+static const USBDescIface desc_iface_keyboard = {
+    .bInterfaceNumber              = 0,
+    .bNumEndpoints                 = 1,
+    .bInterfaceClass               = USB_CLASS_HID,
+    .bInterfaceSubClass            = 0x01, /* boot */
+    .bInterfaceProtocol            = 0x01, /* keyboard */
+    .ndesc                         = 1,
+    .descs = (USBDescOther[]) {
+        {
+            /* HID descriptor */
+            .data = (uint8_t[]) {
+                0x09,          /*  u8  bLength */
+                USB_DT_HID,    /*  u8  bDescriptorType */
+                0x11, 0x01,    /*  u16 HID_class */
+                0x00,          /*  u8  country_code */
+                0x01,          /*  u8  num_descriptors */
+                USB_DT_REPORT, /*  u8  type: Report */
+                0x3f, 0,       /*  u16 len */
+            },
+        },
+    },
+    .eps = (USBDescEndpoint[]) {
+        {
+            .bEndpointAddress      = USB_DIR_IN | 0x01,
+            .bmAttributes          = USB_ENDPOINT_XFER_INT,
+            .wMaxPacketSize        = 8,
+            .bInterval             = 0x0a,
+        },
+    },
+};
+
+static const USBDescDevice desc_device_mouse = {
+    .bcdUSB                        = 0x0100,
+    .bMaxPacketSize0               = 8,
+    .bNumConfigurations            = 1,
+    .confs = (USBDescConfig[]) {
+        {
+            .bNumInterfaces        = 1,
+            .bConfigurationValue   = 1,
+            .iConfiguration        = STR_CONFIG_MOUSE,
+            .bmAttributes          = 0xa0,
+            .bMaxPower             = 50,
+            .ifs = &desc_iface_mouse,
+        },
+    },
+};
+
+static const USBDescDevice desc_device_tablet = {
+    .bcdUSB                        = 0x0100,
+    .bMaxPacketSize0               = 8,
+    .bNumConfigurations            = 1,
+    .confs = (USBDescConfig[]) {
+        {
+            .bNumInterfaces        = 1,
+            .bConfigurationValue   = 1,
+            .iConfiguration        = STR_CONFIG_TABLET,
+            .bmAttributes          = 0xa0,
+            .bMaxPower             = 50,
+            .ifs = &desc_iface_tablet,
+        },
+    },
+};
+
+static const USBDescDevice desc_device_keyboard = {
+    .bcdUSB                        = 0x0100,
+    .bMaxPacketSize0               = 8,
+    .bNumConfigurations            = 1,
+    .confs = (USBDescConfig[]) {
+        {
+            .bNumInterfaces        = 1,
+            .bConfigurationValue   = 1,
+            .iConfiguration        = STR_CONFIG_KEYBOARD,
+            .bmAttributes          = 0xa0,
+            .bMaxPower             = 50,
+            .ifs = &desc_iface_keyboard,
+        },
+    },
+};
+
+static const USBDesc desc_mouse = {
+    .id = {
+        .idVendor          = 0x0627,
+        .idProduct         = 0x0001,
+        .bcdDevice         = 0,
+        .iManufacturer     = STR_MANUFACTURER,
+        .iProduct          = STR_PRODUCT_MOUSE,
+        .iSerialNumber     = STR_SERIALNUMBER,
+    },
+    .full = &desc_device_mouse,
+    .str  = desc_strings,
+};
+
+static const USBDesc desc_tablet = {
+    .id = {
+        .idVendor          = 0x0627,
+        .idProduct         = 0x0001,
+        .bcdDevice         = 0,
+        .iManufacturer     = STR_MANUFACTURER,
+        .iProduct          = STR_PRODUCT_TABLET,
+        .iSerialNumber     = STR_SERIALNUMBER,
+    },
+    .full = &desc_device_tablet,
+    .str  = desc_strings,
+};
+
+static const USBDesc desc_keyboard = {
+    .id = {
+        .idVendor          = 0x0627,
+        .idProduct         = 0x0001,
+        .bcdDevice         = 0,
+        .iManufacturer     = STR_MANUFACTURER,
+        .iProduct          = STR_PRODUCT_KEYBOARD,
+        .iSerialNumber     = STR_SERIALNUMBER,
+    },
+    .full = &desc_device_keyboard,
+    .str  = desc_strings,
 };
 
 static const uint8_t qemu_mouse_hid_report_descriptor[] = {
@@ -647,8 +664,14 @@ static int usb_hid_handle_control(USBDevice *dev, int request, int value,
                                   int index, int length, uint8_t *data)
 {
     USBHIDState *s = (USBHIDState *)dev;
-    int ret = 0;
+    int ret;
 
+    ret = usb_desc_handle_control(dev, request, value, index, length, data);
+    if (ret >= 0) {
+        return ret;
+    }
+
+    ret = 0;
     switch(request) {
     case DeviceRequest | USB_REQ_GET_STATUS:
         data[0] = (1 << USB_DEVICE_SELF_POWERED) |
@@ -676,70 +699,6 @@ static int usb_hid_handle_control(USBDevice *dev, int request, int value,
         dev->addr = value;
         ret = 0;
         break;
-    case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
-        switch(value >> 8) {
-        case USB_DT_DEVICE:
-            memcpy(data, qemu_mouse_dev_descriptor,
-                   sizeof(qemu_mouse_dev_descriptor));
-            ret = sizeof(qemu_mouse_dev_descriptor);
-            break;
-        case USB_DT_CONFIG:
-	    if (s->kind == USB_MOUSE) {
-		memcpy(data, qemu_mouse_config_descriptor,
-		       sizeof(qemu_mouse_config_descriptor));
-		ret = sizeof(qemu_mouse_config_descriptor);
-	    } else if (s->kind == USB_TABLET) {
-		memcpy(data, qemu_tablet_config_descriptor,
-		       sizeof(qemu_tablet_config_descriptor));
-		ret = sizeof(qemu_tablet_config_descriptor);
-            } else if (s->kind == USB_KEYBOARD) {
-                memcpy(data, qemu_keyboard_config_descriptor,
-                       sizeof(qemu_keyboard_config_descriptor));
-                ret = sizeof(qemu_keyboard_config_descriptor);
-            }
-            break;
-        case USB_DT_STRING:
-            switch(value & 0xff) {
-            case 0:
-                /* language ids */
-                data[0] = 4;
-                data[1] = 3;
-                data[2] = 0x09;
-                data[3] = 0x04;
-                ret = 4;
-                break;
-            case 1:
-                /* serial number */
-                ret = set_usb_string(data, "1");
-                break;
-            case 2:
-                /* product description */
-                ret = set_usb_string(data, s->dev.product_desc);
-                break;
-            case 3:
-                /* vendor description */
-                ret = set_usb_string(data, "QEMU " QEMU_VERSION);
-                break;
-            case 4:
-                ret = set_usb_string(data, "HID Mouse");
-                break;
-            case 5:
-                ret = set_usb_string(data, "HID Tablet");
-                break;
-            case 6:
-                ret = set_usb_string(data, "HID Keyboard");
-                break;
-            case 7:
-                ret = set_usb_string(data, "Endpoint1 Interrupt Pipe");
-                break;
-            default:
-                goto fail;
-            }
-            break;
-        default:
-            goto fail;
-        }
-        break;
     case DeviceRequest | USB_REQ_GET_CONFIGURATION:
         data[0] = 1;
         ret = 1;
@@ -912,6 +871,7 @@ static struct USBDeviceInfo hid_info[] = {
         .qdev.name      = "usb-tablet",
         .usbdevice_name = "tablet",
         .qdev.size      = sizeof(USBHIDState),
+        .usb_desc       = &desc_tablet,
         .init           = usb_tablet_initfn,
         .handle_packet  = usb_generic_handle_packet,
         .handle_reset   = usb_mouse_handle_reset,
@@ -923,6 +883,7 @@ static struct USBDeviceInfo hid_info[] = {
         .qdev.name      = "usb-mouse",
         .usbdevice_name = "mouse",
         .qdev.size      = sizeof(USBHIDState),
+        .usb_desc       = &desc_mouse,
         .init           = usb_mouse_initfn,
         .handle_packet  = usb_generic_handle_packet,
         .handle_reset   = usb_mouse_handle_reset,
@@ -934,6 +895,7 @@ static struct USBDeviceInfo hid_info[] = {
         .qdev.name      = "usb-kbd",
         .usbdevice_name = "keyboard",
         .qdev.size      = sizeof(USBHIDState),
+        .usb_desc       = &desc_keyboard,
         .init           = usb_keyboard_initfn,
         .handle_packet  = usb_generic_handle_packet,
         .handle_reset   = usb_keyboard_handle_reset,
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v4 04/32] usb serial: use new descriptor infrastructure.
  2011-01-12 11:19 [Qemu-devel] [PATCH v4 00/32] usb descriptor overhaul + more Gerd Hoffmann
                   ` (2 preceding siblings ...)
  2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 03/32] usb hid: use new descriptor infrastructure Gerd Hoffmann
@ 2011-01-12 11:19 ` Gerd Hoffmann
  2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 05/32] usb storage: " Gerd Hoffmann
                   ` (28 subsequent siblings)
  32 siblings, 0 replies; 37+ messages in thread
From: Gerd Hoffmann @ 2011-01-12 11:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Switch the usb serial drivers (serial, braille) over to the
new descriptor infrastructure.

Note that this removes the freely configurable vendor and product id
properties.  I think the only reason this was configurable is that the
only difference between the serial and the braille device is the
vendor+product id.  Of course the serial and braille devices keep their
different IDs, but they can't be overritten from the command line any
more.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb-serial.c |  200 +++++++++++++++++++++++--------------------------------
 1 files changed, 83 insertions(+), 117 deletions(-)

diff --git a/hw/usb-serial.c b/hw/usb-serial.c
index c19580f..f89eb9b 100644
--- a/hw/usb-serial.c
+++ b/hw/usb-serial.c
@@ -11,6 +11,7 @@
 #include "qemu-common.h"
 #include "qemu-error.h"
 #include "usb.h"
+#include "usb-desc.h"
 #include "qemu-char.h"
 
 //#define DEBUG_Serial
@@ -91,8 +92,6 @@ do { printf("usb-serial: " fmt , ## __VA_ARGS__); } while (0)
 
 typedef struct {
     USBDevice dev;
-    uint32_t vendorid;
-    uint32_t productid;
     uint8_t recv_buf[RECV_BUF];
     uint16_t recv_ptr;
     uint16_t recv_used;
@@ -104,69 +103,78 @@ typedef struct {
     CharDriverState *cs;
 } USBSerialState;
 
-static const uint8_t qemu_serial_dev_descriptor[] = {
-        0x12,       /*  u8 bLength; */
-        0x01,       /*  u8 bDescriptorType; Device */
-        0x00, 0x02, /*  u16 bcdUSB; v2.0 */
-
-        0x00,       /*  u8  bDeviceClass; */
-        0x00,       /*  u8  bDeviceSubClass; */
-        0x00,       /*  u8  bDeviceProtocol; [ low/full speeds only ] */
-        0x08,       /*  u8  bMaxPacketSize0; 8 Bytes */
-
-        /* Vendor and product id are arbitrary.  */
-        0x03, 0x04, /*  u16 idVendor; */
-        0x00, 0xFF, /*  u16 idProduct; */
-        0x00, 0x04, /*  u16 bcdDevice */
-
-        0x01,       /*  u8  iManufacturer; */
-        0x02,       /*  u8  iProduct; */
-        0x03,       /*  u8  iSerialNumber; */
-        0x01        /*  u8  bNumConfigurations; */
+enum {
+    STR_MANUFACTURER = 1,
+    STR_PRODUCT_SERIAL,
+    STR_PRODUCT_BRAILLE,
+    STR_SERIALNUMBER,
 };
 
-static const uint8_t qemu_serial_config_descriptor[] = {
-
-        /* one configuration */
-        0x09,       /*  u8  bLength; */
-        0x02,       /*  u8  bDescriptorType; Configuration */
-        0x20, 0x00, /*  u16 wTotalLength; */
-        0x01,       /*  u8  bNumInterfaces; (1) */
-        0x01,       /*  u8  bConfigurationValue; */
-        0x00,       /*  u8  iConfiguration; */
-        0x80,       /*  u8  bmAttributes;
-                                 Bit 7: must be set,
-                                     6: Self-powered,
-                                     5: Remote wakeup,
-                                     4..0: resvd */
-        100/2,       /*  u8  MaxPower; */
-
-        /* one interface */
-        0x09,       /*  u8  if_bLength; */
-        0x04,       /*  u8  if_bDescriptorType; Interface */
-        0x00,       /*  u8  if_bInterfaceNumber; */
-        0x00,       /*  u8  if_bAlternateSetting; */
-        0x02,       /*  u8  if_bNumEndpoints; */
-        0xff,       /*  u8  if_bInterfaceClass; Vendor Specific */
-        0xff,       /*  u8  if_bInterfaceSubClass; Vendor Specific */
-        0xff,       /*  u8  if_bInterfaceProtocol; Vendor Specific */
-        0x02,       /*  u8  if_iInterface; */
-
-        /* Bulk-In endpoint */
-        0x07,       /*  u8  ep_bLength; */
-        0x05,       /*  u8  ep_bDescriptorType; Endpoint */
-        0x81,       /*  u8  ep_bEndpointAddress; IN Endpoint 1 */
-        0x02,       /*  u8  ep_bmAttributes; Bulk */
-        0x40, 0x00, /*  u16 ep_wMaxPacketSize; */
-        0x00,       /*  u8  ep_bInterval; */
-
-        /* Bulk-Out endpoint */
-        0x07,       /*  u8  ep_bLength; */
-        0x05,       /*  u8  ep_bDescriptorType; Endpoint */
-        0x02,       /*  u8  ep_bEndpointAddress; OUT Endpoint 2 */
-        0x02,       /*  u8  ep_bmAttributes; Bulk */
-        0x40, 0x00, /*  u16 ep_wMaxPacketSize; */
-        0x00        /*  u8  ep_bInterval; */
+static const USBDescStrings desc_strings = {
+    [STR_MANUFACTURER]    = "QEMU " QEMU_VERSION,
+    [STR_PRODUCT_SERIAL]  = "QEMU USB SERIAL",
+    [STR_PRODUCT_BRAILLE] = "QEMU USB BRAILLE",
+    [STR_SERIALNUMBER]    = "1",
+};
+
+static const USBDescIface desc_iface0 = {
+    .bInterfaceNumber              = 0,
+    .bNumEndpoints                 = 2,
+    .bInterfaceClass               = 0xff,
+    .bInterfaceSubClass            = 0xff,
+    .bInterfaceProtocol            = 0xff,
+    .eps = (USBDescEndpoint[]) {
+        {
+            .bEndpointAddress      = USB_DIR_IN | 0x01,
+            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
+            .wMaxPacketSize        = 64,
+        },{
+            .bEndpointAddress      = USB_DIR_OUT | 0x02,
+            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
+            .wMaxPacketSize        = 64,
+        },
+    }
+};
+
+static const USBDescDevice desc_device = {
+    .bcdUSB                        = 0x0200,
+    .bMaxPacketSize0               = 8,
+    .bNumConfigurations            = 1,
+    .confs = (USBDescConfig[]) {
+        {
+            .bNumInterfaces        = 1,
+            .bConfigurationValue   = 1,
+            .bmAttributes          = 0x80,
+            .bMaxPower             = 50,
+            .ifs = &desc_iface0,
+        },
+    },
+};
+
+static const USBDesc desc_serial = {
+    .id = {
+        .idVendor          = 0x0403,
+        .idProduct         = 0x6001,
+        .bcdDevice         = 0x0400,
+        .iManufacturer     = STR_MANUFACTURER,
+        .iProduct          = STR_PRODUCT_SERIAL,
+        .iSerialNumber     = STR_SERIALNUMBER,
+    },
+    .full = &desc_device,
+    .str  = desc_strings,
+};
+
+static const USBDesc desc_braille = {
+    .id = {
+        .idVendor          = 0x0403,
+        .idProduct         = 0xfe72,
+        .bcdDevice         = 0x0400,
+        .iManufacturer     = STR_MANUFACTURER,
+        .iProduct          = STR_PRODUCT_BRAILLE,
+        .iSerialNumber     = STR_SERIALNUMBER,
+    },
+    .full = &desc_device,
+    .str  = desc_strings,
 };
 
 static void usb_serial_reset(USBSerialState *s)
@@ -214,9 +222,15 @@ static int usb_serial_handle_control(USBDevice *dev, int request, int value,
                                   int index, int length, uint8_t *data)
 {
     USBSerialState *s = (USBSerialState *)dev;
-    int ret = 0;
+    int ret;
+
+    DPRINTF("got control %x, value %x\n",request, value);
+    ret = usb_desc_handle_control(dev, request, value, index, length, data);
+    if (ret >= 0) {
+        return ret;
+    }
 
-    //DPRINTF("got control %x, value %x\n",request, value);
+    ret = 0;
     switch (request) {
     case DeviceRequest | USB_REQ_GET_STATUS:
         data[0] = (0 << USB_DEVICE_SELF_POWERED) |
@@ -244,52 +258,6 @@ static int usb_serial_handle_control(USBDevice *dev, int request, int value,
         dev->addr = value;
         ret = 0;
         break;
-    case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
-        switch(value >> 8) {
-        case USB_DT_DEVICE:
-            memcpy(data, qemu_serial_dev_descriptor,
-                   sizeof(qemu_serial_dev_descriptor));
-            data[8] = s->vendorid & 0xff;
-            data[9] = ((s->vendorid) >> 8) & 0xff;
-            data[10] = s->productid & 0xff;
-            data[11] = ((s->productid) >> 8) & 0xff;
-            ret = sizeof(qemu_serial_dev_descriptor);
-            break;
-        case USB_DT_CONFIG:
-            memcpy(data, qemu_serial_config_descriptor,
-                   sizeof(qemu_serial_config_descriptor));
-            ret = sizeof(qemu_serial_config_descriptor);
-            break;
-        case USB_DT_STRING:
-            switch(value & 0xff) {
-            case 0:
-                /* language ids */
-                data[0] = 4;
-                data[1] = 3;
-                data[2] = 0x09;
-                data[3] = 0x04;
-                ret = 4;
-                break;
-            case 1:
-                /* vendor description */
-                ret = set_usb_string(data, "QEMU " QEMU_VERSION);
-                break;
-            case 2:
-                /* product description */
-                ret = set_usb_string(data, "QEMU USB SERIAL");
-                break;
-            case 3:
-                /* serial number */
-                ret = set_usb_string(data, "1");
-                break;
-            default:
-                goto fail;
-            }
-            break;
-        default:
-            goto fail;
-        }
-        break;
     case DeviceRequest | USB_REQ_GET_CONFIGURATION:
         data[0] = 1;
         ret = 1;
@@ -633,6 +601,7 @@ static struct USBDeviceInfo serial_info = {
     .product_desc   = "QEMU USB Serial",
     .qdev.name      = "usb-serial",
     .qdev.size      = sizeof(USBSerialState),
+    .usb_desc       = &desc_serial,
     .init           = usb_serial_initfn,
     .handle_packet  = usb_generic_handle_packet,
     .handle_reset   = usb_serial_handle_reset,
@@ -642,9 +611,7 @@ static struct USBDeviceInfo serial_info = {
     .usbdevice_name = "serial",
     .usbdevice_init = usb_serial_init,
     .qdev.props     = (Property[]) {
-        DEFINE_PROP_CHR("chardev",     USBSerialState, cs),
-        DEFINE_PROP_HEX32("vendorid",  USBSerialState, vendorid,  0x0403),
-        DEFINE_PROP_HEX32("productid", USBSerialState, productid, 0x6001),
+        DEFINE_PROP_CHR("chardev", USBSerialState, cs),
         DEFINE_PROP_END_OF_LIST(),
     },
 };
@@ -653,6 +620,7 @@ static struct USBDeviceInfo braille_info = {
     .product_desc   = "QEMU USB Braille",
     .qdev.name      = "usb-braille",
     .qdev.size      = sizeof(USBSerialState),
+    .usb_desc       = &desc_braille,
     .init           = usb_serial_initfn,
     .handle_packet  = usb_generic_handle_packet,
     .handle_reset   = usb_serial_handle_reset,
@@ -662,9 +630,7 @@ static struct USBDeviceInfo braille_info = {
     .usbdevice_name = "braille",
     .usbdevice_init = usb_braille_init,
     .qdev.props     = (Property[]) {
-        DEFINE_PROP_CHR("chardev",     USBSerialState, cs),
-        DEFINE_PROP_HEX32("vendorid",  USBSerialState, vendorid,  0x0403),
-        DEFINE_PROP_HEX32("productid", USBSerialState, productid, 0xfe72),
+        DEFINE_PROP_CHR("chardev", USBSerialState, cs),
         DEFINE_PROP_END_OF_LIST(),
     },
 };
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v4 05/32] usb storage: use new descriptor infrastructure.
  2011-01-12 11:19 [Qemu-devel] [PATCH v4 00/32] usb descriptor overhaul + more Gerd Hoffmann
                   ` (3 preceding siblings ...)
  2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 04/32] usb serial: " Gerd Hoffmann
@ 2011-01-12 11:19 ` Gerd Hoffmann
  2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 06/32] usb wacom: " Gerd Hoffmann
                   ` (27 subsequent siblings)
  32 siblings, 0 replies; 37+ messages in thread
From: Gerd Hoffmann @ 2011-01-12 11:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Switch the usb storage driver over to the
new descriptor infrastructure.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb-msd.c |  167 ++++++++++++++++++++++------------------------------------
 1 files changed, 63 insertions(+), 104 deletions(-)

diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 0a95d8d..20ab886 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -11,6 +11,7 @@
 #include "qemu-option.h"
 #include "qemu-config.h"
 #include "usb.h"
+#include "usb-desc.h"
 #include "scsi.h"
 #include "console.h"
 #include "monitor.h"
@@ -72,69 +73,62 @@ struct usb_msd_csw {
     uint8_t status;
 };
 
-static const uint8_t qemu_msd_dev_descriptor[] = {
-	0x12,       /*  u8 bLength; */
-	0x01,       /*  u8 bDescriptorType; Device */
-	0x00, 0x01, /*  u16 bcdUSB; v1.0 */
-
-	0x00,	    /*  u8  bDeviceClass; */
-	0x00,	    /*  u8  bDeviceSubClass; */
-	0x00,       /*  u8  bDeviceProtocol; [ low/full speeds only ] */
-	0x08,       /*  u8  bMaxPacketSize0; 8 Bytes */
-
-        /* Vendor and product id are arbitrary.  */
-	0x00, 0x00, /*  u16 idVendor; */
- 	0x00, 0x00, /*  u16 idProduct; */
-	0x00, 0x00, /*  u16 bcdDevice */
-
-	0x01,       /*  u8  iManufacturer; */
-	0x02,       /*  u8  iProduct; */
-	0x03,       /*  u8  iSerialNumber; */
-	0x01        /*  u8  bNumConfigurations; */
+enum {
+    STR_MANUFACTURER = 1,
+    STR_PRODUCT,
+    STR_SERIALNUMBER,
 };
 
-static const uint8_t qemu_msd_config_descriptor[] = {
-
-	/* one configuration */
-	0x09,       /*  u8  bLength; */
-	0x02,       /*  u8  bDescriptorType; Configuration */
-	0x20, 0x00, /*  u16 wTotalLength; */
-	0x01,       /*  u8  bNumInterfaces; (1) */
-	0x01,       /*  u8  bConfigurationValue; */
-	0x00,       /*  u8  iConfiguration; */
-	0xc0,       /*  u8  bmAttributes;
-				 Bit 7: must be set,
-				     6: Self-powered,
-				     5: Remote wakeup,
-				     4..0: resvd */
-	0x00,       /*  u8  MaxPower; */
-
-	/* one interface */
-	0x09,       /*  u8  if_bLength; */
-	0x04,       /*  u8  if_bDescriptorType; Interface */
-	0x00,       /*  u8  if_bInterfaceNumber; */
-	0x00,       /*  u8  if_bAlternateSetting; */
-	0x02,       /*  u8  if_bNumEndpoints; */
-	0x08,       /*  u8  if_bInterfaceClass; MASS STORAGE */
-	0x06,       /*  u8  if_bInterfaceSubClass; SCSI */
-	0x50,       /*  u8  if_bInterfaceProtocol; Bulk Only */
-	0x00,       /*  u8  if_iInterface; */
-
-	/* Bulk-In endpoint */
-	0x07,       /*  u8  ep_bLength; */
-	0x05,       /*  u8  ep_bDescriptorType; Endpoint */
-	0x81,       /*  u8  ep_bEndpointAddress; IN Endpoint 1 */
- 	0x02,       /*  u8  ep_bmAttributes; Bulk */
- 	0x40, 0x00, /*  u16 ep_wMaxPacketSize; */
-	0x00,       /*  u8  ep_bInterval; */
-
-	/* Bulk-Out endpoint */
-	0x07,       /*  u8  ep_bLength; */
-	0x05,       /*  u8  ep_bDescriptorType; Endpoint */
-	0x02,       /*  u8  ep_bEndpointAddress; OUT Endpoint 2 */
- 	0x02,       /*  u8  ep_bmAttributes; Bulk */
- 	0x40, 0x00, /*  u16 ep_wMaxPacketSize; */
-	0x00        /*  u8  ep_bInterval; */
+static const USBDescStrings desc_strings = {
+    [STR_MANUFACTURER] = "QEMU " QEMU_VERSION,
+    [STR_PRODUCT]      = "QEMU USB HARDDRIVE",
+    [STR_SERIALNUMBER] = "1",
+};
+
+static const USBDescIface desc_iface0 = {
+    .bInterfaceNumber              = 0,
+    .bNumEndpoints                 = 2,
+    .bInterfaceClass               = USB_CLASS_MASS_STORAGE,
+    .bInterfaceSubClass            = 0x06, /* SCSI */
+    .bInterfaceProtocol            = 0x50, /* Bulk */
+    .eps = (USBDescEndpoint[]) {
+        {
+            .bEndpointAddress      = USB_DIR_IN | 0x01,
+            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
+            .wMaxPacketSize        = 64,
+        },{
+            .bEndpointAddress      = USB_DIR_OUT | 0x02,
+            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
+            .wMaxPacketSize        = 64,
+        },
+    }
+};
+
+static const USBDescDevice desc_device = {
+    .bcdUSB                        = 0x0100,
+    .bMaxPacketSize0               = 8,
+    .bNumConfigurations            = 1,
+    .confs = (USBDescConfig[]) {
+        {
+            .bNumInterfaces        = 1,
+            .bConfigurationValue   = 1,
+            .bmAttributes          = 0xc0,
+            .ifs = &desc_iface0,
+        },
+    },
+};
+
+static const USBDesc desc = {
+    .id = {
+        .idVendor          = 0,
+        .idProduct         = 0,
+        .bcdDevice         = 0,
+        .iManufacturer     = STR_MANUFACTURER,
+        .iProduct          = STR_PRODUCT,
+        .iSerialNumber     = STR_SERIALNUMBER,
+    },
+    .full = &desc_device,
+    .str  = desc_strings,
 };
 
 static void usb_msd_copy_data(MSDState *s)
@@ -236,8 +230,14 @@ static int usb_msd_handle_control(USBDevice *dev, int request, int value,
                                   int index, int length, uint8_t *data)
 {
     MSDState *s = (MSDState *)dev;
-    int ret = 0;
+    int ret;
 
+    ret = usb_desc_handle_control(dev, request, value, index, length, data);
+    if (ret >= 0) {
+        return ret;
+    }
+
+    ret = 0;
     switch (request) {
     case DeviceRequest | USB_REQ_GET_STATUS:
         data[0] = (1 << USB_DEVICE_SELF_POWERED) |
@@ -265,48 +265,6 @@ static int usb_msd_handle_control(USBDevice *dev, int request, int value,
         dev->addr = value;
         ret = 0;
         break;
-    case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
-        switch(value >> 8) {
-        case USB_DT_DEVICE:
-            memcpy(data, qemu_msd_dev_descriptor,
-                   sizeof(qemu_msd_dev_descriptor));
-            ret = sizeof(qemu_msd_dev_descriptor);
-            break;
-        case USB_DT_CONFIG:
-            memcpy(data, qemu_msd_config_descriptor,
-                   sizeof(qemu_msd_config_descriptor));
-            ret = sizeof(qemu_msd_config_descriptor);
-            break;
-        case USB_DT_STRING:
-            switch(value & 0xff) {
-            case 0:
-                /* language ids */
-                data[0] = 4;
-                data[1] = 3;
-                data[2] = 0x09;
-                data[3] = 0x04;
-                ret = 4;
-                break;
-            case 1:
-                /* vendor description */
-                ret = set_usb_string(data, "QEMU " QEMU_VERSION);
-                break;
-            case 2:
-                /* product description */
-                ret = set_usb_string(data, "QEMU USB HARDDRIVE");
-                break;
-            case 3:
-                /* serial number */
-                ret = set_usb_string(data, "1");
-                break;
-            default:
-                goto fail;
-            }
-            break;
-        default:
-            goto fail;
-        }
-        break;
     case DeviceRequest | USB_REQ_GET_CONFIGURATION:
         data[0] = 1;
         ret = 1;
@@ -625,6 +583,7 @@ static struct USBDeviceInfo msd_info = {
     .product_desc   = "QEMU USB MSD",
     .qdev.name      = "usb-storage",
     .qdev.size      = sizeof(MSDState),
+    .usb_desc       = &desc,
     .init           = usb_msd_initfn,
     .handle_packet  = usb_generic_handle_packet,
     .handle_reset   = usb_msd_handle_reset,
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v4 06/32] usb wacom: use new descriptor infrastructure.
  2011-01-12 11:19 [Qemu-devel] [PATCH v4 00/32] usb descriptor overhaul + more Gerd Hoffmann
                   ` (4 preceding siblings ...)
  2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 05/32] usb storage: " Gerd Hoffmann
@ 2011-01-12 11:19 ` Gerd Hoffmann
  2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 07/32] usb bluetooth: " Gerd Hoffmann
                   ` (26 subsequent siblings)
  32 siblings, 0 replies; 37+ messages in thread
From: Gerd Hoffmann @ 2011-01-12 11:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Switch the usb wavom driver over to the
new descriptor infrastructure.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb-wacom.c |  178 +++++++++++++++++++++++---------------------------------
 1 files changed, 73 insertions(+), 105 deletions(-)

diff --git a/hw/usb-wacom.c b/hw/usb-wacom.c
index 47f26cd..ffe6ac7 100644
--- a/hw/usb-wacom.c
+++ b/hw/usb-wacom.c
@@ -28,6 +28,7 @@
 #include "hw.h"
 #include "console.h"
 #include "usb.h"
+#include "usb-desc.h"
 
 /* Interface requests */
 #define WACOM_GET_REPORT	0x2101
@@ -54,68 +55,75 @@ typedef struct USBWacomState {
     int changed;
 } USBWacomState;
 
-static const uint8_t qemu_wacom_dev_descriptor[] = {
-    0x12,	/*  u8 bLength; */
-    0x01,	/*  u8 bDescriptorType; Device */
-    0x10, 0x10,	/*  u16 bcdUSB; v1.10 */
+enum {
+    STR_MANUFACTURER = 1,
+    STR_PRODUCT,
+    STR_SERIALNUMBER,
+};
 
-    0x00,	/*  u8  bDeviceClass; */
-    0x00,	/*  u8  bDeviceSubClass; */
-    0x00,	/*  u8  bDeviceProtocol; [ low/full speeds only ] */
-    0x08,	/*  u8  bMaxPacketSize0; 8 Bytes */
+static const USBDescStrings desc_strings = {
+    [STR_MANUFACTURER]     = "QEMU " QEMU_VERSION,
+    [STR_PRODUCT]          = "Wacom PenPartner",
+    [STR_SERIALNUMBER]     = "1",
+};
 
-    0x6a, 0x05,	/*  u16 idVendor; */
-    0x00, 0x00,	/*  u16 idProduct; */
-    0x10, 0x42,	/*  u16 bcdDevice */
+static const USBDescIface desc_iface_wacom = {
+    .bInterfaceNumber              = 0,
+    .bNumEndpoints                 = 1,
+    .bInterfaceClass               = USB_CLASS_HID,
+    .bInterfaceSubClass            = 0x01, /* boot */
+    .bInterfaceProtocol            = 0x02,
+    .ndesc                         = 1,
+    .descs = (USBDescOther[]) {
+        {
+            /* HID descriptor */
+            .data = (uint8_t[]) {
+                0x09,          /*  u8  bLength */
+                0x21,          /*  u8  bDescriptorType */
+                0x01, 0x10,    /*  u16 HID_class */
+                0x00,          /*  u8  country_code */
+                0x01,          /*  u8  num_descriptors */
+                0x22,          /*  u8  type: Report */
+                0x6e, 0,       /*  u16 len */
+            },
+        },
+    },
+    .eps = (USBDescEndpoint[]) {
+        {
+            .bEndpointAddress      = USB_DIR_IN | 0x01,
+            .bmAttributes          = USB_ENDPOINT_XFER_INT,
+            .wMaxPacketSize        = 8,
+            .bInterval             = 0x0a,
+        },
+    },
+};
 
-    0x01,	/*  u8  iManufacturer; */
-    0x02,	/*  u8  iProduct; */
-    0x00,	/*  u8  iSerialNumber; */
-    0x01,	/*  u8  bNumConfigurations; */
+static const USBDescDevice desc_device_wacom = {
+    .bcdUSB                        = 0x0110,
+    .bMaxPacketSize0               = 8,
+    .bNumConfigurations            = 1,
+    .confs = (USBDescConfig[]) {
+        {
+            .bNumInterfaces        = 1,
+            .bConfigurationValue   = 1,
+            .bmAttributes          = 0x80,
+            .bMaxPower             = 40,
+            .ifs = &desc_iface_wacom,
+        },
+    },
 };
 
-static const uint8_t qemu_wacom_config_descriptor[] = {
-    /* one configuration */
-    0x09,	/*  u8  bLength; */
-    0x02,	/*  u8  bDescriptorType; Configuration */
-    0x22, 0x00,	/*  u16 wTotalLength; */
-    0x01,	/*  u8  bNumInterfaces; (1) */
-    0x01,	/*  u8  bConfigurationValue; */
-    0x00,	/*  u8  iConfiguration; */
-    0x80,	/*  u8  bmAttributes;
-				 Bit 7: must be set,
-				     6: Self-powered,
-				     5: Remote wakeup,
-				     4..0: resvd */
-    40,		/*  u8  MaxPower; */
-
-    /* one interface */
-    0x09,	/*  u8  if_bLength; */
-    0x04,	/*  u8  if_bDescriptorType; Interface */
-    0x00,	/*  u8  if_bInterfaceNumber; */
-    0x00,	/*  u8  if_bAlternateSetting; */
-    0x01,	/*  u8  if_bNumEndpoints; */
-    0x03,	/*  u8  if_bInterfaceClass; HID */
-    0x01,	/*  u8  if_bInterfaceSubClass; Boot */
-    0x02,	/*  u8  if_bInterfaceProtocol; [usb1.1 or single tt] */
-    0x00,	/*  u8  if_iInterface; */
-
-    /* HID descriptor */
-    0x09,	/*  u8  bLength; */
-    0x21,	/*  u8  bDescriptorType; */
-    0x01, 0x10,	/*  u16 HID_class */
-    0x00,	/*  u8  country_code */
-    0x01,	/*  u8  num_descriptors */
-    0x22,	/*  u8  type; Report */
-    0x6e, 0x00,	/*  u16 len */
-
-    /* one endpoint (status change endpoint) */
-    0x07,	/*  u8  ep_bLength; */
-    0x05,	/*  u8  ep_bDescriptorType; Endpoint */
-    0x81,	/*  u8  ep_bEndpointAddress; IN Endpoint 1 */
-    0x03,	/*  u8  ep_bmAttributes; Interrupt */
-    0x08, 0x00,	/*  u16 ep_wMaxPacketSize; */
-    0x0a,	/*  u8  ep_bInterval; */
+static const USBDesc desc_wacom = {
+    .id = {
+        .idVendor          = 0x056a,
+        .idProduct         = 0x0000,
+        .bcdDevice         = 0x4210,
+        .iManufacturer     = STR_MANUFACTURER,
+        .iProduct          = STR_PRODUCT,
+        .iSerialNumber     = STR_SERIALNUMBER,
+    },
+    .full = &desc_device_wacom,
+    .str  = desc_strings,
 };
 
 static void usb_mouse_event(void *opaque,
@@ -245,8 +253,14 @@ static int usb_wacom_handle_control(USBDevice *dev, int request, int value,
                                     int index, int length, uint8_t *data)
 {
     USBWacomState *s = (USBWacomState *) dev;
-    int ret = 0;
+    int ret;
+
+    ret = usb_desc_handle_control(dev, request, value, index, length, data);
+    if (ret >= 0) {
+        return ret;
+    }
 
+    ret = 0;
     switch (request) {
     case DeviceRequest | USB_REQ_GET_STATUS:
         data[0] = (1 << USB_DEVICE_SELF_POWERED) |
@@ -274,53 +288,6 @@ static int usb_wacom_handle_control(USBDevice *dev, int request, int value,
         dev->addr = value;
         ret = 0;
         break;
-    case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
-        switch (value >> 8) {
-        case USB_DT_DEVICE:
-            memcpy(data, qemu_wacom_dev_descriptor,
-                   sizeof(qemu_wacom_dev_descriptor));
-            ret = sizeof(qemu_wacom_dev_descriptor);
-            break;
-        case USB_DT_CONFIG:
-       	    memcpy(data, qemu_wacom_config_descriptor,
-                   sizeof(qemu_wacom_config_descriptor));
-            ret = sizeof(qemu_wacom_config_descriptor);
-            break;
-        case USB_DT_STRING:
-            switch (value & 0xff) {
-            case 0:
-                /* language ids */
-                data[0] = 4;
-                data[1] = 3;
-                data[2] = 0x09;
-                data[3] = 0x04;
-                ret = 4;
-                break;
-            case 1:
-                /* serial number */
-                ret = set_usb_string(data, "1");
-                break;
-            case 2:
-		ret = set_usb_string(data, "Wacom PenPartner");
-                break;
-            case 3:
-                /* vendor description */
-                ret = set_usb_string(data, "QEMU " QEMU_VERSION);
-                break;
-            case 4:
-                ret = set_usb_string(data, "Wacom Tablet");
-                break;
-            case 5:
-                ret = set_usb_string(data, "Endpoint1 Interrupt Pipe");
-                break;
-            default:
-                goto fail;
-            }
-            break;
-        default:
-            goto fail;
-        }
-        break;
     case DeviceRequest | USB_REQ_GET_CONFIGURATION:
         data[0] = 1;
         ret = 1;
@@ -420,6 +387,7 @@ static struct USBDeviceInfo wacom_info = {
     .qdev.name      = "usb-wacom-tablet",
     .qdev.desc      = "QEMU PenPartner Tablet",
     .usbdevice_name = "wacom-tablet",
+    .usb_desc       = &desc_wacom,
     .qdev.size      = sizeof(USBWacomState),
     .init           = usb_wacom_initfn,
     .handle_packet  = usb_generic_handle_packet,
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v4 07/32] usb bluetooth: use new descriptor infrastructure.
  2011-01-12 11:19 [Qemu-devel] [PATCH v4 00/32] usb descriptor overhaul + more Gerd Hoffmann
                   ` (5 preceding siblings ...)
  2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 06/32] usb wacom: " Gerd Hoffmann
@ 2011-01-12 11:19 ` Gerd Hoffmann
  2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 08/32] usb hub: " Gerd Hoffmann
                   ` (25 subsequent siblings)
  32 siblings, 0 replies; 37+ messages in thread
From: Gerd Hoffmann @ 2011-01-12 11:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Switch the usb bluetooth driver over to the
new descriptor infrastructure.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb-bt.c |  473 +++++++++++++++++++++++++----------------------------------
 1 files changed, 202 insertions(+), 271 deletions(-)

diff --git a/hw/usb-bt.c b/hw/usb-bt.c
index 56d1a6c..d7959ad 100644
--- a/hw/usb-bt.c
+++ b/hw/usb-bt.c
@@ -20,6 +20,7 @@
 
 #include "qemu-common.h"
 #include "usb.h"
+#include "usb-desc.h"
 #include "net.h"
 #include "bt.h"
 
@@ -51,251 +52,202 @@ struct USBBtState {
 #define USB_ACL_EP	2
 #define USB_SCO_EP	3
 
-static const uint8_t qemu_bt_dev_descriptor[] = {
-    0x12,		/*  u8 bLength; */
-    USB_DT_DEVICE,	/*  u8 bDescriptorType; Device */
-    0x10, 0x01,		/*  u16 bcdUSB; v1.10 */
+enum {
+    STR_MANUFACTURER = 1,
+    STR_SERIALNUMBER,
+};
 
-    0xe0,	/*  u8  bDeviceClass; Wireless */
-    0x01,	/*  u8  bDeviceSubClass; Radio Frequency */
-    0x01,	/*  u8  bDeviceProtocol; Bluetooth */
-    0x40,	/*  u8  bMaxPacketSize0; 64 Bytes */
+static const USBDescStrings desc_strings = {
+    [STR_MANUFACTURER]     = "QEMU " QEMU_VERSION,
+    [STR_SERIALNUMBER]     = "1",
+};
 
-    0x12, 0x0a,	/*  u16 idVendor; */
-    0x01, 0x00,	/*  u16 idProduct; Bluetooth Dongle (HCI mode) */
-    0x58, 0x19,	/*  u16 bcdDevice; (some devices have 0x48, 0x02) */
+static const USBDescIface desc_iface_bluetooth[] = {
+    {
+        .bInterfaceNumber              = 0,
+        .bNumEndpoints                 = 3,
+        .bInterfaceClass               = 0xe0, /* Wireless */
+        .bInterfaceSubClass            = 0x01, /* Radio Frequency */
+        .bInterfaceProtocol            = 0x01, /* Bluetooth */
+        .eps = (USBDescEndpoint[]) {
+            {
+                .bEndpointAddress      = USB_DIR_IN | USB_EVT_EP,
+                .bmAttributes          = USB_ENDPOINT_XFER_INT,
+                .wMaxPacketSize        = 0x10,
+                .bInterval             = 0x02,
+            },
+            {
+                .bEndpointAddress      = USB_DIR_OUT | USB_ACL_EP,
+                .bmAttributes          = USB_ENDPOINT_XFER_BULK,
+                .wMaxPacketSize        = 0x40,
+                .bInterval             = 0x0a,
+            },
+            {
+                .bEndpointAddress      = USB_DIR_IN | USB_ACL_EP,
+                .bmAttributes          = USB_ENDPOINT_XFER_BULK,
+                .wMaxPacketSize        = 0x40,
+                .bInterval             = 0x0a,
+            },
+        },
+    },{
+        .bInterfaceNumber              = 1,
+        .bAlternateSetting             = 0,
+        .bNumEndpoints                 = 2,
+        .bInterfaceClass               = 0xe0, /* Wireless */
+        .bInterfaceSubClass            = 0x01, /* Radio Frequency */
+        .bInterfaceProtocol            = 0x01, /* Bluetooth */
+        .eps = (USBDescEndpoint[]) {
+            {
+                .bEndpointAddress      = USB_DIR_OUT | USB_SCO_EP,
+                .bmAttributes          = USB_ENDPOINT_XFER_INT,
+                .wMaxPacketSize        = 0,
+                .bInterval             = 0x01,
+            },
+            {
+                .bEndpointAddress      = USB_DIR_IN | USB_SCO_EP,
+                .bmAttributes          = USB_ENDPOINT_XFER_INT,
+                .wMaxPacketSize        = 0,
+                .bInterval             = 0x01,
+            },
+        },
+    },{
+        .bInterfaceNumber              = 1,
+        .bAlternateSetting             = 1,
+        .bNumEndpoints                 = 2,
+        .bInterfaceClass               = 0xe0, /* Wireless */
+        .bInterfaceSubClass            = 0x01, /* Radio Frequency */
+        .bInterfaceProtocol            = 0x01, /* Bluetooth */
+        .eps = (USBDescEndpoint[]) {
+            {
+                .bEndpointAddress      = USB_DIR_OUT | USB_SCO_EP,
+                .bmAttributes          = USB_ENDPOINT_XFER_INT,
+                .wMaxPacketSize        = 0x09,
+                .bInterval             = 0x01,
+            },
+            {
+                .bEndpointAddress      = USB_DIR_IN | USB_SCO_EP,
+                .bmAttributes          = USB_ENDPOINT_XFER_INT,
+                .wMaxPacketSize        = 0x09,
+                .bInterval             = 0x01,
+            },
+        },
+    },{
+        .bInterfaceNumber              = 1,
+        .bAlternateSetting             = 2,
+        .bNumEndpoints                 = 2,
+        .bInterfaceClass               = 0xe0, /* Wireless */
+        .bInterfaceSubClass            = 0x01, /* Radio Frequency */
+        .bInterfaceProtocol            = 0x01, /* Bluetooth */
+        .eps = (USBDescEndpoint[]) {
+            {
+                .bEndpointAddress      = USB_DIR_OUT | USB_SCO_EP,
+                .bmAttributes          = USB_ENDPOINT_XFER_INT,
+                .wMaxPacketSize        = 0x11,
+                .bInterval             = 0x01,
+            },
+            {
+                .bEndpointAddress      = USB_DIR_IN | USB_SCO_EP,
+                .bmAttributes          = USB_ENDPOINT_XFER_INT,
+                .wMaxPacketSize        = 0x11,
+                .bInterval             = 0x01,
+            },
+        },
+    },{
+        .bInterfaceNumber              = 1,
+        .bAlternateSetting             = 3,
+        .bNumEndpoints                 = 2,
+        .bInterfaceClass               = 0xe0, /* Wireless */
+        .bInterfaceSubClass            = 0x01, /* Radio Frequency */
+        .bInterfaceProtocol            = 0x01, /* Bluetooth */
+        .eps = (USBDescEndpoint[]) {
+            {
+                .bEndpointAddress      = USB_DIR_OUT | USB_SCO_EP,
+                .bmAttributes          = USB_ENDPOINT_XFER_INT,
+                .wMaxPacketSize        = 0x19,
+                .bInterval             = 0x01,
+            },
+            {
+                .bEndpointAddress      = USB_DIR_IN | USB_SCO_EP,
+                .bmAttributes          = USB_ENDPOINT_XFER_INT,
+                .wMaxPacketSize        = 0x19,
+                .bInterval             = 0x01,
+            },
+        },
+    },{
+        .bInterfaceNumber              = 1,
+        .bAlternateSetting             = 4,
+        .bNumEndpoints                 = 2,
+        .bInterfaceClass               = 0xe0, /* Wireless */
+        .bInterfaceSubClass            = 0x01, /* Radio Frequency */
+        .bInterfaceProtocol            = 0x01, /* Bluetooth */
+        .eps = (USBDescEndpoint[]) {
+            {
+                .bEndpointAddress      = USB_DIR_OUT | USB_SCO_EP,
+                .bmAttributes          = USB_ENDPOINT_XFER_INT,
+                .wMaxPacketSize        = 0x21,
+                .bInterval             = 0x01,
+            },
+            {
+                .bEndpointAddress      = USB_DIR_IN | USB_SCO_EP,
+                .bmAttributes          = USB_ENDPOINT_XFER_INT,
+                .wMaxPacketSize        = 0x21,
+                .bInterval             = 0x01,
+            },
+        },
+    },{
+        .bInterfaceNumber              = 1,
+        .bAlternateSetting             = 5,
+        .bNumEndpoints                 = 2,
+        .bInterfaceClass               = 0xe0, /* Wireless */
+        .bInterfaceSubClass            = 0x01, /* Radio Frequency */
+        .bInterfaceProtocol            = 0x01, /* Bluetooth */
+        .eps = (USBDescEndpoint[]) {
+            {
+                .bEndpointAddress      = USB_DIR_OUT | USB_SCO_EP,
+                .bmAttributes          = USB_ENDPOINT_XFER_INT,
+                .wMaxPacketSize        = 0x31,
+                .bInterval             = 0x01,
+            },
+            {
+                .bEndpointAddress      = USB_DIR_IN | USB_SCO_EP,
+                .bmAttributes          = USB_ENDPOINT_XFER_INT,
+                .wMaxPacketSize        = 0x31,
+                .bInterval             = 0x01,
+            },
+        },
+    }
+};
 
-    0x00,	/*  u8  iManufacturer; */
-    0x00,	/*  u8  iProduct; */
-    0x00,	/*  u8  iSerialNumber; */
-    0x01,	/*  u8  bNumConfigurations; */
+static const USBDescDevice desc_device_bluetooth = {
+    .bcdUSB                        = 0x0110,
+    .bDeviceClass                  = 0xe0, /* Wireless */
+    .bDeviceSubClass               = 0x01, /* Radio Frequency */
+    .bDeviceProtocol               = 0x01, /* Bluetooth */
+    .bMaxPacketSize0               = 64,
+    .bNumConfigurations            = 1,
+    .confs = (USBDescConfig[]) {
+        {
+            .bNumInterfaces        = 2,
+            .bConfigurationValue   = 1,
+            .bmAttributes          = 0xc0,
+            .bMaxPower             = 0,
+            .nif = ARRAY_SIZE(desc_iface_bluetooth),
+            .ifs = desc_iface_bluetooth,
+        },
+    },
 };
 
-static const uint8_t qemu_bt_config_descriptor[] = {
-    /* one configuration */
-    0x09,		/*  u8  bLength; */
-    USB_DT_CONFIG,	/*  u8  bDescriptorType; */
-    0xb1, 0x00,		/*  u16 wTotalLength; */
-    0x02,		/*  u8  bNumInterfaces; (2) */
-    0x01,		/*  u8  bConfigurationValue; */
-    0x00,		/*  u8  iConfiguration; */
-    0xc0,		/*  u8  bmAttributes;
-				     Bit 7: must be set,
-					 6: Self-powered,
-					 5: Remote wakeup,
-					 4..0: resvd */
-    0x00,		/*  u8  MaxPower; */
-
-    /* USB 1.1:
-     * USB 2.0, single TT organization (mandatory):
-     *	one interface, protocol 0
-     *
-     * USB 2.0, multiple TT organization (optional):
-     *	two interfaces, protocols 1 (like single TT)
-     *	and 2 (multiple TT mode) ... config is
-     *	sometimes settable
-     *	NOT IMPLEMENTED
-     */
-
-    /* interface one */
-    0x09,		/*  u8  if_bLength; */
-    USB_DT_INTERFACE,	/*  u8  if_bDescriptorType; */
-    0x00,		/*  u8  if_bInterfaceNumber; */
-    0x00,		/*  u8  if_bAlternateSetting; */
-    0x03,		/*  u8  if_bNumEndpoints; */
-    0xe0,		/*  u8  if_bInterfaceClass; Wireless */
-    0x01,		/*  u8  if_bInterfaceSubClass; Radio Frequency */
-    0x01,		/*  u8  if_bInterfaceProtocol; Bluetooth */
-    0x00,		/*  u8  if_iInterface; */
-
-    /* endpoint one */
-    0x07,		/*  u8  ep_bLength; */
-    USB_DT_ENDPOINT,	/*  u8  ep_bDescriptorType; */
-    USB_DIR_IN | USB_EVT_EP,	/*  u8  ep_bEndpointAddress; */
-    0x03,		/*  u8  ep_bmAttributes; Interrupt */
-    0x10, 0x00,		/*  u16 ep_wMaxPacketSize; */
-    0x02,		/*  u8  ep_bInterval; */
-
-    /* endpoint two */
-    0x07,		/*  u8  ep_bLength; */
-    USB_DT_ENDPOINT,	/*  u8  ep_bDescriptorType; */
-    USB_DIR_OUT | USB_ACL_EP,	/*  u8  ep_bEndpointAddress; */
-    0x02,		/*  u8  ep_bmAttributes; Bulk */
-    0x40, 0x00,		/*  u16 ep_wMaxPacketSize; */
-    0x0a,		/*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
-
-    /* endpoint three */
-    0x07,		/*  u8  ep_bLength; */
-    USB_DT_ENDPOINT,	/*  u8  ep_bDescriptorType; */
-    USB_DIR_IN | USB_ACL_EP,	/*  u8  ep_bEndpointAddress; */
-    0x02,		/*  u8  ep_bmAttributes; Bulk */
-    0x40, 0x00,		/*  u16 ep_wMaxPacketSize; */
-    0x0a,		/*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
-
-    /* interface two setting one */
-    0x09,		/*  u8  if_bLength; */
-    USB_DT_INTERFACE,	/*  u8  if_bDescriptorType; */
-    0x01,		/*  u8  if_bInterfaceNumber; */
-    0x00,		/*  u8  if_bAlternateSetting; */
-    0x02,		/*  u8  if_bNumEndpoints; */
-    0xe0,		/*  u8  if_bInterfaceClass; Wireless */
-    0x01,		/*  u8  if_bInterfaceSubClass; Radio Frequency */
-    0x01,		/*  u8  if_bInterfaceProtocol; Bluetooth */
-    0x00,		/*  u8  if_iInterface; */
-
-    /* endpoint one */
-    0x07,		/*  u8  ep_bLength; */
-    USB_DT_ENDPOINT,	/*  u8  ep_bDescriptorType; */
-    USB_DIR_OUT | USB_SCO_EP,	/*  u8  ep_bEndpointAddress; */
-    0x01,		/*  u8  ep_bmAttributes; Isochronous */
-    0x00, 0x00,		/*  u16 ep_wMaxPacketSize; */
-    0x01,		/*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
-
-    /* endpoint two */
-    0x07,		/*  u8  ep_bLength; */
-    USB_DT_ENDPOINT,	/*  u8  ep_bDescriptorType; */
-    USB_DIR_IN | USB_SCO_EP,	/*  u8  ep_bEndpointAddress; */
-    0x01,		/*  u8  ep_bmAttributes; Isochronous */
-    0x00, 0x00,		/*  u16 ep_wMaxPacketSize; */
-    0x01,		/*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
-
-    /* interface two setting two */
-    0x09,		/*  u8  if_bLength; */
-    USB_DT_INTERFACE,	/*  u8  if_bDescriptorType; */
-    0x01,		/*  u8  if_bInterfaceNumber; */
-    0x01,		/*  u8  if_bAlternateSetting; */
-    0x02,		/*  u8  if_bNumEndpoints; */
-    0xe0,		/*  u8  if_bInterfaceClass; Wireless */
-    0x01,		/*  u8  if_bInterfaceSubClass; Radio Frequency */
-    0x01,		/*  u8  if_bInterfaceProtocol; Bluetooth */
-    0x00,		/*  u8  if_iInterface; */
-
-    /* endpoint one */
-    0x07,		/*  u8  ep_bLength; */
-    USB_DT_ENDPOINT,	/*  u8  ep_bDescriptorType; */
-    USB_DIR_OUT | USB_SCO_EP,	/*  u8  ep_bEndpointAddress; */
-    0x01,		/*  u8  ep_bmAttributes; Isochronous */
-    0x09, 0x00,		/*  u16 ep_wMaxPacketSize; */
-    0x01,		/*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
-
-    /* endpoint two */
-    0x07,		/*  u8  ep_bLength; */
-    USB_DT_ENDPOINT,	/*  u8  ep_bDescriptorType; */
-    USB_DIR_IN | USB_SCO_EP,	/*  u8  ep_bEndpointAddress; */
-    0x01,		/*  u8  ep_bmAttributes; Isochronous */
-    0x09, 0x00,		/*  u16 ep_wMaxPacketSize; */
-    0x01,		/*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
-
-    /* interface two setting three */
-    0x09,		/*  u8  if_bLength; */
-    USB_DT_INTERFACE,	/*  u8  if_bDescriptorType; */
-    0x01,		/*  u8  if_bInterfaceNumber; */
-    0x02,		/*  u8  if_bAlternateSetting; */
-    0x02,		/*  u8  if_bNumEndpoints; */
-    0xe0,		/*  u8  if_bInterfaceClass; Wireless */
-    0x01,		/*  u8  if_bInterfaceSubClass; Radio Frequency */
-    0x01,		/*  u8  if_bInterfaceProtocol; Bluetooth */
-    0x00,		/*  u8  if_iInterface; */
-
-    /* endpoint one */
-    0x07,		/*  u8  ep_bLength; */
-    USB_DT_ENDPOINT,	/*  u8  ep_bDescriptorType; */
-    USB_DIR_OUT | USB_SCO_EP,	/*  u8  ep_bEndpointAddress; */
-    0x01,		/*  u8  ep_bmAttributes; Isochronous */
-    0x11, 0x00,		/*  u16 ep_wMaxPacketSize; */
-    0x01,		/*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
-
-    /* endpoint two */
-    0x07,		/*  u8  ep_bLength; */
-    USB_DT_ENDPOINT,	/*  u8  ep_bDescriptorType; */
-    USB_DIR_IN | USB_SCO_EP,	/*  u8  ep_bEndpointAddress; */
-    0x01,		/*  u8  ep_bmAttributes; Isochronous */
-    0x11, 0x00,		/*  u16 ep_wMaxPacketSize; */
-    0x01,		/*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
-
-    /* interface two setting four */
-    0x09,		/*  u8  if_bLength; */
-    USB_DT_INTERFACE,	/*  u8  if_bDescriptorType; */
-    0x01,		/*  u8  if_bInterfaceNumber; */
-    0x03,		/*  u8  if_bAlternateSetting; */
-    0x02,		/*  u8  if_bNumEndpoints; */
-    0xe0,		/*  u8  if_bInterfaceClass; Wireless */
-    0x01,		/*  u8  if_bInterfaceSubClass; Radio Frequency */
-    0x01,		/*  u8  if_bInterfaceProtocol; Bluetooth */
-    0x00,		/*  u8  if_iInterface; */
-
-    /* endpoint one */
-    0x07,		/*  u8  ep_bLength; */
-    USB_DT_ENDPOINT,	/*  u8  ep_bDescriptorType; */
-    USB_DIR_OUT | USB_SCO_EP,	/*  u8  ep_bEndpointAddress; */
-    0x01,		/*  u8  ep_bmAttributes; Isochronous */
-    0x19, 0x00,		/*  u16 ep_wMaxPacketSize; */
-    0x01,		/*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
-
-    /* endpoint two */
-    0x07,		/*  u8  ep_bLength; */
-    USB_DT_ENDPOINT,	/*  u8  ep_bDescriptorType; */
-    USB_DIR_IN | USB_SCO_EP,	/*  u8  ep_bEndpointAddress; */
-    0x01,		/*  u8  ep_bmAttributes; Isochronous */
-    0x19, 0x00,		/*  u16 ep_wMaxPacketSize; */
-    0x01,		/*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
-
-    /* interface two setting five */
-    0x09,		/*  u8  if_bLength; */
-    USB_DT_INTERFACE,	/*  u8  if_bDescriptorType; */
-    0x01,		/*  u8  if_bInterfaceNumber; */
-    0x04,		/*  u8  if_bAlternateSetting; */
-    0x02,		/*  u8  if_bNumEndpoints; */
-    0xe0,		/*  u8  if_bInterfaceClass; Wireless */
-    0x01,		/*  u8  if_bInterfaceSubClass; Radio Frequency */
-    0x01,		/*  u8  if_bInterfaceProtocol; Bluetooth */
-    0x00,		/*  u8  if_iInterface; */
-
-    /* endpoint one */
-    0x07,		/*  u8  ep_bLength; */
-    USB_DT_ENDPOINT,	/*  u8  ep_bDescriptorType; */
-    USB_DIR_OUT | USB_SCO_EP,	/*  u8  ep_bEndpointAddress; */
-    0x01,		/*  u8  ep_bmAttributes; Isochronous */
-    0x21, 0x00,		/*  u16 ep_wMaxPacketSize; */
-    0x01,		/*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
-
-    /* endpoint two */
-    0x07,		/*  u8  ep_bLength; */
-    USB_DT_ENDPOINT,	/*  u8  ep_bDescriptorType; */
-    USB_DIR_IN | USB_SCO_EP,	/*  u8  ep_bEndpointAddress; */
-    0x01,		/*  u8  ep_bmAttributes; Isochronous */
-    0x21, 0x00,		/*  u16 ep_wMaxPacketSize; */
-    0x01,		/*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
-
-    /* interface two setting six */
-    0x09,		/*  u8  if_bLength; */
-    USB_DT_INTERFACE,	/*  u8  if_bDescriptorType; */
-    0x01,		/*  u8  if_bInterfaceNumber; */
-    0x05,		/*  u8  if_bAlternateSetting; */
-    0x02,		/*  u8  if_bNumEndpoints; */
-    0xe0,		/*  u8  if_bInterfaceClass; Wireless */
-    0x01,		/*  u8  if_bInterfaceSubClass; Radio Frequency */
-    0x01,		/*  u8  if_bInterfaceProtocol; Bluetooth */
-    0x00,		/*  u8  if_iInterface; */
-
-    /* endpoint one */
-    0x07,		/*  u8  ep_bLength; */
-    USB_DT_ENDPOINT,	/*  u8  ep_bDescriptorType; */
-    USB_DIR_OUT | USB_SCO_EP,	/*  u8  ep_bEndpointAddress; */
-    0x01,		/*  u8  ep_bmAttributes; Isochronous */
-    0x31, 0x00,		/*  u16 ep_wMaxPacketSize; */
-    0x01,		/*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
-
-    /* endpoint two */
-    0x07,		/*  u8  ep_bLength; */
-    USB_DT_ENDPOINT,	/*  u8  ep_bDescriptorType; */
-    USB_DIR_IN | USB_SCO_EP,	/*  u8  ep_bEndpointAddress; */
-    0x01,		/*  u8  ep_bmAttributes; Isochronous */
-    0x31, 0x00,		/*  u16 ep_wMaxPacketSize; */
-    0x01,		/*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
-
-    /* If implemented, the DFU interface descriptor goes here with no
-     * endpoints or alternative settings.  */
+static const USBDesc desc_bluetooth = {
+    .id = {
+        .idVendor          = 0x0a12,
+        .idProduct         = 0x0001,
+        .bcdDevice         = 0x1958,
+        .iManufacturer     = STR_MANUFACTURER,
+        .iProduct          = 0,
+        .iSerialNumber     = STR_SERIALNUMBER,
+    },
+    .full = &desc_device_bluetooth,
+    .str  = desc_strings,
 };
 
 static void usb_bt_fifo_reset(struct usb_hci_in_fifo_s *fifo)
@@ -424,8 +376,14 @@ static int usb_bt_handle_control(USBDevice *dev, int request, int value,
                 int index, int length, uint8_t *data)
 {
     struct USBBtState *s = (struct USBBtState *) dev->opaque;
-    int ret = 0;
+    int ret;
+
+    ret = usb_desc_handle_control(dev, request, value, index, length, data);
+    if (ret >= 0) {
+        return ret;
+    }
 
+    ret = 0;
     switch (request) {
     case DeviceRequest | USB_REQ_GET_STATUS:
     case InterfaceRequest | USB_REQ_GET_STATUS:
@@ -459,42 +417,14 @@ static int usb_bt_handle_control(USBDevice *dev, int request, int value,
         dev->addr = value;
         ret = 0;
         break;
-    case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
-        switch (value >> 8) {
-        case USB_DT_DEVICE:
-            ret = sizeof(qemu_bt_dev_descriptor);
-            memcpy(data, qemu_bt_dev_descriptor, ret);
-            break;
-        case USB_DT_CONFIG:
-            ret = sizeof(qemu_bt_config_descriptor);
-            memcpy(data, qemu_bt_config_descriptor, ret);
-            break;
-        case USB_DT_STRING:
-            switch(value & 0xff) {
-            case 0:
-                /* language ids */
-                data[0] = 4;
-                data[1] = 3;
-                data[2] = 0x09;
-                data[3] = 0x04;
-                ret = 4;
-                break;
-            default:
-                goto fail;
-            }
-            break;
-        default:
-            goto fail;
-        }
-        break;
     case DeviceRequest | USB_REQ_GET_CONFIGURATION:
-        data[0] = qemu_bt_config_descriptor[0x5];
+        data[0] = 1;
         ret = 1;
         s->config = 0;
         break;
     case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
         ret = 0;
-        if (value != qemu_bt_config_descriptor[0x5] && value != 0) {
+        if (value != 1 && value != 0) {
             printf("%s: Wrong SET_CONFIGURATION request (%i)\n",
                             __FUNCTION__, value);
             goto fail;
@@ -648,6 +578,7 @@ static struct USBDeviceInfo bt_info = {
     .product_desc   = "QEMU BT dongle",
     .qdev.name      = "usb-bt-dongle",
     .qdev.size      = sizeof(struct USBBtState),
+    .usb_desc       = &desc_bluetooth,
     .init           = usb_bt_initfn,
     .handle_packet  = usb_generic_handle_packet,
     .handle_reset   = usb_bt_handle_reset,
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v4 08/32] usb hub: use new descriptor infrastructure.
  2011-01-12 11:19 [Qemu-devel] [PATCH v4 00/32] usb descriptor overhaul + more Gerd Hoffmann
                   ` (6 preceding siblings ...)
  2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 07/32] usb bluetooth: " Gerd Hoffmann
@ 2011-01-12 11:19 ` Gerd Hoffmann
  2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 09/32] usb descriptors: add settable strings Gerd Hoffmann
                   ` (24 subsequent siblings)
  32 siblings, 0 replies; 37+ messages in thread
From: Gerd Hoffmann @ 2011-01-12 11:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Switch the usb hub driver over to the
new descriptor infrastructure.

It also removes the nr_ports variable and MAX_PORTS define and
introduces a NUM_PORTS define instead.  The numver of ports was
(and still is) fixed at 8 anyway.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb-hub.c |  141 ++++++++++++++++++++++++++++++++--------------------------
 1 files changed, 78 insertions(+), 63 deletions(-)

diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index 8a3f829..421d43d 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -23,10 +23,11 @@
  */
 #include "qemu-common.h"
 #include "usb.h"
+#include "usb-desc.h"
 
 //#define DEBUG
 
-#define MAX_PORTS 8
+#define NUM_PORTS 8
 
 typedef struct USBHubPort {
     USBPort port;
@@ -36,8 +37,7 @@ typedef struct USBHubPort {
 
 typedef struct USBHubState {
     USBDevice dev;
-    int nb_ports;
-    USBHubPort ports[MAX_PORTS];
+    USBHubPort ports[NUM_PORTS];
 } USBHubState;
 
 #define ClearHubFeature		(0x2000 | USB_REQ_CLEAR_FEATURE)
@@ -83,6 +83,60 @@ typedef struct USBHubState {
 
 /* same as Linux kernel root hubs */
 
+enum {
+    STR_MANUFACTURER = 1,
+    STR_PRODUCT,
+    STR_SERIALNUMBER,
+};
+
+static const USBDescStrings desc_strings = {
+    [STR_MANUFACTURER] = "QEMU " QEMU_VERSION,
+    [STR_PRODUCT]      = "QEMU USB Hub",
+    [STR_SERIALNUMBER] = "314159",
+};
+
+static const USBDescIface desc_iface_hub = {
+    .bInterfaceNumber              = 0,
+    .bNumEndpoints                 = 1,
+    .bInterfaceClass               = USB_CLASS_HUB,
+    .eps = (USBDescEndpoint[]) {
+        {
+            .bEndpointAddress      = USB_DIR_IN | 0x01,
+            .bmAttributes          = USB_ENDPOINT_XFER_INT,
+            .wMaxPacketSize        = 1 + (NUM_PORTS + 7) / 8,
+            .bInterval             = 0xff,
+        },
+    }
+};
+
+static const USBDescDevice desc_device_hub = {
+    .bcdUSB                        = 0x0110,
+    .bDeviceClass                  = USB_CLASS_HUB,
+    .bMaxPacketSize0               = 8,
+    .bNumConfigurations            = 1,
+    .confs = (USBDescConfig[]) {
+        {
+            .bNumInterfaces        = 1,
+            .bConfigurationValue   = 1,
+            .bmAttributes          = 0xe0,
+            .ifs = &desc_iface_hub,
+        },
+    },
+};
+
+static const USBDesc desc_hub = {
+    .id = {
+        .idVendor          = 0,
+        .idProduct         = 0,
+        .bcdDevice         = 0x0101,
+        .iManufacturer     = STR_MANUFACTURER,
+        .iProduct          = STR_PRODUCT,
+        .iSerialNumber     = STR_SERIALNUMBER,
+    },
+    .full = &desc_device_hub,
+    .str  = desc_strings,
+};
+
 static const uint8_t qemu_hub_dev_descriptor[] = {
 	0x12,       /*  u8 bLength; */
 	0x01,       /*  u8 bDescriptorType; Device */
@@ -209,6 +263,11 @@ static int usb_hub_handle_control(USBDevice *dev, int request, int value,
     USBHubState *s = (USBHubState *)dev;
     int ret;
 
+    ret = usb_desc_handle_control(dev, request, value, index, length, data);
+    if (ret >= 0) {
+        return ret;
+    }
+
     switch(request) {
     case DeviceRequest | USB_REQ_GET_STATUS:
         data[0] = (1 << USB_DEVICE_SELF_POWERED) |
@@ -242,53 +301,6 @@ static int usb_hub_handle_control(USBDevice *dev, int request, int value,
         dev->addr = value;
         ret = 0;
         break;
-    case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
-        switch(value >> 8) {
-        case USB_DT_DEVICE:
-            memcpy(data, qemu_hub_dev_descriptor,
-                   sizeof(qemu_hub_dev_descriptor));
-            ret = sizeof(qemu_hub_dev_descriptor);
-            break;
-        case USB_DT_CONFIG:
-            memcpy(data, qemu_hub_config_descriptor,
-                   sizeof(qemu_hub_config_descriptor));
-
-            /* status change endpoint size based on number
-             * of ports */
-            data[22] = (s->nb_ports + 1 + 7) / 8;
-
-            ret = sizeof(qemu_hub_config_descriptor);
-            break;
-        case USB_DT_STRING:
-            switch(value & 0xff) {
-            case 0:
-                /* language ids */
-                data[0] = 4;
-                data[1] = 3;
-                data[2] = 0x09;
-                data[3] = 0x04;
-                ret = 4;
-                break;
-            case 1:
-                /* serial number */
-                ret = set_usb_string(data, "314159");
-                break;
-            case 2:
-                /* product description */
-                ret = set_usb_string(data, "QEMU USB Hub");
-                break;
-            case 3:
-                /* vendor description */
-                ret = set_usb_string(data, "QEMU " QEMU_VERSION);
-                break;
-            default:
-                goto fail;
-            }
-            break;
-        default:
-            goto fail;
-        }
-        break;
     case DeviceRequest | USB_REQ_GET_CONFIGURATION:
         data[0] = 1;
         ret = 1;
@@ -315,8 +327,9 @@ static int usb_hub_handle_control(USBDevice *dev, int request, int value,
         {
             unsigned int n = index - 1;
             USBHubPort *port;
-            if (n >= s->nb_ports)
+            if (n >= NUM_PORTS) {
                 goto fail;
+            }
             port = &s->ports[n];
             data[0] = port->wPortStatus;
             data[1] = port->wPortStatus >> 8;
@@ -338,8 +351,9 @@ static int usb_hub_handle_control(USBDevice *dev, int request, int value,
             unsigned int n = index - 1;
             USBHubPort *port;
             USBDevice *dev;
-            if (n >= s->nb_ports)
+            if (n >= NUM_PORTS) {
                 goto fail;
+            }
             port = &s->ports[n];
             dev = port->port.dev;
             switch(value) {
@@ -367,8 +381,9 @@ static int usb_hub_handle_control(USBDevice *dev, int request, int value,
             unsigned int n = index - 1;
             USBHubPort *port;
 
-            if (n >= s->nb_ports)
+            if (n >= NUM_PORTS) {
                 goto fail;
+            }
             port = &s->ports[n];
             switch(value) {
             case PORT_ENABLE:
@@ -403,17 +418,17 @@ static int usb_hub_handle_control(USBDevice *dev, int request, int value,
             unsigned int n, limit, var_hub_size = 0;
             memcpy(data, qemu_hub_hub_descriptor,
                    sizeof(qemu_hub_hub_descriptor));
-            data[2] = s->nb_ports;
+            data[2] = NUM_PORTS;
 
             /* fill DeviceRemovable bits */
-            limit = ((s->nb_ports + 1 + 7) / 8) + 7;
+            limit = ((NUM_PORTS + 1 + 7) / 8) + 7;
             for (n = 7; n < limit; n++) {
                 data[n] = 0x00;
                 var_hub_size++;
             }
 
             /* fill PortPwrCtrlMask bits */
-            limit = limit + ((s->nb_ports + 7) / 8);
+            limit = limit + ((NUM_PORTS + 7) / 8);
             for (;n < limit; n++) {
                 data[n] = 0xff;
                 var_hub_size++;
@@ -442,14 +457,14 @@ static int usb_hub_handle_data(USBDevice *dev, USBPacket *p)
             USBHubPort *port;
             unsigned int status;
             int i, n;
-            n = (s->nb_ports + 1 + 7) / 8;
+            n = (NUM_PORTS + 1 + 7) / 8;
             if (p->len == 1) { /* FreeBSD workaround */
                 n = 1;
             } else if (n > p->len) {
                 return USB_RET_BABBLE;
             }
             status = 0;
-            for(i = 0; i < s->nb_ports; i++) {
+            for(i = 0; i < NUM_PORTS; i++) {
                 port = &s->ports[i];
                 if (port->wPortChange)
                     status |= (1 << (i + 1));
@@ -481,7 +496,7 @@ static int usb_hub_broadcast_packet(USBHubState *s, USBPacket *p)
     USBDevice *dev;
     int i, ret;
 
-    for(i = 0; i < s->nb_ports; i++) {
+    for(i = 0; i < NUM_PORTS; i++) {
         port = &s->ports[i];
         dev = port->port.dev;
         if (dev && (port->wPortStatus & PORT_STAT_ENABLE)) {
@@ -518,7 +533,7 @@ static void usb_hub_handle_destroy(USBDevice *dev)
     USBHubState *s = (USBHubState *)dev;
     int i;
 
-    for (i = 0; i < s->nb_ports; i++) {
+    for (i = 0; i < NUM_PORTS; i++) {
         usb_unregister_port(usb_bus_from_device(dev),
                             &s->ports[i].port);
     }
@@ -530,9 +545,8 @@ static int usb_hub_initfn(USBDevice *dev)
     USBHubPort *port;
     int i;
 
-    s->dev.speed  = USB_SPEED_FULL,
-    s->nb_ports = MAX_PORTS; /* FIXME: make configurable */
-    for (i = 0; i < s->nb_ports; i++) {
+    s->dev.speed = USB_SPEED_FULL;
+    for (i = 0; i < NUM_PORTS; i++) {
         port = &s->ports[i];
         usb_register_port(usb_bus_from_device(dev),
                           &port->port, s, i, &s->dev, usb_hub_attach);
@@ -547,6 +561,7 @@ static struct USBDeviceInfo hub_info = {
     .qdev.name      = "usb-hub",
     .qdev.fw_name    = "hub",
     .qdev.size      = sizeof(USBHubState),
+    .usb_desc       = &desc_hub,
     .init           = usb_hub_initfn,
     .handle_packet  = usb_hub_handle_packet,
     .handle_reset   = usb_hub_handle_reset,
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v4 09/32] usb descriptors: add settable strings.
  2011-01-12 11:19 [Qemu-devel] [PATCH v4 00/32] usb descriptor overhaul + more Gerd Hoffmann
                   ` (7 preceding siblings ...)
  2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 08/32] usb hub: " Gerd Hoffmann
@ 2011-01-12 11:19 ` Gerd Hoffmann
  2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 10/32] usb storage: serial number support Gerd Hoffmann
                   ` (23 subsequent siblings)
  32 siblings, 0 replies; 37+ messages in thread
From: Gerd Hoffmann @ 2011-01-12 11:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

This patch allows to set usb descriptor strings per device instance.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb-bus.c  |    1 +
 hw/usb-desc.c |   52 ++++++++++++++++++++++++++++++++++++++++++++--------
 hw/usb-desc.h |    4 +++-
 hw/usb.h      |    9 +++++++++
 4 files changed, 57 insertions(+), 9 deletions(-)

diff --git a/hw/usb-bus.c b/hw/usb-bus.c
index 8b4583c..af537c2 100644
--- a/hw/usb-bus.c
+++ b/hw/usb-bus.c
@@ -48,6 +48,7 @@ static int usb_qdev_init(DeviceState *qdev, DeviceInfo *base)
     pstrcpy(dev->product_desc, sizeof(dev->product_desc), info->product_desc);
     dev->info = info;
     dev->auto_attach = 1;
+    QLIST_INIT(&dev->strings);
     rc = dev->info->init(dev);
     if (rc == 0 && dev->auto_attach)
         usb_device_attach(dev);
diff --git a/hw/usb-desc.c b/hw/usb-desc.c
index 559ced7..69ab207 100644
--- a/hw/usb-desc.c
+++ b/hw/usb-desc.c
@@ -151,9 +151,42 @@ int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len)
     return bLength;
 }
 
-int usb_desc_string(const char* const *str, int index, uint8_t *dest, size_t len)
+/* ------------------------------------------------------------------ */
+
+void usb_desc_set_string(USBDevice *dev, uint8_t index, const char *str)
+{
+    USBDescString *s;
+
+    QLIST_FOREACH(s, &dev->strings, next) {
+        if (s->index == index) {
+            break;
+        }
+    }
+    if (s == NULL) {
+        s = qemu_mallocz(sizeof(*s));
+        s->index = index;
+        QLIST_INSERT_HEAD(&dev->strings, s, next);
+    }
+    qemu_free(s->str);
+    s->str = qemu_strdup(str);
+}
+
+const char *usb_desc_get_string(USBDevice *dev, uint8_t index)
+{
+    USBDescString *s;
+
+    QLIST_FOREACH(s, &dev->strings, next) {
+        if (s->index == index) {
+            return s->str;
+        }
+    }
+    return NULL;
+}
+
+int usb_desc_string(USBDevice *dev, int index, uint8_t *dest, size_t len)
 {
     uint8_t bLength, pos, i;
+    const char *str;
 
     if (len < 4) {
         return -1;
@@ -168,22 +201,25 @@ int usb_desc_string(const char* const *str, int index, uint8_t *dest, size_t len
         return 4;
     }
 
-    if (str[index] == NULL) {
-        return 0;
+    str = usb_desc_get_string(dev, index);
+    if (str == NULL) {
+        str = dev->info->usb_desc->str[index];
+        if (str == NULL) {
+            return 0;
+        }
     }
-    bLength = strlen(str[index]) * 2 + 2;
+
+    bLength = strlen(str) * 2 + 2;
     dest[0] = bLength;
     dest[1] = USB_DT_STRING;
     i = 0; pos = 2;
     while (pos+1 < bLength && pos+1 < len) {
-        dest[pos++] = str[index][i++];
+        dest[pos++] = str[i++];
         dest[pos++] = 0;
     }
     return pos;
 }
 
-/* ------------------------------------------------------------------ */
-
 int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len)
 {
     const USBDesc *desc = dev->info->usb_desc;
@@ -204,7 +240,7 @@ int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len
         trace_usb_desc_config(dev->addr, index, len, ret);
         break;
     case USB_DT_STRING:
-        ret = usb_desc_string(desc->str, index, buf, sizeof(buf));
+        ret = usb_desc_string(dev, index, buf, sizeof(buf));
         trace_usb_desc_string(dev->addr, index, len, ret);
         break;
     default:
diff --git a/hw/usb-desc.h b/hw/usb-desc.h
index d80efdb..20fc400 100644
--- a/hw/usb-desc.h
+++ b/hw/usb-desc.h
@@ -76,9 +76,11 @@ int usb_desc_config(const USBDescConfig *conf, uint8_t *dest, size_t len);
 int usb_desc_iface(const USBDescIface *iface, uint8_t *dest, size_t len);
 int usb_desc_endpoint(const USBDescEndpoint *ep, uint8_t *dest, size_t len);
 int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len);
-int usb_desc_string(const char* const *str, int index, uint8_t *dest, size_t len);
 
 /* control message emulation helpers */
+void usb_desc_set_string(USBDevice *dev, uint8_t index, const char *str);
+const char *usb_desc_get_string(USBDevice *dev, uint8_t index);
+int usb_desc_string(USBDevice *dev, int index, uint8_t *dest, size_t len);
 int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len);
 int usb_desc_handle_control(USBDevice *dev, int request, int value,
                             int index, int length, uint8_t *data);
diff --git a/hw/usb.h b/hw/usb.h
index a29b6d6..7b5c8df 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -135,6 +135,13 @@ typedef struct USBDescConfig USBDescConfig;
 typedef struct USBDescIface USBDescIface;
 typedef struct USBDescEndpoint USBDescEndpoint;
 typedef struct USBDescOther USBDescOther;
+typedef struct USBDescString USBDescString;
+
+struct USBDescString {
+    uint8_t index;
+    char *str;
+    QLIST_ENTRY(USBDescString) next;
+};
 
 /* definition of a USB device */
 struct USBDevice {
@@ -155,6 +162,8 @@ struct USBDevice {
     int setup_state;
     int setup_len;
     int setup_index;
+
+    QLIST_HEAD(, USBDescString) strings;
 };
 
 struct USBDeviceInfo {
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v4 10/32] usb storage: serial number support
  2011-01-12 11:19 [Qemu-devel] [PATCH v4 00/32] usb descriptor overhaul + more Gerd Hoffmann
                   ` (8 preceding siblings ...)
  2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 09/32] usb descriptors: add settable strings Gerd Hoffmann
@ 2011-01-12 11:19 ` Gerd Hoffmann
  2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 11/32] usb network: use new descriptor infrastructure Gerd Hoffmann
                   ` (22 subsequent siblings)
  32 siblings, 0 replies; 37+ messages in thread
From: Gerd Hoffmann @ 2011-01-12 11:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

If a serial number is present for the drive fill it into the usb
serialnumber string descriptor.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb-msd.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 20ab886..9aa8888 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -482,6 +482,7 @@ static int usb_msd_initfn(USBDevice *dev)
 {
     MSDState *s = DO_UPCAST(MSDState, dev, dev);
     BlockDriverState *bs = s->conf.bs;
+    DriveInfo *dinfo;
 
     if (!bs) {
         error_report("usb-msd: drive property not set");
@@ -500,6 +501,11 @@ static int usb_msd_initfn(USBDevice *dev)
     bdrv_detach(bs, &s->dev.qdev);
     s->conf.bs = NULL;
 
+    dinfo = drive_get_by_blockdev(bs);
+    if (dinfo && dinfo->serial) {
+        usb_desc_set_string(dev, STR_SERIALNUMBER, dinfo->serial);
+    }
+
     s->dev.speed = USB_SPEED_FULL;
     scsi_bus_new(&s->bus, &s->dev.qdev, 0, 1, usb_msd_command_complete);
     s->scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0);
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v4 11/32] usb network: use new descriptor infrastructure.
  2011-01-12 11:19 [Qemu-devel] [PATCH v4 00/32] usb descriptor overhaul + more Gerd Hoffmann
                   ` (9 preceding siblings ...)
  2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 10/32] usb storage: serial number support Gerd Hoffmann
@ 2011-01-12 11:19 ` Gerd Hoffmann
  2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 12/32] usb: move USB_REQ_SET_ADDRESS handling to common code Gerd Hoffmann
                   ` (21 subsequent siblings)
  32 siblings, 0 replies; 37+ messages in thread
From: Gerd Hoffmann @ 2011-01-12 11:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Switch the usb network driver over to the
new descriptor infrastructure.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb-net.c |  453 +++++++++++++++++++++++++++-------------------------------
 1 files changed, 209 insertions(+), 244 deletions(-)

diff --git a/hw/usb-net.c b/hw/usb-net.c
index 8492455..b2fe42e 100644
--- a/hw/usb-net.c
+++ b/hw/usb-net.c
@@ -25,6 +25,7 @@
 
 #include "qemu-common.h"
 #include "usb.h"
+#include "usb-desc.h"
 #include "net.h"
 #include "qemu-queue.h"
 #include "sysemu.h"
@@ -89,182 +90,209 @@ enum usbstring_idx {
 
 #define ETH_FRAME_LEN			1514 /* Max. octets in frame sans FCS */
 
-/*
- * mostly the same descriptor as the linux gadget rndis driver
- */
-static const uint8_t qemu_net_dev_descriptor[] = {
-    0x12,			/*  u8 bLength; */
-    USB_DT_DEVICE,		/*  u8 bDescriptorType; Device */
-    0x00, 0x02,			/*  u16 bcdUSB; v2.0 */
-    USB_CLASS_COMM,		/*  u8  bDeviceClass; */
-    0x00,			/*  u8  bDeviceSubClass; */
-    0x00,			/*  u8  bDeviceProtocol; [ low/full only ] */
-    0x40,			/*  u8  bMaxPacketSize0 */
-    RNDIS_VENDOR_NUM & 0xff, RNDIS_VENDOR_NUM >> 8,	/*  u16 idVendor; */
-    RNDIS_PRODUCT_NUM & 0xff, RNDIS_PRODUCT_NUM >> 8,	/*  u16 idProduct; */
-    0x00, 0x00,			/*  u16 bcdDevice */
-    STRING_MANUFACTURER,	/*  u8  iManufacturer; */
-    STRING_PRODUCT,		/*  u8  iProduct; */
-    STRING_SERIALNUMBER,	/*  u8  iSerialNumber; */
-    0x02,			/*  u8  bNumConfigurations; */
+static const USBDescStrings usb_net_stringtable = {
+    [STRING_MANUFACTURER]       = "QEMU",
+    [STRING_PRODUCT]            = "RNDIS/QEMU USB Network Device",
+    [STRING_ETHADDR]            = "400102030405",
+    [STRING_DATA]               = "QEMU USB Net Data Interface",
+    [STRING_CONTROL]            = "QEMU USB Net Control Interface",
+    [STRING_RNDIS_CONTROL]      = "QEMU USB Net RNDIS Control Interface",
+    [STRING_CDC]                = "QEMU USB Net CDC",
+    [STRING_SUBSET]             = "QEMU USB Net Subset",
+    [STRING_RNDIS]              = "QEMU USB Net RNDIS",
+    [STRING_SERIALNUMBER]       = "1",
 };
 
-static const uint8_t qemu_net_rndis_config_descriptor[] = {
-    /* Configuration Descriptor */
-    0x09,			/*  u8  bLength */
-    USB_DT_CONFIG,		/*  u8  bDescriptorType */
-    0x43, 0x00,			/*  le16 wTotalLength */
-    0x02,			/*  u8  bNumInterfaces */
-    DEV_RNDIS_CONFIG_VALUE,	/*  u8  bConfigurationValue */
-    STRING_RNDIS,		/*  u8  iConfiguration */
-    0xc0,			/*  u8  bmAttributes */
-    0x32,			/*  u8  bMaxPower */
-    /* RNDIS Control Interface */
-    0x09,			/*  u8  bLength */
-    USB_DT_INTERFACE,		/*  u8  bDescriptorType */
-    0x00,			/*  u8  bInterfaceNumber */
-    0x00,			/*  u8  bAlternateSetting */
-    0x01,			/*  u8  bNumEndpoints */
-    USB_CLASS_COMM,		/*  u8  bInterfaceClass */
-    USB_CDC_SUBCLASS_ACM,	/*  u8  bInterfaceSubClass */
-    USB_CDC_ACM_PROTO_VENDOR,	/*  u8  bInterfaceProtocol */
-    STRING_RNDIS_CONTROL,	/*  u8  iInterface */
-    /* Header Descriptor */
-    0x05,			/*  u8    bLength */
-    USB_DT_CS_INTERFACE,	/*  u8    bDescriptorType */
-    USB_CDC_HEADER_TYPE,	/*  u8    bDescriptorSubType */
-    0x10, 0x01,			/*  le16  bcdCDC */
-    /* Call Management Descriptor */
-    0x05,			/*  u8    bLength */
-    USB_DT_CS_INTERFACE,	/*  u8    bDescriptorType */
-    USB_CDC_CALL_MANAGEMENT_TYPE,	/*  u8    bDescriptorSubType */
-    0x00,			/*  u8    bmCapabilities */
-    0x01,			/*  u8    bDataInterface */
-    /* ACM Descriptor */
-    0x04,			/*  u8    bLength */
-    USB_DT_CS_INTERFACE,	/*  u8    bDescriptorType */
-    USB_CDC_ACM_TYPE,		/*  u8    bDescriptorSubType */
-    0x00,			/*  u8    bmCapabilities */
-    /* Union Descriptor */
-    0x05,			/*  u8    bLength */
-    USB_DT_CS_INTERFACE,	/*  u8    bDescriptorType */
-    USB_CDC_UNION_TYPE,		/*  u8    bDescriptorSubType */
-    0x00,			/*  u8    bMasterInterface0 */
-    0x01,			/*  u8    bSlaveInterface0 */
-    /* Status Descriptor */
-    0x07,			/*  u8  bLength */
-    USB_DT_ENDPOINT,		/*  u8  bDescriptorType */
-    USB_DIR_IN | 1,		/*  u8  bEndpointAddress */
-    USB_ENDPOINT_XFER_INT,	/*  u8  bmAttributes */
-    STATUS_BYTECOUNT & 0xff, STATUS_BYTECOUNT >> 8, /*  le16 wMaxPacketSize */
-    1 << LOG2_STATUS_INTERVAL_MSEC,	/*  u8  bInterval */
-    /* RNDIS Data Interface */
-    0x09,			/*  u8  bLength */
-    USB_DT_INTERFACE,		/*  u8  bDescriptorType */
-    0x01,			/*  u8  bInterfaceNumber */
-    0x00,			/*  u8  bAlternateSetting */
-    0x02,			/*  u8  bNumEndpoints */
-    USB_CLASS_CDC_DATA,		/*  u8  bInterfaceClass */
-    0x00,			/*  u8  bInterfaceSubClass */
-    0x00,			/*  u8  bInterfaceProtocol */
-    STRING_DATA,		/*  u8  iInterface */
-    /* Source Endpoint */
-    0x07,			/*  u8  bLength */
-    USB_DT_ENDPOINT,		/*  u8  bDescriptorType */
-    USB_DIR_IN | 2,		/*  u8  bEndpointAddress */
-    USB_ENDPOINT_XFER_BULK,	/*  u8  bmAttributes */
-    0x40, 0x00,			/*  le16 wMaxPacketSize */
-    0x00,			/*  u8  bInterval */
-    /* Sink Endpoint */
-    0x07,			/*  u8  bLength */
-    USB_DT_ENDPOINT,		/*  u8  bDescriptorType */
-    USB_DIR_OUT | 2,		/*  u8  bEndpointAddress */
-    USB_ENDPOINT_XFER_BULK,	/*  u8  bmAttributes */
-    0x40, 0x00,			/*  le16 wMaxPacketSize */
-    0x00			/*  u8  bInterval */
+static const USBDescIface desc_iface_rndis[] = {
+    {
+        /* RNDIS Control Interface */
+        .bInterfaceNumber              = 0,
+        .bNumEndpoints                 = 1,
+        .bInterfaceClass               = USB_CLASS_COMM,
+        .bInterfaceSubClass            = USB_CDC_SUBCLASS_ACM,
+        .bInterfaceProtocol            = USB_CDC_ACM_PROTO_VENDOR,
+        .iInterface                    = STRING_RNDIS_CONTROL,
+        .ndesc                         = 4,
+        .descs = (USBDescOther[]) {
+            {
+                /* Header Descriptor */
+                .data = (uint8_t[]) {
+                    0x05,                       /*  u8    bLength */
+                    USB_DT_CS_INTERFACE,        /*  u8    bDescriptorType */
+                    USB_CDC_HEADER_TYPE,        /*  u8    bDescriptorSubType */
+                    0x10, 0x01,                 /*  le16  bcdCDC */
+                },
+            },{
+                /* Call Management Descriptor */
+                .data = (uint8_t[]) {
+                    0x05,                       /*  u8    bLength */
+                    USB_DT_CS_INTERFACE,        /*  u8    bDescriptorType */
+                    USB_CDC_CALL_MANAGEMENT_TYPE, /*  u8    bDescriptorSubType */
+                    0x00,                       /*  u8    bmCapabilities */
+                    0x01,                       /*  u8    bDataInterface */
+                },
+            },{
+                /* ACM Descriptor */
+                .data = (uint8_t[]) {
+                    0x04,                       /*  u8    bLength */
+                    USB_DT_CS_INTERFACE,        /*  u8    bDescriptorType */
+                    USB_CDC_ACM_TYPE,           /*  u8    bDescriptorSubType */
+                    0x00,                       /*  u8    bmCapabilities */
+                },
+            },{
+                /* Union Descriptor */
+                .data = (uint8_t[]) {
+                    0x05,                       /*  u8    bLength */
+                    USB_DT_CS_INTERFACE,        /*  u8    bDescriptorType */
+                    USB_CDC_UNION_TYPE,         /*  u8    bDescriptorSubType */
+                    0x00,                       /*  u8    bMasterInterface0 */
+                    0x01,                       /*  u8    bSlaveInterface0 */
+                },
+            },
+        },
+        .eps = (USBDescEndpoint[]) {
+            {
+                .bEndpointAddress      = USB_DIR_IN | 0x01,
+                .bmAttributes          = USB_ENDPOINT_XFER_INT,
+                .wMaxPacketSize        = STATUS_BYTECOUNT,
+                .bInterval             = 1 << LOG2_STATUS_INTERVAL_MSEC,
+            },
+        }
+    },{
+        /* RNDIS Data Interface */
+        .bInterfaceNumber              = 1,
+        .bNumEndpoints                 = 2,
+        .bInterfaceClass               = USB_CLASS_CDC_DATA,
+        .iInterface                    = STRING_DATA,
+        .eps = (USBDescEndpoint[]) {
+            {
+                .bEndpointAddress      = USB_DIR_IN | 0x02,
+                .bmAttributes          = USB_ENDPOINT_XFER_BULK,
+                .wMaxPacketSize        = 0x40,
+            },{
+                .bEndpointAddress      = USB_DIR_OUT | 0x02,
+                .bmAttributes          = USB_ENDPOINT_XFER_BULK,
+                .wMaxPacketSize        = 0x40,
+            }
+        }
+    }
 };
 
-static const uint8_t qemu_net_cdc_config_descriptor[] = {
-    /* Configuration Descriptor */
-    0x09,			/*  u8  bLength */
-    USB_DT_CONFIG,		/*  u8  bDescriptorType */
-    0x50, 0x00,			/*  le16 wTotalLength */
-    0x02,			/*  u8  bNumInterfaces */
-    DEV_CONFIG_VALUE,		/*  u8  bConfigurationValue */
-    STRING_CDC,			/*  u8  iConfiguration */
-    0xc0,			/*  u8  bmAttributes */
-    0x32,			/*  u8  bMaxPower */
-    /* CDC Control Interface */
-    0x09,			/*  u8  bLength */
-    USB_DT_INTERFACE,		/*  u8  bDescriptorType */
-    0x00,			/*  u8  bInterfaceNumber */
-    0x00,			/*  u8  bAlternateSetting */
-    0x01,			/*  u8  bNumEndpoints */
-    USB_CLASS_COMM,		/*  u8  bInterfaceClass */
-    USB_CDC_SUBCLASS_ETHERNET,	/*  u8  bInterfaceSubClass */
-    USB_CDC_PROTO_NONE,		/*  u8  bInterfaceProtocol */
-    STRING_CONTROL,		/*  u8  iInterface */
-    /* Header Descriptor */
-    0x05,			/*  u8    bLength */
-    USB_DT_CS_INTERFACE,	/*  u8    bDescriptorType */
-    USB_CDC_HEADER_TYPE,	/*  u8    bDescriptorSubType */
-    0x10, 0x01,			/*  le16  bcdCDC */
-    /* Union Descriptor */
-    0x05,			/*  u8    bLength */
-    USB_DT_CS_INTERFACE,	/*  u8    bDescriptorType */
-    USB_CDC_UNION_TYPE,		/*  u8    bDescriptorSubType */
-    0x00,			/*  u8    bMasterInterface0 */
-    0x01,			/*  u8    bSlaveInterface0 */
-    /* Ethernet Descriptor */
-    0x0d,			/*  u8    bLength */
-    USB_DT_CS_INTERFACE,	/*  u8    bDescriptorType */
-    USB_CDC_ETHERNET_TYPE,	/*  u8    bDescriptorSubType */
-    STRING_ETHADDR,		/*  u8    iMACAddress */
-    0x00, 0x00, 0x00, 0x00,	/*  le32  bmEthernetStatistics */
-    ETH_FRAME_LEN & 0xff, ETH_FRAME_LEN >> 8,	/*  le16  wMaxSegmentSize */
-    0x00, 0x00,			/*  le16  wNumberMCFilters */
-    0x00,			/*  u8    bNumberPowerFilters */
-    /* Status Descriptor */
-    0x07,			/*  u8  bLength */
-    USB_DT_ENDPOINT,		/*  u8  bDescriptorType */
-    USB_DIR_IN | 1,		/*  u8  bEndpointAddress */
-    USB_ENDPOINT_XFER_INT,	/*  u8  bmAttributes */
-    STATUS_BYTECOUNT & 0xff, STATUS_BYTECOUNT >> 8, /*  le16 wMaxPacketSize */
-    1 << LOG2_STATUS_INTERVAL_MSEC,	/*  u8  bInterval */
-    /* CDC Data (nop) Interface */
-    0x09,			/*  u8  bLength */
-    USB_DT_INTERFACE,		/*  u8  bDescriptorType */
-    0x01,			/*  u8  bInterfaceNumber */
-    0x00,			/*  u8  bAlternateSetting */
-    0x00,			/*  u8  bNumEndpoints */
-    USB_CLASS_CDC_DATA,		/*  u8  bInterfaceClass */
-    0x00,			/*  u8  bInterfaceSubClass */
-    0x00,			/*  u8  bInterfaceProtocol */
-    0x00,			/*  u8  iInterface */
-    /* CDC Data Interface */
-    0x09,			/*  u8  bLength */
-    USB_DT_INTERFACE,		/*  u8  bDescriptorType */
-    0x01,			/*  u8  bInterfaceNumber */
-    0x01,			/*  u8  bAlternateSetting */
-    0x02,			/*  u8  bNumEndpoints */
-    USB_CLASS_CDC_DATA,		/*  u8  bInterfaceClass */
-    0x00,			/*  u8  bInterfaceSubClass */
-    0x00,			/*  u8  bInterfaceProtocol */
-    STRING_DATA,		/*  u8  iInterface */
-    /* Source Endpoint */
-    0x07,			/*  u8  bLength */
-    USB_DT_ENDPOINT,		/*  u8  bDescriptorType */
-    USB_DIR_IN | 2,		/*  u8  bEndpointAddress */
-    USB_ENDPOINT_XFER_BULK,	/*  u8  bmAttributes */
-    0x40, 0x00,			/*  le16 wMaxPacketSize */
-    0x00,			/*  u8  bInterval */
-    /* Sink Endpoint */
-    0x07,			/*  u8  bLength */
-    USB_DT_ENDPOINT,		/*  u8  bDescriptorType */
-    USB_DIR_OUT | 2,		/*  u8  bEndpointAddress */
-    USB_ENDPOINT_XFER_BULK,	/*  u8  bmAttributes */
-    0x40, 0x00,			/*  le16 wMaxPacketSize */
-    0x00			/*  u8  bInterval */
+static const USBDescIface desc_iface_cdc[] = {
+    {
+        /* CDC Control Interface */
+        .bInterfaceNumber              = 0,
+        .bNumEndpoints                 = 1,
+        .bInterfaceClass               = USB_CLASS_COMM,
+        .bInterfaceSubClass            = USB_CDC_SUBCLASS_ETHERNET,
+        .bInterfaceProtocol            = USB_CDC_PROTO_NONE,
+        .iInterface                    = STRING_CONTROL,
+        .ndesc                         = 3,
+        .descs = (USBDescOther[]) {
+            {
+                /* Header Descriptor */
+                .data = (uint8_t[]) {
+                    0x05,                       /*  u8    bLength */
+                    USB_DT_CS_INTERFACE,        /*  u8    bDescriptorType */
+                    USB_CDC_HEADER_TYPE,        /*  u8    bDescriptorSubType */
+                    0x10, 0x01,                 /*  le16  bcdCDC */
+                },
+            },{
+                /* Union Descriptor */
+                .data = (uint8_t[]) {
+                    0x05,                       /*  u8    bLength */
+                    USB_DT_CS_INTERFACE,        /*  u8    bDescriptorType */
+                    USB_CDC_UNION_TYPE,         /*  u8    bDescriptorSubType */
+                    0x00,                       /*  u8    bMasterInterface0 */
+                    0x01,                       /*  u8    bSlaveInterface0 */
+                },
+            },{
+                /* Ethernet Descriptor */
+                .data = (uint8_t[]) {
+                    0x0d,                       /*  u8    bLength */
+                    USB_DT_CS_INTERFACE,        /*  u8    bDescriptorType */
+                    USB_CDC_ETHERNET_TYPE,      /*  u8    bDescriptorSubType */
+                    STRING_ETHADDR,             /*  u8    iMACAddress */
+                    0x00, 0x00, 0x00, 0x00,     /*  le32  bmEthernetStatistics */
+                    ETH_FRAME_LEN & 0xff,
+                    ETH_FRAME_LEN >> 8,         /*  le16  wMaxSegmentSize */
+                    0x00, 0x00,                 /*  le16  wNumberMCFilters */
+                    0x00,                       /*  u8    bNumberPowerFilters */
+                },
+            },
+        },
+        .eps = (USBDescEndpoint[]) {
+            {
+                .bEndpointAddress      = USB_DIR_IN | 0x01,
+                .bmAttributes          = USB_ENDPOINT_XFER_INT,
+                .wMaxPacketSize        = STATUS_BYTECOUNT,
+                .bInterval             = 1 << LOG2_STATUS_INTERVAL_MSEC,
+            },
+        }
+    },{
+        /* CDC Data Interface (off) */
+        .bInterfaceNumber              = 1,
+        .bAlternateSetting             = 0,
+        .bNumEndpoints                 = 0,
+        .bInterfaceClass               = USB_CLASS_CDC_DATA,
+    },{
+        /* CDC Data Interface */
+        .bInterfaceNumber              = 1,
+        .bAlternateSetting             = 1,
+        .bNumEndpoints                 = 2,
+        .bInterfaceClass               = USB_CLASS_CDC_DATA,
+        .iInterface                    = STRING_DATA,
+        .eps = (USBDescEndpoint[]) {
+            {
+                .bEndpointAddress      = USB_DIR_IN | 0x02,
+                .bmAttributes          = USB_ENDPOINT_XFER_BULK,
+                .wMaxPacketSize        = 0x40,
+            },{
+                .bEndpointAddress      = USB_DIR_OUT | 0x02,
+                .bmAttributes          = USB_ENDPOINT_XFER_BULK,
+                .wMaxPacketSize        = 0x40,
+            }
+        }
+    }
+};
+
+static const USBDescDevice desc_device_net = {
+    .bcdUSB                        = 0x0200,
+    .bDeviceClass                  = USB_CLASS_COMM,
+    .bMaxPacketSize0               = 0x40,
+    .bNumConfigurations            = 2,
+    .confs = (USBDescConfig[]) {
+        {
+            .bNumInterfaces        = 2,
+            .bConfigurationValue   = DEV_RNDIS_CONFIG_VALUE,
+            .iConfiguration        = STRING_RNDIS,
+            .bmAttributes          = 0xc0,
+            .bMaxPower             = 0x32,
+            .nif = ARRAY_SIZE(desc_iface_rndis),
+            .ifs = desc_iface_rndis,
+        },{
+            .bNumInterfaces        = 2,
+            .bConfigurationValue   = DEV_CONFIG_VALUE,
+            .iConfiguration        = STRING_CDC,
+            .bmAttributes          = 0xc0,
+            .bMaxPower             = 0x32,
+            .nif = ARRAY_SIZE(desc_iface_cdc),
+            .ifs = desc_iface_cdc,
+        }
+    },
+};
+
+static const USBDesc desc_net = {
+    .id = {
+        .idVendor          = RNDIS_VENDOR_NUM,
+        .idProduct         = RNDIS_PRODUCT_NUM,
+        .bcdDevice         = 0,
+        .iManufacturer     = STRING_MANUFACTURER,
+        .iProduct          = STRING_PRODUCT,
+        .iSerialNumber     = STRING_SERIALNUMBER,
+    },
+    .full = &desc_device_net,
+    .str  = usb_net_stringtable,
 };
 
 /*
@@ -1010,25 +1038,18 @@ static void usb_net_handle_reset(USBDevice *dev)
 {
 }
 
-static const char * const usb_net_stringtable[] = {
-    [STRING_MANUFACTURER]	= "QEMU",
-    [STRING_PRODUCT]		= "RNDIS/QEMU USB Network Device",
-    [STRING_ETHADDR]		= "400102030405",
-    [STRING_DATA]		= "QEMU USB Net Data Interface",
-    [STRING_CONTROL]		= "QEMU USB Net Control Interface",
-    [STRING_RNDIS_CONTROL]	= "QEMU USB Net RNDIS Control Interface",
-    [STRING_CDC]		= "QEMU USB Net CDC",
-    [STRING_SUBSET]		= "QEMU USB Net Subset",
-    [STRING_RNDIS]		= "QEMU USB Net RNDIS",
-    [STRING_SERIALNUMBER]	= "1",
-};
-
 static int usb_net_handle_control(USBDevice *dev, int request, int value,
                 int index, int length, uint8_t *data)
 {
     USBNetState *s = (USBNetState *) dev;
-    int ret = 0;
+    int ret;
 
+    ret = usb_desc_handle_control(dev, request, value, index, length, data);
+    if (ret >= 0) {
+        return ret;
+    }
+
+    ret = 0;
     switch(request) {
     case DeviceRequest | USB_REQ_GET_STATUS:
         data[0] = (1 << USB_DEVICE_SELF_POWERED) |
@@ -1100,64 +1121,6 @@ static int usb_net_handle_control(USBDevice *dev, int request, int value,
 #endif
         break;
 
-    case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
-        switch(value >> 8) {
-        case USB_DT_DEVICE:
-            ret = sizeof(qemu_net_dev_descriptor);
-            memcpy(data, qemu_net_dev_descriptor, ret);
-            break;
-
-        case USB_DT_CONFIG:
-            switch (value & 0xff) {
-            case 0:
-                ret = sizeof(qemu_net_rndis_config_descriptor);
-                memcpy(data, qemu_net_rndis_config_descriptor, ret);
-                break;
-
-            case 1:
-                ret = sizeof(qemu_net_cdc_config_descriptor);
-                memcpy(data, qemu_net_cdc_config_descriptor, ret);
-                break;
-
-            default:
-                goto fail;
-            }
-
-            data[2] = ret & 0xff;
-            data[3] = ret >> 8;
-            break;
-
-        case USB_DT_STRING:
-            switch (value & 0xff) {
-            case 0:
-                /* language ids */
-                data[0] = 4;
-                data[1] = 3;
-                data[2] = 0x09;
-                data[3] = 0x04;
-                ret = 4;
-                break;
-
-            case STRING_ETHADDR:
-                ret = set_usb_string(data, s->usbstring_mac);
-                break;
-
-            default:
-                if (ARRAY_SIZE(usb_net_stringtable) > (value & 0xff)) {
-                    ret = set_usb_string(data,
-                                    usb_net_stringtable[value & 0xff]);
-                    break;
-                }
-
-                goto fail;
-            }
-            break;
-
-        default:
-            goto fail;
-        }
-        break;
-
     case DeviceRequest | USB_REQ_GET_CONFIGURATION:
         data[0] = s->rndis ? DEV_RNDIS_CONFIG_VALUE : DEV_CONFIG_VALUE;
         ret = 1;
@@ -1463,6 +1426,7 @@ static int usb_net_initfn(USBDevice *dev)
              s->conf.macaddr.a[3],
              s->conf.macaddr.a[4],
              s->conf.macaddr.a[5]);
+    usb_desc_set_string(dev, STRING_ETHADDR, s->usbstring_mac);
 
     add_boot_device_path(s->conf.bootindex, &dev->qdev, "/ethernet@0");
     return 0;
@@ -1500,6 +1464,7 @@ static struct USBDeviceInfo net_info = {
     .qdev.name      = "usb-net",
     .qdev.fw_name    = "network",
     .qdev.size      = sizeof(USBNetState),
+    .usb_desc       = &desc_net,
     .init           = usb_net_initfn,
     .handle_packet  = usb_generic_handle_packet,
     .handle_reset   = usb_net_handle_reset,
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v4 12/32] usb: move USB_REQ_SET_ADDRESS handling to common code
  2011-01-12 11:19 [Qemu-devel] [PATCH v4 00/32] usb descriptor overhaul + more Gerd Hoffmann
                   ` (10 preceding siblings ...)
  2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 11/32] usb network: use new descriptor infrastructure Gerd Hoffmann
@ 2011-01-12 11:19 ` Gerd Hoffmann
  2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 13/32] usb: move USB_REQ_{GET, SET}_CONFIGURATION " Gerd Hoffmann
                   ` (20 subsequent siblings)
  32 siblings, 0 replies; 37+ messages in thread
From: Gerd Hoffmann @ 2011-01-12 11:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

USB_REQ_SET_ADDRESS handling is identical in *all* emulated devices.
Move it to common code.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb-bt.c     |    4 ----
 hw/usb-desc.c   |    6 ++++++
 hw/usb-hid.c    |    4 ----
 hw/usb-hub.c    |    4 ----
 hw/usb-msd.c    |    4 ----
 hw/usb-net.c    |    5 -----
 hw/usb-serial.c |    4 ----
 hw/usb-wacom.c  |    4 ----
 trace-events    |    1 +
 9 files changed, 7 insertions(+), 29 deletions(-)

diff --git a/hw/usb-bt.c b/hw/usb-bt.c
index d7959ad..c0bfc35 100644
--- a/hw/usb-bt.c
+++ b/hw/usb-bt.c
@@ -413,10 +413,6 @@ static int usb_bt_handle_control(USBDevice *dev, int request, int value,
         }
         ret = 0;
         break;
-    case DeviceOutRequest | USB_REQ_SET_ADDRESS:
-        dev->addr = value;
-        ret = 0;
-        break;
     case DeviceRequest | USB_REQ_GET_CONFIGURATION:
         data[0] = 1;
         ret = 1;
diff --git a/hw/usb-desc.c b/hw/usb-desc.c
index 69ab207..3e87f46 100644
--- a/hw/usb-desc.c
+++ b/hw/usb-desc.c
@@ -266,6 +266,12 @@ int usb_desc_handle_control(USBDevice *dev, int request, int value,
 
     assert(desc != NULL);
     switch(request) {
+    case DeviceOutRequest | USB_REQ_SET_ADDRESS:
+        dev->addr = value;
+        trace_usb_set_addr(dev->addr);
+        ret = 0;
+        break;
+
     case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
         ret = usb_desc_get_descriptor(dev, value, data, length);
         break;
diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index 74d17fc..72daddf 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -695,10 +695,6 @@ static int usb_hid_handle_control(USBDevice *dev, int request, int value,
         }
         ret = 0;
         break;
-    case DeviceOutRequest | USB_REQ_SET_ADDRESS:
-        dev->addr = value;
-        ret = 0;
-        break;
     case DeviceRequest | USB_REQ_GET_CONFIGURATION:
         data[0] = 1;
         ret = 1;
diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index 421d43d..1d321ac 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -297,10 +297,6 @@ static int usb_hub_handle_control(USBDevice *dev, int request, int value,
         }
         ret = 0;
         break;
-    case DeviceOutRequest | USB_REQ_SET_ADDRESS:
-        dev->addr = value;
-        ret = 0;
-        break;
     case DeviceRequest | USB_REQ_GET_CONFIGURATION:
         data[0] = 1;
         ret = 1;
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 9aa8888..b54ccbc 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -261,10 +261,6 @@ static int usb_msd_handle_control(USBDevice *dev, int request, int value,
         }
         ret = 0;
         break;
-    case DeviceOutRequest | USB_REQ_SET_ADDRESS:
-        dev->addr = value;
-        ret = 0;
-        break;
     case DeviceRequest | USB_REQ_GET_CONFIGURATION:
         data[0] = 1;
         ret = 1;
diff --git a/hw/usb-net.c b/hw/usb-net.c
index b2fe42e..141d749 100644
--- a/hw/usb-net.c
+++ b/hw/usb-net.c
@@ -1076,11 +1076,6 @@ static int usb_net_handle_control(USBDevice *dev, int request, int value,
         ret = 0;
         break;
 
-    case DeviceOutRequest | USB_REQ_SET_ADDRESS:
-        dev->addr = value;
-        ret = 0;
-        break;
-
     case ClassInterfaceOutRequest | USB_CDC_SEND_ENCAPSULATED_COMMAND:
         if (!s->rndis || value || index != 0)
             goto fail;
diff --git a/hw/usb-serial.c b/hw/usb-serial.c
index f89eb9b..c1f31c7 100644
--- a/hw/usb-serial.c
+++ b/hw/usb-serial.c
@@ -254,10 +254,6 @@ static int usb_serial_handle_control(USBDevice *dev, int request, int value,
         }
         ret = 0;
         break;
-    case DeviceOutRequest | USB_REQ_SET_ADDRESS:
-        dev->addr = value;
-        ret = 0;
-        break;
     case DeviceRequest | USB_REQ_GET_CONFIGURATION:
         data[0] = 1;
         ret = 1;
diff --git a/hw/usb-wacom.c b/hw/usb-wacom.c
index ffe6ac7..ad1c3ae 100644
--- a/hw/usb-wacom.c
+++ b/hw/usb-wacom.c
@@ -284,10 +284,6 @@ static int usb_wacom_handle_control(USBDevice *dev, int request, int value,
         }
         ret = 0;
         break;
-    case DeviceOutRequest | USB_REQ_SET_ADDRESS:
-        dev->addr = value;
-        ret = 0;
-        break;
     case DeviceRequest | USB_REQ_GET_CONFIGURATION:
         data[0] = 1;
         ret = 1;
diff --git a/trace-events b/trace-events
index 8264ff0..7948c6c 100644
--- a/trace-events
+++ b/trace-events
@@ -194,6 +194,7 @@ disable sun4m_iommu_bad_addr(uint64_t addr) "bad addr %"PRIx64""
 disable usb_desc_device(int addr, int len, int ret) "dev %d query device, len %d, ret %d"
 disable usb_desc_config(int addr, int index, int len, int ret) "dev %d query config %d, len %d, ret %d"
 disable usb_desc_string(int addr, int index, int len, int ret) "dev %d query string %d, len %d, ret %d"
+disable usb_set_addr(int addr) "dev %d"
 
 # vl.c
 disable vm_state_notify(int running, int reason) "running %d reason %d"
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v4 13/32] usb: move USB_REQ_{GET, SET}_CONFIGURATION handling to common code
  2011-01-12 11:19 [Qemu-devel] [PATCH v4 00/32] usb descriptor overhaul + more Gerd Hoffmann
                   ` (11 preceding siblings ...)
  2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 12/32] usb: move USB_REQ_SET_ADDRESS handling to common code Gerd Hoffmann
@ 2011-01-12 11:19 ` Gerd Hoffmann
  2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 14/32] usb: move remote wakeup " Gerd Hoffmann
                   ` (19 subsequent siblings)
  32 siblings, 0 replies; 37+ messages in thread
From: Gerd Hoffmann @ 2011-01-12 11:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

This patch adds fields to the USBDevice struct for the current
speed (hard-wired to full speed for now) and current device
configuration.  Also a init function is added which inializes
these fields.  This allows USB_REQ_{GET,SET}_CONFIGURATION
handling to be moved to common code.

For most drivers the conversion is trivial ad they support a single
configuration only anyway.  One exception is bluetooth where some
device-specific setup code runs after get/set configuration.  The
other is usb-net which actually has two configurations so the
the code to check for the active configuration has been adapted.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb-bt.c     |   31 ++++++++++++-------------------
 hw/usb-desc.c   |   32 ++++++++++++++++++++++++++++----
 hw/usb-desc.h   |    1 +
 hw/usb-hid.c    |   10 ++--------
 hw/usb-hub.c    |    9 +--------
 hw/usb-msd.c    |    9 +--------
 hw/usb-net.c    |   45 +++++++++++++++------------------------------
 hw/usb-serial.c |   10 ++--------
 hw/usb-wacom.c  |    9 +--------
 hw/usb.h        |    2 ++
 trace-events    |    1 +
 11 files changed, 66 insertions(+), 93 deletions(-)

diff --git a/hw/usb-bt.c b/hw/usb-bt.c
index c0bfc35..36c90a3 100644
--- a/hw/usb-bt.c
+++ b/hw/usb-bt.c
@@ -380,6 +380,17 @@ static int usb_bt_handle_control(USBDevice *dev, int request, int value,
 
     ret = usb_desc_handle_control(dev, request, value, index, length, data);
     if (ret >= 0) {
+        switch (request) {
+        case DeviceRequest | USB_REQ_GET_CONFIGURATION:
+            s->config = 0;
+            break;
+        case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
+            s->config = 1;
+            usb_bt_fifo_reset(&s->evt);
+            usb_bt_fifo_reset(&s->acl);
+            usb_bt_fifo_reset(&s->sco);
+            break;
+        }
         return ret;
     }
 
@@ -413,23 +424,6 @@ static int usb_bt_handle_control(USBDevice *dev, int request, int value,
         }
         ret = 0;
         break;
-    case DeviceRequest | USB_REQ_GET_CONFIGURATION:
-        data[0] = 1;
-        ret = 1;
-        s->config = 0;
-        break;
-    case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
-        ret = 0;
-        if (value != 1 && value != 0) {
-            printf("%s: Wrong SET_CONFIGURATION request (%i)\n",
-                            __FUNCTION__, value);
-            goto fail;
-        }
-        s->config = 1;
-        usb_bt_fifo_reset(&s->evt);
-        usb_bt_fifo_reset(&s->acl);
-        usb_bt_fifo_reset(&s->sco);
-        break;
     case InterfaceRequest | USB_REQ_GET_INTERFACE:
         if (value != 0 || (index & ~1) || length != 1)
             goto fail;
@@ -544,8 +538,7 @@ static void usb_bt_handle_destroy(USBDevice *dev)
 
 static int usb_bt_initfn(USBDevice *dev)
 {
-    struct USBBtState *s = DO_UPCAST(struct USBBtState, dev, dev);
-    s->dev.speed = USB_SPEED_HIGH;
+    usb_desc_init(dev);
     return 0;
 }
 
diff --git a/hw/usb-desc.c b/hw/usb-desc.c
index 3e87f46..14c9e11 100644
--- a/hw/usb-desc.c
+++ b/hw/usb-desc.c
@@ -153,6 +153,16 @@ int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len)
 
 /* ------------------------------------------------------------------ */
 
+void usb_desc_init(USBDevice *dev)
+{
+    const USBDesc *desc = dev->info->usb_desc;
+
+    assert(desc != NULL);
+    dev->speed  = USB_SPEED_FULL;
+    dev->device = desc->full;
+    dev->config = dev->device->confs;
+}
+
 void usb_desc_set_string(USBDevice *dev, uint8_t index, const char *str)
 {
     USBDescString *s;
@@ -230,12 +240,12 @@ int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len
 
     switch(type) {
     case USB_DT_DEVICE:
-        ret = usb_desc_device(&desc->id, desc->full, buf, sizeof(buf));
+        ret = usb_desc_device(&desc->id, dev->device, buf, sizeof(buf));
         trace_usb_desc_device(dev->addr, len, ret);
         break;
     case USB_DT_CONFIG:
-        if (index < desc->full->bNumConfigurations) {
-            ret = usb_desc_config(desc->full->confs + index, buf, sizeof(buf));
+        if (index < dev->device->bNumConfigurations) {
+            ret = usb_desc_config(dev->device->confs + index, buf, sizeof(buf));
         }
         trace_usb_desc_config(dev->addr, index, len, ret);
         break;
@@ -262,7 +272,7 @@ int usb_desc_handle_control(USBDevice *dev, int request, int value,
                             int index, int length, uint8_t *data)
 {
     const USBDesc *desc = dev->info->usb_desc;
-    int ret = -1;
+    int i, ret = -1;
 
     assert(desc != NULL);
     switch(request) {
@@ -275,6 +285,20 @@ int usb_desc_handle_control(USBDevice *dev, int request, int value,
     case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
         ret = usb_desc_get_descriptor(dev, value, data, length);
         break;
+
+    case DeviceRequest | USB_REQ_GET_CONFIGURATION:
+        data[0] = dev->config->bConfigurationValue;
+        ret = 1;
+        break;
+    case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
+        for (i = 0; i < dev->device->bNumConfigurations; i++) {
+            if (dev->device->confs[i].bConfigurationValue == value) {
+                dev->config = dev->device->confs + i;
+                ret = 0;
+            }
+        }
+        trace_usb_set_config(dev->addr, value, ret);
+        break;
     }
     return ret;
 }
diff --git a/hw/usb-desc.h b/hw/usb-desc.h
index 20fc400..d441725 100644
--- a/hw/usb-desc.h
+++ b/hw/usb-desc.h
@@ -78,6 +78,7 @@ int usb_desc_endpoint(const USBDescEndpoint *ep, uint8_t *dest, size_t len);
 int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len);
 
 /* control message emulation helpers */
+void usb_desc_init(USBDevice *dev);
 void usb_desc_set_string(USBDevice *dev, uint8_t index, const char *str);
 const char *usb_desc_get_string(USBDevice *dev, uint8_t index);
 int usb_desc_string(USBDevice *dev, int index, uint8_t *dest, size_t len);
diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index 72daddf..21c0c72 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -695,13 +695,6 @@ static int usb_hid_handle_control(USBDevice *dev, int request, int value,
         }
         ret = 0;
         break;
-    case DeviceRequest | USB_REQ_GET_CONFIGURATION:
-        data[0] = 1;
-        ret = 1;
-        break;
-    case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
-        ret = 0;
-        break;
     case DeviceRequest | USB_REQ_GET_INTERFACE:
         data[0] = 0;
         ret = 1;
@@ -822,7 +815,8 @@ static void usb_hid_handle_destroy(USBDevice *dev)
 static int usb_hid_initfn(USBDevice *dev, int kind)
 {
     USBHIDState *s = DO_UPCAST(USBHIDState, dev, dev);
-    s->dev.speed = USB_SPEED_FULL;
+
+    usb_desc_init(dev);
     s->kind = kind;
 
     if (s->kind == USB_MOUSE) {
diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index 1d321ac..fc0b94b 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -297,13 +297,6 @@ static int usb_hub_handle_control(USBDevice *dev, int request, int value,
         }
         ret = 0;
         break;
-    case DeviceRequest | USB_REQ_GET_CONFIGURATION:
-        data[0] = 1;
-        ret = 1;
-        break;
-    case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
-        ret = 0;
-        break;
     case DeviceRequest | USB_REQ_GET_INTERFACE:
         data[0] = 0;
         ret = 1;
@@ -541,7 +534,7 @@ static int usb_hub_initfn(USBDevice *dev)
     USBHubPort *port;
     int i;
 
-    s->dev.speed = USB_SPEED_FULL;
+    usb_desc_init(dev);
     for (i = 0; i < NUM_PORTS; i++) {
         port = &s->ports[i];
         usb_register_port(usb_bus_from_device(dev),
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index b54ccbc..56c6f3d 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -261,13 +261,6 @@ static int usb_msd_handle_control(USBDevice *dev, int request, int value,
         }
         ret = 0;
         break;
-    case DeviceRequest | USB_REQ_GET_CONFIGURATION:
-        data[0] = 1;
-        ret = 1;
-        break;
-    case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
-        ret = 0;
-        break;
     case DeviceRequest | USB_REQ_GET_INTERFACE:
         data[0] = 0;
         ret = 1;
@@ -502,7 +495,7 @@ static int usb_msd_initfn(USBDevice *dev)
         usb_desc_set_string(dev, STR_SERIALNUMBER, dinfo->serial);
     }
 
-    s->dev.speed = USB_SPEED_FULL;
+    usb_desc_init(dev);
     scsi_bus_new(&s->bus, &s->dev.qdev, 0, 1, usb_msd_command_complete);
     s->scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0);
     if (!s->scsi_dev) {
diff --git a/hw/usb-net.c b/hw/usb-net.c
index 141d749..f123045 100644
--- a/hw/usb-net.c
+++ b/hw/usb-net.c
@@ -627,7 +627,6 @@ struct rndis_response {
 typedef struct USBNetState {
     USBDevice dev;
 
-    unsigned int rndis;
     enum rndis_state rndis_state;
     uint32_t medium;
     uint32_t speed;
@@ -648,6 +647,11 @@ typedef struct USBNetState {
     QTAILQ_HEAD(rndis_resp_head, rndis_response) rndis_resp;
 } USBNetState;
 
+static int is_rndis(USBNetState *s)
+{
+    return s->dev.config->bConfigurationValue == DEV_RNDIS_CONFIG_VALUE;
+}
+
 static int ndis_query(USBNetState *s, uint32_t oid,
                       uint8_t *inbuf, unsigned int inlen, uint8_t *outbuf,
                       size_t outlen)
@@ -1077,8 +1081,9 @@ static int usb_net_handle_control(USBDevice *dev, int request, int value,
         break;
 
     case ClassInterfaceOutRequest | USB_CDC_SEND_ENCAPSULATED_COMMAND:
-        if (!s->rndis || value || index != 0)
+        if (!is_rndis(s) || value || index != 0) {
             goto fail;
+        }
 #ifdef TRAFFIC_DEBUG
         {
             unsigned int i;
@@ -1095,8 +1100,9 @@ static int usb_net_handle_control(USBDevice *dev, int request, int value,
         break;
 
     case ClassInterfaceRequest | USB_CDC_GET_ENCAPSULATED_RESPONSE:
-        if (!s->rndis || value || index != 0)
+        if (!is_rndis(s) || value || index != 0) {
             goto fail;
+        }
         ret = rndis_get_response(s, data);
         if (!ret) {
             data[0] = 0;
@@ -1116,27 +1122,6 @@ static int usb_net_handle_control(USBDevice *dev, int request, int value,
 #endif
         break;
 
-    case DeviceRequest | USB_REQ_GET_CONFIGURATION:
-        data[0] = s->rndis ? DEV_RNDIS_CONFIG_VALUE : DEV_CONFIG_VALUE;
-        ret = 1;
-        break;
-
-    case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
-        switch (value & 0xff) {
-        case DEV_CONFIG_VALUE:
-            s->rndis = 0;
-            break;
-
-        case DEV_RNDIS_CONFIG_VALUE:
-            s->rndis = 1;
-            break;
-
-        default:
-            goto fail;
-        }
-        ret = 0;
-        break;
-
     case DeviceRequest | USB_REQ_GET_INTERFACE:
     case InterfaceRequest | USB_REQ_GET_INTERFACE:
         data[0] = 0;
@@ -1207,7 +1192,7 @@ static int usb_net_handle_datain(USBNetState *s, USBPacket *p)
     memcpy(p->data, &s->in_buf[s->in_ptr], ret);
     s->in_ptr += ret;
     if (s->in_ptr >= s->in_len &&
-                    (s->rndis || (s->in_len & (64 - 1)) || !ret)) {
+                    (is_rndis(s) || (s->in_len & (64 - 1)) || !ret)) {
         /* no short packet necessary */
         s->in_ptr = s->in_len = 0;
     }
@@ -1256,7 +1241,7 @@ static int usb_net_handle_dataout(USBNetState *s, USBPacket *p)
     memcpy(&s->out_buf[s->out_ptr], p->data, sz);
     s->out_ptr += sz;
 
-    if (!s->rndis) {
+    if (!is_rndis(s)) {
         if (ret < 64) {
             qemu_send_packet(&s->nic->nc, s->out_buf, s->out_ptr);
             s->out_ptr = 0;
@@ -1327,7 +1312,7 @@ static ssize_t usbnet_receive(VLANClientState *nc, const uint8_t *buf, size_t si
     USBNetState *s = DO_UPCAST(NICState, nc, nc)->opaque;
     struct rndis_packet_msg_type *msg;
 
-    if (s->rndis) {
+    if (is_rndis(s)) {
         msg = (struct rndis_packet_msg_type *) s->in_buf;
         if (!s->rndis_state == RNDIS_DATA_INITIALIZED)
             return -1;
@@ -1363,8 +1348,9 @@ static int usbnet_can_receive(VLANClientState *nc)
 {
     USBNetState *s = DO_UPCAST(NICState, nc, nc)->opaque;
 
-    if (s->rndis && !s->rndis_state == RNDIS_DATA_INITIALIZED)
+    if (is_rndis(s) && !s->rndis_state == RNDIS_DATA_INITIALIZED) {
         return 1;
+    }
 
     return !s->in_len;
 }
@@ -1397,9 +1383,8 @@ static int usb_net_initfn(USBDevice *dev)
 {
     USBNetState *s = DO_UPCAST(USBNetState, dev, dev);
 
-    s->dev.speed  = USB_SPEED_FULL;
+    usb_desc_init(dev);
 
-    s->rndis = 1;
     s->rndis_state = RNDIS_UNINITIALIZED;
     QTAILQ_INIT(&s->rndis_resp);
 
diff --git a/hw/usb-serial.c b/hw/usb-serial.c
index c1f31c7..2bdb10b 100644
--- a/hw/usb-serial.c
+++ b/hw/usb-serial.c
@@ -254,13 +254,6 @@ static int usb_serial_handle_control(USBDevice *dev, int request, int value,
         }
         ret = 0;
         break;
-    case DeviceRequest | USB_REQ_GET_CONFIGURATION:
-        data[0] = 1;
-        ret = 1;
-        break;
-    case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
-        ret = 0;
-        break;
     case DeviceRequest | USB_REQ_GET_INTERFACE:
         data[0] = 0;
         ret = 1;
@@ -507,7 +500,8 @@ static void usb_serial_event(void *opaque, int event)
 static int usb_serial_initfn(USBDevice *dev)
 {
     USBSerialState *s = DO_UPCAST(USBSerialState, dev, dev);
-    s->dev.speed = USB_SPEED_FULL;
+
+    usb_desc_init(dev);
 
     if (!s->cs) {
         error_report("Property chardev is required");
diff --git a/hw/usb-wacom.c b/hw/usb-wacom.c
index ad1c3ae..3a98e80 100644
--- a/hw/usb-wacom.c
+++ b/hw/usb-wacom.c
@@ -284,13 +284,6 @@ static int usb_wacom_handle_control(USBDevice *dev, int request, int value,
         }
         ret = 0;
         break;
-    case DeviceRequest | USB_REQ_GET_CONFIGURATION:
-        data[0] = 1;
-        ret = 1;
-        break;
-    case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
-        ret = 0;
-        break;
     case DeviceRequest | USB_REQ_GET_INTERFACE:
         data[0] = 0;
         ret = 1;
@@ -373,7 +366,7 @@ static void usb_wacom_handle_destroy(USBDevice *dev)
 static int usb_wacom_initfn(USBDevice *dev)
 {
     USBWacomState *s = DO_UPCAST(USBWacomState, dev, dev);
-    s->dev.speed = USB_SPEED_FULL;
+    usb_desc_init(dev);
     s->changed = 1;
     return 0;
 }
diff --git a/hw/usb.h b/hw/usb.h
index 7b5c8df..966d47e 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -164,6 +164,8 @@ struct USBDevice {
     int setup_index;
 
     QLIST_HEAD(, USBDescString) strings;
+    const USBDescDevice *device;
+    const USBDescConfig *config;
 };
 
 struct USBDeviceInfo {
diff --git a/trace-events b/trace-events
index 7948c6c..9ef8474 100644
--- a/trace-events
+++ b/trace-events
@@ -195,6 +195,7 @@ disable usb_desc_device(int addr, int len, int ret) "dev %d query device, len %d
 disable usb_desc_config(int addr, int index, int len, int ret) "dev %d query config %d, len %d, ret %d"
 disable usb_desc_string(int addr, int index, int len, int ret) "dev %d query string %d, len %d, ret %d"
 disable usb_set_addr(int addr) "dev %d"
+disable usb_set_config(int addr, int config, int ret) "dev %d, config %d, ret %d"
 
 # vl.c
 disable vm_state_notify(int running, int reason) "running %d reason %d"
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v4 14/32] usb: move remote wakeup handling to common code
  2011-01-12 11:19 [Qemu-devel] [PATCH v4 00/32] usb descriptor overhaul + more Gerd Hoffmann
                   ` (12 preceding siblings ...)
  2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 13/32] usb: move USB_REQ_{GET, SET}_CONFIGURATION " Gerd Hoffmann
@ 2011-01-12 11:19 ` Gerd Hoffmann
  2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 15/32] usb: create USBPortOps, move attach there Gerd Hoffmann
                   ` (18 subsequent siblings)
  32 siblings, 0 replies; 37+ messages in thread
From: Gerd Hoffmann @ 2011-01-12 11:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

This patch moves setting and clearing the remote_wakeup feature
bit (via USB_REQ_{SET,CLEAR}_FEATURE) to common code.  Also
USB_REQ_GET_STATUS handling is moved to common code.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb-bt.c     |   21 +++------------------
 hw/usb-desc.c   |   26 ++++++++++++++++++++++++++
 hw/usb-hid.c    |   22 ----------------------
 hw/usb-hub.c    |   22 ----------------------
 hw/usb-msd.c    |   23 -----------------------
 hw/usb-net.c    |   25 -------------------------
 hw/usb-serial.c |   22 ----------------------
 hw/usb-wacom.c  |   23 -----------------------
 trace-events    |    2 ++
 9 files changed, 31 insertions(+), 155 deletions(-)

diff --git a/hw/usb-bt.c b/hw/usb-bt.c
index 36c90a3..22e6845 100644
--- a/hw/usb-bt.c
+++ b/hw/usb-bt.c
@@ -396,33 +396,18 @@ static int usb_bt_handle_control(USBDevice *dev, int request, int value,
 
     ret = 0;
     switch (request) {
-    case DeviceRequest | USB_REQ_GET_STATUS:
     case InterfaceRequest | USB_REQ_GET_STATUS:
     case EndpointRequest | USB_REQ_GET_STATUS:
-        data[0] = (1 << USB_DEVICE_SELF_POWERED) |
-            (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
+        data[0] = 0x00;
         data[1] = 0x00;
         ret = 2;
         break;
-    case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
     case InterfaceOutRequest | USB_REQ_CLEAR_FEATURE:
     case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
-        if (value == USB_DEVICE_REMOTE_WAKEUP) {
-            dev->remote_wakeup = 0;
-        } else {
-            goto fail;
-        }
-        ret = 0;
-        break;
-    case DeviceOutRequest | USB_REQ_SET_FEATURE:
+        goto fail;
     case InterfaceOutRequest | USB_REQ_SET_FEATURE:
     case EndpointOutRequest | USB_REQ_SET_FEATURE:
-        if (value == USB_DEVICE_REMOTE_WAKEUP) {
-            dev->remote_wakeup = 1;
-        } else {
-            goto fail;
-        }
-        ret = 0;
+        goto fail;
         break;
     case InterfaceRequest | USB_REQ_GET_INTERFACE:
         if (value != 0 || (index & ~1) || length != 1)
diff --git a/hw/usb-desc.c b/hw/usb-desc.c
index 14c9e11..56ef734 100644
--- a/hw/usb-desc.c
+++ b/hw/usb-desc.c
@@ -299,6 +299,32 @@ int usb_desc_handle_control(USBDevice *dev, int request, int value,
         }
         trace_usb_set_config(dev->addr, value, ret);
         break;
+
+    case DeviceRequest | USB_REQ_GET_STATUS:
+        data[0] = 0;
+        if (dev->config->bmAttributes & 0x40) {
+            data[0] |= 1 << USB_DEVICE_SELF_POWERED;
+        }
+        if (dev->remote_wakeup) {
+            data[0] |= 1 << USB_DEVICE_REMOTE_WAKEUP;
+        }
+        data[1] = 0x00;
+        ret = 2;
+        break;
+    case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
+        if (value == USB_DEVICE_REMOTE_WAKEUP) {
+            dev->remote_wakeup = 0;
+            ret = 0;
+        }
+        trace_usb_clear_device_feature(dev->addr, value, ret);
+        break;
+    case DeviceOutRequest | USB_REQ_SET_FEATURE:
+        if (value == USB_DEVICE_REMOTE_WAKEUP) {
+            dev->remote_wakeup = 1;
+            ret = 0;
+        }
+        trace_usb_set_device_feature(dev->addr, value, ret);
+        break;
     }
     return ret;
 }
diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index 21c0c72..1c35960 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -673,28 +673,6 @@ static int usb_hid_handle_control(USBDevice *dev, int request, int value,
 
     ret = 0;
     switch(request) {
-    case DeviceRequest | USB_REQ_GET_STATUS:
-        data[0] = (1 << USB_DEVICE_SELF_POWERED) |
-            (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
-        data[1] = 0x00;
-        ret = 2;
-        break;
-    case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
-        if (value == USB_DEVICE_REMOTE_WAKEUP) {
-            dev->remote_wakeup = 0;
-        } else {
-            goto fail;
-        }
-        ret = 0;
-        break;
-    case DeviceOutRequest | USB_REQ_SET_FEATURE:
-        if (value == USB_DEVICE_REMOTE_WAKEUP) {
-            dev->remote_wakeup = 1;
-        } else {
-            goto fail;
-        }
-        ret = 0;
-        break;
     case DeviceRequest | USB_REQ_GET_INTERFACE:
         data[0] = 0;
         ret = 1;
diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index fc0b94b..3c7c3ee 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -269,34 +269,12 @@ static int usb_hub_handle_control(USBDevice *dev, int request, int value,
     }
 
     switch(request) {
-    case DeviceRequest | USB_REQ_GET_STATUS:
-        data[0] = (1 << USB_DEVICE_SELF_POWERED) |
-            (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
-        data[1] = 0x00;
-        ret = 2;
-        break;
-    case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
-        if (value == USB_DEVICE_REMOTE_WAKEUP) {
-            dev->remote_wakeup = 0;
-        } else {
-            goto fail;
-        }
-        ret = 0;
-        break;
     case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
         if (value == 0 && index != 0x81) { /* clear ep halt */
             goto fail;
         }
         ret = 0;
         break;
-    case DeviceOutRequest | USB_REQ_SET_FEATURE:
-        if (value == USB_DEVICE_REMOTE_WAKEUP) {
-            dev->remote_wakeup = 1;
-        } else {
-            goto fail;
-        }
-        ret = 0;
-        break;
     case DeviceRequest | USB_REQ_GET_INTERFACE:
         data[0] = 0;
         ret = 1;
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 56c6f3d..74e657e 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -239,28 +239,6 @@ static int usb_msd_handle_control(USBDevice *dev, int request, int value,
 
     ret = 0;
     switch (request) {
-    case DeviceRequest | USB_REQ_GET_STATUS:
-        data[0] = (1 << USB_DEVICE_SELF_POWERED) |
-            (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
-        data[1] = 0x00;
-        ret = 2;
-        break;
-    case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
-        if (value == USB_DEVICE_REMOTE_WAKEUP) {
-            dev->remote_wakeup = 0;
-        } else {
-            goto fail;
-        }
-        ret = 0;
-        break;
-    case DeviceOutRequest | USB_REQ_SET_FEATURE:
-        if (value == USB_DEVICE_REMOTE_WAKEUP) {
-            dev->remote_wakeup = 1;
-        } else {
-            goto fail;
-        }
-        ret = 0;
-        break;
     case DeviceRequest | USB_REQ_GET_INTERFACE:
         data[0] = 0;
         ret = 1;
@@ -285,7 +263,6 @@ static int usb_msd_handle_control(USBDevice *dev, int request, int value,
         ret = 1;
         break;
     default:
-    fail:
         ret = USB_RET_STALL;
         break;
     }
diff --git a/hw/usb-net.c b/hw/usb-net.c
index f123045..bf51bb3 100644
--- a/hw/usb-net.c
+++ b/hw/usb-net.c
@@ -1055,31 +1055,6 @@ static int usb_net_handle_control(USBDevice *dev, int request, int value,
 
     ret = 0;
     switch(request) {
-    case DeviceRequest | USB_REQ_GET_STATUS:
-        data[0] = (1 << USB_DEVICE_SELF_POWERED) |
-                (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
-        data[1] = 0x00;
-        ret = 2;
-        break;
-
-    case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
-        if (value == USB_DEVICE_REMOTE_WAKEUP) {
-            dev->remote_wakeup = 0;
-        } else {
-            goto fail;
-        }
-        ret = 0;
-        break;
-
-    case DeviceOutRequest | USB_REQ_SET_FEATURE:
-        if (value == USB_DEVICE_REMOTE_WAKEUP) {
-            dev->remote_wakeup = 1;
-        } else {
-            goto fail;
-        }
-        ret = 0;
-        break;
-
     case ClassInterfaceOutRequest | USB_CDC_SEND_ENCAPSULATED_COMMAND:
         if (!is_rndis(s) || value || index != 0) {
             goto fail;
diff --git a/hw/usb-serial.c b/hw/usb-serial.c
index 2bdb10b..6763d52 100644
--- a/hw/usb-serial.c
+++ b/hw/usb-serial.c
@@ -232,28 +232,6 @@ static int usb_serial_handle_control(USBDevice *dev, int request, int value,
 
     ret = 0;
     switch (request) {
-    case DeviceRequest | USB_REQ_GET_STATUS:
-        data[0] = (0 << USB_DEVICE_SELF_POWERED) |
-            (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
-        data[1] = 0x00;
-        ret = 2;
-        break;
-    case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
-        if (value == USB_DEVICE_REMOTE_WAKEUP) {
-            dev->remote_wakeup = 0;
-        } else {
-            goto fail;
-        }
-        ret = 0;
-        break;
-    case DeviceOutRequest | USB_REQ_SET_FEATURE:
-        if (value == USB_DEVICE_REMOTE_WAKEUP) {
-            dev->remote_wakeup = 1;
-        } else {
-            goto fail;
-        }
-        ret = 0;
-        break;
     case DeviceRequest | USB_REQ_GET_INTERFACE:
         data[0] = 0;
         ret = 1;
diff --git a/hw/usb-wacom.c b/hw/usb-wacom.c
index 3a98e80..16be7a2 100644
--- a/hw/usb-wacom.c
+++ b/hw/usb-wacom.c
@@ -262,28 +262,6 @@ static int usb_wacom_handle_control(USBDevice *dev, int request, int value,
 
     ret = 0;
     switch (request) {
-    case DeviceRequest | USB_REQ_GET_STATUS:
-        data[0] = (1 << USB_DEVICE_SELF_POWERED) |
-            (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
-        data[1] = 0x00;
-        ret = 2;
-        break;
-    case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
-        if (value == USB_DEVICE_REMOTE_WAKEUP) {
-            dev->remote_wakeup = 0;
-        } else {
-            goto fail;
-        }
-        ret = 0;
-        break;
-    case DeviceOutRequest | USB_REQ_SET_FEATURE:
-        if (value == USB_DEVICE_REMOTE_WAKEUP) {
-            dev->remote_wakeup = 1;
-        } else {
-            goto fail;
-        }
-        ret = 0;
-        break;
     case DeviceRequest | USB_REQ_GET_INTERFACE:
         data[0] = 0;
         ret = 1;
@@ -320,7 +298,6 @@ static int usb_wacom_handle_control(USBDevice *dev, int request, int value,
         ret = 0;
         break;
     default:
-    fail:
         ret = USB_RET_STALL;
         break;
     }
diff --git a/trace-events b/trace-events
index 9ef8474..45e7582 100644
--- a/trace-events
+++ b/trace-events
@@ -196,6 +196,8 @@ disable usb_desc_config(int addr, int index, int len, int ret) "dev %d query con
 disable usb_desc_string(int addr, int index, int len, int ret) "dev %d query string %d, len %d, ret %d"
 disable usb_set_addr(int addr) "dev %d"
 disable usb_set_config(int addr, int config, int ret) "dev %d, config %d, ret %d"
+disable usb_clear_device_feature(int addr, int feature, int ret) "dev %d, feature %d, ret %d"
+disable usb_set_device_feature(int addr, int feature, int ret) "dev %d, feature %d, ret %d"
 
 # vl.c
 disable vm_state_notify(int running, int reason) "running %d reason %d"
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v4 15/32] usb: create USBPortOps, move attach there.
  2011-01-12 11:19 [Qemu-devel] [PATCH v4 00/32] usb descriptor overhaul + more Gerd Hoffmann
                   ` (13 preceding siblings ...)
  2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 14/32] usb: move remote wakeup " Gerd Hoffmann
@ 2011-01-12 11:19 ` Gerd Hoffmann
  2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 16/32] usb: rework attach/detach workflow Gerd Hoffmann
                   ` (17 subsequent siblings)
  32 siblings, 0 replies; 37+ messages in thread
From: Gerd Hoffmann @ 2011-01-12 11:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Create USBPortOps struct, move the attach function to that struct.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb-bus.c  |    6 ++++--
 hw/usb-hub.c  |    6 +++++-
 hw/usb-musb.c |    6 +++++-
 hw/usb-ohci.c |    6 +++++-
 hw/usb-uhci.c |    6 +++++-
 hw/usb.c      |    2 +-
 hw/usb.h      |    8 +++++---
 7 files changed, 30 insertions(+), 10 deletions(-)

diff --git a/hw/usb-bus.c b/hw/usb-bus.c
index af537c2..9dc8793 100644
--- a/hw/usb-bus.c
+++ b/hw/usb-bus.c
@@ -113,12 +113,14 @@ USBDevice *usb_create_simple(USBBus *bus, const char *name)
 }
 
 void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
-                       USBDevice *pdev, usb_attachfn attach)
+                       USBDevice *pdev, USBPortOps *ops)
 {
     port->opaque = opaque;
     port->index = index;
-    port->attach = attach;
     port->pdev = pdev;
+    port->opaque = opaque;
+    port->index = index;
+    port->ops = ops;
     QTAILQ_INSERT_TAIL(&bus->free, port, next);
     bus->nfree++;
 }
diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index 3c7c3ee..b3d7298 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -506,6 +506,10 @@ static void usb_hub_handle_destroy(USBDevice *dev)
     }
 }
 
+static USBPortOps usb_hub_port_ops = {
+    .attach = usb_hub_attach,
+};
+
 static int usb_hub_initfn(USBDevice *dev)
 {
     USBHubState *s = DO_UPCAST(USBHubState, dev, dev);
@@ -516,7 +520,7 @@ static int usb_hub_initfn(USBDevice *dev)
     for (i = 0; i < NUM_PORTS; i++) {
         port = &s->ports[i];
         usb_register_port(usb_bus_from_device(dev),
-                          &port->port, s, i, &s->dev, usb_hub_attach);
+                          &port->port, s, i, &s->dev, &usb_hub_port_ops);
         port->wPortStatus = PORT_STAT_POWER;
         port->wPortChange = 0;
     }
diff --git a/hw/usb-musb.c b/hw/usb-musb.c
index 9efe7a6..592d3e6 100644
--- a/hw/usb-musb.c
+++ b/hw/usb-musb.c
@@ -261,6 +261,10 @@
 
 static void musb_attach(USBPort *port, USBDevice *dev);
 
+static USBPortOps musb_port_ops = {
+    .attach = musb_attach,
+};
+
 typedef struct {
     uint16_t faddr[2];
     uint8_t haddr[2];
@@ -343,7 +347,7 @@ struct MUSBState {
     }
 
     usb_bus_new(&s->bus, NULL /* FIXME */);
-    usb_register_port(&s->bus, &s->port, s, 0, NULL, musb_attach);
+    usb_register_port(&s->bus, &s->port, s, 0, NULL, &musb_port_ops);
 
     return s;
 }
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index 240e840..7b13bdd 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -1669,6 +1669,10 @@ static CPUWriteMemoryFunc * const ohci_writefn[3]={
     ohci_mem_write
 };
 
+static USBPortOps ohci_port_ops = {
+    .attach = ohci_attach,
+};
+
 static void usb_ohci_init(OHCIState *ohci, DeviceState *dev,
                           int num_ports, uint32_t localmem_base)
 {
@@ -1699,7 +1703,7 @@ static void usb_ohci_init(OHCIState *ohci, DeviceState *dev,
     usb_bus_new(&ohci->bus, dev);
     ohci->num_ports = num_ports;
     for (i = 0; i < num_ports; i++) {
-        usb_register_port(&ohci->bus, &ohci->rhport[i].port, ohci, i, NULL, ohci_attach);
+        usb_register_port(&ohci->bus, &ohci->rhport[i].port, ohci, i, NULL, &ohci_port_ops);
     }
 
     ohci->async_td = 0;
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index b9b822f..0f9ef1e 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -1101,6 +1101,10 @@ static void uhci_map(PCIDevice *pci_dev, int region_num,
     register_ioport_read(addr, 32, 1, uhci_ioport_readb, s);
 }
 
+static USBPortOps uhci_port_ops = {
+    .attach = uhci_attach,
+};
+
 static int usb_uhci_common_initfn(UHCIState *s)
 {
     uint8_t *pci_conf = s->dev.config;
@@ -1115,7 +1119,7 @@ static int usb_uhci_common_initfn(UHCIState *s)
 
     usb_bus_new(&s->bus, &s->dev.qdev);
     for(i = 0; i < NB_PORTS; i++) {
-        usb_register_port(&s->bus, &s->ports[i].port, s, i, NULL, uhci_attach);
+        usb_register_port(&s->bus, &s->ports[i].port, s, i, NULL, &uhci_port_ops);
     }
     s->frame_timer = qemu_new_timer(vm_clock, uhci_frame_timer, s);
     s->expire_time = qemu_get_clock(vm_clock) +
diff --git a/hw/usb.c b/hw/usb.c
index a326bcf..39d29f3 100644
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -28,7 +28,7 @@
 
 void usb_attach(USBPort *port, USBDevice *dev)
 {
-    port->attach(port, dev);
+    port->ops->attach(port, dev);
 }
 
 /**********************/
diff --git a/hw/usb.h b/hw/usb.h
index 966d47e..218788f 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -216,12 +216,14 @@ struct USBDeviceInfo {
     USBDevice *(*usbdevice_init)(const char *params);
 };
 
-typedef void (*usb_attachfn)(USBPort *port, USBDevice *dev);
+typedef struct USBPortOps {
+    void (*attach)(USBPort *port, USBDevice *dev);
+} USBPortOps;
 
 /* USB port on which a device can be connected */
 struct USBPort {
     USBDevice *dev;
-    usb_attachfn attach;
+    USBPortOps *ops;
     void *opaque;
     USBDevice *pdev;
     int index; /* internal port index, may be used with the opaque */
@@ -333,7 +335,7 @@ USBDevice *usb_create(USBBus *bus, const char *name);
 USBDevice *usb_create_simple(USBBus *bus, const char *name);
 USBDevice *usbdevice_create(const char *cmdline);
 void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
-                       USBDevice *pdev, usb_attachfn attach);
+                       USBDevice *pdev, USBPortOps *ops);
 void usb_unregister_port(USBBus *bus, USBPort *port);
 int usb_device_attach(USBDevice *dev);
 int usb_device_detach(USBDevice *dev);
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v4 16/32] usb: rework attach/detach workflow
  2011-01-12 11:19 [Qemu-devel] [PATCH v4 00/32] usb descriptor overhaul + more Gerd Hoffmann
                   ` (14 preceding siblings ...)
  2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 15/32] usb: create USBPortOps, move attach there Gerd Hoffmann
@ 2011-01-12 11:19 ` Gerd Hoffmann
  2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 17/32] usb: add usb_wakeup() + wakeup callback to port ops Gerd Hoffmann
                   ` (16 subsequent siblings)
  32 siblings, 0 replies; 37+ messages in thread
From: Gerd Hoffmann @ 2011-01-12 11:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Add separate detach callback to USBPortOps, split
uhci/ohci/musb/usbhub attach functions into two.

Move common code to the usb_attach() function, only
the hardware-specific bits remain in the attach/detach
callbacks.

Keep track of the port it is attached to for each usb device.

[ v3: fix tyops in usb-musb.c ]

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb-hub.c  |   46 ++++++++++++++------------------
 hw/usb-musb.c |   36 ++++++++-----------------
 hw/usb-ohci.c |   80 +++++++++++++++++++++++++++------------------------------
 hw/usb-uhci.c |   69 +++++++++++++++++++++---------------------------
 hw/usb.c      |   20 +++++++++++++-
 hw/usb.h      |    4 ++-
 6 files changed, 122 insertions(+), 133 deletions(-)

diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index b3d7298..8837bd9 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -218,37 +218,30 @@ static const uint8_t qemu_hub_hub_descriptor[] =
         /* DeviceRemovable and PortPwrCtrlMask patched in later */
 };
 
-static void usb_hub_attach(USBPort *port1, USBDevice *dev)
+static void usb_hub_attach(USBPort *port1)
 {
     USBHubState *s = port1->opaque;
     USBHubPort *port = &s->ports[port1->index];
 
-    if (dev) {
-        if (port->port.dev)
-            usb_attach(port1, NULL);
-
-        port->wPortStatus |= PORT_STAT_CONNECTION;
-        port->wPortChange |= PORT_STAT_C_CONNECTION;
-        if (dev->speed == USB_SPEED_LOW)
-            port->wPortStatus |= PORT_STAT_LOW_SPEED;
-        else
-            port->wPortStatus &= ~PORT_STAT_LOW_SPEED;
-        port->port.dev = dev;
-        /* send the attach message */
-        usb_send_msg(dev, USB_MSG_ATTACH);
+    port->wPortStatus |= PORT_STAT_CONNECTION;
+    port->wPortChange |= PORT_STAT_C_CONNECTION;
+    if (port->port.dev->speed == USB_SPEED_LOW) {
+        port->wPortStatus |= PORT_STAT_LOW_SPEED;
     } else {
-        dev = port->port.dev;
-        if (dev) {
-            port->wPortStatus &= ~PORT_STAT_CONNECTION;
-            port->wPortChange |= PORT_STAT_C_CONNECTION;
-            if (port->wPortStatus & PORT_STAT_ENABLE) {
-                port->wPortStatus &= ~PORT_STAT_ENABLE;
-                port->wPortChange |= PORT_STAT_C_ENABLE;
-            }
-            /* send the detach message */
-            usb_send_msg(dev, USB_MSG_DETACH);
-            port->port.dev = NULL;
-        }
+        port->wPortStatus &= ~PORT_STAT_LOW_SPEED;
+    }
+}
+
+static void usb_hub_detach(USBPort *port1)
+{
+    USBHubState *s = port1->opaque;
+    USBHubPort *port = &s->ports[port1->index];
+
+    port->wPortStatus &= ~PORT_STAT_CONNECTION;
+    port->wPortChange |= PORT_STAT_C_CONNECTION;
+    if (port->wPortStatus & PORT_STAT_ENABLE) {
+        port->wPortStatus &= ~PORT_STAT_ENABLE;
+        port->wPortChange |= PORT_STAT_C_ENABLE;
     }
 }
 
@@ -508,6 +501,7 @@ static void usb_hub_handle_destroy(USBDevice *dev)
 
 static USBPortOps usb_hub_port_ops = {
     .attach = usb_hub_attach,
+    .detach = usb_hub_detach,
 };
 
 static int usb_hub_initfn(USBDevice *dev)
diff --git a/hw/usb-musb.c b/hw/usb-musb.c
index 592d3e6..233a265 100644
--- a/hw/usb-musb.c
+++ b/hw/usb-musb.c
@@ -259,10 +259,12 @@
 #endif
 
 
-static void musb_attach(USBPort *port, USBDevice *dev);
+static void musb_attach(USBPort *port);
+static void musb_detach(USBPort *port);
 
 static USBPortOps musb_port_ops = {
     .attach = musb_attach,
+    .detach = musb_detach,
 };
 
 typedef struct {
@@ -464,34 +466,20 @@ static void musb_session_update(MUSBState *s, int prev_dev, int prev_sess)
 }
 
 /* Attach or detach a device on our only port.  */
-static void musb_attach(USBPort *port, USBDevice *dev)
+static void musb_attach(USBPort *port)
 {
     MUSBState *s = (MUSBState *) port->opaque;
-    USBDevice *curr;
 
-    port = &s->port;
-    curr = port->dev;
-
-    if (dev) {
-        if (curr) {
-            usb_attach(port, NULL);
-            /* TODO: signal some interrupts */
-        }
-
-        musb_intr_set(s, musb_irq_vbus_request, 1);
-
-        /* Send the attach message to device */
-        usb_send_msg(dev, USB_MSG_ATTACH);
-    } else if (curr) {
-        /* Send the detach message */
-        usb_send_msg(curr, USB_MSG_DETACH);
-
-        musb_intr_set(s, musb_irq_disconnect, 1);
-    }
+    musb_intr_set(s, musb_irq_vbus_request, 1);
+    musb_session_update(s, 0, s->session);
+}
 
-    port->dev = dev;
+static void musb_detach(USBPort *port)
+{
+    MUSBState *s = (MUSBState *) port->opaque;
 
-    musb_session_update(s, !!curr, s->session);
+    musb_intr_set(s, musb_irq_disconnect, 1);
+    musb_session_update(s, 1, s->session);
 }
 
 static inline void musb_cb_tick0(void *opaque)
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index 7b13bdd..c859540 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -322,52 +322,46 @@ static inline void ohci_set_interrupt(OHCIState *ohci, uint32_t intr)
 }
 
 /* Attach or detach a device on a root hub port.  */
-static void ohci_attach(USBPort *port1, USBDevice *dev)
+static void ohci_attach(USBPort *port1)
 {
     OHCIState *s = port1->opaque;
     OHCIPort *port = &s->rhport[port1->index];
-    uint32_t old_state = port->ctrl;
 
-    if (dev) {
-        if (port->port.dev) {
-            usb_attach(port1, NULL);
-        }
-        /* set connect status */
-        port->ctrl |= OHCI_PORT_CCS | OHCI_PORT_CSC;
-
-        /* update speed */
-        if (dev->speed == USB_SPEED_LOW)
-            port->ctrl |= OHCI_PORT_LSDA;
-        else
-            port->ctrl &= ~OHCI_PORT_LSDA;
-        port->port.dev = dev;
-
-        /* notify of remote-wakeup */
-        if ((s->ctl & OHCI_CTL_HCFS) == OHCI_USB_SUSPEND)
-            ohci_set_interrupt(s, OHCI_INTR_RD);
-
-        /* send the attach message */
-        usb_send_msg(dev, USB_MSG_ATTACH);
-        DPRINTF("usb-ohci: Attached port %d\n", port1->index);
+    /* set connect status */
+    port->ctrl |= OHCI_PORT_CCS | OHCI_PORT_CSC;
+
+    /* update speed */
+    if (port->port.dev->speed == USB_SPEED_LOW) {
+        port->ctrl |= OHCI_PORT_LSDA;
     } else {
-        /* set connect status */
-        if (port->ctrl & OHCI_PORT_CCS) {
-            port->ctrl &= ~OHCI_PORT_CCS;
-            port->ctrl |= OHCI_PORT_CSC;
-        }
-        /* disable port */
-        if (port->ctrl & OHCI_PORT_PES) {
-            port->ctrl &= ~OHCI_PORT_PES;
-            port->ctrl |= OHCI_PORT_PESC;
-        }
-        dev = port->port.dev;
-        if (dev) {
-            /* send the detach message */
-            usb_send_msg(dev, USB_MSG_DETACH);
-        }
-        port->port.dev = NULL;
-        DPRINTF("usb-ohci: Detached port %d\n", port1->index);
+        port->ctrl &= ~OHCI_PORT_LSDA;
+    }
+
+    /* notify of remote-wakeup */
+    if ((s->ctl & OHCI_CTL_HCFS) == OHCI_USB_SUSPEND) {
+        ohci_set_interrupt(s, OHCI_INTR_RD);
+    }
+
+    DPRINTF("usb-ohci: Attached port %d\n", port1->index);
+}
+
+static void ohci_detach(USBPort *port1)
+{
+    OHCIState *s = port1->opaque;
+    OHCIPort *port = &s->rhport[port1->index];
+    uint32_t old_state = port->ctrl;
+
+    /* set connect status */
+    if (port->ctrl & OHCI_PORT_CCS) {
+        port->ctrl &= ~OHCI_PORT_CCS;
+        port->ctrl |= OHCI_PORT_CSC;
+    }
+    /* disable port */
+    if (port->ctrl & OHCI_PORT_PES) {
+        port->ctrl &= ~OHCI_PORT_PES;
+        port->ctrl |= OHCI_PORT_PESC;
     }
+    DPRINTF("usb-ohci: Detached port %d\n", port1->index);
 
     if (old_state != port->ctrl)
         ohci_set_interrupt(s, OHCI_INTR_RHSC);
@@ -413,8 +407,9 @@ static void ohci_reset(void *opaque)
       {
         port = &ohci->rhport[i];
         port->ctrl = 0;
-        if (port->port.dev)
-            ohci_attach(&port->port, port->port.dev);
+        if (port->port.dev) {
+            usb_attach(&port->port, port->port.dev);
+        }
       }
     if (ohci->async_td) {
         usb_cancel_packet(&ohci->usb_packet);
@@ -1671,6 +1666,7 @@ static CPUWriteMemoryFunc * const ohci_writefn[3]={
 
 static USBPortOps ohci_port_ops = {
     .attach = ohci_attach,
+    .detach = ohci_detach,
 };
 
 static void usb_ohci_init(OHCIState *ohci, DeviceState *dev,
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index 0f9ef1e..5e2e34a 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -307,8 +307,6 @@ static UHCIAsync *uhci_async_find_td(UHCIState *s, uint32_t addr, uint32_t token
     return match;
 }
 
-static void uhci_attach(USBPort *port1, USBDevice *dev);
-
 static void uhci_update_irq(UHCIState *s)
 {
     int level;
@@ -348,8 +346,9 @@ static void uhci_reset(void *opaque)
     for(i = 0; i < NB_PORTS; i++) {
         port = &s->ports[i];
         port->ctrl = 0x0080;
-        if (port->port.dev)
-            uhci_attach(&port->port, port->port.dev);
+        if (port->port.dev) {
+            usb_attach(&port->port, port->port.dev);
+        }
     }
 
     uhci_async_cancel_all(s);
@@ -593,50 +592,41 @@ static void uhci_resume (void *opaque)
     }
 }
 
-static void uhci_attach(USBPort *port1, USBDevice *dev)
+static void uhci_attach(USBPort *port1)
 {
     UHCIState *s = port1->opaque;
     UHCIPort *port = &s->ports[port1->index];
 
-    if (dev) {
-        if (port->port.dev) {
-            usb_attach(port1, NULL);
-        }
-        /* set connect status */
-        port->ctrl |= UHCI_PORT_CCS | UHCI_PORT_CSC;
+    /* set connect status */
+    port->ctrl |= UHCI_PORT_CCS | UHCI_PORT_CSC;
 
-        /* update speed */
-        if (dev->speed == USB_SPEED_LOW)
-            port->ctrl |= UHCI_PORT_LSDA;
-        else
-            port->ctrl &= ~UHCI_PORT_LSDA;
-
-        uhci_resume(s);
-
-        port->port.dev = dev;
-        /* send the attach message */
-        usb_send_msg(dev, USB_MSG_ATTACH);
+    /* update speed */
+    if (port->port.dev->speed == USB_SPEED_LOW) {
+        port->ctrl |= UHCI_PORT_LSDA;
     } else {
-        /* set connect status */
-        if (port->ctrl & UHCI_PORT_CCS) {
-            port->ctrl &= ~UHCI_PORT_CCS;
-            port->ctrl |= UHCI_PORT_CSC;
-        }
-        /* disable port */
-        if (port->ctrl & UHCI_PORT_EN) {
-            port->ctrl &= ~UHCI_PORT_EN;
-            port->ctrl |= UHCI_PORT_ENC;
-        }
+        port->ctrl &= ~UHCI_PORT_LSDA;
+    }
 
-        uhci_resume(s);
+    uhci_resume(s);
+}
 
-        dev = port->port.dev;
-        if (dev) {
-            /* send the detach message */
-            usb_send_msg(dev, USB_MSG_DETACH);
-        }
-        port->port.dev = NULL;
+static void uhci_detach(USBPort *port1)
+{
+    UHCIState *s = port1->opaque;
+    UHCIPort *port = &s->ports[port1->index];
+
+    /* set connect status */
+    if (port->ctrl & UHCI_PORT_CCS) {
+        port->ctrl &= ~UHCI_PORT_CCS;
+        port->ctrl |= UHCI_PORT_CSC;
     }
+    /* disable port */
+    if (port->ctrl & UHCI_PORT_EN) {
+        port->ctrl &= ~UHCI_PORT_EN;
+        port->ctrl |= UHCI_PORT_ENC;
+    }
+
+    uhci_resume(s);
 }
 
 static int uhci_broadcast_packet(UHCIState *s, USBPacket *p)
@@ -1103,6 +1093,7 @@ static void uhci_map(PCIDevice *pci_dev, int region_num,
 
 static USBPortOps uhci_port_ops = {
     .attach = uhci_attach,
+    .detach = uhci_detach,
 };
 
 static int usb_uhci_common_initfn(UHCIState *s)
diff --git a/hw/usb.c b/hw/usb.c
index 39d29f3..2eda86a 100644
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -28,7 +28,25 @@
 
 void usb_attach(USBPort *port, USBDevice *dev)
 {
-    port->ops->attach(port, dev);
+    if (dev != NULL) {
+        /* attach */
+        if (port->dev) {
+            usb_attach(port, NULL);
+        }
+        dev->port = port;
+        port->dev = dev;
+        port->ops->attach(port);
+        usb_send_msg(dev, USB_MSG_ATTACH);
+    } else {
+        /* detach */
+        dev = port->dev;
+        port->ops->detach(port);
+        if (dev) {
+            usb_send_msg(dev, USB_MSG_DETACH);
+            dev->port = NULL;
+            port->dev = NULL;
+        }
+    }
 }
 
 /**********************/
diff --git a/hw/usb.h b/hw/usb.h
index 218788f..3744d19 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -147,6 +147,7 @@ struct USBDescString {
 struct USBDevice {
     DeviceState qdev;
     USBDeviceInfo *info;
+    USBPort *port;
     void *opaque;
 
     int speed;
@@ -217,7 +218,8 @@ struct USBDeviceInfo {
 };
 
 typedef struct USBPortOps {
-    void (*attach)(USBPort *port, USBDevice *dev);
+    void (*attach)(USBPort *port);
+    void (*detach)(USBPort *port);
 } USBPortOps;
 
 /* USB port on which a device can be connected */
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v4 17/32] usb: add usb_wakeup() + wakeup callback to port ops
  2011-01-12 11:19 [Qemu-devel] [PATCH v4 00/32] usb descriptor overhaul + more Gerd Hoffmann
                   ` (15 preceding siblings ...)
  2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 16/32] usb: rework attach/detach workflow Gerd Hoffmann
@ 2011-01-12 11:19 ` Gerd Hoffmann
  2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 18/32] usb: uhci: remote wakeup support Gerd Hoffmann
                   ` (15 subsequent siblings)
  32 siblings, 0 replies; 37+ messages in thread
From: Gerd Hoffmann @ 2011-01-12 11:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Add wakeup callback to port ops for remote wakeup handling.
Also add a usb_wakeup() function for devices which want
trigger a remote wakeup.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb.c |    7 +++++++
 hw/usb.h |    2 ++
 2 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/hw/usb.c b/hw/usb.c
index 2eda86a..ba720b4 100644
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -49,6 +49,13 @@ void usb_attach(USBPort *port, USBDevice *dev)
     }
 }
 
+void usb_wakeup(USBDevice *dev)
+{
+    if (dev->remote_wakeup && dev->port && dev->port->ops->wakeup) {
+        dev->port->ops->wakeup(dev);
+    }
+}
+
 /**********************/
 
 /* generic USB device helpers (you are not forced to use them when
diff --git a/hw/usb.h b/hw/usb.h
index 3744d19..250ec71 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -220,6 +220,7 @@ struct USBDeviceInfo {
 typedef struct USBPortOps {
     void (*attach)(USBPort *port);
     void (*detach)(USBPort *port);
+    void (*wakeup)(USBDevice *dev);
 } USBPortOps;
 
 /* USB port on which a device can be connected */
@@ -275,6 +276,7 @@ static inline void usb_cancel_packet(USBPacket * p)
 }
 
 void usb_attach(USBPort *port, USBDevice *dev);
+void usb_wakeup(USBDevice *dev);
 int usb_generic_handle_packet(USBDevice *s, USBPacket *p);
 int set_usb_string(uint8_t *buf, const char *str);
 void usb_send_msg(USBDevice *dev, int msg);
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v4 18/32] usb: uhci: remote wakeup support.
  2011-01-12 11:19 [Qemu-devel] [PATCH v4 00/32] usb descriptor overhaul + more Gerd Hoffmann
                   ` (16 preceding siblings ...)
  2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 17/32] usb: add usb_wakeup() + wakeup callback to port ops Gerd Hoffmann
@ 2011-01-12 11:20 ` Gerd Hoffmann
  2011-01-12 12:25   ` Stefan Hajnoczi
  2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 19/32] usb: hub: " Gerd Hoffmann
                   ` (14 subsequent siblings)
  32 siblings, 1 reply; 37+ messages in thread
From: Gerd Hoffmann @ 2011-01-12 11:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Add support for remote wakeup to the UHCI adapter.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb-uhci.c |   23 +++++++++++++++++++++--
 1 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index 5e2e34a..2d2a9e7 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -57,13 +57,18 @@
 #define TD_CTRL_NAK     (1 << 19)
 #define TD_CTRL_TIMEOUT (1 << 18)
 
+#define UHCI_PORT_SUSPEND (1 << 12)
 #define UHCI_PORT_RESET (1 << 9)
 #define UHCI_PORT_LSDA  (1 << 8)
+#define UHCI_PORT_RD    (1 << 6)
 #define UHCI_PORT_ENC   (1 << 3)
 #define UHCI_PORT_EN    (1 << 2)
 #define UHCI_PORT_CSC   (1 << 1)
 #define UHCI_PORT_CCS   (1 << 0)
 
+#define UHCI_PORT_READ_ONLY    (0x1bb)
+#define UHCI_PORT_WRITE_CLEAR  (UHCI_PORT_CSC | UHCI_PORT_ENC)
+
 #define FRAME_TIMER_FREQ 1000
 
 #define FRAME_MAX_LOOPS  100
@@ -497,9 +502,10 @@ static void uhci_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
                     usb_send_msg(dev, USB_MSG_RESET);
                 }
             }
-            port->ctrl = (port->ctrl & 0x01fb) | (val & ~0x01fb);
+            port->ctrl &= UHCI_PORT_READ_ONLY;
+            port->ctrl |= (val & ~UHCI_PORT_READ_ONLY);
             /* some bits are reset when a '1' is written to them */
-            port->ctrl &= ~(val & 0x000a);
+            port->ctrl &= ~(val & UHCI_PORT_WRITE_CLEAR);
         }
         break;
     }
@@ -629,6 +635,18 @@ static void uhci_detach(USBPort *port1)
     uhci_resume(s);
 }
 
+static void uhci_wakeup(USBDevice *dev)
+{
+    USBBus *bus = usb_bus_from_device(dev);
+    UHCIState *s = container_of(bus, UHCIState, bus);
+    UHCIPort *port = s->ports + dev->port->index;
+
+    if (port->ctrl & UHCI_PORT_SUSPEND && !(port->ctrl & UHCI_PORT_RD)) {
+        port->ctrl |= UHCI_PORT_RD;
+        uhci_resume(s);
+    }
+}
+
 static int uhci_broadcast_packet(UHCIState *s, USBPacket *p)
 {
     int i, ret;
@@ -1094,6 +1112,7 @@ static void uhci_map(PCIDevice *pci_dev, int region_num,
 static USBPortOps uhci_port_ops = {
     .attach = uhci_attach,
     .detach = uhci_detach,
+    .wakeup = uhci_wakeup,
 };
 
 static int usb_uhci_common_initfn(UHCIState *s)
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v4 19/32] usb: hub: remote wakeup support.
  2011-01-12 11:19 [Qemu-devel] [PATCH v4 00/32] usb descriptor overhaul + more Gerd Hoffmann
                   ` (17 preceding siblings ...)
  2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 18/32] usb: uhci: remote wakeup support Gerd Hoffmann
@ 2011-01-12 11:20 ` Gerd Hoffmann
  2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 20/32] usb: hid: " Gerd Hoffmann
                   ` (13 subsequent siblings)
  32 siblings, 0 replies; 37+ messages in thread
From: Gerd Hoffmann @ 2011-01-12 11:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

This patch makes the usb hub handle remote wakeup requests from devices
properly by updating the port status register and forwarding the wakeup
to the upstream port.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb-hub.c |   12 ++++++++++++
 1 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index 8837bd9..8a80151 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -245,6 +245,17 @@ static void usb_hub_detach(USBPort *port1)
     }
 }
 
+static void usb_hub_wakeup(USBDevice *dev)
+{
+    USBHubState *s = dev->port->opaque;
+    USBHubPort *port = &s->ports[dev->port->index];
+
+    if (port->wPortStatus & PORT_STAT_SUSPEND) {
+        port->wPortChange |= PORT_STAT_C_SUSPEND;
+        usb_wakeup(&s->dev);
+    }
+}
+
 static void usb_hub_handle_reset(USBDevice *dev)
 {
     /* XXX: do it */
@@ -502,6 +513,7 @@ static void usb_hub_handle_destroy(USBDevice *dev)
 static USBPortOps usb_hub_port_ops = {
     .attach = usb_hub_attach,
     .detach = usb_hub_detach,
+    .wakeup = usb_hub_wakeup,
 };
 
 static int usb_hub_initfn(USBDevice *dev)
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v4 20/32] usb: hid: remote wakeup support.
  2011-01-12 11:19 [Qemu-devel] [PATCH v4 00/32] usb descriptor overhaul + more Gerd Hoffmann
                   ` (18 preceding siblings ...)
  2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 19/32] usb: hub: " Gerd Hoffmann
@ 2011-01-12 11:20 ` Gerd Hoffmann
  2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 21/32] usb: hid: change serial number to "42" Gerd Hoffmann
                   ` (12 subsequent siblings)
  32 siblings, 0 replies; 37+ messages in thread
From: Gerd Hoffmann @ 2011-01-12 11:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Add usb_wakeup() call to the hid driver so remote wakeup actually works.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb-hid.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index 1c35960..60fa57f 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -429,6 +429,8 @@ static void usb_hid_changed(USBHIDState *hs)
 
     if (hs->datain)
         hs->datain(hs->datain_opaque);
+
+    usb_wakeup(&hs->dev);
 }
 
 static void usb_mouse_event(void *opaque,
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v4 21/32] usb: hid: change serial number to "42".
  2011-01-12 11:19 [Qemu-devel] [PATCH v4 00/32] usb descriptor overhaul + more Gerd Hoffmann
                   ` (19 preceding siblings ...)
  2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 20/32] usb: hid: " Gerd Hoffmann
@ 2011-01-12 11:20 ` Gerd Hoffmann
  2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 22/32] usb: add speed mask to ports Gerd Hoffmann
                   ` (11 subsequent siblings)
  32 siblings, 0 replies; 37+ messages in thread
From: Gerd Hoffmann @ 2011-01-12 11:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

It would be nice to have some way to signal our hid devices support
remote wakeup.  There is a descriptor bit for that of course.  Problem
with using is one is that older qemu versions used to set the bit even
though they did *not* support remote wakeup.  Bummer.

This patch changes the serial number of our hid devices from "1" to "42"
to signal "it is safe to enable remote wakeup".  The serial number was
choosen because it isn't used for anything and it is available in sysfs
so it is easy to match it using udev rules like this:

ACTION=="add", SUBSYSTEM=="usb", \
	ATTR{product}=="QEMU USB Tablet", ATTR{serial}=="42", \
	RUN+="usb_enable_autosuspend %p"

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb-hid.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index 60fa57f..1fec163 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -90,7 +90,7 @@ static const USBDescStrings desc_strings = {
     [STR_PRODUCT_MOUSE]    = "QEMU USB Mouse",
     [STR_PRODUCT_TABLET]   = "QEMU USB Tablet",
     [STR_PRODUCT_KEYBOARD] = "QEMU USB Keyboard",
-    [STR_SERIALNUMBER]     = "1",
+    [STR_SERIALNUMBER]     = "42", /* == remote wakeup works */
     [STR_CONFIG_MOUSE]     = "HID Mouse",
     [STR_CONFIG_TABLET]    = "HID Tablet",
     [STR_CONFIG_KEYBOARD]  = "HID Keyboard",
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v4 22/32] usb: add speed mask to ports
  2011-01-12 11:19 [Qemu-devel] [PATCH v4 00/32] usb descriptor overhaul + more Gerd Hoffmann
                   ` (20 preceding siblings ...)
  2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 21/32] usb: hid: change serial number to "42" Gerd Hoffmann
@ 2011-01-12 11:20 ` Gerd Hoffmann
  2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 23/32] usb: add attach callback Gerd Hoffmann
                   ` (10 subsequent siblings)
  32 siblings, 0 replies; 37+ messages in thread
From: Gerd Hoffmann @ 2011-01-12 11:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Add a field to usb ports indicating the speed(s) they are
able to handle.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb-bus.c  |    3 ++-
 hw/usb-hub.c  |    3 ++-
 hw/usb-musb.c |    3 ++-
 hw/usb-ohci.c |    3 ++-
 hw/usb-uhci.c |    3 ++-
 hw/usb.h      |    9 ++++++++-
 6 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/hw/usb-bus.c b/hw/usb-bus.c
index 9dc8793..e94b88d 100644
--- a/hw/usb-bus.c
+++ b/hw/usb-bus.c
@@ -113,7 +113,7 @@ USBDevice *usb_create_simple(USBBus *bus, const char *name)
 }
 
 void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
-                       USBDevice *pdev, USBPortOps *ops)
+                       USBDevice *pdev, USBPortOps *ops, int speedmask)
 {
     port->opaque = opaque;
     port->index = index;
@@ -121,6 +121,7 @@ void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
     port->opaque = opaque;
     port->index = index;
     port->ops = ops;
+    port->speedmask = speedmask;
     QTAILQ_INSERT_TAIL(&bus->free, port, next);
     bus->nfree++;
 }
diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index 8a80151..ba712d6 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -526,7 +526,8 @@ static int usb_hub_initfn(USBDevice *dev)
     for (i = 0; i < NUM_PORTS; i++) {
         port = &s->ports[i];
         usb_register_port(usb_bus_from_device(dev),
-                          &port->port, s, i, &s->dev, &usb_hub_port_ops);
+                          &port->port, s, i, &s->dev, &usb_hub_port_ops,
+                          USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
         port->wPortStatus = PORT_STAT_POWER;
         port->wPortChange = 0;
     }
diff --git a/hw/usb-musb.c b/hw/usb-musb.c
index 233a265..87eb9ca 100644
--- a/hw/usb-musb.c
+++ b/hw/usb-musb.c
@@ -349,7 +349,8 @@ struct MUSBState {
     }
 
     usb_bus_new(&s->bus, NULL /* FIXME */);
-    usb_register_port(&s->bus, &s->port, s, 0, NULL, &musb_port_ops);
+    usb_register_port(&s->bus, &s->port, s, 0, NULL, &musb_port_ops,
+                      USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
 
     return s;
 }
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index c859540..0d42716 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -1699,7 +1699,8 @@ static void usb_ohci_init(OHCIState *ohci, DeviceState *dev,
     usb_bus_new(&ohci->bus, dev);
     ohci->num_ports = num_ports;
     for (i = 0; i < num_ports; i++) {
-        usb_register_port(&ohci->bus, &ohci->rhport[i].port, ohci, i, NULL, &ohci_port_ops);
+        usb_register_port(&ohci->bus, &ohci->rhport[i].port, ohci, i, NULL, &ohci_port_ops,
+                          USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
     }
 
     ohci->async_td = 0;
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index 2d2a9e7..253561f 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -1129,7 +1129,8 @@ static int usb_uhci_common_initfn(UHCIState *s)
 
     usb_bus_new(&s->bus, &s->dev.qdev);
     for(i = 0; i < NB_PORTS; i++) {
-        usb_register_port(&s->bus, &s->ports[i].port, s, i, NULL, &uhci_port_ops);
+        usb_register_port(&s->bus, &s->ports[i].port, s, i, NULL, &uhci_port_ops,
+                          USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
     }
     s->frame_timer = qemu_new_timer(vm_clock, uhci_frame_timer, s);
     s->expire_time = qemu_get_clock(vm_clock) +
diff --git a/hw/usb.h b/hw/usb.h
index 250ec71..407a114 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -44,6 +44,12 @@
 #define USB_SPEED_LOW   0
 #define USB_SPEED_FULL  1
 #define USB_SPEED_HIGH  2
+#define USB_SPEED_SUPER 3
+
+#define USB_SPEED_MASK_LOW   (1 << USB_SPEED_LOW)
+#define USB_SPEED_MASK_FULL  (1 << USB_SPEED_FULL)
+#define USB_SPEED_MASK_HIGH  (1 << USB_SPEED_HIGH)
+#define USB_SPEED_MASK_SUPER (1 << USB_SPEED_SUPER)
 
 #define USB_STATE_NOTATTACHED 0
 #define USB_STATE_ATTACHED    1
@@ -226,6 +232,7 @@ typedef struct USBPortOps {
 /* USB port on which a device can be connected */
 struct USBPort {
     USBDevice *dev;
+    int speedmask;
     USBPortOps *ops;
     void *opaque;
     USBDevice *pdev;
@@ -339,7 +346,7 @@ USBDevice *usb_create(USBBus *bus, const char *name);
 USBDevice *usb_create_simple(USBBus *bus, const char *name);
 USBDevice *usbdevice_create(const char *cmdline);
 void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
-                       USBDevice *pdev, USBPortOps *ops);
+                       USBDevice *pdev, USBPortOps *ops, int speedmask);
 void usb_unregister_port(USBBus *bus, USBPort *port);
 int usb_device_attach(USBDevice *dev);
 int usb_device_detach(USBDevice *dev);
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v4 23/32] usb: add attach callback
  2011-01-12 11:19 [Qemu-devel] [PATCH v4 00/32] usb descriptor overhaul + more Gerd Hoffmann
                   ` (21 preceding siblings ...)
  2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 22/32] usb: add speed mask to ports Gerd Hoffmann
@ 2011-01-12 11:20 ` Gerd Hoffmann
  2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 24/32] usb: add usb_desc_attach Gerd Hoffmann
                   ` (9 subsequent siblings)
  32 siblings, 0 replies; 37+ messages in thread
From: Gerd Hoffmann @ 2011-01-12 11:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Add handle_attach() callback to USBDeviceInfo which is called by the
generic package handler when the device is attached to the usb bus
(i.e. plugged into a port).

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb.c |    7 ++++++-
 hw/usb.h |    5 +++++
 2 files changed, 11 insertions(+), 1 deletions(-)

diff --git a/hw/usb.c b/hw/usb.c
index ba720b4..82a6217 100644
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -194,6 +194,9 @@ int usb_generic_handle_packet(USBDevice *s, USBPacket *p)
     switch(p->pid) {
     case USB_MSG_ATTACH:
         s->state = USB_STATE_ATTACHED;
+        if (s->info->handle_attach) {
+            s->info->handle_attach(s);
+        }
         return 0;
 
     case USB_MSG_DETACH:
@@ -204,7 +207,9 @@ int usb_generic_handle_packet(USBDevice *s, USBPacket *p)
         s->remote_wakeup = 0;
         s->addr = 0;
         s->state = USB_STATE_DEFAULT;
-        s->info->handle_reset(s);
+        if (s->info->handle_reset) {
+            s->info->handle_reset(s);
+        }
         return 0;
     }
 
diff --git a/hw/usb.h b/hw/usb.h
index 407a114..892ff72 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -194,6 +194,11 @@ struct USBDeviceInfo {
     void (*handle_destroy)(USBDevice *dev);
 
     /*
+     * Attach the device
+     */
+    void (*handle_attach)(USBDevice *dev);
+
+    /*
      * Reset the device
      */
     void (*handle_reset)(USBDevice *dev);
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v4 24/32] usb: add usb_desc_attach
  2011-01-12 11:19 [Qemu-devel] [PATCH v4 00/32] usb descriptor overhaul + more Gerd Hoffmann
                   ` (22 preceding siblings ...)
  2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 23/32] usb: add attach callback Gerd Hoffmann
@ 2011-01-12 11:20 ` Gerd Hoffmann
  2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 25/32] usb: add device qualifier support Gerd Hoffmann
                   ` (8 subsequent siblings)
  32 siblings, 0 replies; 37+ messages in thread
From: Gerd Hoffmann @ 2011-01-12 11:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Add usb_desc_attach() which sets up the device according to the speed
the usb port is able to handle.  This function can be hooked into the
handle_attach callback.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb-desc.c |   36 +++++++++++++++++++++++++++++++++---
 hw/usb-desc.h |    1 +
 2 files changed, 34 insertions(+), 3 deletions(-)

diff --git a/hw/usb-desc.c b/hw/usb-desc.c
index 56ef734..f01e1cf 100644
--- a/hw/usb-desc.c
+++ b/hw/usb-desc.c
@@ -153,16 +153,46 @@ int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len)
 
 /* ------------------------------------------------------------------ */
 
-void usb_desc_init(USBDevice *dev)
+static void usb_desc_setdefaults(USBDevice *dev)
 {
     const USBDesc *desc = dev->info->usb_desc;
 
     assert(desc != NULL);
-    dev->speed  = USB_SPEED_FULL;
-    dev->device = desc->full;
+    switch (dev->speed) {
+    case USB_SPEED_LOW:
+    case USB_SPEED_FULL:
+        dev->device = desc->full;
+        break;
+    case USB_SPEED_HIGH:
+        dev->device = desc->high;
+        break;
+    }
     dev->config = dev->device->confs;
 }
 
+void usb_desc_init(USBDevice *dev)
+{
+    dev->speed = USB_SPEED_FULL;
+    usb_desc_setdefaults(dev);
+}
+
+void usb_desc_attach(USBDevice *dev)
+{
+    const USBDesc *desc = dev->info->usb_desc;
+
+    assert(desc != NULL);
+    if (desc->high && (dev->port->speedmask & USB_SPEED_MASK_HIGH)) {
+        dev->speed = USB_SPEED_HIGH;
+    } else if (desc->full && (dev->port->speedmask & USB_SPEED_MASK_FULL)) {
+        dev->speed = USB_SPEED_FULL;
+    } else {
+        fprintf(stderr, "usb: port/device speed mismatch for \"%s\"\n",
+                dev->info->product_desc);
+        return;
+    }
+    usb_desc_setdefaults(dev);
+}
+
 void usb_desc_set_string(USBDevice *dev, uint8_t index, const char *str)
 {
     USBDescString *s;
diff --git a/hw/usb-desc.h b/hw/usb-desc.h
index d441725..484c7c7 100644
--- a/hw/usb-desc.h
+++ b/hw/usb-desc.h
@@ -79,6 +79,7 @@ int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len);
 
 /* control message emulation helpers */
 void usb_desc_init(USBDevice *dev);
+void usb_desc_attach(USBDevice *dev);
 void usb_desc_set_string(USBDevice *dev, uint8_t index, const char *str);
 const char *usb_desc_get_string(USBDevice *dev, uint8_t index);
 int usb_desc_string(USBDevice *dev, int index, uint8_t *dest, size_t len);
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v4 25/32] usb: add device qualifier support
  2011-01-12 11:19 [Qemu-devel] [PATCH v4 00/32] usb descriptor overhaul + more Gerd Hoffmann
                   ` (23 preceding siblings ...)
  2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 24/32] usb: add usb_desc_attach Gerd Hoffmann
@ 2011-01-12 11:20 ` Gerd Hoffmann
  2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 26/32] usb storage: high speed support Gerd Hoffmann
                   ` (7 subsequent siblings)
  32 siblings, 0 replies; 37+ messages in thread
From: Gerd Hoffmann @ 2011-01-12 11:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Add support for device_qualifier and other_speed_config descriptors.
These are used to query the "other speed" configuration of usb 2.0
devices, i.e. in high-speed mode they return the full-speed
configuration and visa versa.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb-desc.c |   46 ++++++++++++++++++++++++++++++++++++++++++++++
 hw/usb-desc.h |    2 ++
 hw/usb.h      |    2 ++
 trace-events  |    2 ++
 4 files changed, 52 insertions(+), 0 deletions(-)

diff --git a/hw/usb-desc.c b/hw/usb-desc.c
index f01e1cf..62591f2 100644
--- a/hw/usb-desc.c
+++ b/hw/usb-desc.c
@@ -48,6 +48,30 @@ int usb_desc_device(const USBDescID *id, const USBDescDevice *dev,
     return bLength;
 }
 
+int usb_desc_device_qualifier(const USBDescDevice *dev,
+                              uint8_t *dest, size_t len)
+{
+    uint8_t bLength = 0x0a;
+
+    if (len < bLength) {
+        return -1;
+    }
+
+    dest[0x00] = bLength;
+    dest[0x01] = USB_DT_DEVICE_QUALIFIER;
+
+    dest[0x02] = usb_lo(dev->bcdUSB);
+    dest[0x03] = usb_hi(dev->bcdUSB);
+    dest[0x04] = dev->bDeviceClass;
+    dest[0x05] = dev->bDeviceSubClass;
+    dest[0x06] = dev->bDeviceProtocol;
+    dest[0x07] = dev->bMaxPacketSize0;
+    dest[0x08] = dev->bNumConfigurations;
+    dest[0x09] = 0; /* reserved */
+
+    return bLength;
+}
+
 int usb_desc_config(const USBDescConfig *conf, uint8_t *dest, size_t len)
 {
     uint8_t  bLength = 0x09;
@@ -263,11 +287,18 @@ int usb_desc_string(USBDevice *dev, int index, uint8_t *dest, size_t len)
 int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len)
 {
     const USBDesc *desc = dev->info->usb_desc;
+    const USBDescDevice *other_dev;
     uint8_t buf[256];
     uint8_t type = value >> 8;
     uint8_t index = value & 0xff;
     int ret = -1;
 
+    if (dev->speed == USB_SPEED_HIGH) {
+        other_dev = dev->info->usb_desc->full;
+    } else {
+        other_dev = dev->info->usb_desc->high;
+    }
+
     switch(type) {
     case USB_DT_DEVICE:
         ret = usb_desc_device(&desc->id, dev->device, buf, sizeof(buf));
@@ -283,6 +314,21 @@ int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len
         ret = usb_desc_string(dev, index, buf, sizeof(buf));
         trace_usb_desc_string(dev->addr, index, len, ret);
         break;
+
+    case USB_DT_DEVICE_QUALIFIER:
+        if (other_dev != NULL) {
+            ret = usb_desc_device_qualifier(other_dev, buf, sizeof(buf));
+        }
+        trace_usb_desc_device_qualifier(dev->addr, len, ret);
+        break;
+    case USB_DT_OTHER_SPEED_CONFIG:
+        if (other_dev != NULL && index < other_dev->bNumConfigurations) {
+            ret = usb_desc_config(other_dev->confs + index, buf, sizeof(buf));
+            buf[0x01] = USB_DT_OTHER_SPEED_CONFIG;
+        }
+        trace_usb_desc_other_speed_config(dev->addr, index, len, ret);
+        break;
+
     default:
         fprintf(stderr, "%s: %d unknown type %d (len %zd)\n", __FUNCTION__,
                 dev->addr, type, len);
diff --git a/hw/usb-desc.h b/hw/usb-desc.h
index 484c7c7..ac734ab 100644
--- a/hw/usb-desc.h
+++ b/hw/usb-desc.h
@@ -72,6 +72,8 @@ struct USBDesc {
 /* generate usb packages from structs */
 int usb_desc_device(const USBDescID *id, const USBDescDevice *dev,
                     uint8_t *dest, size_t len);
+int usb_desc_device_qualifier(const USBDescDevice *dev,
+                              uint8_t *dest, size_t len);
 int usb_desc_config(const USBDescConfig *conf, uint8_t *dest, size_t len);
 int usb_desc_iface(const USBDescIface *iface, uint8_t *dest, size_t len);
 int usb_desc_endpoint(const USBDescEndpoint *ep, uint8_t *dest, size_t len);
diff --git a/hw/usb.h b/hw/usb.h
index 892ff72..99139e2 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -122,6 +122,8 @@
 #define USB_DT_STRING			0x03
 #define USB_DT_INTERFACE		0x04
 #define USB_DT_ENDPOINT			0x05
+#define USB_DT_DEVICE_QUALIFIER         0x06
+#define USB_DT_OTHER_SPEED_CONFIG       0x07
 
 #define USB_ENDPOINT_XFER_CONTROL	0
 #define USB_ENDPOINT_XFER_ISOC		1
diff --git a/trace-events b/trace-events
index 45e7582..19cee6a 100644
--- a/trace-events
+++ b/trace-events
@@ -192,7 +192,9 @@ disable sun4m_iommu_bad_addr(uint64_t addr) "bad addr %"PRIx64""
 
 # hw/usb-desc.c
 disable usb_desc_device(int addr, int len, int ret) "dev %d query device, len %d, ret %d"
+disable usb_desc_device_qualifier(int addr, int len, int ret) "dev %d query device qualifier, len %d, ret %d"
 disable usb_desc_config(int addr, int index, int len, int ret) "dev %d query config %d, len %d, ret %d"
+disable usb_desc_other_speed_config(int addr, int index, int len, int ret) "dev %d query config %d, len %d, ret %d"
 disable usb_desc_string(int addr, int index, int len, int ret) "dev %d query string %d, len %d, ret %d"
 disable usb_set_addr(int addr) "dev %d"
 disable usb_set_config(int addr, int config, int ret) "dev %d, config %d, ret %d"
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v4 26/32] usb storage: high speed support
  2011-01-12 11:19 [Qemu-devel] [PATCH v4 00/32] usb descriptor overhaul + more Gerd Hoffmann
                   ` (24 preceding siblings ...)
  2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 25/32] usb: add device qualifier support Gerd Hoffmann
@ 2011-01-12 11:20 ` Gerd Hoffmann
  2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 27/32] usb storage: fix status reporting Gerd Hoffmann
                   ` (6 subsequent siblings)
  32 siblings, 0 replies; 37+ messages in thread
From: Gerd Hoffmann @ 2011-01-12 11:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Add high speed support to the usb mass storage device.  With this patch
applied the linux kernel recognises the usb storage device as highspeed
capable device and suggests to connect it to a highspeed port instead of
the uhci.  Tested with both uhci and (not-yet submitted) ehci.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb-msd.c |   51 ++++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 46 insertions(+), 5 deletions(-)

diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 74e657e..7b8189f 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -77,15 +77,19 @@ enum {
     STR_MANUFACTURER = 1,
     STR_PRODUCT,
     STR_SERIALNUMBER,
+    STR_CONFIG_FULL,
+    STR_CONFIG_HIGH,
 };
 
 static const USBDescStrings desc_strings = {
     [STR_MANUFACTURER] = "QEMU " QEMU_VERSION,
     [STR_PRODUCT]      = "QEMU USB HARDDRIVE",
     [STR_SERIALNUMBER] = "1",
+    [STR_CONFIG_FULL]  = "Full speed config (usb 1.1)",
+    [STR_CONFIG_HIGH]  = "High speed config (usb 2.0)",
 };
 
-static const USBDescIface desc_iface0 = {
+static const USBDescIface desc_iface_full = {
     .bInterfaceNumber              = 0,
     .bNumEndpoints                 = 2,
     .bInterfaceClass               = USB_CLASS_MASS_STORAGE,
@@ -104,16 +108,51 @@ static const USBDescIface desc_iface0 = {
     }
 };
 
-static const USBDescDevice desc_device = {
-    .bcdUSB                        = 0x0100,
+static const USBDescDevice desc_device_full = {
+    .bcdUSB                        = 0x0200,
     .bMaxPacketSize0               = 8,
     .bNumConfigurations            = 1,
     .confs = (USBDescConfig[]) {
         {
             .bNumInterfaces        = 1,
             .bConfigurationValue   = 1,
+            .iConfiguration        = STR_CONFIG_FULL,
             .bmAttributes          = 0xc0,
-            .ifs = &desc_iface0,
+            .ifs = &desc_iface_full,
+        },
+    },
+};
+
+static const USBDescIface desc_iface_high = {
+    .bInterfaceNumber              = 0,
+    .bNumEndpoints                 = 2,
+    .bInterfaceClass               = USB_CLASS_MASS_STORAGE,
+    .bInterfaceSubClass            = 0x06, /* SCSI */
+    .bInterfaceProtocol            = 0x50, /* Bulk */
+    .eps = (USBDescEndpoint[]) {
+        {
+            .bEndpointAddress      = USB_DIR_IN | 0x01,
+            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
+            .wMaxPacketSize        = 512,
+        },{
+            .bEndpointAddress      = USB_DIR_OUT | 0x02,
+            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
+            .wMaxPacketSize        = 512,
+        },
+    }
+};
+
+static const USBDescDevice desc_device_high = {
+    .bcdUSB                        = 0x0200,
+    .bMaxPacketSize0               = 64,
+    .bNumConfigurations            = 1,
+    .confs = (USBDescConfig[]) {
+        {
+            .bNumInterfaces        = 1,
+            .bConfigurationValue   = 1,
+            .iConfiguration        = STR_CONFIG_HIGH,
+            .bmAttributes          = 0xc0,
+            .ifs = &desc_iface_high,
         },
     },
 };
@@ -127,7 +166,8 @@ static const USBDesc desc = {
         .iProduct          = STR_PRODUCT,
         .iSerialNumber     = STR_SERIALNUMBER,
     },
-    .full = &desc_device,
+    .full = &desc_device_full,
+    .high = &desc_device_high,
     .str  = desc_strings,
 };
 
@@ -558,6 +598,7 @@ static struct USBDeviceInfo msd_info = {
     .usb_desc       = &desc,
     .init           = usb_msd_initfn,
     .handle_packet  = usb_generic_handle_packet,
+    .handle_attach  = usb_desc_attach,
     .handle_reset   = usb_msd_handle_reset,
     .handle_control = usb_msd_handle_control,
     .handle_data    = usb_msd_handle_data,
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v4 27/32] usb storage: fix status reporting
  2011-01-12 11:19 [Qemu-devel] [PATCH v4 00/32] usb descriptor overhaul + more Gerd Hoffmann
                   ` (25 preceding siblings ...)
  2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 26/32] usb storage: high speed support Gerd Hoffmann
@ 2011-01-12 11:20 ` Gerd Hoffmann
  2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 28/32] usb storage: handle long responses Gerd Hoffmann
                   ` (5 subsequent siblings)
  32 siblings, 0 replies; 37+ messages in thread
From: Gerd Hoffmann @ 2011-01-12 11:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Change usb_msd_send_status() to take a pointer to the status packet
instead of writing the status to s->usb_buf which might not point
to the correct location.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb-msd.c |   13 +++++++------
 1 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 7b8189f..28c12dd 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -196,15 +196,18 @@ static void usb_msd_copy_data(MSDState *s)
     }
 }
 
-static void usb_msd_send_status(MSDState *s)
+static void usb_msd_send_status(MSDState *s, USBPacket *p)
 {
     struct usb_msd_csw csw;
+    int len;
 
     csw.sig = cpu_to_le32(0x53425355);
     csw.tag = cpu_to_le32(s->tag);
     csw.residue = s->residue;
     csw.status = s->result;
-    memcpy(s->usb_buf, &csw, 13);
+
+    len = MIN(sizeof(csw), p->len);
+    memcpy(p->data, &csw, len);
 }
 
 static void usb_msd_command_complete(SCSIBus *bus, int reason, uint32_t tag,
@@ -224,7 +227,7 @@ static void usb_msd_command_complete(SCSIBus *bus, int reason, uint32_t tag,
             if (s->data_len == 0 && s->mode == USB_MSDM_DATAOUT) {
                 /* A deferred packet with no write data remaining must be
                    the status read packet.  */
-                usb_msd_send_status(s);
+                usb_msd_send_status(s, p);
                 s->mode = USB_MSDM_CBW;
             } else {
                 if (s->data_len) {
@@ -425,9 +428,7 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
             if (len < 13)
                 goto fail;
 
-            s->usb_len = len;
-            s->usb_buf = data;
-            usb_msd_send_status(s);
+            usb_msd_send_status(s, p);
             s->mode = USB_MSDM_CBW;
             ret = 13;
             break;
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v4 28/32] usb storage: handle long responses
  2011-01-12 11:19 [Qemu-devel] [PATCH v4 00/32] usb descriptor overhaul + more Gerd Hoffmann
                   ` (26 preceding siblings ...)
  2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 27/32] usb storage: fix status reporting Gerd Hoffmann
@ 2011-01-12 11:20 ` Gerd Hoffmann
  2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 29/32] usb: keep track of physical port address Gerd Hoffmann
                   ` (4 subsequent siblings)
  32 siblings, 0 replies; 37+ messages in thread
From: Gerd Hoffmann @ 2011-01-12 11:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

The scsi layer may return us more data than the guests wants to have.
Handle this by just ignoring the extra bytes and calling the
{read,write}_data callback to finish the request.

Seen happening in real life with some extended inquiry command.
With this patch applied the linux kernel stops reseting the device
once at boot.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb-msd.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 28c12dd..729d96c 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -187,7 +187,7 @@ static void usb_msd_copy_data(MSDState *s)
     s->usb_buf += len;
     s->scsi_buf += len;
     s->data_len -= len;
-    if (s->scsi_len == 0) {
+    if (s->scsi_len == 0 || s->data_len == 0) {
         if (s->mode == USB_MSDM_DATAIN) {
             s->scsi_dev->info->read_data(s->scsi_dev, s->tag);
         } else if (s->mode == USB_MSDM_DATAOUT) {
@@ -434,7 +434,7 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
             break;
 
         case USB_MSDM_DATAIN:
-            DPRINTF("Data in %d/%d\n", len, s->data_len);
+            DPRINTF("Data in %d/%d, scsi_len %d\n", len, s->data_len, s->scsi_len);
             if (len > s->data_len)
                 len = s->data_len;
             s->usb_buf = data;
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v4 29/32] usb: keep track of physical port address.
  2011-01-12 11:19 [Qemu-devel] [PATCH v4 00/32] usb descriptor overhaul + more Gerd Hoffmann
                   ` (27 preceding siblings ...)
  2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 28/32] usb storage: handle long responses Gerd Hoffmann
@ 2011-01-12 11:20 ` Gerd Hoffmann
  2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 30/32] usb: add port property Gerd Hoffmann
                   ` (3 subsequent siblings)
  32 siblings, 0 replies; 37+ messages in thread
From: Gerd Hoffmann @ 2011-01-12 11:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Add a path string to USBPort.  Add usb_port_location() function to set
the physical location of the usb port.  Update all drivers implementing
usb ports to call it.  Update the monitor commands to print it.  Wind it
up in qdev.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb-bus.c  |   26 +++++++++++++++++++++++---
 hw/usb-hub.c  |   11 +++++++++++
 hw/usb-musb.c |    1 +
 hw/usb-ohci.c |    1 +
 hw/usb-uhci.c |    1 +
 hw/usb.h      |    2 ++
 6 files changed, 39 insertions(+), 3 deletions(-)

diff --git a/hw/usb-bus.c b/hw/usb-bus.c
index e94b88d..0cb03c9 100644
--- a/hw/usb-bus.c
+++ b/hw/usb-bus.c
@@ -5,12 +5,15 @@
 #include "monitor.h"
 
 static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent);
+
+static char *usb_get_dev_path(DeviceState *dev);
 static char *usbbus_get_fw_dev_path(DeviceState *dev);
 
 static struct BusInfo usb_bus_info = {
     .name      = "USB",
     .size      = sizeof(USBBus),
     .print_dev = usb_bus_dev_print,
+    .get_dev_path = usb_get_dev_path,
     .get_fw_dev_path = usbbus_get_fw_dev_path,
 };
 static int next_usb_bus = 0;
@@ -126,6 +129,16 @@ void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
     bus->nfree++;
 }
 
+void usb_port_location(USBPort *downstream, USBPort *upstream, int portnr)
+{
+    if (upstream) {
+        snprintf(downstream->path, sizeof(downstream->path), "%s.%d",
+                 upstream->path, portnr);
+    } else {
+        snprintf(downstream->path, sizeof(downstream->path), "%d", portnr);
+    }
+}
+
 void usb_unregister_port(USBBus *bus, USBPort *port)
 {
     if (port->dev)
@@ -235,12 +248,19 @@ static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent)
     USBDevice *dev = DO_UPCAST(USBDevice, qdev, qdev);
     USBBus *bus = usb_bus_from_device(dev);
 
-    monitor_printf(mon, "%*saddr %d.%d, speed %s, name %s%s\n",
+    monitor_printf(mon, "%*saddr %d.%d, port %s, speed %s, name %s%s\n",
                    indent, "", bus->busnr, dev->addr,
+                   dev->port ? dev->port->path : "-",
                    usb_speed(dev->speed), dev->product_desc,
                    dev->attached ? ", attached" : "");
 }
 
+static char *usb_get_dev_path(DeviceState *qdev)
+{
+    USBDevice *dev = DO_UPCAST(USBDevice, qdev, qdev);
+    return qemu_strdup(dev->port->path);
+}
+
 void usb_info(Monitor *mon)
 {
     USBBus *bus;
@@ -257,8 +277,8 @@ void usb_info(Monitor *mon)
             dev = port->dev;
             if (!dev)
                 continue;
-            monitor_printf(mon, "  Device %d.%d, Speed %s Mb/s, Product %s\n",
-                           bus->busnr, dev->addr, usb_speed(dev->speed),
+            monitor_printf(mon, "  Device %d.%d, Port %s, Speed %s Mb/s, Product %s\n",
+                           bus->busnr, dev->addr, port->path, usb_speed(dev->speed),
                            dev->product_desc);
         }
     }
diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index ba712d6..387c40c 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -256,6 +256,16 @@ static void usb_hub_wakeup(USBDevice *dev)
     }
 }
 
+static void usb_hub_handle_attach(USBDevice *dev)
+{
+    USBHubState *s = DO_UPCAST(USBHubState, dev, dev);
+    int i;
+
+    for (i = 0; i < NUM_PORTS; i++) {
+        usb_port_location(&s->ports[i].port, dev->port, i+1);
+    }
+}
+
 static void usb_hub_handle_reset(USBDevice *dev)
 {
     /* XXX: do it */
@@ -542,6 +552,7 @@ static struct USBDeviceInfo hub_info = {
     .usb_desc       = &desc_hub,
     .init           = usb_hub_initfn,
     .handle_packet  = usb_hub_handle_packet,
+    .handle_attach  = usb_hub_handle_attach,
     .handle_reset   = usb_hub_handle_reset,
     .handle_control = usb_hub_handle_control,
     .handle_data    = usb_hub_handle_data,
diff --git a/hw/usb-musb.c b/hw/usb-musb.c
index 87eb9ca..4b5f35b 100644
--- a/hw/usb-musb.c
+++ b/hw/usb-musb.c
@@ -351,6 +351,7 @@ struct MUSBState {
     usb_bus_new(&s->bus, NULL /* FIXME */);
     usb_register_port(&s->bus, &s->port, s, 0, NULL, &musb_port_ops,
                       USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
+    usb_port_location(&s->port, NULL, 1);
 
     return s;
 }
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index 0d42716..6344f81 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -1701,6 +1701,7 @@ static void usb_ohci_init(OHCIState *ohci, DeviceState *dev,
     for (i = 0; i < num_ports; i++) {
         usb_register_port(&ohci->bus, &ohci->rhport[i].port, ohci, i, NULL, &ohci_port_ops,
                           USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
+        usb_port_location(&ohci->rhport[i].port, NULL, i+1);
     }
 
     ohci->async_td = 0;
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index 253561f..6db1960 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -1131,6 +1131,7 @@ static int usb_uhci_common_initfn(UHCIState *s)
     for(i = 0; i < NB_PORTS; i++) {
         usb_register_port(&s->bus, &s->ports[i].port, s, i, NULL, &uhci_port_ops,
                           USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
+        usb_port_location(&s->ports[i].port, NULL, i+1);
     }
     s->frame_timer = qemu_new_timer(vm_clock, uhci_frame_timer, s);
     s->expire_time = qemu_get_clock(vm_clock) +
diff --git a/hw/usb.h b/hw/usb.h
index 99139e2..8fdda29 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -240,6 +240,7 @@ typedef struct USBPortOps {
 struct USBPort {
     USBDevice *dev;
     int speedmask;
+    char path[16];
     USBPortOps *ops;
     void *opaque;
     USBDevice *pdev;
@@ -354,6 +355,7 @@ USBDevice *usb_create_simple(USBBus *bus, const char *name);
 USBDevice *usbdevice_create(const char *cmdline);
 void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
                        USBDevice *pdev, USBPortOps *ops, int speedmask);
+void usb_port_location(USBPort *downstream, USBPort *upstream, int portnr);
 void usb_unregister_port(USBBus *bus, USBPort *port);
 int usb_device_attach(USBDevice *dev);
 int usb_device_detach(USBDevice *dev);
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v4 30/32] usb: add port property.
  2011-01-12 11:19 [Qemu-devel] [PATCH v4 00/32] usb descriptor overhaul + more Gerd Hoffmann
                   ` (28 preceding siblings ...)
  2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 29/32] usb: keep track of physical port address Gerd Hoffmann
@ 2011-01-12 11:20 ` Gerd Hoffmann
  2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 31/32] usb: rewrite fw path, fix numbering Gerd Hoffmann
                   ` (2 subsequent siblings)
  32 siblings, 0 replies; 37+ messages in thread
From: Gerd Hoffmann @ 2011-01-12 11:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

This allows to explictily set the physical port where you want to
plug the usb device.  Example:

  -device usb-tablet,bus=usb.0,port=2

With explicit port addressing qemu can and will not automagically add
USB Hubs.  This means that:

  (a) You can plug two devices of your choice into the two uhci
      root ports.
  (b) If you want plug in more that two devices you have to care
      about adding a hub yourself.

Plugging a hub works this way:

  -device usb-hub,bus=usb.0,port=1

Use this to add a device to the hub:

  -device usb-tablet,bus=usb.0,port=1.1

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb-bus.c |   26 ++++++++++++++++++++++----
 hw/usb.h     |    1 +
 2 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/hw/usb-bus.c b/hw/usb-bus.c
index 0cb03c9..1f59f9a 100644
--- a/hw/usb-bus.c
+++ b/hw/usb-bus.c
@@ -15,6 +15,10 @@ static struct BusInfo usb_bus_info = {
     .print_dev = usb_bus_dev_print,
     .get_dev_path = usb_get_dev_path,
     .get_fw_dev_path = usbbus_get_fw_dev_path,
+    .props      = (Property[]) {
+        DEFINE_PROP_STRING("port", USBDevice, port_path),
+        DEFINE_PROP_END_OF_LIST()
+    },
 };
 static int next_usb_bus = 0;
 static QTAILQ_HEAD(, USBBus) busses = QTAILQ_HEAD_INITIALIZER(busses);
@@ -157,9 +161,22 @@ static void do_attach(USBDevice *dev)
                 dev->product_desc);
         return;
     }
-    dev->attached++;
+    if (dev->port_path) {
+        QTAILQ_FOREACH(port, &bus->free, next) {
+            if (strcmp(port->path, dev->port_path) == 0) {
+                break;
+            }
+        }
+        if (port == NULL) {
+            fprintf(stderr, "Warning: usb port %s (bus %s) not found\n",
+                    dev->port_path, bus->qbus.name);
+            return;
+        }
+    } else {
+        port = QTAILQ_FIRST(&bus->free);
+    }
 
-    port = QTAILQ_FIRST(&bus->free);
+    dev->attached++;
     QTAILQ_REMOVE(&bus->free, port, next);
     bus->nfree--;
 
@@ -173,8 +190,9 @@ int usb_device_attach(USBDevice *dev)
 {
     USBBus *bus = usb_bus_from_device(dev);
 
-    if (bus->nfree == 1) {
-        /* Create a new hub and chain it on.  */
+    if (bus->nfree == 1 && dev->port_path == NULL) {
+        /* Create a new hub and chain it on
+           (unless a physical port location is specified). */
         usb_create_simple(bus, "usb-hub");
     }
     do_attach(dev);
diff --git a/hw/usb.h b/hw/usb.h
index 8fdda29..c6e3e25 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -156,6 +156,7 @@ struct USBDevice {
     DeviceState qdev;
     USBDeviceInfo *info;
     USBPort *port;
+    char *port_path;
     void *opaque;
 
     int speed;
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v4 31/32] usb: rewrite fw path, fix numbering
  2011-01-12 11:19 [Qemu-devel] [PATCH v4 00/32] usb descriptor overhaul + more Gerd Hoffmann
                   ` (29 preceding siblings ...)
  2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 30/32] usb: add port property Gerd Hoffmann
@ 2011-01-12 11:20 ` Gerd Hoffmann
  2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 32/32] usb: zap pdev from usbport Gerd Hoffmann
  2011-01-21 15:00 ` [Qemu-devel] Re: [PATCH v4 00/32] usb descriptor overhaul + more Gerd Hoffmann
  32 siblings, 0 replies; 37+ messages in thread
From: Gerd Hoffmann @ 2011-01-12 11:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

This patch rewrites the firmware path code to use the physical port
location tracking just added to the qemu usb core.  It also fixes the
port numbering to start with "1" in the firmware path.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb-bus.c |   68 ++++++++++++++++++++++-----------------------------------
 1 files changed, 26 insertions(+), 42 deletions(-)

diff --git a/hw/usb-bus.c b/hw/usb-bus.c
index 1f59f9a..f89176b 100644
--- a/hw/usb-bus.c
+++ b/hw/usb-bus.c
@@ -7,14 +7,14 @@
 static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent);
 
 static char *usb_get_dev_path(DeviceState *dev);
-static char *usbbus_get_fw_dev_path(DeviceState *dev);
+static char *usb_get_fw_dev_path(DeviceState *qdev);
 
 static struct BusInfo usb_bus_info = {
     .name      = "USB",
     .size      = sizeof(USBBus),
     .print_dev = usb_bus_dev_print,
     .get_dev_path = usb_get_dev_path,
-    .get_fw_dev_path = usbbus_get_fw_dev_path,
+    .get_fw_dev_path = usb_get_fw_dev_path,
     .props      = (Property[]) {
         DEFINE_PROP_STRING("port", USBDevice, port_path),
         DEFINE_PROP_END_OF_LIST()
@@ -279,6 +279,30 @@ static char *usb_get_dev_path(DeviceState *qdev)
     return qemu_strdup(dev->port->path);
 }
 
+static char *usb_get_fw_dev_path(DeviceState *qdev)
+{
+    USBDevice *dev = DO_UPCAST(USBDevice, qdev, qdev);
+    char *fw_path, *in;
+    int pos = 0;
+    long nr;
+
+    fw_path = qemu_malloc(32 + strlen(dev->port->path) * 6);
+    in = dev->port->path;
+    while (true) {
+        nr = strtol(in, &in, 10);
+        if (in[0] == '.') {
+            /* some hub between root port and device */
+            pos += sprintf(fw_path + pos, "hub@%ld/", nr);
+            in++;
+        } else {
+            /* the device itself */
+            pos += sprintf(fw_path + pos, "%s@%ld", qdev_fw_name(qdev), nr);
+            break;
+        }
+    }
+    return fw_path;
+}
+
 void usb_info(Monitor *mon)
 {
     USBBus *bus;
@@ -351,43 +375,3 @@ USBDevice *usbdevice_create(const char *cmdline)
     }
     return usb->usbdevice_init(params);
 }
-
-static int usbbus_get_fw_dev_path_helper(USBDevice *d, USBBus *bus, char *p,
-                                         int len)
-{
-    int l = 0;
-    USBPort *port;
-
-    QTAILQ_FOREACH(port, &bus->used, next) {
-        if (port->dev == d) {
-            if (port->pdev) {
-                l = usbbus_get_fw_dev_path_helper(port->pdev, bus, p, len);
-            }
-            l += snprintf(p + l, len - l, "%s@%x/", qdev_fw_name(&d->qdev),
-                          port->index);
-            break;
-        }
-    }
-
-    return l;
-}
-
-static char *usbbus_get_fw_dev_path(DeviceState *dev)
-{
-    USBDevice *d = (USBDevice*)dev;
-    USBBus *bus = usb_bus_from_device(d);
-    char path[100];
-    int l;
-
-    assert(d->attached != 0);
-
-    l = usbbus_get_fw_dev_path_helper(d, bus, path, sizeof(path));
-
-    if (l == 0) {
-        abort();
-    }
-
-    path[l-1] = '\0';
-
-    return strdup(path);
-}
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Qemu-devel] [PATCH v4 32/32] usb: zap pdev from usbport
  2011-01-12 11:19 [Qemu-devel] [PATCH v4 00/32] usb descriptor overhaul + more Gerd Hoffmann
                   ` (30 preceding siblings ...)
  2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 31/32] usb: rewrite fw path, fix numbering Gerd Hoffmann
@ 2011-01-12 11:20 ` Gerd Hoffmann
  2011-01-21 15:00 ` [Qemu-devel] Re: [PATCH v4 00/32] usb descriptor overhaul + more Gerd Hoffmann
  32 siblings, 0 replies; 37+ messages in thread
From: Gerd Hoffmann @ 2011-01-12 11:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

It isn't needed any more.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb-bus.c  |    3 +--
 hw/usb-hub.c  |    2 +-
 hw/usb-musb.c |    2 +-
 hw/usb-ohci.c |    2 +-
 hw/usb-uhci.c |    2 +-
 hw/usb.h      |    3 +--
 6 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/hw/usb-bus.c b/hw/usb-bus.c
index f89176b..6e2e5fd 100644
--- a/hw/usb-bus.c
+++ b/hw/usb-bus.c
@@ -120,11 +120,10 @@ USBDevice *usb_create_simple(USBBus *bus, const char *name)
 }
 
 void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
-                       USBDevice *pdev, USBPortOps *ops, int speedmask)
+                       USBPortOps *ops, int speedmask)
 {
     port->opaque = opaque;
     port->index = index;
-    port->pdev = pdev;
     port->opaque = opaque;
     port->index = index;
     port->ops = ops;
diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index 387c40c..78698ca 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -536,7 +536,7 @@ static int usb_hub_initfn(USBDevice *dev)
     for (i = 0; i < NUM_PORTS; i++) {
         port = &s->ports[i];
         usb_register_port(usb_bus_from_device(dev),
-                          &port->port, s, i, &s->dev, &usb_hub_port_ops,
+                          &port->port, s, i, &usb_hub_port_ops,
                           USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
         port->wPortStatus = PORT_STAT_POWER;
         port->wPortChange = 0;
diff --git a/hw/usb-musb.c b/hw/usb-musb.c
index 4b5f35b..782cfa2 100644
--- a/hw/usb-musb.c
+++ b/hw/usb-musb.c
@@ -349,7 +349,7 @@ struct MUSBState {
     }
 
     usb_bus_new(&s->bus, NULL /* FIXME */);
-    usb_register_port(&s->bus, &s->port, s, 0, NULL, &musb_port_ops,
+    usb_register_port(&s->bus, &s->port, s, 0, &musb_port_ops,
                       USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
     usb_port_location(&s->port, NULL, 1);
 
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index 6344f81..09ea0b6 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -1699,7 +1699,7 @@ static void usb_ohci_init(OHCIState *ohci, DeviceState *dev,
     usb_bus_new(&ohci->bus, dev);
     ohci->num_ports = num_ports;
     for (i = 0; i < num_ports; i++) {
-        usb_register_port(&ohci->bus, &ohci->rhport[i].port, ohci, i, NULL, &ohci_port_ops,
+        usb_register_port(&ohci->bus, &ohci->rhport[i].port, ohci, i, &ohci_port_ops,
                           USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
         usb_port_location(&ohci->rhport[i].port, NULL, i+1);
     }
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index 6db1960..b384e1d 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -1129,7 +1129,7 @@ static int usb_uhci_common_initfn(UHCIState *s)
 
     usb_bus_new(&s->bus, &s->dev.qdev);
     for(i = 0; i < NB_PORTS; i++) {
-        usb_register_port(&s->bus, &s->ports[i].port, s, i, NULL, &uhci_port_ops,
+        usb_register_port(&s->bus, &s->ports[i].port, s, i, &uhci_port_ops,
                           USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
         usb_port_location(&s->ports[i].port, NULL, i+1);
     }
diff --git a/hw/usb.h b/hw/usb.h
index c6e3e25..5c1da3e 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -244,7 +244,6 @@ struct USBPort {
     char path[16];
     USBPortOps *ops;
     void *opaque;
-    USBDevice *pdev;
     int index; /* internal port index, may be used with the opaque */
     QTAILQ_ENTRY(USBPort) next;
 };
@@ -355,7 +354,7 @@ USBDevice *usb_create(USBBus *bus, const char *name);
 USBDevice *usb_create_simple(USBBus *bus, const char *name);
 USBDevice *usbdevice_create(const char *cmdline);
 void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
-                       USBDevice *pdev, USBPortOps *ops, int speedmask);
+                       USBPortOps *ops, int speedmask);
 void usb_port_location(USBPort *downstream, USBPort *upstream, int portnr);
 void usb_unregister_port(USBBus *bus, USBPort *port);
 int usb_device_attach(USBDevice *dev);
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* Re: [Qemu-devel] [PATCH v4 18/32] usb: uhci: remote wakeup support.
  2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 18/32] usb: uhci: remote wakeup support Gerd Hoffmann
@ 2011-01-12 12:25   ` Stefan Hajnoczi
  2011-01-14 11:56     ` Gerd Hoffmann
  0 siblings, 1 reply; 37+ messages in thread
From: Stefan Hajnoczi @ 2011-01-12 12:25 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: qemu-devel

On Wed, Jan 12, 2011 at 11:20 AM, Gerd Hoffmann <kraxel@redhat.com> wrote:
> Add support for remote wakeup to the UHCI adapter.

It would be nice to document the guest configuration steps for users
so they can take advantage of this.  Perhaps on the qemu.org wiki?  Or
http://www.linux-kvm.org/page/Usb_related?

Stefan

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Qemu-devel] [PATCH v4 18/32] usb: uhci: remote wakeup support.
  2011-01-12 12:25   ` Stefan Hajnoczi
@ 2011-01-14 11:56     ` Gerd Hoffmann
  0 siblings, 0 replies; 37+ messages in thread
From: Gerd Hoffmann @ 2011-01-14 11:56 UTC (permalink / raw)
  To: Stefan Hajnoczi; +Cc: qemu-devel

On 01/12/11 13:25, Stefan Hajnoczi wrote:
> On Wed, Jan 12, 2011 at 11:20 AM, Gerd Hoffmann<kraxel@redhat.com>  wrote:
>> Add support for remote wakeup to the UHCI adapter.
>
> It would be nice to document the guest configuration steps for users
> so they can take advantage of this.  Perhaps on the qemu.org wiki?  Or
> http://www.linux-kvm.org/page/Usb_related?

qemu wiki is probably the better place as this isn't kvm-specific.  Will 
do once this is merged.

cheers,
   Gerd

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [Qemu-devel] Re: [PATCH v4 00/32] usb descriptor overhaul + more
  2011-01-12 11:19 [Qemu-devel] [PATCH v4 00/32] usb descriptor overhaul + more Gerd Hoffmann
                   ` (31 preceding siblings ...)
  2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 32/32] usb: zap pdev from usbport Gerd Hoffmann
@ 2011-01-21 15:00 ` Gerd Hoffmann
  2011-01-21 17:04   ` Aurelien Jarno
  32 siblings, 1 reply; 37+ messages in thread
From: Gerd Hoffmann @ 2011-01-21 15:00 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: qemu-devel

On 01/12/11 12:19, Gerd Hoffmann wrote:
>    Hi,
>
> Here is a update of the usb descriptor patches and a bunch of
> improvements on top of that.  This patch series features:

[ ... ]

> The following changes since commit 05bf441eb69a813d3893174d54faa6afa8c0d39b:
>
>    cris: Remove unused orig_flags (2011-01-10 23:28:08 +0100)
>
> are available in the git repository at:
>    git://anongit.freedesktop.org/spice/qemu usb.4

Ping?

cheers,
   Gerd

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Qemu-devel] Re: [PATCH v4 00/32] usb descriptor overhaul + more
  2011-01-21 15:00 ` [Qemu-devel] Re: [PATCH v4 00/32] usb descriptor overhaul + more Gerd Hoffmann
@ 2011-01-21 17:04   ` Aurelien Jarno
  0 siblings, 0 replies; 37+ messages in thread
From: Aurelien Jarno @ 2011-01-21 17:04 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: qemu-devel

On Fri, Jan 21, 2011 at 04:00:47PM +0100, Gerd Hoffmann wrote:
> On 01/12/11 12:19, Gerd Hoffmann wrote:
>>    Hi,
>>
>> Here is a update of the usb descriptor patches and a bunch of
>> improvements on top of that.  This patch series features:
>
> [ ... ]
>
>> The following changes since commit 05bf441eb69a813d3893174d54faa6afa8c0d39b:
>>
>>    cris: Remove unused orig_flags (2011-01-10 23:28:08 +0100)
>>
>> are available in the git repository at:
>>    git://anongit.freedesktop.org/spice/qemu usb.4
>
> Ping?
>

Pulled. Thanks for all the good work.


-- 
Aurelien Jarno	                        GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

^ permalink raw reply	[flat|nested] 37+ messages in thread

end of thread, other threads:[~2011-01-21 17:04 UTC | newest]

Thread overview: 37+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-01-12 11:19 [Qemu-devel] [PATCH v4 00/32] usb descriptor overhaul + more Gerd Hoffmann
2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 01/32] usb: update MAINTAINERS Gerd Hoffmann
2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 02/32] usb: data structs and helpers for usb descriptors Gerd Hoffmann
2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 03/32] usb hid: use new descriptor infrastructure Gerd Hoffmann
2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 04/32] usb serial: " Gerd Hoffmann
2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 05/32] usb storage: " Gerd Hoffmann
2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 06/32] usb wacom: " Gerd Hoffmann
2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 07/32] usb bluetooth: " Gerd Hoffmann
2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 08/32] usb hub: " Gerd Hoffmann
2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 09/32] usb descriptors: add settable strings Gerd Hoffmann
2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 10/32] usb storage: serial number support Gerd Hoffmann
2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 11/32] usb network: use new descriptor infrastructure Gerd Hoffmann
2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 12/32] usb: move USB_REQ_SET_ADDRESS handling to common code Gerd Hoffmann
2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 13/32] usb: move USB_REQ_{GET, SET}_CONFIGURATION " Gerd Hoffmann
2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 14/32] usb: move remote wakeup " Gerd Hoffmann
2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 15/32] usb: create USBPortOps, move attach there Gerd Hoffmann
2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 16/32] usb: rework attach/detach workflow Gerd Hoffmann
2011-01-12 11:19 ` [Qemu-devel] [PATCH v4 17/32] usb: add usb_wakeup() + wakeup callback to port ops Gerd Hoffmann
2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 18/32] usb: uhci: remote wakeup support Gerd Hoffmann
2011-01-12 12:25   ` Stefan Hajnoczi
2011-01-14 11:56     ` Gerd Hoffmann
2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 19/32] usb: hub: " Gerd Hoffmann
2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 20/32] usb: hid: " Gerd Hoffmann
2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 21/32] usb: hid: change serial number to "42" Gerd Hoffmann
2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 22/32] usb: add speed mask to ports Gerd Hoffmann
2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 23/32] usb: add attach callback Gerd Hoffmann
2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 24/32] usb: add usb_desc_attach Gerd Hoffmann
2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 25/32] usb: add device qualifier support Gerd Hoffmann
2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 26/32] usb storage: high speed support Gerd Hoffmann
2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 27/32] usb storage: fix status reporting Gerd Hoffmann
2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 28/32] usb storage: handle long responses Gerd Hoffmann
2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 29/32] usb: keep track of physical port address Gerd Hoffmann
2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 30/32] usb: add port property Gerd Hoffmann
2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 31/32] usb: rewrite fw path, fix numbering Gerd Hoffmann
2011-01-12 11:20 ` [Qemu-devel] [PATCH v4 32/32] usb: zap pdev from usbport Gerd Hoffmann
2011-01-21 15:00 ` [Qemu-devel] Re: [PATCH v4 00/32] usb descriptor overhaul + more Gerd Hoffmann
2011-01-21 17:04   ` Aurelien Jarno

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.