[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 4/8] usb-redir: Handle interrupt packets async
From: |
Hans de Goede |
Subject: |
[Qemu-devel] [PATCH 4/8] usb-redir: Handle interrupt packets async |
Date: |
Tue, 6 Nov 2012 15:08:17 +0100 |
This allows to hcd code to slow down its timer, rather then having to
poll us every ms.
Signed-off-by: Hans de Goede <address@hidden>
---
hw/usb/redirect.c | 64 ++++++++++++++++++++++++++++++++++++++++---------------
1 file changed, 47 insertions(+), 17 deletions(-)
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index ad601d8..5367876 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -68,6 +68,7 @@ struct endp_data {
QTAILQ_HEAD(, buf_packet) bufpq;
int32_t bufpq_size;
int32_t bufpq_target_size;
+ USBPacket *pending_async_packet;
};
struct PacketIdQueueEntry {
@@ -323,12 +324,23 @@ static void packet_id_queue_empty(struct PacketIdQueue *q)
static void usbredir_cancel_packet(USBDevice *udev, USBPacket *p)
{
USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
+ int ep_idx;
if (p->combined) {
usb_combined_packet_cancel(udev, p);
return;
}
+ ep_idx = p->ep->nr;
+ if (p->pid == USB_TOKEN_IN) {
+ ep_idx += 16;
+ }
+ if (dev->endpoint[ep_idx].pending_async_packet) {
+ assert(dev->endpoint[ep_idx].pending_async_packet == p);
+ dev->endpoint[ep_idx].pending_async_packet = NULL;
+ return;
+ }
+
packet_id_queue_add(&dev->cancelled, p->id);
usbredirparser_send_cancel_data_packet(dev->parser, p->id);
usbredirparser_do_write(dev->parser);
@@ -366,8 +378,12 @@ static void usbredir_fill_already_in_flight(USBRedirDevice
*dev)
usbredir_fill_already_in_flight_from_ep(dev, &udev->ep_ctl);
for (ep = 0; ep < USB_MAX_ENDPOINTS; ep++) {
- usbredir_fill_already_in_flight_from_ep(dev, &udev->ep_in[ep]);
- usbredir_fill_already_in_flight_from_ep(dev, &udev->ep_out[ep]);
+ if (udev->ep_in[ep].type == USB_ENDPOINT_XFER_BULK) {
+ usbredir_fill_already_in_flight_from_ep(dev, &udev->ep_in[ep]);
+ }
+ if (udev->ep_out[ep].type == USB_ENDPOINT_XFER_BULK) {
+ usbredir_fill_already_in_flight_from_ep(dev, &udev->ep_out[ep]);
+ }
}
}
@@ -620,12 +636,25 @@ static void usbredir_handle_bulk_data(USBRedirDevice
*dev, USBPacket *p,
p->status = USB_RET_ASYNC;
}
+static void usbredir_interrupt_in_complete(USBRedirDevice *dev, USBPacket *p,
+ uint8_t ep, int status, uint8_t *data, int len)
+{
+ DPRINTF("interrupt-token-in ep %02X status %d len %d\n", ep, status, len);
+
+ if (len > p->iov.size) {
+ ERROR("received int data is larger then packet ep %02X\n", ep);
+ len = p->iov.size;
+ status = usb_redir_babble;
+ }
+ usb_packet_copy(p, data, len);
+ usbredir_handle_status(dev, p, status);
+}
+
static void usbredir_handle_interrupt_in_data(USBRedirDevice *dev,
USBPacket *p, uint8_t ep)
{
/* Input interrupt endpoint, buffered packet input */
struct buf_packet *intp;
- int status, len;
if (!dev->endpoint[EP2I(ep)].interrupt_started &&
QTAILQ_EMPTY(&dev->endpoint[EP2I(ep)].bufpq)) {
@@ -647,22 +676,15 @@ static void
usbredir_handle_interrupt_in_data(USBRedirDevice *dev,
intp = QTAILQ_FIRST(&dev->endpoint[EP2I(ep)].bufpq);
if (intp == NULL) {
DPRINTF2("interrupt-token-in ep %02X, no intp\n", ep);
- p->status = USB_RET_NAK;
+ assert(dev->endpoint[EP2I(ep)].pending_async_packet == NULL);
+ dev->endpoint[EP2I(ep)].pending_async_packet = p;
+ p->status = USB_RET_ASYNC;
return;
}
- DPRINTF("interrupt-token-in ep %02X status %d len %d\n", ep,
- intp->status, intp->len);
- status = intp->status;
- len = intp->len;
- if (len > p->iov.size) {
- ERROR("received int data is larger then packet ep %02X\n", ep);
- len = p->iov.size;
- status = usb_redir_babble;
- }
- usb_packet_copy(p, intp->data, len);
+ usbredir_interrupt_in_complete(dev, p, ep, intp->status,
+ intp->data, intp->len);
bufp_free(dev, intp, ep);
- usbredir_handle_status(dev, p, status);
}
static void usbredir_handle_interrupt_out_data(USBRedirDevice *dev,
@@ -1661,8 +1683,16 @@ static void usbredir_interrupt_packet(void *priv,
uint64_t id,
return;
}
- /* bufp_alloc also adds the packet to the ep queue */
- bufp_alloc(dev, data, data_len, interrupt_packet->status, ep);
+ if (dev->endpoint[EP2I(ep)].pending_async_packet) {
+ USBPacket *p = dev->endpoint[EP2I(ep)].pending_async_packet;
+ usbredir_interrupt_in_complete(dev, p, ep,
+ interrupt_packet->status, data, data_len);
+ usb_packet_complete(&dev->dev, p);
+ dev->endpoint[EP2I(ep)].pending_async_packet = NULL;
+ } else {
+ /* bufp_alloc also adds the packet to the ep queue */
+ bufp_alloc(dev, data, data_len, interrupt_packet->status, ep);
+ }
} else {
USBPacket *p = usbredir_find_packet_by_id(dev, ep, id);
if (p) {
--
1.7.12.1
- [Qemu-devel] usb: Move interrupt handling from poll to async handling, Hans de Goede, 2012/11/06
- [Qemu-devel] [PATCH 2/8] usb-redir: Store interrupt receiving status in the bufp-queue, Hans de Goede, 2012/11/06
- [Qemu-devel] [PATCH 1/8] usb-redir: Split usb_handle_interrupt_data into separate in/out functions, Hans de Goede, 2012/11/06
- [Qemu-devel] [PATCH 6/8] hid: Change idle handling to use a timer, Hans de Goede, 2012/11/06
- [Qemu-devel] [PATCH 5/8] ehci: Lower timer freq when there are no iso packets in the periodic schedule, Hans de Goede, 2012/11/06
- [Qemu-devel] [PATCH 4/8] usb-redir: Handle interrupt packets async,
Hans de Goede <=
- [Qemu-devel] [PATCH 7/8] usb-hid: Move from NAK/polling to async packet handling, Hans de Goede, 2012/11/06
- [Qemu-devel] [PATCH 8/8] usb-hid: Allow connecting to a USB-2 device, Hans de Goede, 2012/11/06
- [Qemu-devel] [PATCH 3/8] usb-redir: Only add actually in flight packets to the in flight queue, Hans de Goede, 2012/11/06
- Re: [Qemu-devel] usb: Move interrupt handling from poll to async handling, Gerd Hoffmann, 2012/11/06