* [Qemu-devel] [PATCH 01/12] usb: data structs and helpers for usb descriptors.
2010-11-29 16:03 [Qemu-devel] [PATCH 00/12] usb descriptor overhaul Gerd Hoffmann
@ 2010-11-29 16:03 ` Gerd Hoffmann
2010-11-29 16:03 ` [Qemu-devel] [PATCH 02/12] usb hid: use new descriptor infrastructure Gerd Hoffmann
` (10 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Gerd Hoffmann @ 2010-11-29 16:03 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 | 240 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
hw/usb-desc.h | 86 ++++++++++++++++++++
hw/usb.h | 9 ++
4 files changed, 336 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 d457c33..410e7b0 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -80,7 +80,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 usb-audio.o
+common-obj-y += usb-serial.o usb-net.o usb-bus.o usb-audio.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..22f14bb
--- /dev/null
+++ b/hw/usb-desc.c
@@ -0,0 +1,240 @@
+#include "usb.h"
+#include "usb-desc.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:
+ fprintf(stderr, "%s: %d DEVICE (len %zd)\n", __FUNCTION__,
+ dev->addr, len);
+ ret = usb_desc_device(&desc->id, desc->full, buf, sizeof(buf));
+ break;
+ case USB_DT_CONFIG:
+ fprintf(stderr, "%s: %d CONFIG %d (len %zd)\n", __FUNCTION__,
+ dev->addr, index, len);
+ if (index < desc->full->bNumConfigurations) {
+ ret = usb_desc_config(desc->full->confs + index, buf, sizeof(buf));
+ }
+ break;
+ case USB_DT_STRING:
+ fprintf(stderr, "%s: %d STRING %d (len %zd)\n", __FUNCTION__,
+ dev->addr, index, len);
+ ret = usb_desc_string(desc->str, index, buf, sizeof(buf));
+ break;
+ default:
+ fprintf(stderr, "%s: %d unknown type %d (len %zd)\n", __FUNCTION__,
+ dev->addr, type, len);
+ }
+
+ if (ret > 0) {
+ if (ret > len) {
+ ret = len;
+ }
+ memcpy(dest, buf, ret);
+ }
+ fprintf(stderr, "%s: -> ret %d\n", __FUNCTION__, 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 111aa39..5430742 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -135,6 +135,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;
@@ -197,6 +205,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;
--
1.7.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH 02/12] usb hid: use new descriptor infrastructure.
2010-11-29 16:03 [Qemu-devel] [PATCH 00/12] usb descriptor overhaul Gerd Hoffmann
2010-11-29 16:03 ` [Qemu-devel] [PATCH 01/12] usb: data structs and helpers for usb descriptors Gerd Hoffmann
@ 2010-11-29 16:03 ` Gerd Hoffmann
2010-11-29 16:04 ` [Qemu-devel] [PATCH 03/12] usb serial: " Gerd Hoffmann
` (9 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Gerd Hoffmann @ 2010-11-29 16:03 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 | 445 ++++++++++++++++++++++++++-------------------------------
1 files changed, 203 insertions(+), 242 deletions(-)
diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index 882d933..2efdc3b 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 = 4,
+ .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[] = {
@@ -649,6 +666,11 @@ static int usb_hid_handle_control(USBDevice *dev, int request, int value,
USBHIDState *s = (USBHIDState *)dev;
int ret = 0;
+ 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) |
@@ -676,70 +698,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 +870,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 +882,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 +894,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] 13+ messages in thread
* [Qemu-devel] [PATCH 03/12] usb serial: use new descriptor infrastructure.
2010-11-29 16:03 [Qemu-devel] [PATCH 00/12] usb descriptor overhaul Gerd Hoffmann
2010-11-29 16:03 ` [Qemu-devel] [PATCH 01/12] usb: data structs and helpers for usb descriptors Gerd Hoffmann
2010-11-29 16:03 ` [Qemu-devel] [PATCH 02/12] usb hid: use new descriptor infrastructure Gerd Hoffmann
@ 2010-11-29 16:04 ` Gerd Hoffmann
2010-11-29 16:04 ` [Qemu-devel] [PATCH 04/12] usb storage: " Gerd Hoffmann
` (8 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Gerd Hoffmann @ 2010-11-29 16:04 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 | 195 ++++++++++++++++++++++--------------------------------
1 files changed, 80 insertions(+), 115 deletions(-)
diff --git a/hw/usb-serial.c b/hw/usb-serial.c
index c19580f..85d8d3f 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)
@@ -217,6 +225,11 @@ static int usb_serial_handle_control(USBDevice *dev, int request, int value,
int ret = 0;
//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;
+ }
+
switch (request) {
case DeviceRequest | USB_REQ_GET_STATUS:
data[0] = (0 << USB_DEVICE_SELF_POWERED) |
@@ -244,52 +257,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 +600,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 +610,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 +619,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 +629,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] 13+ messages in thread
* [Qemu-devel] [PATCH 04/12] usb storage: use new descriptor infrastructure.
2010-11-29 16:03 [Qemu-devel] [PATCH 00/12] usb descriptor overhaul Gerd Hoffmann
` (2 preceding siblings ...)
2010-11-29 16:04 ` [Qemu-devel] [PATCH 03/12] usb serial: " Gerd Hoffmann
@ 2010-11-29 16:04 ` Gerd Hoffmann
2010-11-29 16:04 ` [Qemu-devel] [PATCH 05/12] usb wacom: " Gerd Hoffmann
` (7 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Gerd Hoffmann @ 2010-11-29 16:04 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 | 164 +++++++++++++++++++++------------------------------------
1 files changed, 61 insertions(+), 103 deletions(-)
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 0a95d8d..b049122 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)
@@ -238,6 +232,11 @@ static int usb_msd_handle_control(USBDevice *dev, int request, int value,
MSDState *s = (MSDState *)dev;
int ret = 0;
+ 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) |
@@ -265,48 +264,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 +582,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] 13+ messages in thread
* [Qemu-devel] [PATCH 05/12] usb wacom: use new descriptor infrastructure.
2010-11-29 16:03 [Qemu-devel] [PATCH 00/12] usb descriptor overhaul Gerd Hoffmann
` (3 preceding siblings ...)
2010-11-29 16:04 ` [Qemu-devel] [PATCH 04/12] usb storage: " Gerd Hoffmann
@ 2010-11-29 16:04 ` Gerd Hoffmann
2010-11-29 16:04 ` [Qemu-devel] [PATCH 06/12] usb bluetooth: " Gerd Hoffmann
` (6 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Gerd Hoffmann @ 2010-11-29 16:04 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 | 175 +++++++++++++++++++++++---------------------------------
1 files changed, 71 insertions(+), 104 deletions(-)
diff --git a/hw/usb-wacom.c b/hw/usb-wacom.c
index 47f26cd..d0263a6 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,
@@ -247,6 +255,11 @@ static int usb_wacom_handle_control(USBDevice *dev, int request, int value,
USBWacomState *s = (USBWacomState *) dev;
int ret = 0;
+ 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) |
@@ -274,53 +287,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 +386,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] 13+ messages in thread
* [Qemu-devel] [PATCH 06/12] usb bluetooth: use new descriptor infrastructure.
2010-11-29 16:03 [Qemu-devel] [PATCH 00/12] usb descriptor overhaul Gerd Hoffmann
` (4 preceding siblings ...)
2010-11-29 16:04 ` [Qemu-devel] [PATCH 05/12] usb wacom: " Gerd Hoffmann
@ 2010-11-29 16:04 ` Gerd Hoffmann
2010-11-29 16:04 ` [Qemu-devel] [PATCH 07/12] usb hub: " Gerd Hoffmann
` (5 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Gerd Hoffmann @ 2010-11-29 16:04 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 | 470 +++++++++++++++++++++++++----------------------------------
1 files changed, 200 insertions(+), 270 deletions(-)
diff --git a/hw/usb-bt.c b/hw/usb-bt.c
index 56d1a6c..44da655 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)
@@ -426,6 +378,11 @@ static int usb_bt_handle_control(USBDevice *dev, int request, int value,
struct USBBtState *s = (struct USBBtState *) dev->opaque;
int ret = 0;
+ ret = usb_desc_handle_control(dev, request, value, index, length, data);
+ if (ret >= 0) {
+ return ret;
+ }
+
switch (request) {
case DeviceRequest | USB_REQ_GET_STATUS:
case InterfaceRequest | USB_REQ_GET_STATUS:
@@ -459,42 +416,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 +577,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] 13+ messages in thread
* [Qemu-devel] [PATCH 07/12] usb hub: use new descriptor infrastructure.
2010-11-29 16:03 [Qemu-devel] [PATCH 00/12] usb descriptor overhaul Gerd Hoffmann
` (5 preceding siblings ...)
2010-11-29 16:04 ` [Qemu-devel] [PATCH 06/12] usb bluetooth: " Gerd Hoffmann
@ 2010-11-29 16:04 ` Gerd Hoffmann
2010-11-29 16:04 ` [Qemu-devel] [PATCH 08/12] usb descriptors: add settable strings Gerd Hoffmann
` (4 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Gerd Hoffmann @ 2010-11-29 16:04 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 2a1edfc..0f8d060 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, usb_hub_attach);
@@ -546,6 +560,7 @@ static struct USBDeviceInfo hub_info = {
.product_desc = "QEMU USB Hub",
.qdev.name = "usb-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] 13+ messages in thread
* [Qemu-devel] [PATCH 08/12] usb descriptors: add settable strings.
2010-11-29 16:03 [Qemu-devel] [PATCH 00/12] usb descriptor overhaul Gerd Hoffmann
` (6 preceding siblings ...)
2010-11-29 16:04 ` [Qemu-devel] [PATCH 07/12] usb hub: " Gerd Hoffmann
@ 2010-11-29 16:04 ` Gerd Hoffmann
2010-11-29 16:04 ` [Qemu-devel] [PATCH 09/12] usb storage: serial number support Gerd Hoffmann
` (3 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Gerd Hoffmann @ 2010-11-29 16:04 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 b692503..15a42ff 100644
--- a/hw/usb-bus.c
+++ b/hw/usb-bus.c
@@ -46,6 +46,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 22f14bb..59af8e2 100644
--- a/hw/usb-desc.c
+++ b/hw/usb-desc.c
@@ -150,9 +150,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;
@@ -167,22 +200,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;
@@ -207,7 +243,7 @@ int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len
case USB_DT_STRING:
fprintf(stderr, "%s: %d STRING %d (len %zd)\n", __FUNCTION__,
dev->addr, index, len);
- ret = usb_desc_string(desc->str, index, buf, sizeof(buf));
+ ret = usb_desc_string(dev, index, buf, sizeof(buf));
break;
default:
fprintf(stderr, "%s: %d unknown type %d (len %zd)\n", __FUNCTION__,
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 5430742..47c2957 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -142,6 +142,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 {
@@ -162,6 +169,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] 13+ messages in thread
* [Qemu-devel] [PATCH 09/12] usb storage: serial number support
2010-11-29 16:03 [Qemu-devel] [PATCH 00/12] usb descriptor overhaul Gerd Hoffmann
` (7 preceding siblings ...)
2010-11-29 16:04 ` [Qemu-devel] [PATCH 08/12] usb descriptors: add settable strings Gerd Hoffmann
@ 2010-11-29 16:04 ` Gerd Hoffmann
2010-11-29 16:04 ` [Qemu-devel] [PATCH 10/12] usb network: use new descriptor infrastructure Gerd Hoffmann
` (2 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Gerd Hoffmann @ 2010-11-29 16:04 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 b049122..7b6a0d7 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -481,6 +481,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");
@@ -499,6 +500,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] 13+ messages in thread
* [Qemu-devel] [PATCH 10/12] usb network: use new descriptor infrastructure.
2010-11-29 16:03 [Qemu-devel] [PATCH 00/12] usb descriptor overhaul Gerd Hoffmann
` (8 preceding siblings ...)
2010-11-29 16:04 ` [Qemu-devel] [PATCH 09/12] usb storage: serial number support Gerd Hoffmann
@ 2010-11-29 16:04 ` Gerd Hoffmann
2010-11-29 16:04 ` [Qemu-devel] [PATCH 11/12] usb: move USB_REQ_SET_ADDRESS handling to common code Gerd Hoffmann
2010-11-29 16:04 ` [Qemu-devel] [PATCH 12/12] usb: move USB_REQ_{GET, SET}_CONFIGURATION " Gerd Hoffmann
11 siblings, 0 replies; 13+ messages in thread
From: Gerd Hoffmann @ 2010-11-29 16:04 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 | 450 +++++++++++++++++++++++++++-------------------------------
1 files changed, 207 insertions(+), 243 deletions(-)
diff --git a/hw/usb-net.c b/hw/usb-net.c
index 54d23fb..057c753 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"
@@ -85,182 +86,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 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 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 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 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 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 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,
};
/*
@@ -1006,25 +1034,17 @@ 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;
+ 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) |
@@ -1096,64 +1116,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;
@@ -1459,6 +1421,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);
return 0;
}
@@ -1494,6 +1457,7 @@ static struct USBDeviceInfo net_info = {
.product_desc = "QEMU USB Network Interface",
.qdev.name = "usb-net",
.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] 13+ messages in thread
* [Qemu-devel] [PATCH 11/12] usb: move USB_REQ_SET_ADDRESS handling to common code
2010-11-29 16:03 [Qemu-devel] [PATCH 00/12] usb descriptor overhaul Gerd Hoffmann
` (9 preceding siblings ...)
2010-11-29 16:04 ` [Qemu-devel] [PATCH 10/12] usb network: use new descriptor infrastructure Gerd Hoffmann
@ 2010-11-29 16:04 ` Gerd Hoffmann
2010-11-29 16:04 ` [Qemu-devel] [PATCH 12/12] usb: move USB_REQ_{GET, SET}_CONFIGURATION " Gerd Hoffmann
11 siblings, 0 replies; 13+ messages in thread
From: Gerd Hoffmann @ 2010-11-29 16:04 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 | 4 ++++
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 ----
8 files changed, 4 insertions(+), 29 deletions(-)
diff --git a/hw/usb-bt.c b/hw/usb-bt.c
index 44da655..cb51750 100644
--- a/hw/usb-bt.c
+++ b/hw/usb-bt.c
@@ -412,10 +412,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 59af8e2..36dabec 100644
--- a/hw/usb-desc.c
+++ b/hw/usb-desc.c
@@ -268,6 +268,10 @@ 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;
+ 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 2efdc3b..a5e3804 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -694,10 +694,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 0f8d060..51a67a2 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 7b6a0d7..a4d5c49 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -260,10 +260,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 057c753..502a079 100644
--- a/hw/usb-net.c
+++ b/hw/usb-net.c
@@ -1071,11 +1071,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 85d8d3f..e3cc49a 100644
--- a/hw/usb-serial.c
+++ b/hw/usb-serial.c
@@ -253,10 +253,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 d0263a6..6b50b06 100644
--- a/hw/usb-wacom.c
+++ b/hw/usb-wacom.c
@@ -283,10 +283,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;
--
1.7.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH 12/12] usb: move USB_REQ_{GET, SET}_CONFIGURATION handling to common code
2010-11-29 16:03 [Qemu-devel] [PATCH 00/12] usb descriptor overhaul Gerd Hoffmann
` (10 preceding siblings ...)
2010-11-29 16:04 ` [Qemu-devel] [PATCH 11/12] usb: move USB_REQ_SET_ADDRESS handling to common code Gerd Hoffmann
@ 2010-11-29 16:04 ` Gerd Hoffmann
11 siblings, 0 replies; 13+ messages in thread
From: Gerd Hoffmann @ 2010-11-29 16:04 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 | 31 +++++++++++++++++++++++++++----
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 ++
10 files changed, 64 insertions(+), 93 deletions(-)
diff --git a/hw/usb-bt.c b/hw/usb-bt.c
index cb51750..a41e006 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;
}
@@ -412,23 +423,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;
@@ -543,8 +537,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 36dabec..bbb1d2b 100644
--- a/hw/usb-desc.c
+++ b/hw/usb-desc.c
@@ -152,6 +152,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;
@@ -231,13 +241,13 @@ int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len
case USB_DT_DEVICE:
fprintf(stderr, "%s: %d DEVICE (len %zd)\n", __FUNCTION__,
dev->addr, len);
- ret = usb_desc_device(&desc->id, desc->full, buf, sizeof(buf));
+ ret = usb_desc_device(&desc->id, dev->device, buf, sizeof(buf));
break;
case USB_DT_CONFIG:
fprintf(stderr, "%s: %d CONFIG %d (len %zd)\n", __FUNCTION__,
dev->addr, index, len);
- 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));
}
break;
case USB_DT_STRING:
@@ -264,7 +274,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,19 @@ 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:
+ ret = -1;
+ for (i = 0; i < dev->device->bNumConfigurations; i++) {
+ if (dev->device->confs[i].bConfigurationValue == value) {
+ dev->config = dev->device->confs + i;
+ ret = 0;
+ }
+ }
+ 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 a5e3804..5f9164e 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -694,13 +694,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;
@@ -821,7 +814,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 51a67a2..d21dfc0 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 a4d5c49..2ed9310 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -260,13 +260,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;
@@ -501,7 +494,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 502a079..c945390 100644
--- a/hw/usb-net.c
+++ b/hw/usb-net.c
@@ -623,7 +623,6 @@ struct rndis_response {
typedef struct USBNetState {
USBDevice dev;
- unsigned int rndis;
enum rndis_state rndis_state;
uint32_t medium;
uint32_t speed;
@@ -644,6 +643,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)
@@ -1072,8 +1076,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;
@@ -1090,8 +1095,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;
@@ -1111,27 +1117,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;
@@ -1202,7 +1187,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;
}
@@ -1251,7 +1236,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;
@@ -1322,7 +1307,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;
@@ -1358,8 +1343,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;
}
@@ -1392,9 +1378,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 e3cc49a..ab8cfb0 100644
--- a/hw/usb-serial.c
+++ b/hw/usb-serial.c
@@ -253,13 +253,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;
@@ -506,7 +499,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 6b50b06..ba059d1 100644
--- a/hw/usb-wacom.c
+++ b/hw/usb-wacom.c
@@ -283,13 +283,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;
@@ -372,7 +365,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 47c2957..d29cf79 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -171,6 +171,8 @@ struct USBDevice {
int setup_index;
QLIST_HEAD(, USBDescString) strings;
+ const USBDescDevice *device;
+ const USBDescConfig *config;
};
struct USBDeviceInfo {
--
1.7.1
^ permalink raw reply related [flat|nested] 13+ messages in thread