From patchwork Fri Mar 2 13:19:28 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gerd Hoffmann X-Patchwork-Id: 144262 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 0E72AB6EEA for ; Sat, 3 Mar 2012 00:47:03 +1100 (EST) Received: from localhost ([::1]:57337 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S3SPp-0000Iu-54 for incoming@patchwork.ozlabs.org; Fri, 02 Mar 2012 08:20:57 -0500 Received: from eggs.gnu.org ([208.118.235.92]:58226) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S3SOv-00068T-C5 for qemu-devel@nongnu.org; Fri, 02 Mar 2012 08:20:17 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1S3SOW-0007tY-3h for qemu-devel@nongnu.org; Fri, 02 Mar 2012 08:20:00 -0500 Received: from mx1.redhat.com ([209.132.183.28]:35099) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S3SOV-0007sm-RZ for qemu-devel@nongnu.org; Fri, 02 Mar 2012 08:19:36 -0500 Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q22DJY6v003634 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Fri, 2 Mar 2012 08:19:34 -0500 Received: from rincewind.home.kraxel.org (ovpn-116-25.ams2.redhat.com [10.36.116.25]) by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id q22DJXaQ031653; Fri, 2 Mar 2012 08:19:33 -0500 Received: by rincewind.home.kraxel.org (Postfix, from userid 500) id DB64142242; Fri, 2 Mar 2012 14:19:31 +0100 (CET) From: Gerd Hoffmann To: qemu-devel@nongnu.org Date: Fri, 2 Mar 2012 14:19:28 +0100 Message-Id: <1330694370-1078-6-git-send-email-kraxel@redhat.com> In-Reply-To: <1330694370-1078-1-git-send-email-kraxel@redhat.com> References: <1330694370-1078-1-git-send-email-kraxel@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.132.183.28 Cc: Gerd Hoffmann Subject: [Qemu-devel] [PATCH 5/7] usb: add shortcut for control transfers X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Add a more direct code path to submit control transfers. Instead of feeding three usb packets (setup, data, ack) to usb_handle_packet and have the do_token_* functions in usb.c poke the control transfer parameters out of it just submit a single packet carrying the actual data with the control xfer parameters filled into USBPacket->parameters. Signed-off-by: Gerd Hoffmann --- hw/usb.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ hw/usb.h | 1 + 2 files changed, 60 insertions(+), 0 deletions(-) diff --git a/hw/usb.c b/hw/usb.c index 800d912..1ec2e90 100644 --- a/hw/usb.c +++ b/hw/usb.c @@ -95,6 +95,7 @@ void usb_wakeup(USBEndpoint *ep) #define SETUP_STATE_SETUP 1 #define SETUP_STATE_DATA 2 #define SETUP_STATE_ACK 3 +#define SETUP_STATE_PARAM 4 static int do_token_setup(USBDevice *s, USBPacket *p) { @@ -226,6 +227,50 @@ static int do_token_out(USBDevice *s, USBPacket *p) } } +static int do_parameter(USBDevice *s, USBPacket *p) +{ + int request, value, index; + int i, ret = 0; + + for (i = 0; i < 8; i++) { + s->setup_buf[i] = p->parameter >> (i*8); + } + + s->setup_state = SETUP_STATE_PARAM; + s->setup_len = (s->setup_buf[7] << 8) | s->setup_buf[6]; + s->setup_index = 0; + + request = (s->setup_buf[0] << 8) | s->setup_buf[1]; + value = (s->setup_buf[3] << 8) | s->setup_buf[2]; + index = (s->setup_buf[5] << 8) | s->setup_buf[4]; + + if (s->setup_len > sizeof(s->data_buf)) { + fprintf(stderr, + "usb_generic_handle_packet: ctrl buffer too small (%d > %zu)\n", + s->setup_len, sizeof(s->data_buf)); + return USB_RET_STALL; + } + + if (p->pid == USB_TOKEN_OUT) { + usb_packet_copy(p, s->data_buf, s->setup_len); + } + + ret = usb_device_handle_control(s, p, request, value, index, + s->setup_len, s->data_buf); + if (ret < 0) { + return ret; + } + + if (ret < s->setup_len) { + s->setup_len = ret; + } + if (p->pid == USB_TOKEN_IN) { + usb_packet_copy(p, s->data_buf, s->setup_len); + } + + return ret; +} + /* ctrl complete function for devices which use usb_generic_handle_packet and may return USB_RET_ASYNC from their handle_control callback. Device code which does this *must* call this function instead of the normal @@ -250,6 +295,16 @@ void usb_generic_async_ctrl_complete(USBDevice *s, USBPacket *p) p->result = 0; break; + case SETUP_STATE_PARAM: + if (p->result < s->setup_len) { + s->setup_len = p->result; + } + if (p->pid == USB_TOKEN_IN) { + p->result = 0; + usb_packet_copy(p, s->data_buf, s->setup_len); + } + break; + default: break; } @@ -292,6 +347,9 @@ static int usb_process_one(USBPacket *p) if (p->ep->nr == 0) { /* control pipe */ + if (p->parameter) { + return do_parameter(dev, p); + } switch (p->pid) { case USB_TOKEN_SETUP: return do_token_setup(dev, p); @@ -416,6 +474,7 @@ void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep) p->pid = pid; p->ep = ep; p->result = 0; + p->parameter = 0; qemu_iovec_reset(&p->iov); usb_packet_set_state(p, USB_PACKET_SETUP); } diff --git a/hw/usb.h b/hw/usb.h index 5bcc9b5..24147e9 100644 --- a/hw/usb.h +++ b/hw/usb.h @@ -326,6 +326,7 @@ struct USBPacket { int pid; USBEndpoint *ep; QEMUIOVector iov; + uint64_t parameter; /* control transfers */ int result; /* transfer length or USB_RET_* status code */ /* Internal use by the USB layer. */ USBPacketState state;