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