qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Gerd Hoffmann <kraxel@redhat.com>
To: qemu-devel@nongnu.org
Cc: Gerd Hoffmann <kraxel@redhat.com>
Subject: [Qemu-devel] [PATCH 18/20] usb: add shortcut for control transfers
Date: Wed,  7 Mar 2012 14:05:18 +0100	[thread overview]
Message-ID: <1331125520-13467-19-git-send-email-kraxel@redhat.com> (raw)
In-Reply-To: <1331125520-13467-1-git-send-email-kraxel@redhat.com>

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 <kraxel@redhat.com>
---
 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 f6df0ad..d60d03d 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -327,6 +327,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;
-- 
1.7.1

  parent reply	other threads:[~2012-03-07 13:06 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-03-07 13:05 [Qemu-devel] [PULL 00/20] usb patch queue Gerd Hoffmann
2012-03-07 13:05 ` [Qemu-devel] [PATCH 01/20] usb-redir: Set ep type and interface Gerd Hoffmann
2012-03-07 13:05 ` [Qemu-devel] [PATCH 02/20] usb-ehci: Never follow table entries with the T-bit set Gerd Hoffmann
2012-03-07 13:05 ` [Qemu-devel] [PATCH 03/20] usb-ehci: split our qh queue into async and periodic queues Gerd Hoffmann
2012-03-07 13:05 ` [Qemu-devel] [PATCH 04/20] usb-ehci: always call ehci_queues_rip_unused for period queues Gerd Hoffmann
2012-03-07 13:05 ` [Qemu-devel] [PATCH 05/20] usb-ehci: Drop cached qhs when the doorbell gets rung Gerd Hoffmann
2012-03-07 13:05 ` [Qemu-devel] [PATCH 06/20] usb-ehci: Rip the queues when the async or period schedule is halted Gerd Hoffmann
2012-03-07 13:05 ` [Qemu-devel] [PATCH 07/20] usb-ehci: Any packet completion except for NAK should set the interrupt Gerd Hoffmann
2012-03-07 13:05 ` [Qemu-devel] [PATCH 08/20] usb-ehci: Fix cerr tracking Gerd Hoffmann
2012-03-07 13:05 ` [Qemu-devel] [PATCH 09/20] usb-ehci: Remove dead nakcnt code Gerd Hoffmann
2012-03-07 13:05 ` [Qemu-devel] [PATCH 10/20] usb-ehci: Fix and simplify nakcnt handling Gerd Hoffmann
2012-03-07 13:05 ` [Qemu-devel] [PATCH 11/20] usb-ehci: Cleanup itd error handling Gerd Hoffmann
2012-03-07 13:05 ` [Qemu-devel] [PATCH 12/20] usb: return BABBLE rather then NAK when we receive too much data Gerd Hoffmann
2012-03-07 13:05 ` [Qemu-devel] [PATCH 13/20] usb: add USB_RET_IOERROR Gerd Hoffmann
2012-03-07 13:05 ` [Qemu-devel] [PATCH 14/20] uhci_fill_queue: zap debug printf Gerd Hoffmann
2012-03-07 13:05 ` [Qemu-devel] [PATCH 15/20] usb: queue can have async packets Gerd Hoffmann
2012-03-07 13:05 ` [Qemu-devel] [PATCH 16/20] usb: add pipelining option to usb endpoints Gerd Hoffmann
2012-03-07 13:05 ` [Qemu-devel] [PATCH 17/20] usb-host: enable pipelineing for bulk endpoints Gerd Hoffmann
2012-03-07 13:05 ` Gerd Hoffmann [this message]
2012-03-07 13:05 ` [Qemu-devel] [PATCH 19/20] xhci: fix control xfers Gerd Hoffmann
2012-03-07 13:05 ` [Qemu-devel] [PATCH 20/20] xhci: fix port status Gerd Hoffmann
2012-03-09 19:17 ` [Qemu-devel] [PULL 00/20] usb patch queue Anthony Liguori

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1331125520-13467-19-git-send-email-kraxel@redhat.com \
    --to=kraxel@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).