From patchwork Fri Dec 17 11:26:24 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gerd Hoffmann X-Patchwork-Id: 75886 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 09ABFB7088 for ; Sat, 18 Dec 2010 00:07:01 +1100 (EST) Received: from localhost ([127.0.0.1]:38410 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PTYvf-0002Ad-Tx for incoming@patchwork.ozlabs.org; Fri, 17 Dec 2010 06:56:56 -0500 Received: from [140.186.70.92] (port=39101 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PTYSs-0007yG-Gf for qemu-devel@nongnu.org; Fri, 17 Dec 2010 06:27:12 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1PTYSp-0007SS-Qa for qemu-devel@nongnu.org; Fri, 17 Dec 2010 06:27:09 -0500 Received: from mx1.redhat.com ([209.132.183.28]:42705) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1PTYSp-0007SE-EP for qemu-devel@nongnu.org; Fri, 17 Dec 2010 06:27:07 -0500 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id oBHBR6kE025794 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Fri, 17 Dec 2010 06:27:06 -0500 Received: from rincewind.home.kraxel.org (vpn2-10-81.ams2.redhat.com [10.36.10.81]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id oBHBQvs9001637; Fri, 17 Dec 2010 06:26:58 -0500 Received: by rincewind.home.kraxel.org (Postfix, from userid 500) id 70BA5411DA; Fri, 17 Dec 2010 12:26:47 +0100 (CET) From: Gerd Hoffmann To: qemu-devel@nongnu.org Date: Fri, 17 Dec 2010 12:26:24 +0100 Message-Id: <1292585206-24862-9-git-send-email-kraxel@redhat.com> In-Reply-To: <1292585206-24862-1-git-send-email-kraxel@redhat.com> References: <1292585206-24862-1-git-send-email-kraxel@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. Cc: Gerd Hoffmann Subject: [Qemu-devel] [PATCH 08/30] usb hub: use new descriptor infrastructure. X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org 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 --- 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,