From patchwork Fri Dec 17 11:26:41 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gerd Hoffmann X-Patchwork-Id: 75876 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 1AA311007D3 for ; Fri, 17 Dec 2010 23:05:06 +1100 (EST) Received: from localhost ([127.0.0.1]:38768 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PTZ3X-0006DA-AS for incoming@patchwork.ozlabs.org; Fri, 17 Dec 2010 07:05:03 -0500 Received: from [140.186.70.92] (port=39383 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PTYTF-0008Ch-Q8 for qemu-devel@nongnu.org; Fri, 17 Dec 2010 06:27:35 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1PTYTA-0007YS-Sy for qemu-devel@nongnu.org; Fri, 17 Dec 2010 06:27:30 -0500 Received: from mx1.redhat.com ([209.132.183.28]:63435) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1PTYTA-0007Y4-Cs for qemu-devel@nongnu.org; Fri, 17 Dec 2010 06:27:28 -0500 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id oBHBRRm0021046 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Fri, 17 Dec 2010 06:27:27 -0500 Received: from rincewind.home.kraxel.org (vpn2-10-81.ams2.redhat.com [10.36.10.81]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id oBHBRMPa015130; Fri, 17 Dec 2010 06:27:24 -0500 Received: by rincewind.home.kraxel.org (Postfix, from userid 500) id 62F2341363; Fri, 17 Dec 2010 12:26:48 +0100 (CET) From: Gerd Hoffmann To: qemu-devel@nongnu.org Date: Fri, 17 Dec 2010 12:26:41 +0100 Message-Id: <1292585206-24862-26-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.67 on 10.5.11.11 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. Cc: Gerd Hoffmann Subject: [Qemu-devel] [PATCH 25/30] usb: add device qualifier support 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 Add support for device_qualifier and other_speed_config descriptors. These are used to query the "other speed" configuration of usb 2.0 devices, i.e. in high-speed mode they return the full-speed configuration and visa versa. Signed-off-by: Gerd Hoffmann --- hw/usb-desc.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ hw/usb-desc.h | 2 ++ hw/usb.h | 2 ++ trace-events | 2 ++ 4 files changed, 52 insertions(+), 0 deletions(-) diff --git a/hw/usb-desc.c b/hw/usb-desc.c index f01e1cf..62591f2 100644 --- a/hw/usb-desc.c +++ b/hw/usb-desc.c @@ -48,6 +48,30 @@ int usb_desc_device(const USBDescID *id, const USBDescDevice *dev, return bLength; } +int usb_desc_device_qualifier(const USBDescDevice *dev, + uint8_t *dest, size_t len) +{ + uint8_t bLength = 0x0a; + + if (len < bLength) { + return -1; + } + + dest[0x00] = bLength; + dest[0x01] = USB_DT_DEVICE_QUALIFIER; + + dest[0x02] = usb_lo(dev->bcdUSB); + dest[0x03] = usb_hi(dev->bcdUSB); + dest[0x04] = dev->bDeviceClass; + dest[0x05] = dev->bDeviceSubClass; + dest[0x06] = dev->bDeviceProtocol; + dest[0x07] = dev->bMaxPacketSize0; + dest[0x08] = dev->bNumConfigurations; + dest[0x09] = 0; /* reserved */ + + return bLength; +} + int usb_desc_config(const USBDescConfig *conf, uint8_t *dest, size_t len) { uint8_t bLength = 0x09; @@ -263,11 +287,18 @@ int usb_desc_string(USBDevice *dev, int index, uint8_t *dest, size_t len) int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len) { const USBDesc *desc = dev->info->usb_desc; + const USBDescDevice *other_dev; uint8_t buf[256]; uint8_t type = value >> 8; uint8_t index = value & 0xff; int ret = -1; + if (dev->speed == USB_SPEED_HIGH) { + other_dev = dev->info->usb_desc->full; + } else { + other_dev = dev->info->usb_desc->high; + } + switch(type) { case USB_DT_DEVICE: ret = usb_desc_device(&desc->id, dev->device, buf, sizeof(buf)); @@ -283,6 +314,21 @@ int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len ret = usb_desc_string(dev, index, buf, sizeof(buf)); trace_usb_desc_string(dev->addr, index, len, ret); break; + + case USB_DT_DEVICE_QUALIFIER: + if (other_dev != NULL) { + ret = usb_desc_device_qualifier(other_dev, buf, sizeof(buf)); + } + trace_usb_desc_device_qualifier(dev->addr, len, ret); + break; + case USB_DT_OTHER_SPEED_CONFIG: + if (other_dev != NULL && index < other_dev->bNumConfigurations) { + ret = usb_desc_config(other_dev->confs + index, buf, sizeof(buf)); + buf[0x01] = USB_DT_OTHER_SPEED_CONFIG; + } + trace_usb_desc_other_speed_config(dev->addr, index, len, ret); + break; + default: fprintf(stderr, "%s: %d unknown type %d (len %zd)\n", __FUNCTION__, dev->addr, type, len); diff --git a/hw/usb-desc.h b/hw/usb-desc.h index 484c7c7..ac734ab 100644 --- a/hw/usb-desc.h +++ b/hw/usb-desc.h @@ -72,6 +72,8 @@ struct USBDesc { /* generate usb packages from structs */ int usb_desc_device(const USBDescID *id, const USBDescDevice *dev, uint8_t *dest, size_t len); +int usb_desc_device_qualifier(const USBDescDevice *dev, + uint8_t *dest, size_t len); int usb_desc_config(const USBDescConfig *conf, uint8_t *dest, size_t len); int usb_desc_iface(const USBDescIface *iface, uint8_t *dest, size_t len); int usb_desc_endpoint(const USBDescEndpoint *ep, uint8_t *dest, size_t len); diff --git a/hw/usb.h b/hw/usb.h index 0219816..15d2438 100644 --- a/hw/usb.h +++ b/hw/usb.h @@ -122,6 +122,8 @@ #define USB_DT_STRING 0x03 #define USB_DT_INTERFACE 0x04 #define USB_DT_ENDPOINT 0x05 +#define USB_DT_DEVICE_QUALIFIER 0x06 +#define USB_DT_OTHER_SPEED_CONFIG 0x07 #define USB_ENDPOINT_XFER_CONTROL 0 #define USB_ENDPOINT_XFER_ISOC 1 diff --git a/trace-events b/trace-events index 8bece3c..c96a77e 100644 --- a/trace-events +++ b/trace-events @@ -192,7 +192,9 @@ disable sun4m_iommu_bad_addr(uint64_t addr) "bad addr %"PRIx64"" # hw/usb-desc.c disable usb_desc_device(int addr, int len, int ret) "dev %d query device, len %d, ret %d" +disable usb_desc_device_qualifier(int addr, int len, int ret) "dev %d query device qualifier, len %d, ret %d" disable usb_desc_config(int addr, int index, int len, int ret) "dev %d query config %d, len %d, ret %d" +disable usb_desc_other_speed_config(int addr, int index, int len, int ret) "dev %d query config %d, len %d, ret %d" disable usb_desc_string(int addr, int index, int len, int ret) "dev %d query string %d, len %d, ret %d" disable usb_set_addr(int addr) "dev %d" disable usb_set_config(int addr, int config, int ret) "dev %d, config %d, ret %d"