* [Qemu-devel] [PATCH 00/25] *** SUBJECT HERE ***
@ 2012-01-23 14:54 Gerd Hoffmann
2012-01-23 14:54 ` [Qemu-devel] [PATCH 01/25] usb: kill USB_MSG_{ATTACH,DETACH} Gerd Hoffmann
` (25 more replies)
0 siblings, 26 replies; 27+ messages in thread
From: Gerd Hoffmann @ 2012-01-23 14:54 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
*** BLURB HERE ***
Gerd Hoffmann (25):
usb: kill USB_MSG_{ATTACH,DETACH}
usb: kill USB_MSG_RESET
usb: kill usb_send_msg
usb: add usb_find_device()
usb-hub: implement find_device
usb: handle dev == NULL in usb_handle_packet()
usb-uhci: switch to usb_find_device()
usb-ehci: switch to usb_find_device()
usb-ohci: switch to usb_find_device()
usb-musb: switch to usb_find_device()
usb-xhci: switch to usb_find_device()
usb: kill handle_packet callback
usb: fold usb_generic_handle_packet into usb_handle_packet
usb: USBPacket: add status, rename owner -> ep
usb: add USBEndpoint->{nr,pid}
usb: Set USBEndpoint in usb_packet_setup().
usb: maintain async packet list per endpoint
usb: pass USBEndpoint to usb_wakeup
usb: add USBBusOps->wakeup_endpoint
xhci: signal low- and fullspeed support
xhci: add trb type name lookup support.
xhci: stop on errors
xhci: kill port arg from xhci_setup_packet
xhci: remote wakeup support
xhci: handle USB_RET_NAK
hw/usb-audio.c | 5 +-
hw/usb-bt.c | 5 +-
hw/usb-ccid.c | 7 +-
hw/usb-ehci.c | 88 +++++++++-----------
hw/usb-hid.c | 9 +-
hw/usb-hub.c | 72 ++++++----------
hw/usb-msd.c | 3 +-
hw/usb-musb.c | 18 ++--
hw/usb-net.c | 7 +-
hw/usb-ohci.c | 81 +++++++++---------
hw/usb-serial.c | 4 +-
hw/usb-uhci.c | 64 +++++---------
hw/usb-wacom.c | 3 +-
hw/usb-xhci.c | 246 +++++++++++++++++++++++++++++++++++++++++++++--------
hw/usb.c | 254 ++++++++++++++++++++++++++++++++++++-------------------
hw/usb.h | 54 +++++++-----
usb-bsd.c | 3 +-
usb-linux.c | 45 +++++-----
usb-redir.c | 3 +-
19 files changed, 593 insertions(+), 378 deletions(-)
^ permalink raw reply [flat|nested] 27+ messages in thread
* [Qemu-devel] [PATCH 01/25] usb: kill USB_MSG_{ATTACH,DETACH}
2012-01-23 14:54 [Qemu-devel] [PATCH 00/25] *** SUBJECT HERE *** Gerd Hoffmann
@ 2012-01-23 14:54 ` Gerd Hoffmann
2012-01-23 14:54 ` [Qemu-devel] [PATCH 02/25] usb: kill USB_MSG_RESET Gerd Hoffmann
` (24 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Gerd Hoffmann @ 2012-01-23 14:54 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
The USB subsystem pipes internal attach/detach notifications through
usb_handle_packet() with a special magic PID. This indirection is a
pretty pointless excercise as it ends up being handled by
usb_generic_handle_packet anyway. Remove it.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb.c | 18 +++++-------------
hw/usb.h | 2 --
2 files changed, 5 insertions(+), 15 deletions(-)
diff --git a/hw/usb.c b/hw/usb.c
index 860538a..8242647 100644
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -35,7 +35,10 @@ void usb_attach(USBPort *port)
assert(dev->attached);
assert(dev->state == USB_STATE_NOTATTACHED);
port->ops->attach(port);
- usb_send_msg(dev, USB_MSG_ATTACH);
+ dev->state = USB_STATE_ATTACHED;
+ if (dev->info->handle_attach) {
+ dev->info->handle_attach(dev);
+ }
}
void usb_detach(USBPort *port)
@@ -45,7 +48,7 @@ void usb_detach(USBPort *port)
assert(dev != NULL);
assert(dev->state != USB_STATE_NOTATTACHED);
port->ops->detach(port);
- usb_send_msg(dev, USB_MSG_DETACH);
+ dev->state = USB_STATE_NOTATTACHED;
}
void usb_reset(USBPort *port)
@@ -218,17 +221,6 @@ static int do_token_out(USBDevice *s, USBPacket *p)
int usb_generic_handle_packet(USBDevice *s, USBPacket *p)
{
switch(p->pid) {
- case USB_MSG_ATTACH:
- s->state = USB_STATE_ATTACHED;
- if (s->info->handle_attach) {
- s->info->handle_attach(s);
- }
- return 0;
-
- case USB_MSG_DETACH:
- s->state = USB_STATE_NOTATTACHED;
- return 0;
-
case USB_MSG_RESET:
s->remote_wakeup = 0;
s->addr = 0;
diff --git a/hw/usb.h b/hw/usb.h
index 37f7d96..73155cf 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -37,8 +37,6 @@
#define USB_TOKEN_OUT 0xe1 /* host -> device */
/* specific usb messages, also sent in the 'pid' parameter */
-#define USB_MSG_ATTACH 0x100
-#define USB_MSG_DETACH 0x101
#define USB_MSG_RESET 0x102
#define USB_RET_NODEV (-1)
--
1.7.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [Qemu-devel] [PATCH 02/25] usb: kill USB_MSG_RESET
2012-01-23 14:54 [Qemu-devel] [PATCH 00/25] *** SUBJECT HERE *** Gerd Hoffmann
2012-01-23 14:54 ` [Qemu-devel] [PATCH 01/25] usb: kill USB_MSG_{ATTACH,DETACH} Gerd Hoffmann
@ 2012-01-23 14:54 ` Gerd Hoffmann
2012-01-23 14:54 ` [Qemu-devel] [PATCH 03/25] usb: kill usb_send_msg Gerd Hoffmann
` (23 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Gerd Hoffmann @ 2012-01-23 14:54 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
The USB subsystem pipes internal reset notifications through
usb_handle_packet() with a special magic PID. This indirection
is a pretty pointless excercise as it ends up being handled by
usb_generic_handle_packet anyway.
Replace the USB_MSG_RESET with a usb_device_reset() function
which can be called directly. Also rename the existing usb_reset()
function to usb_port_reset() to avoid confusion.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb-ehci.c | 4 ++--
hw/usb-hub.c | 2 +-
hw/usb-musb.c | 2 +-
hw/usb-ohci.c | 4 ++--
hw/usb-uhci.c | 10 +++-------
hw/usb-xhci.c | 4 +---
hw/usb.c | 28 +++++++++++++++-------------
hw/usb.h | 6 ++----
8 files changed, 27 insertions(+), 33 deletions(-)
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index 34f1f63..7c75510 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -888,7 +888,7 @@ static void ehci_reset(void *opaque)
}
if (devs[i] && devs[i]->attached) {
usb_attach(&s->ports[i]);
- usb_send_msg(devs[i], USB_MSG_RESET);
+ usb_device_reset(devs[i]);
}
}
ehci_queues_rip_all(s);
@@ -987,7 +987,7 @@ static void handle_port_status_write(EHCIState *s, int port, uint32_t val)
if (!(val & PORTSC_PRESET) &&(*portsc & PORTSC_PRESET)) {
trace_usb_ehci_port_reset(port, 0);
if (dev && dev->attached) {
- usb_reset(&s->ports[port]);
+ usb_port_reset(&s->ports[port]);
*portsc &= ~PORTSC_CSC;
}
diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index 069611b..d83cfb5 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -305,7 +305,7 @@ static int usb_hub_handle_control(USBDevice *dev, USBPacket *p,
break;
case PORT_RESET:
if (dev && dev->attached) {
- usb_send_msg(dev, USB_MSG_RESET);
+ usb_device_reset(dev);
port->wPortChange |= PORT_STAT_C_RESET;
/* set enable bit */
port->wPortStatus |= PORT_STAT_ENABLE;
diff --git a/hw/usb-musb.c b/hw/usb-musb.c
index 4f528d2..c2753c9 100644
--- a/hw/usb-musb.c
+++ b/hw/usb-musb.c
@@ -1310,7 +1310,7 @@ static void musb_writeb(void *opaque, target_phys_addr_t addr, uint32_t value)
s->power = (value & 0xef) | (s->power & 0x10);
/* MGC_M_POWER_RESET is also read-only in Peripheral Mode */
if ((value & MGC_M_POWER_RESET) && s->port.dev) {
- usb_send_msg(s->port.dev, USB_MSG_RESET);
+ usb_device_reset(s->port.dev);
/* Negotiate high-speed operation if MGC_M_POWER_HSENAB is set. */
if ((value & MGC_M_POWER_HSENAB) &&
s->port.dev->speed == USB_SPEED_HIGH)
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index 69463d2..77f8949 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -449,7 +449,7 @@ static void ohci_reset(void *opaque)
port = &ohci->rhport[i];
port->ctrl = 0;
if (port->port.dev && port->port.dev->attached) {
- usb_reset(&port->port);
+ usb_port_reset(&port->port);
}
}
if (ohci->async_td) {
@@ -1435,7 +1435,7 @@ static void ohci_port_set_status(OHCIState *ohci, int portnum, uint32_t val)
if (ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PRS)) {
DPRINTF("usb-ohci: port %d: RESET\n", portnum);
- usb_send_msg(port->port.dev, USB_MSG_RESET);
+ usb_device_reset(port->port.dev);
port->ctrl &= ~OHCI_PORT_PRS;
/* ??? Should this also set OHCI_PORT_PESC. */
port->ctrl |= OHCI_PORT_PES | OHCI_PORT_PRSC;
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index 25d4e8c..485dc1d 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -342,7 +342,7 @@ static void uhci_reset(void *opaque)
port = &s->ports[i];
port->ctrl = 0x0080;
if (port->port.dev && port->port.dev->attached) {
- usb_reset(&port->port);
+ usb_port_reset(&port->port);
}
}
@@ -440,16 +440,12 @@ static void uhci_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
}
if (val & UHCI_CMD_GRESET) {
UHCIPort *port;
- USBDevice *dev;
int i;
/* send reset on the USB bus */
for(i = 0; i < NB_PORTS; i++) {
port = &s->ports[i];
- dev = port->port.dev;
- if (dev && dev->attached) {
- usb_send_msg(dev, USB_MSG_RESET);
- }
+ usb_device_reset(port->port.dev);
}
uhci_reset(s);
return;
@@ -491,7 +487,7 @@ static void uhci_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
/* port reset */
if ( (val & UHCI_PORT_RESET) &&
!(port->ctrl & UHCI_PORT_RESET) ) {
- usb_send_msg(dev, USB_MSG_RESET);
+ usb_device_reset(dev);
}
}
port->ctrl &= UHCI_PORT_READ_ONLY;
diff --git a/hw/usb-xhci.c b/hw/usb-xhci.c
index 28fe9de..e089a1b 100644
--- a/hw/usb-xhci.c
+++ b/hw/usb-xhci.c
@@ -2346,9 +2346,7 @@ static void xhci_port_write(XHCIState *xhci, uint32_t reg, uint32_t val)
/* write-1-to-start bits */
if (val & PORTSC_PR) {
DPRINTF("xhci: port %d reset\n", port);
- if (xhci->ports[port].port.dev) {
- usb_send_msg(xhci->ports[port].port.dev, USB_MSG_RESET);
- }
+ usb_device_reset(xhci->ports[port].port.dev);
portsc |= PORTSC_PRC | PORTSC_PED;
}
xhci->ports[port].portsc = portsc;
diff --git a/hw/usb.c b/hw/usb.c
index 8242647..e81c06d 100644
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -51,14 +51,27 @@ void usb_detach(USBPort *port)
dev->state = USB_STATE_NOTATTACHED;
}
-void usb_reset(USBPort *port)
+void usb_port_reset(USBPort *port)
{
USBDevice *dev = port->dev;
assert(dev != NULL);
usb_detach(port);
usb_attach(port);
- usb_send_msg(dev, USB_MSG_RESET);
+ usb_device_reset(dev);
+}
+
+void usb_device_reset(USBDevice *dev)
+{
+ if (dev == NULL || !dev->attached) {
+ return;
+ }
+ dev->remote_wakeup = 0;
+ dev->addr = 0;
+ dev->state = USB_STATE_DEFAULT;
+ if (dev->info->handle_reset) {
+ dev->info->handle_reset(dev);
+ }
}
void usb_wakeup(USBDevice *dev)
@@ -220,17 +233,6 @@ static int do_token_out(USBDevice *s, USBPacket *p)
*/
int usb_generic_handle_packet(USBDevice *s, USBPacket *p)
{
- switch(p->pid) {
- case USB_MSG_RESET:
- s->remote_wakeup = 0;
- s->addr = 0;
- s->state = USB_STATE_DEFAULT;
- if (s->info->handle_reset) {
- s->info->handle_reset(s);
- }
- return 0;
- }
-
/* Rest of the PIDs must match our address */
if (s->state < USB_STATE_DEFAULT || p->devaddr != s->addr)
return USB_RET_NODEV;
diff --git a/hw/usb.h b/hw/usb.h
index 73155cf..4f5a75a 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -36,9 +36,6 @@
#define USB_TOKEN_IN 0x69 /* device -> host */
#define USB_TOKEN_OUT 0xe1 /* host -> device */
-/* specific usb messages, also sent in the 'pid' parameter */
-#define USB_MSG_RESET 0x102
-
#define USB_RET_NODEV (-1)
#define USB_RET_NAK (-2)
#define USB_RET_STALL (-3)
@@ -346,7 +343,8 @@ int usb_ep_get_max_packet_size(USBDevice *dev, int pid, int ep);
void usb_attach(USBPort *port);
void usb_detach(USBPort *port);
-void usb_reset(USBPort *port);
+void usb_port_reset(USBPort *port);
+void usb_device_reset(USBDevice *dev);
void usb_wakeup(USBDevice *dev);
int usb_generic_handle_packet(USBDevice *s, USBPacket *p);
void usb_generic_async_ctrl_complete(USBDevice *s, USBPacket *p);
--
1.7.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [Qemu-devel] [PATCH 03/25] usb: kill usb_send_msg
2012-01-23 14:54 [Qemu-devel] [PATCH 00/25] *** SUBJECT HERE *** Gerd Hoffmann
2012-01-23 14:54 ` [Qemu-devel] [PATCH 01/25] usb: kill USB_MSG_{ATTACH,DETACH} Gerd Hoffmann
2012-01-23 14:54 ` [Qemu-devel] [PATCH 02/25] usb: kill USB_MSG_RESET Gerd Hoffmann
@ 2012-01-23 14:54 ` Gerd Hoffmann
2012-01-23 14:54 ` [Qemu-devel] [PATCH 04/25] usb: add usb_find_device() Gerd Hoffmann
` (22 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Gerd Hoffmann @ 2012-01-23 14:54 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
No users left. Zap it.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb.c | 13 -------------
hw/usb.h | 1 -
2 files changed, 0 insertions(+), 14 deletions(-)
diff --git a/hw/usb.c b/hw/usb.c
index e81c06d..a6eea99 100644
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -299,19 +299,6 @@ int set_usb_string(uint8_t *buf, const char *str)
return q - buf;
}
-/* Send an internal message to a USB device. */
-void usb_send_msg(USBDevice *dev, int msg)
-{
- USBPacket p;
- int ret;
-
- memset(&p, 0, sizeof(p));
- p.pid = msg;
- ret = usb_handle_packet(dev, &p);
- /* This _must_ be synchronous */
- assert(ret != USB_RET_ASYNC);
-}
-
/* Hand over a packet to a device for processing. Return value
USB_RET_ASYNC indicates the processing isn't finished yet, the
driver will call usb_packet_complete() when done processing it. */
diff --git a/hw/usb.h b/hw/usb.h
index 4f5a75a..b1afea3 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -349,7 +349,6 @@ void usb_wakeup(USBDevice *dev);
int usb_generic_handle_packet(USBDevice *s, USBPacket *p);
void usb_generic_async_ctrl_complete(USBDevice *s, USBPacket *p);
int set_usb_string(uint8_t *buf, const char *str);
-void usb_send_msg(USBDevice *dev, int msg);
/* usb-linux.c */
USBDevice *usb_host_device_open(const char *devname);
--
1.7.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [Qemu-devel] [PATCH 04/25] usb: add usb_find_device()
2012-01-23 14:54 [Qemu-devel] [PATCH 00/25] *** SUBJECT HERE *** Gerd Hoffmann
` (2 preceding siblings ...)
2012-01-23 14:54 ` [Qemu-devel] [PATCH 03/25] usb: kill usb_send_msg Gerd Hoffmann
@ 2012-01-23 14:54 ` Gerd Hoffmann
2012-01-23 14:54 ` [Qemu-devel] [PATCH 05/25] usb-hub: implement find_device Gerd Hoffmann
` (21 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Gerd Hoffmann @ 2012-01-23 14:54 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Add usb_find_device(). This function will check whenever a device with
a specific address is connected to the specified port. Usually this
will just check state and address of the device hooked up to the port,
but in case of a hub it will ask the hub to check all hub ports for a
matching device.
This patch doesn't put the code into use yet, see the following patches
for details.
The master plan is to separate device lookup and packet processing.
Right now the usb code simply walks all devices, calls
usb_handle_packet() on each until one accepts the packet (by returning
something different that USB_RET_NODEV). I want to have a device lookup
first, then call usb_handle_packet() once, for the device which actually
processes the packet.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb.c | 16 ++++++++++++++++
hw/usb.h | 8 ++++++++
2 files changed, 24 insertions(+), 0 deletions(-)
diff --git a/hw/usb.c b/hw/usb.c
index a6eea99..5482c92 100644
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -299,6 +299,22 @@ int set_usb_string(uint8_t *buf, const char *str)
return q - buf;
}
+USBDevice *usb_find_device(USBPort *port, uint8_t addr)
+{
+ USBDevice *dev = port->dev;
+
+ if (dev == NULL || !dev->attached || dev->state != USB_STATE_DEFAULT) {
+ return NULL;
+ }
+ if (dev->addr == addr) {
+ return dev;
+ }
+ if (dev->info->find_device) {
+ return dev->info->find_device(dev, addr);
+ }
+ return NULL;
+}
+
/* Hand over a packet to a device for processing. Return value
USB_RET_ASYNC indicates the processing isn't finished yet, the
driver will call usb_packet_complete() when done processing it. */
diff --git a/hw/usb.h b/hw/usb.h
index b1afea3..b0ba3e0 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -219,6 +219,12 @@ struct USBDeviceInfo {
int (*init)(USBDevice *dev);
/*
+ * Walk (enabled) downstream ports, check for a matching device.
+ * Only hubs implement this.
+ */
+ USBDevice *(*find_device)(USBDevice *dev, uint8_t addr);
+
+ /*
* Process USB packet.
* Called by the HC (Host Controller).
*
@@ -326,6 +332,8 @@ void usb_packet_copy(USBPacket *p, void *ptr, size_t bytes);
void usb_packet_skip(USBPacket *p, size_t bytes);
void usb_packet_cleanup(USBPacket *p);
+USBDevice *usb_find_device(USBPort *port, uint8_t addr);
+
int usb_handle_packet(USBDevice *dev, USBPacket *p);
void usb_packet_complete(USBDevice *dev, USBPacket *p);
void usb_cancel_packet(USBPacket * p);
--
1.7.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [Qemu-devel] [PATCH 05/25] usb-hub: implement find_device
2012-01-23 14:54 [Qemu-devel] [PATCH 00/25] *** SUBJECT HERE *** Gerd Hoffmann
` (3 preceding siblings ...)
2012-01-23 14:54 ` [Qemu-devel] [PATCH 04/25] usb: add usb_find_device() Gerd Hoffmann
@ 2012-01-23 14:54 ` Gerd Hoffmann
2012-01-23 14:54 ` [Qemu-devel] [PATCH 06/25] usb: handle dev == NULL in usb_handle_packet() Gerd Hoffmann
` (20 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Gerd Hoffmann @ 2012-01-23 14:54 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Implement the find_device callback for the usb hub. It'll loop over all
ports, calling usb_find_device for all enabled ports until it finds a
matching device.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb-hub.c | 21 +++++++++++++++++++++
1 files changed, 21 insertions(+), 0 deletions(-)
diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index d83cfb5..c9f30d9 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -220,6 +220,26 @@ static void usb_hub_complete(USBPort *port, USBPacket *packet)
s->dev.port->ops->complete(s->dev.port, packet);
}
+static USBDevice *usb_hub_find_device(USBDevice *dev, uint8_t addr)
+{
+ USBHubState *s = DO_UPCAST(USBHubState, dev, dev);
+ USBHubPort *port;
+ USBDevice *downstream;
+ int i;
+
+ for (i = 0; i < NUM_PORTS; i++) {
+ port = &s->ports[i];
+ if (!(port->wPortStatus & PORT_STAT_ENABLE)) {
+ continue;
+ }
+ downstream = usb_find_device(&port->port, addr);
+ if (downstream != NULL) {
+ return downstream;
+ }
+ }
+ return NULL;
+}
+
static void usb_hub_handle_reset(USBDevice *dev)
{
USBHubState *s = DO_UPCAST(USBHubState, dev, dev);
@@ -541,6 +561,7 @@ static struct USBDeviceInfo hub_info = {
.qdev.vmsd = &vmstate_usb_hub,
.usb_desc = &desc_hub,
.init = usb_hub_initfn,
+ .find_device = usb_hub_find_device,
.handle_packet = usb_hub_handle_packet,
.handle_reset = usb_hub_handle_reset,
.handle_control = usb_hub_handle_control,
--
1.7.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [Qemu-devel] [PATCH 06/25] usb: handle dev == NULL in usb_handle_packet()
2012-01-23 14:54 [Qemu-devel] [PATCH 00/25] *** SUBJECT HERE *** Gerd Hoffmann
` (4 preceding siblings ...)
2012-01-23 14:54 ` [Qemu-devel] [PATCH 05/25] usb-hub: implement find_device Gerd Hoffmann
@ 2012-01-23 14:54 ` Gerd Hoffmann
2012-01-23 14:54 ` [Qemu-devel] [PATCH 07/25] usb-uhci: switch to usb_find_device() Gerd Hoffmann
` (19 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Gerd Hoffmann @ 2012-01-23 14:54 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Allow passing in a NULL pointer, return USB_RET_NODEV in that case.
Removes the burden to to a NULL pointer check from the callers.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/hw/usb.c b/hw/usb.c
index 5482c92..80afd99 100644
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -322,6 +322,10 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p)
{
int ret;
+ if (dev == NULL) {
+ return USB_RET_NODEV;
+ }
+
assert(p->owner == NULL);
ret = dev->info->handle_packet(dev, p);
if (ret == USB_RET_ASYNC) {
--
1.7.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [Qemu-devel] [PATCH 07/25] usb-uhci: switch to usb_find_device()
2012-01-23 14:54 [Qemu-devel] [PATCH 00/25] *** SUBJECT HERE *** Gerd Hoffmann
` (5 preceding siblings ...)
2012-01-23 14:54 ` [Qemu-devel] [PATCH 06/25] usb: handle dev == NULL in usb_handle_packet() Gerd Hoffmann
@ 2012-01-23 14:54 ` Gerd Hoffmann
2012-01-23 14:54 ` [Qemu-devel] [PATCH 08/25] usb-ehci: " Gerd Hoffmann
` (18 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Gerd Hoffmann @ 2012-01-23 14:54 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Switch over UHCI to use the new usb_find_device()
function for device lookup.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb-uhci.c | 45 +++++++++++++++------------------------------
1 files changed, 15 insertions(+), 30 deletions(-)
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index 485dc1d..868ac83 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -94,15 +94,6 @@ static const char *pid2str(int pid)
#define DPRINTF(...)
#endif
-#ifdef DEBUG_DUMP_DATA
-static void dump_data(USBPacket *p, int ret)
-{
- iov_hexdump(p->iov.iov, p->iov.niov, stderr, "uhci", ret);
-}
-#else
-static void dump_data(USBPacket *p, int ret) {}
-#endif
-
typedef struct UHCIState UHCIState;
/*
@@ -643,30 +634,22 @@ static void uhci_wakeup(USBPort *port1)
}
}
-static int uhci_broadcast_packet(UHCIState *s, USBPacket *p)
+static USBDevice *uhci_find_device(UHCIState *s, uint8_t addr)
{
- int i, ret;
-
- DPRINTF("uhci: packet enter. pid %s addr 0x%02x ep %d len %zd\n",
- pid2str(p->pid), p->devaddr, p->devep, p->iov.size);
- if (p->pid == USB_TOKEN_OUT || p->pid == USB_TOKEN_SETUP)
- dump_data(p, 0);
+ USBDevice *dev;
+ int i;
- ret = USB_RET_NODEV;
- for (i = 0; i < NB_PORTS && ret == USB_RET_NODEV; i++) {
+ for (i = 0; i < NB_PORTS; i++) {
UHCIPort *port = &s->ports[i];
- USBDevice *dev = port->port.dev;
-
- if (dev && dev->attached && (port->ctrl & UHCI_PORT_EN)) {
- ret = usb_handle_packet(dev, p);
+ if (!(port->ctrl & UHCI_PORT_EN)) {
+ continue;
+ }
+ dev = usb_find_device(&port->port, addr);
+ if (dev != NULL) {
+ return dev;
}
}
-
- DPRINTF("uhci: packet exit. ret %d len %zd\n", ret, p->iov.size);
- if (p->pid == USB_TOKEN_IN && ret > 0)
- dump_data(p, ret);
-
- return ret;
+ return NULL;
}
static void uhci_async_complete(USBPort *port, USBPacket *packet);
@@ -830,13 +813,15 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, uint32_t *in
switch(pid) {
case USB_TOKEN_OUT:
case USB_TOKEN_SETUP:
- len = uhci_broadcast_packet(s, &async->packet);
+ len = usb_handle_packet(uhci_find_device(s, async->packet.devaddr),
+ &async->packet);
if (len >= 0)
len = max_len;
break;
case USB_TOKEN_IN:
- len = uhci_broadcast_packet(s, &async->packet);
+ len = usb_handle_packet(uhci_find_device(s, async->packet.devaddr),
+ &async->packet);
break;
default:
--
1.7.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [Qemu-devel] [PATCH 08/25] usb-ehci: switch to usb_find_device()
2012-01-23 14:54 [Qemu-devel] [PATCH 00/25] *** SUBJECT HERE *** Gerd Hoffmann
` (6 preceding siblings ...)
2012-01-23 14:54 ` [Qemu-devel] [PATCH 07/25] usb-uhci: switch to usb_find_device() Gerd Hoffmann
@ 2012-01-23 14:54 ` Gerd Hoffmann
2012-01-23 14:54 ` [Qemu-devel] [PATCH 09/25] usb-ohci: " Gerd Hoffmann
` (17 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Gerd Hoffmann @ 2012-01-23 14:54 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Switch over EHCI to use the new usb_find_device()
function for device lookup.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb-ehci.c | 69 ++++++++++++++++++++++++---------------------------------
1 files changed, 29 insertions(+), 40 deletions(-)
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index 7c75510..797b333 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -850,6 +850,26 @@ static int ehci_register_companion(USBBus *bus, USBPort *ports[],
return 0;
}
+static USBDevice *ehci_find_device(EHCIState *ehci, uint8_t addr)
+{
+ USBDevice *dev;
+ USBPort *port;
+ int i;
+
+ for (i = 0; i < NB_PORTS; i++) {
+ port = &ehci->ports[i];
+ if (!(ehci->portsc[i] & PORTSC_PED)) {
+ DPRINTF("Port %d not enabled\n", i);
+ continue;
+ }
+ dev = usb_find_device(port, addr);
+ if (dev != NULL) {
+ return dev;
+ }
+ }
+ return NULL;
+}
+
/* 4.1 host controller initialization */
static void ehci_reset(void *opaque)
{
@@ -1336,10 +1356,8 @@ err:
static int ehci_execute(EHCIQueue *q)
{
- USBPort *port;
USBDevice *dev;
int ret;
- int i;
int endp;
int devadr;
@@ -1375,27 +1393,12 @@ static int ehci_execute(EHCIQueue *q)
usb_packet_map(&q->packet, &q->sgl);
// TO-DO: associating device with ehci port
- for(i = 0; i < NB_PORTS; i++) {
- port = &q->ehci->ports[i];
- dev = port->dev;
-
- if (!(q->ehci->portsc[i] &(PORTSC_CONNECT))) {
- DPRINTF("Port %d, no exec, not connected(%08X)\n",
- i, q->ehci->portsc[i]);
- continue;
- }
-
- ret = usb_handle_packet(dev, &q->packet);
-
- DPRINTF("submit: qh %x next %x qtd %x pid %x len %zd "
- "(total %d) endp %x ret %d\n",
- q->qhaddr, q->qh.next, q->qtdaddr, q->pid,
- q->packet.iov.size, q->tbytes, endp, ret);
-
- if (ret != USB_RET_NODEV) {
- break;
- }
- }
+ dev = ehci_find_device(q->ehci, q->packet.devaddr);
+ ret = usb_handle_packet(dev, &q->packet);
+ DPRINTF("submit: qh %x next %x qtd %x pid %x len %zd "
+ "(total %d) endp %x ret %d\n",
+ q->qhaddr, q->qh.next, q->qtdaddr, q->pid,
+ q->packet.iov.size, q->tbytes, endp, ret);
if (ret > BUFF_SIZE) {
fprintf(stderr, "ret from usb_handle_packet > BUFF_SIZE\n");
@@ -1411,10 +1414,9 @@ static int ehci_execute(EHCIQueue *q)
static int ehci_process_itd(EHCIState *ehci,
EHCIitd *itd)
{
- USBPort *port;
USBDevice *dev;
int ret;
- uint32_t i, j, len, pid, dir, devaddr, endp;
+ uint32_t i, len, pid, dir, devaddr, endp;
uint32_t pg, off, ptr1, ptr2, max, mult;
dir =(itd->bufptr[1] & ITD_BUFPTR_DIRECTION);
@@ -1455,21 +1457,8 @@ static int ehci_process_itd(EHCIState *ehci,
usb_packet_setup(&ehci->ipacket, pid, devaddr, endp);
usb_packet_map(&ehci->ipacket, &ehci->isgl);
- ret = USB_RET_NODEV;
- for (j = 0; j < NB_PORTS; j++) {
- port = &ehci->ports[j];
- dev = port->dev;
-
- if (!(ehci->portsc[j] &(PORTSC_CONNECT))) {
- continue;
- }
-
- ret = usb_handle_packet(dev, &ehci->ipacket);
-
- if (ret != USB_RET_NODEV) {
- break;
- }
- }
+ dev = ehci_find_device(ehci, ehci->ipacket.devaddr);
+ ret = usb_handle_packet(dev, &ehci->ipacket);
usb_packet_unmap(&ehci->ipacket);
qemu_sglist_destroy(&ehci->isgl);
--
1.7.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [Qemu-devel] [PATCH 09/25] usb-ohci: switch to usb_find_device()
2012-01-23 14:54 [Qemu-devel] [PATCH 00/25] *** SUBJECT HERE *** Gerd Hoffmann
` (7 preceding siblings ...)
2012-01-23 14:54 ` [Qemu-devel] [PATCH 08/25] usb-ehci: " Gerd Hoffmann
@ 2012-01-23 14:54 ` Gerd Hoffmann
2012-01-23 14:54 ` [Qemu-devel] [PATCH 10/25] usb-musb: " Gerd Hoffmann
` (16 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Gerd Hoffmann @ 2012-01-23 14:54 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Switch over OHCI to use the new usb_find_device()
function for device lookup.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb-ohci.c | 73 +++++++++++++++++++++++++++++----------------------------
1 files changed, 37 insertions(+), 36 deletions(-)
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index 77f8949..e79b9a8 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -408,6 +408,23 @@ static void ohci_child_detach(USBPort *port1, USBDevice *child)
ohci_async_cancel_device(s, child);
}
+static USBDevice *ohci_find_device(OHCIState *ohci, uint8_t addr)
+{
+ USBDevice *dev;
+ int i;
+
+ for (i = 0; i < ohci->num_ports; i++) {
+ if ((ohci->rhport[i].ctrl & OHCI_PORT_PES) == 0) {
+ continue;
+ }
+ dev = usb_find_device(&ohci->rhport[i].port, addr);
+ if (dev != NULL) {
+ return dev;
+ }
+ }
+ return NULL;
+}
+
/* Reset the controller */
static void ohci_reset(void *opaque)
{
@@ -779,20 +796,12 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed,
if (completion) {
ret = ohci->usb_packet.result;
} else {
- ret = USB_RET_NODEV;
- for (i = 0; i < ohci->num_ports; i++) {
- dev = ohci->rhport[i].port.dev;
- if ((ohci->rhport[i].ctrl & OHCI_PORT_PES) == 0)
- continue;
- usb_packet_setup(&ohci->usb_packet, pid,
- OHCI_BM(ed->flags, ED_FA),
- OHCI_BM(ed->flags, ED_EN));
- usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, len);
- ret = usb_handle_packet(dev, &ohci->usb_packet);
- if (ret != USB_RET_NODEV)
- break;
- }
-
+ usb_packet_setup(&ohci->usb_packet, pid,
+ OHCI_BM(ed->flags, ED_FA),
+ OHCI_BM(ed->flags, ED_EN));
+ usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, len);
+ dev = ohci_find_device(ohci, ohci->usb_packet.devaddr);
+ ret = usb_handle_packet(dev, &ohci->usb_packet);
if (ret == USB_RET_ASYNC) {
return 1;
}
@@ -972,31 +981,23 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
ohci->async_td = 0;
ohci->async_complete = 0;
} else {
- ret = USB_RET_NODEV;
- for (i = 0; i < ohci->num_ports; i++) {
- dev = ohci->rhport[i].port.dev;
- if ((ohci->rhport[i].ctrl & OHCI_PORT_PES) == 0)
- continue;
-
- if (ohci->async_td) {
- /* ??? The hardware should allow one active packet per
- endpoint. We only allow one active packet per controller.
- This should be sufficient as long as devices respond in a
- timely manner.
- */
+ if (ohci->async_td) {
+ /* ??? The hardware should allow one active packet per
+ endpoint. We only allow one active packet per controller.
+ This should be sufficient as long as devices respond in a
+ timely manner.
+ */
#ifdef DEBUG_PACKET
- DPRINTF("Too many pending packets\n");
+ DPRINTF("Too many pending packets\n");
#endif
- return 1;
- }
- usb_packet_setup(&ohci->usb_packet, pid,
- OHCI_BM(ed->flags, ED_FA),
- OHCI_BM(ed->flags, ED_EN));
- usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, pktlen);
- ret = usb_handle_packet(dev, &ohci->usb_packet);
- if (ret != USB_RET_NODEV)
- break;
+ return 1;
}
+ usb_packet_setup(&ohci->usb_packet, pid,
+ OHCI_BM(ed->flags, ED_FA),
+ OHCI_BM(ed->flags, ED_EN));
+ usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, pktlen);
+ dev = ohci_find_device(ohci, ohci->usb_packet.devaddr);
+ ret = usb_handle_packet(dev, &ohci->usb_packet);
#ifdef DEBUG_PACKET
DPRINTF("ret=%d\n", ret);
#endif
--
1.7.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [Qemu-devel] [PATCH 10/25] usb-musb: switch to usb_find_device()
2012-01-23 14:54 [Qemu-devel] [PATCH 00/25] *** SUBJECT HERE *** Gerd Hoffmann
` (8 preceding siblings ...)
2012-01-23 14:54 ` [Qemu-devel] [PATCH 09/25] usb-ohci: " Gerd Hoffmann
@ 2012-01-23 14:54 ` Gerd Hoffmann
2012-01-23 14:54 ` [Qemu-devel] [PATCH 11/25] usb-xhci: " Gerd Hoffmann
` (15 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Gerd Hoffmann @ 2012-01-23 14:54 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Switch over musb to use the new usb_find_device()
function for device lookup.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb-musb.c | 7 +++----
1 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/hw/usb-musb.c b/hw/usb-musb.c
index c2753c9..ecac631 100644
--- a/hw/usb-musb.c
+++ b/hw/usb-musb.c
@@ -605,6 +605,7 @@ static int musb_timeout(int ttype, int speed, int val)
static void musb_packet(MUSBState *s, MUSBEndPoint *ep,
int epnum, int pid, int len, USBCallback cb, int dir)
{
+ USBDevice *dev;
int ret;
int idx = epnum && dir;
int ttype;
@@ -628,10 +629,8 @@ static void musb_packet(MUSBState *s, MUSBEndPoint *ep,
ep->packey[dir].ep = ep;
ep->packey[dir].dir = dir;
- if (s->port.dev)
- ret = usb_handle_packet(s->port.dev, &ep->packey[dir].p);
- else
- ret = USB_RET_NODEV;
+ dev = usb_find_device(&s->port, ep->packey[dir].p.devaddr);
+ ret = usb_handle_packet(dev, &ep->packey[dir].p);
if (ret == USB_RET_ASYNC) {
ep->status[dir] = len;
--
1.7.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [Qemu-devel] [PATCH 11/25] usb-xhci: switch to usb_find_device()
2012-01-23 14:54 [Qemu-devel] [PATCH 00/25] *** SUBJECT HERE *** Gerd Hoffmann
` (9 preceding siblings ...)
2012-01-23 14:54 ` [Qemu-devel] [PATCH 10/25] usb-musb: " Gerd Hoffmann
@ 2012-01-23 14:54 ` Gerd Hoffmann
2012-01-23 14:54 ` [Qemu-devel] [PATCH 12/25] usb: kill handle_packet callback Gerd Hoffmann
` (14 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Gerd Hoffmann @ 2012-01-23 14:54 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Switch over xHCI to use the new usb_find_device()
function for device lookup.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb-xhci.c | 12 ++++++++++--
1 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/hw/usb-xhci.c b/hw/usb-xhci.c
index e089a1b..a9767e3 100644
--- a/hw/usb-xhci.c
+++ b/hw/usb-xhci.c
@@ -1385,6 +1385,14 @@ static int xhci_complete_packet(XHCITransfer *xfer, int ret)
return 0;
}
+static USBDevice *xhci_find_device(XHCIPort *port, uint8_t addr)
+{
+ if (!(port->portsc & PORTSC_PED)) {
+ return NULL;
+ }
+ return usb_find_device(&port->port, addr);
+}
+
static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
{
XHCITRB *trb_setup, *trb_status;
@@ -1444,7 +1452,7 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
xfer->data_length = wLength;
port = &xhci->ports[xhci->slots[xfer->slotid-1].port-1];
- dev = port->port.dev;
+ dev = xhci_find_device(port, xhci->slots[xfer->slotid-1].devaddr);
if (!dev) {
fprintf(stderr, "xhci: slot %d port %d has no device\n", xfer->slotid,
xhci->slots[xfer->slotid-1].port);
@@ -1502,7 +1510,7 @@ static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx
}
port = &xhci->ports[xhci->slots[xfer->slotid-1].port-1];
- dev = port->port.dev;
+ dev = xhci_find_device(port, xhci->slots[xfer->slotid-1].devaddr);
if (!dev) {
fprintf(stderr, "xhci: slot %d port %d has no device\n", xfer->slotid,
xhci->slots[xfer->slotid-1].port);
--
1.7.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [Qemu-devel] [PATCH 12/25] usb: kill handle_packet callback
2012-01-23 14:54 [Qemu-devel] [PATCH 00/25] *** SUBJECT HERE *** Gerd Hoffmann
` (10 preceding siblings ...)
2012-01-23 14:54 ` [Qemu-devel] [PATCH 11/25] usb-xhci: " Gerd Hoffmann
@ 2012-01-23 14:54 ` Gerd Hoffmann
2012-01-23 14:54 ` [Qemu-devel] [PATCH 13/25] usb: fold usb_generic_handle_packet into usb_handle_packet Gerd Hoffmann
` (13 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Gerd Hoffmann @ 2012-01-23 14:54 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
All drivers except usb-hub use usb_generic_handle_packet. The only
reason the usb hub has its own function is that it used to be called
with packets which are intended for downstream devices. With the new,
separate device lookup step this doesn't happen any more, so the need
for a different handle_packet callback is gone.
So we can kill the handle_packet callback and just call
usb_generic_handle_packet directly. The special hub handling in
usb_handle_packet() can go away for the same reason.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb-audio.c | 1 -
hw/usb-bt.c | 1 -
hw/usb-ccid.c | 1 -
hw/usb-hid.c | 3 ---
hw/usb-hub.c | 39 ---------------------------------------
hw/usb-msd.c | 1 -
hw/usb-net.c | 1 -
hw/usb-serial.c | 2 --
hw/usb-wacom.c | 1 -
hw/usb.c | 15 ++++-----------
hw/usb.h | 10 ----------
usb-bsd.c | 1 -
usb-linux.c | 1 -
usb-redir.c | 1 -
14 files changed, 4 insertions(+), 74 deletions(-)
diff --git a/hw/usb-audio.c b/hw/usb-audio.c
index b22d578..560f8e3 100644
--- a/hw/usb-audio.c
+++ b/hw/usb-audio.c
@@ -682,7 +682,6 @@ static struct USBDeviceInfo usb_audio_info = {
.qdev.vmsd = &vmstate_usb_audio,
.usb_desc = &desc_audio,
.init = usb_audio_initfn,
- .handle_packet = usb_generic_handle_packet,
.handle_reset = usb_audio_handle_reset,
.handle_control = usb_audio_handle_control,
.handle_data = usb_audio_handle_data,
diff --git a/hw/usb-bt.c b/hw/usb-bt.c
index 0c1270b..ab1f5e5 100644
--- a/hw/usb-bt.c
+++ b/hw/usb-bt.c
@@ -534,7 +534,6 @@ static struct USBDeviceInfo bt_info = {
.qdev.vmsd = &vmstate_usb_bt,
.usb_desc = &desc_bluetooth,
.init = usb_bt_initfn,
- .handle_packet = usb_generic_handle_packet,
.handle_reset = usb_bt_handle_reset,
.handle_control = usb_bt_handle_control,
.handle_data = usb_bt_handle_data,
diff --git a/hw/usb-ccid.c b/hw/usb-ccid.c
index e9935ad..63c4bcf 100644
--- a/hw/usb-ccid.c
+++ b/hw/usb-ccid.c
@@ -1293,7 +1293,6 @@ static struct USBDeviceInfo ccid_info = {
.qdev.size = sizeof(USBCCIDState),
.init = ccid_initfn,
.usb_desc = &desc_ccid,
- .handle_packet = usb_generic_handle_packet,
.handle_reset = ccid_handle_reset,
.handle_control = ccid_handle_control,
.handle_data = ccid_handle_data,
diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index 997f828..e40bb80 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -562,7 +562,6 @@ static struct USBDeviceInfo hid_info[] = {
.qdev.vmsd = &vmstate_usb_ptr,
.usb_desc = &desc_tablet,
.init = usb_tablet_initfn,
- .handle_packet = usb_generic_handle_packet,
.handle_reset = usb_hid_handle_reset,
.handle_control = usb_hid_handle_control,
.handle_data = usb_hid_handle_data,
@@ -575,7 +574,6 @@ static struct USBDeviceInfo hid_info[] = {
.qdev.vmsd = &vmstate_usb_ptr,
.usb_desc = &desc_mouse,
.init = usb_mouse_initfn,
- .handle_packet = usb_generic_handle_packet,
.handle_reset = usb_hid_handle_reset,
.handle_control = usb_hid_handle_control,
.handle_data = usb_hid_handle_data,
@@ -588,7 +586,6 @@ static struct USBDeviceInfo hid_info[] = {
.qdev.vmsd = &vmstate_usb_kbd,
.usb_desc = &desc_keyboard,
.init = usb_keyboard_initfn,
- .handle_packet = usb_generic_handle_packet,
.handle_reset = usb_hid_handle_reset,
.handle_control = usb_hid_handle_control,
.handle_data = usb_hid_handle_data,
diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index c9f30d9..49fc349 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -455,44 +455,6 @@ static int usb_hub_handle_data(USBDevice *dev, USBPacket *p)
return ret;
}
-static int usb_hub_broadcast_packet(USBHubState *s, USBPacket *p)
-{
- USBHubPort *port;
- USBDevice *dev;
- int i, ret;
-
- for(i = 0; i < NUM_PORTS; i++) {
- port = &s->ports[i];
- dev = port->port.dev;
- if (dev && dev->attached && (port->wPortStatus & PORT_STAT_ENABLE)) {
- ret = usb_handle_packet(dev, p);
- if (ret != USB_RET_NODEV) {
- return ret;
- }
- }
- }
- return USB_RET_NODEV;
-}
-
-static int usb_hub_handle_packet(USBDevice *dev, USBPacket *p)
-{
- USBHubState *s = (USBHubState *)dev;
-
-#if defined(DEBUG) && 0
- printf("usb_hub: pid=0x%x\n", pid);
-#endif
- if (dev->state == USB_STATE_DEFAULT &&
- dev->addr != 0 &&
- p->devaddr != dev->addr &&
- (p->pid == USB_TOKEN_SETUP ||
- p->pid == USB_TOKEN_OUT ||
- p->pid == USB_TOKEN_IN)) {
- /* broadcast the packet to the devices */
- return usb_hub_broadcast_packet(s, p);
- }
- return usb_generic_handle_packet(dev, p);
-}
-
static void usb_hub_handle_destroy(USBDevice *dev)
{
USBHubState *s = (USBHubState *)dev;
@@ -562,7 +524,6 @@ static struct USBDeviceInfo hub_info = {
.usb_desc = &desc_hub,
.init = usb_hub_initfn,
.find_device = usb_hub_find_device,
- .handle_packet = usb_hub_handle_packet,
.handle_reset = usb_hub_handle_reset,
.handle_control = usb_hub_handle_control,
.handle_data = usb_hub_handle_data,
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 186831d..46681fd 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -644,7 +644,6 @@ static struct USBDeviceInfo msd_info = {
.qdev.vmsd = &vmstate_usb_msd,
.usb_desc = &desc,
.init = usb_msd_initfn,
- .handle_packet = usb_generic_handle_packet,
.cancel_packet = usb_msd_cancel_io,
.handle_attach = usb_desc_attach,
.handle_reset = usb_msd_handle_reset,
diff --git a/hw/usb-net.c b/hw/usb-net.c
index 2f527a8..6a35f0f 100644
--- a/hw/usb-net.c
+++ b/hw/usb-net.c
@@ -1393,7 +1393,6 @@ static struct USBDeviceInfo net_info = {
.qdev.vmsd = &vmstate_usb_net,
.usb_desc = &desc_net,
.init = usb_net_initfn,
- .handle_packet = usb_generic_handle_packet,
.handle_reset = usb_net_handle_reset,
.handle_control = usb_net_handle_control,
.handle_data = usb_net_handle_data,
diff --git a/hw/usb-serial.c b/hw/usb-serial.c
index e3c8238..391f41e 100644
--- a/hw/usb-serial.c
+++ b/hw/usb-serial.c
@@ -577,7 +577,6 @@ static struct USBDeviceInfo serial_info = {
.qdev.vmsd = &vmstate_usb_serial,
.usb_desc = &desc_serial,
.init = usb_serial_initfn,
- .handle_packet = usb_generic_handle_packet,
.handle_reset = usb_serial_handle_reset,
.handle_control = usb_serial_handle_control,
.handle_data = usb_serial_handle_data,
@@ -597,7 +596,6 @@ static struct USBDeviceInfo braille_info = {
.qdev.vmsd = &vmstate_usb_serial,
.usb_desc = &desc_braille,
.init = usb_serial_initfn,
- .handle_packet = usb_generic_handle_packet,
.handle_reset = usb_serial_handle_reset,
.handle_control = usb_serial_handle_control,
.handle_data = usb_serial_handle_data,
diff --git a/hw/usb-wacom.c b/hw/usb-wacom.c
index 61d5b18..6ebaed1 100644
--- a/hw/usb-wacom.c
+++ b/hw/usb-wacom.c
@@ -358,7 +358,6 @@ static struct USBDeviceInfo wacom_info = {
.qdev.size = sizeof(USBWacomState),
.qdev.vmsd = &vmstate_usb_wacom,
.init = usb_wacom_initfn,
- .handle_packet = usb_generic_handle_packet,
.handle_reset = usb_wacom_handle_reset,
.handle_control = usb_wacom_handle_control,
.handle_data = usb_wacom_handle_data,
diff --git a/hw/usb.c b/hw/usb.c
index 80afd99..70a4bc5 100644
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -231,7 +231,7 @@ static int do_token_out(USBDevice *s, USBPacket *p)
*
* Returns length of the transaction or one of the USB_RET_XXX codes.
*/
-int usb_generic_handle_packet(USBDevice *s, USBPacket *p)
+static int usb_generic_handle_packet(USBDevice *s, USBPacket *p)
{
/* Rest of the PIDs must match our address */
if (s->state < USB_STATE_DEFAULT || p->devaddr != s->addr)
@@ -325,18 +325,12 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p)
if (dev == NULL) {
return USB_RET_NODEV;
}
+ assert(dev->addr == p->devaddr);
assert(p->owner == NULL);
- ret = dev->info->handle_packet(dev, p);
+ ret = usb_generic_handle_packet(dev, p);
if (ret == USB_RET_ASYNC) {
- if (p->owner == NULL) {
- p->owner = usb_ep_get(dev, p->pid, p->devep);
- } else {
- /* We'll end up here when usb_handle_packet is called
- * recursively due to a hub being in the chain. Nothing
- * to do. Leave p->owner pointing to the device, not the
- * hub. */;
- }
+ p->owner = usb_ep_get(dev, p->pid, p->devep);
}
return ret;
}
@@ -346,7 +340,6 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p)
handle_packet. */
void usb_packet_complete(USBDevice *dev, USBPacket *p)
{
- /* Note: p->owner != dev is possible in case dev is a hub */
assert(p->owner != NULL);
p->owner = NULL;
dev->port->ops->complete(dev->port, p);
diff --git a/hw/usb.h b/hw/usb.h
index b0ba3e0..82ca924 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -225,15 +225,6 @@ struct USBDeviceInfo {
USBDevice *(*find_device)(USBDevice *dev, uint8_t addr);
/*
- * Process USB packet.
- * Called by the HC (Host Controller).
- *
- * Returns length of the transaction
- * or one of the USB_RET_XXX codes.
- */
- int (*handle_packet)(USBDevice *dev, USBPacket *p);
-
- /*
* Called when a packet is canceled.
*/
void (*cancel_packet)(USBDevice *dev, USBPacket *p);
@@ -354,7 +345,6 @@ void usb_detach(USBPort *port);
void usb_port_reset(USBPort *port);
void usb_device_reset(USBDevice *dev);
void usb_wakeup(USBDevice *dev);
-int usb_generic_handle_packet(USBDevice *s, USBPacket *p);
void usb_generic_async_ctrl_complete(USBDevice *s, USBPacket *p);
int set_usb_string(uint8_t *buf, const char *str);
diff --git a/usb-bsd.c b/usb-bsd.c
index 1187552..2f34f1b 100644
--- a/usb-bsd.c
+++ b/usb-bsd.c
@@ -402,7 +402,6 @@ static struct USBDeviceInfo usb_host_dev_info = {
.qdev.name = "usb-host",
.qdev.size = sizeof(USBHostDevice),
.init = usb_host_initfn,
- .handle_packet = usb_generic_handle_packet,
.handle_reset = usb_host_handle_reset,
.handle_control = usb_host_handle_control,
.handle_data = usb_host_handle_data,
diff --git a/usb-linux.c b/usb-linux.c
index 56898dd..26d1cc4 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -1408,7 +1408,6 @@ static struct USBDeviceInfo usb_host_dev_info = {
.qdev.size = sizeof(USBHostDevice),
.qdev.vmsd = &vmstate_usb_host,
.init = usb_host_initfn,
- .handle_packet = usb_generic_handle_packet,
.cancel_packet = usb_host_async_cancel,
.handle_data = usb_host_handle_data,
.handle_control = usb_host_handle_control,
diff --git a/usb-redir.c b/usb-redir.c
index 79d29ec..459eae8 100644
--- a/usb-redir.c
+++ b/usb-redir.c
@@ -1321,7 +1321,6 @@ static struct USBDeviceInfo usbredir_dev_info = {
.qdev.size = sizeof(USBRedirDevice),
.init = usbredir_initfn,
.handle_destroy = usbredir_handle_destroy,
- .handle_packet = usb_generic_handle_packet,
.cancel_packet = usbredir_cancel_packet,
.handle_reset = usbredir_handle_reset,
.handle_data = usbredir_handle_data,
--
1.7.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [Qemu-devel] [PATCH 13/25] usb: fold usb_generic_handle_packet into usb_handle_packet
2012-01-23 14:54 [Qemu-devel] [PATCH 00/25] *** SUBJECT HERE *** Gerd Hoffmann
` (11 preceding siblings ...)
2012-01-23 14:54 ` [Qemu-devel] [PATCH 12/25] usb: kill handle_packet callback Gerd Hoffmann
@ 2012-01-23 14:54 ` Gerd Hoffmann
2012-01-23 14:55 ` [Qemu-devel] [PATCH 14/25] usb: USBPacket: add status, rename owner -> ep Gerd Hoffmann
` (12 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Gerd Hoffmann @ 2012-01-23 14:54 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
There is no reason to have a separate usb_generic_handle_packet function
any more, fold it into usb_handle_packet(). Also call the do_token_*
functions which handle control transfer emulation for control pipe
packets only.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb.c | 58 +++++++++++++++++++++++++---------------------------------
1 files changed, 25 insertions(+), 33 deletions(-)
diff --git a/hw/usb.c b/hw/usb.c
index 70a4bc5..0bf98a0 100644
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -144,8 +144,7 @@ static int do_token_in(USBDevice *s, USBPacket *p)
int request, value, index;
int ret = 0;
- if (p->devep != 0)
- return s->info->handle_data(s, p);
+ assert(p->devep == 0);
request = (s->setup_buf[0] << 8) | s->setup_buf[1];
value = (s->setup_buf[3] << 8) | s->setup_buf[2];
@@ -191,8 +190,7 @@ static int do_token_in(USBDevice *s, USBPacket *p)
static int do_token_out(USBDevice *s, USBPacket *p)
{
- if (p->devep != 0)
- return s->info->handle_data(s, p);
+ assert(p->devep == 0);
switch(s->setup_state) {
case SETUP_STATE_ACK:
@@ -225,33 +223,6 @@ static int do_token_out(USBDevice *s, USBPacket *p)
}
}
-/*
- * Generic packet handler.
- * Called by the HC (host controller).
- *
- * Returns length of the transaction or one of the USB_RET_XXX codes.
- */
-static int usb_generic_handle_packet(USBDevice *s, USBPacket *p)
-{
- /* Rest of the PIDs must match our address */
- if (s->state < USB_STATE_DEFAULT || p->devaddr != s->addr)
- return USB_RET_NODEV;
-
- switch (p->pid) {
- case USB_TOKEN_SETUP:
- return do_token_setup(s, p);
-
- case USB_TOKEN_IN:
- return do_token_in(s, p);
-
- case USB_TOKEN_OUT:
- return do_token_out(s, p);
-
- default:
- return USB_RET_STALL;
- }
-}
-
/* 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
@@ -326,9 +297,30 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p)
return USB_RET_NODEV;
}
assert(dev->addr == p->devaddr);
-
+ assert(dev->state == USB_STATE_DEFAULT);
assert(p->owner == NULL);
- ret = usb_generic_handle_packet(dev, p);
+
+ if (p->devep == 0) {
+ /* control pipe */
+ switch (p->pid) {
+ case USB_TOKEN_SETUP:
+ ret = do_token_setup(dev, p);
+ break;
+ case USB_TOKEN_IN:
+ ret = do_token_in(dev, p);
+ break;
+ case USB_TOKEN_OUT:
+ ret = do_token_out(dev, p);
+ break;
+ default:
+ ret = USB_RET_STALL;
+ break;
+ }
+ } else {
+ /* data pipe */
+ ret = dev->info->handle_data(dev, p);
+ }
+
if (ret == USB_RET_ASYNC) {
p->owner = usb_ep_get(dev, p->pid, p->devep);
}
--
1.7.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [Qemu-devel] [PATCH 14/25] usb: USBPacket: add status, rename owner -> ep
2012-01-23 14:54 [Qemu-devel] [PATCH 00/25] *** SUBJECT HERE *** Gerd Hoffmann
` (12 preceding siblings ...)
2012-01-23 14:54 ` [Qemu-devel] [PATCH 13/25] usb: fold usb_generic_handle_packet into usb_handle_packet Gerd Hoffmann
@ 2012-01-23 14:55 ` Gerd Hoffmann
2012-01-23 14:55 ` [Qemu-devel] [PATCH 15/25] usb: add USBEndpoint->{nr,pid} Gerd Hoffmann
` (11 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Gerd Hoffmann @ 2012-01-23 14:55 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Add enum to track the status of USBPackets, use that instead of the
owner pointer to figure whenever a usb packet is currently in flight
or not. Add some more packet status sanity checks. Also rename the
USBEndpoint pointer from "owner" to "ep".
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb-ehci.c | 4 ++--
hw/usb-musb.c | 4 ++--
hw/usb-ohci.c | 4 ++--
hw/usb-uhci.c | 4 ++--
hw/usb.c | 18 +++++++++++-------
hw/usb.h | 19 ++++++++++++++++---
6 files changed, 35 insertions(+), 18 deletions(-)
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index 797b333..0ddcac6 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -715,8 +715,8 @@ static void ehci_queues_rip_device(EHCIState *ehci, USBDevice *dev)
EHCIQueue *q, *tmp;
QTAILQ_FOREACH_SAFE(q, &ehci->queues, next, tmp) {
- if (q->packet.owner == NULL ||
- q->packet.owner->dev != dev) {
+ if (!usb_packet_is_inflight(&q->packet) ||
+ q->packet.ep->dev != dev) {
continue;
}
ehci_free_queue(q);
diff --git a/hw/usb-musb.c b/hw/usb-musb.c
index ecac631..f4e52f1 100644
--- a/hw/usb-musb.c
+++ b/hw/usb-musb.c
@@ -811,8 +811,8 @@ static void musb_async_cancel_device(MUSBState *s, USBDevice *dev)
for (ep = 0; ep < 16; ep++) {
for (dir = 0; dir < 2; dir++) {
- if (s->ep[ep].packey[dir].p.owner == NULL ||
- s->ep[ep].packey[dir].p.owner->dev != dev) {
+ if (!usb_packet_is_inflight(&s->ep[ep].packey[dir].p) ||
+ s->ep[ep].packey[dir].p.ep->dev != dev) {
continue;
}
usb_cancel_packet(&s->ep[ep].packey[dir].p);
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index e79b9a8..4e33638 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -1709,8 +1709,8 @@ static void ohci_mem_write(void *opaque,
static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev)
{
if (ohci->async_td &&
- ohci->usb_packet.owner != NULL &&
- ohci->usb_packet.owner->dev == dev) {
+ usb_packet_is_inflight(&ohci->usb_packet) &&
+ ohci->usb_packet.ep->dev == dev) {
usb_cancel_packet(&ohci->usb_packet);
ohci->async_td = 0;
}
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index 868ac83..341e112 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -236,8 +236,8 @@ static void uhci_async_cancel_device(UHCIState *s, USBDevice *dev)
UHCIAsync *curr, *n;
QTAILQ_FOREACH_SAFE(curr, &s->async_pending, next, n) {
- if (curr->packet.owner == NULL ||
- curr->packet.owner->dev != dev) {
+ if (!usb_packet_is_inflight(&curr->packet) ||
+ curr->packet.ep->dev != dev) {
continue;
}
uhci_async_unlink(s, curr);
diff --git a/hw/usb.c b/hw/usb.c
index 0bf98a0..9f44565 100644
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -298,7 +298,7 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p)
}
assert(dev->addr == p->devaddr);
assert(dev->state == USB_STATE_DEFAULT);
- assert(p->owner == NULL);
+ assert(p->state == USB_PACKET_SETUP);
if (p->devep == 0) {
/* control pipe */
@@ -322,7 +322,8 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p)
}
if (ret == USB_RET_ASYNC) {
- p->owner = usb_ep_get(dev, p->pid, p->devep);
+ p->ep = usb_ep_get(dev, p->pid, p->devep);
+ p->state = USB_PACKET_ASYNC;
}
return ret;
}
@@ -332,8 +333,8 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p)
handle_packet. */
void usb_packet_complete(USBDevice *dev, USBPacket *p)
{
- assert(p->owner != NULL);
- p->owner = NULL;
+ assert(p->state == USB_PACKET_ASYNC);
+ p->state = USB_PACKET_COMPLETE;
dev->port->ops->complete(dev->port, p);
}
@@ -342,9 +343,9 @@ void usb_packet_complete(USBDevice *dev, USBPacket *p)
completed. */
void usb_cancel_packet(USBPacket * p)
{
- assert(p->owner != NULL);
- p->owner->dev->info->cancel_packet(p->owner->dev, p);
- p->owner = NULL;
+ assert(p->state == USB_PACKET_ASYNC);
+ p->state = USB_PACKET_CANCELED;
+ p->ep->dev->info->cancel_packet(p->ep->dev, p);
}
@@ -355,6 +356,8 @@ void usb_packet_init(USBPacket *p)
void usb_packet_setup(USBPacket *p, int pid, uint8_t addr, uint8_t ep)
{
+ assert(!usb_packet_is_inflight(p));
+ p->state = USB_PACKET_SETUP;
p->pid = pid;
p->devaddr = addr;
p->devep = ep;
@@ -398,6 +401,7 @@ void usb_packet_skip(USBPacket *p, size_t bytes)
void usb_packet_cleanup(USBPacket *p)
{
+ assert(!usb_packet_is_inflight(p));
qemu_iovec_destroy(&p->iov);
}
diff --git a/hw/usb.h b/hw/usb.h
index 82ca924..2c834d7 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -283,8 +283,7 @@ typedef struct USBPortOps {
void (*wakeup)(USBPort *port);
/*
* Note that port->dev will be different then the device from which
- * the packet originated when a hub is involved, if you want the orginating
- * device use p->owner
+ * the packet originated when a hub is involved.
*/
void (*complete)(USBPort *port, USBPacket *p);
} USBPortOps;
@@ -303,15 +302,24 @@ struct USBPort {
typedef void USBCallback(USBPacket * packet, void *opaque);
/* Structure used to hold information about an active USB packet. */
+typedef enum USBPacketState {
+ USB_PACKET_UNDEFINED = 0,
+ USB_PACKET_SETUP,
+ USB_PACKET_ASYNC,
+ USB_PACKET_COMPLETE,
+ USB_PACKET_CANCELED,
+} USBPacketState;
+
struct USBPacket {
/* Data fields for use by the driver. */
int pid;
uint8_t devaddr;
uint8_t devep;
+ USBEndpoint *ep;
QEMUIOVector iov;
int result; /* transfer length or USB_RET_* status code */
/* Internal use by the USB layer. */
- USBEndpoint *owner;
+ USBPacketState state;
};
void usb_packet_init(USBPacket *p);
@@ -323,6 +331,11 @@ void usb_packet_copy(USBPacket *p, void *ptr, size_t bytes);
void usb_packet_skip(USBPacket *p, size_t bytes);
void usb_packet_cleanup(USBPacket *p);
+static inline bool usb_packet_is_inflight(USBPacket *p)
+{
+ return p->state == USB_PACKET_ASYNC;
+}
+
USBDevice *usb_find_device(USBPort *port, uint8_t addr);
int usb_handle_packet(USBDevice *dev, USBPacket *p);
--
1.7.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [Qemu-devel] [PATCH 15/25] usb: add USBEndpoint->{nr,pid}
2012-01-23 14:54 [Qemu-devel] [PATCH 00/25] *** SUBJECT HERE *** Gerd Hoffmann
` (13 preceding siblings ...)
2012-01-23 14:55 ` [Qemu-devel] [PATCH 14/25] usb: USBPacket: add status, rename owner -> ep Gerd Hoffmann
@ 2012-01-23 14:55 ` Gerd Hoffmann
2012-01-23 14:55 ` [Qemu-devel] [PATCH 16/25] usb: Set USBEndpoint in usb_packet_setup() Gerd Hoffmann
` (10 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Gerd Hoffmann @ 2012-01-23 14:55 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Add a "nr" and "pid" fields to USBEndpoint so you can easily figure the
endpoint number and direction of any given endpoint.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb.c | 5 +++++
hw/usb.h | 2 ++
2 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/hw/usb.c b/hw/usb.c
index 9f44565..73b3ec2 100644
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -409,10 +409,15 @@ void usb_ep_init(USBDevice *dev)
{
int ep;
+ dev->ep_ctl.nr = 0;
dev->ep_ctl.type = USB_ENDPOINT_XFER_CONTROL;
dev->ep_ctl.ifnum = 0;
dev->ep_ctl.dev = dev;
for (ep = 0; ep < USB_MAX_ENDPOINTS; ep++) {
+ dev->ep_in[ep].nr = ep + 1;
+ dev->ep_out[ep].nr = ep + 1;
+ dev->ep_in[ep].pid = USB_TOKEN_IN;
+ dev->ep_out[ep].pid = USB_TOKEN_OUT;
dev->ep_in[ep].type = USB_ENDPOINT_XFER_INVALID;
dev->ep_out[ep].type = USB_ENDPOINT_XFER_INVALID;
dev->ep_in[ep].ifnum = 0;
diff --git a/hw/usb.h b/hw/usb.h
index 2c834d7..5202f3c 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -169,6 +169,8 @@ struct USBDescString {
#define USB_MAX_INTERFACES 16
struct USBEndpoint {
+ uint8_t nr;
+ uint8_t pid;
uint8_t type;
uint8_t ifnum;
int max_packet_size;
--
1.7.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [Qemu-devel] [PATCH 16/25] usb: Set USBEndpoint in usb_packet_setup().
2012-01-23 14:54 [Qemu-devel] [PATCH 00/25] *** SUBJECT HERE *** Gerd Hoffmann
` (14 preceding siblings ...)
2012-01-23 14:55 ` [Qemu-devel] [PATCH 15/25] usb: add USBEndpoint->{nr,pid} Gerd Hoffmann
@ 2012-01-23 14:55 ` Gerd Hoffmann
2012-01-23 14:55 ` [Qemu-devel] [PATCH 17/25] usb: maintain async packet list per endpoint Gerd Hoffmann
` (9 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Gerd Hoffmann @ 2012-01-23 14:55 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
With the separation of the device lookup (via usb_find_device) and
packet processing we can lookup device and endpoint before setting up
the usb packet. So we can initialize USBPacket->ep early and keep it
valid for the whole lifecycle of the USBPacket. Also the devaddr and
devep fields are not needed any more.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb-audio.c | 4 ++--
hw/usb-bt.c | 4 ++--
hw/usb-ccid.c | 2 +-
hw/usb-ehci.c | 15 +++++++++------
hw/usb-hid.c | 2 +-
hw/usb-hub.c | 2 +-
hw/usb-msd.c | 2 +-
hw/usb-musb.c | 7 ++++---
hw/usb-net.c | 6 +++---
hw/usb-ohci.c | 16 ++++++++--------
hw/usb-serial.c | 2 +-
hw/usb-uhci.c | 13 +++++++------
hw/usb-wacom.c | 2 +-
hw/usb-xhci.c | 27 +++++++++++++--------------
hw/usb.c | 21 ++++++++++++---------
hw/usb.h | 4 +---
usb-bsd.c | 2 +-
usb-linux.c | 44 ++++++++++++++++++++++----------------------
usb-redir.c | 2 +-
19 files changed, 91 insertions(+), 86 deletions(-)
diff --git a/hw/usb-audio.c b/hw/usb-audio.c
index 560f8e3..45a82f5 100644
--- a/hw/usb-audio.c
+++ b/hw/usb-audio.c
@@ -607,7 +607,7 @@ static int usb_audio_handle_data(USBDevice *dev, USBPacket *p)
switch (p->pid) {
case USB_TOKEN_OUT:
- switch (p->devep) {
+ switch (p->ep->nr) {
case 1:
ret = usb_audio_handle_dataout(s, p);
break;
@@ -624,7 +624,7 @@ fail:
if (ret == USB_RET_STALL && s->debug) {
fprintf(stderr, "usb-audio: failed data transaction: "
"pid 0x%x ep 0x%x len 0x%zx\n",
- p->pid, p->devep, p->iov.size);
+ p->pid, p->ep->nr, p->iov.size);
}
return ret;
}
diff --git a/hw/usb-bt.c b/hw/usb-bt.c
index ab1f5e5..d2860be 100644
--- a/hw/usb-bt.c
+++ b/hw/usb-bt.c
@@ -423,7 +423,7 @@ static int usb_bt_handle_data(USBDevice *dev, USBPacket *p)
switch (p->pid) {
case USB_TOKEN_IN:
- switch (p->devep & 0xf) {
+ switch (p->ep->nr) {
case USB_EVT_EP:
ret = usb_bt_fifo_dequeue(&s->evt, p);
break;
@@ -442,7 +442,7 @@ static int usb_bt_handle_data(USBDevice *dev, USBPacket *p)
break;
case USB_TOKEN_OUT:
- switch (p->devep & 0xf) {
+ switch (p->ep->nr) {
case USB_ACL_EP:
usb_bt_fifo_out_enqueue(s, &s->outacl, s->hci->acl_send,
usb_bt_hci_acl_complete, p);
diff --git a/hw/usb-ccid.c b/hw/usb-ccid.c
index 63c4bcf..504df87 100644
--- a/hw/usb-ccid.c
+++ b/hw/usb-ccid.c
@@ -959,7 +959,7 @@ static int ccid_handle_data(USBDevice *dev, USBPacket *p)
break;
case USB_TOKEN_IN:
- switch (p->devep & 0xf) {
+ switch (p->ep->nr) {
case CCID_BULK_IN_EP:
if (!p->iov.size) {
ret = USB_RET_NAK;
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index 0ddcac6..0d6e667 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -1357,6 +1357,7 @@ err:
static int ehci_execute(EHCIQueue *q)
{
USBDevice *dev;
+ USBEndpoint *ep;
int ret;
int endp;
int devadr;
@@ -1387,13 +1388,13 @@ static int ehci_execute(EHCIQueue *q)
endp = get_field(q->qh.epchar, QH_EPCHAR_EP);
devadr = get_field(q->qh.epchar, QH_EPCHAR_DEVADDR);
- ret = USB_RET_NODEV;
+ /* TODO: associating device with ehci port */
+ dev = ehci_find_device(q->ehci, devadr);
+ ep = usb_ep_get(dev, q->pid, endp);
- usb_packet_setup(&q->packet, q->pid, devadr, endp);
+ usb_packet_setup(&q->packet, q->pid, ep);
usb_packet_map(&q->packet, &q->sgl);
- // TO-DO: associating device with ehci port
- dev = ehci_find_device(q->ehci, q->packet.devaddr);
ret = usb_handle_packet(dev, &q->packet);
DPRINTF("submit: qh %x next %x qtd %x pid %x len %zd "
"(total %d) endp %x ret %d\n",
@@ -1415,6 +1416,7 @@ static int ehci_process_itd(EHCIState *ehci,
EHCIitd *itd)
{
USBDevice *dev;
+ USBEndpoint *ep;
int ret;
uint32_t i, len, pid, dir, devaddr, endp;
uint32_t pg, off, ptr1, ptr2, max, mult;
@@ -1454,10 +1456,11 @@ static int ehci_process_itd(EHCIState *ehci,
pid = dir ? USB_TOKEN_IN : USB_TOKEN_OUT;
- usb_packet_setup(&ehci->ipacket, pid, devaddr, endp);
+ dev = ehci_find_device(ehci, devaddr);
+ ep = usb_ep_get(dev, pid, endp);
+ usb_packet_setup(&ehci->ipacket, pid, ep);
usb_packet_map(&ehci->ipacket, &ehci->isgl);
- dev = ehci_find_device(ehci, ehci->ipacket.devaddr);
ret = usb_handle_packet(dev, &ehci->ipacket);
usb_packet_unmap(&ehci->ipacket);
diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index e40bb80..f64eb2d 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -463,7 +463,7 @@ static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
switch (p->pid) {
case USB_TOKEN_IN:
- if (p->devep == 1) {
+ if (p->ep->nr == 1) {
int64_t curtime = qemu_get_clock_ns(vm_clock);
if (!hid_has_events(hs) &&
(!hs->idle || hs->next_idle_clock - curtime > 0)) {
diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index 49fc349..88164f5 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -416,7 +416,7 @@ static int usb_hub_handle_data(USBDevice *dev, USBPacket *p)
switch(p->pid) {
case USB_TOKEN_IN:
- if (p->devep == 1) {
+ if (p->ep->nr == 1) {
USBHubPort *port;
unsigned int status;
uint8_t buf[4];
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 46681fd..c7d98b6 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -341,7 +341,7 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
uint32_t tag;
int ret = 0;
struct usb_msd_cbw cbw;
- uint8_t devep = p->devep;
+ uint8_t devep = p->ep->nr;
switch (p->pid) {
case USB_TOKEN_OUT:
diff --git a/hw/usb-musb.c b/hw/usb-musb.c
index f4e52f1..820907a 100644
--- a/hw/usb-musb.c
+++ b/hw/usb-musb.c
@@ -606,6 +606,7 @@ static void musb_packet(MUSBState *s, MUSBEndPoint *ep,
int epnum, int pid, int len, USBCallback cb, int dir)
{
USBDevice *dev;
+ USBEndpoint *uep;
int ret;
int idx = epnum && dir;
int ttype;
@@ -623,13 +624,13 @@ static void musb_packet(MUSBState *s, MUSBEndPoint *ep,
ep->delayed_cb[dir] = cb;
/* A wild guess on the FADDR semantics... */
- usb_packet_setup(&ep->packey[dir].p, pid, ep->faddr[idx],
- ep->type[idx] & 0xf);
+ dev = usb_find_device(&s->port, ep->faddr[idx]);
+ uep = usb_ep_get(dev, pid, ep->type[idx] & 0xf);
+ usb_packet_setup(&ep->packey[dir].p, pid, uep);
usb_packet_addbuf(&ep->packey[dir].p, ep->buf[idx], len);
ep->packey[dir].ep = ep;
ep->packey[dir].dir = dir;
- dev = usb_find_device(&s->port, ep->packey[dir].p.devaddr);
ret = usb_handle_packet(dev, &ep->packey[dir].p);
if (ret == USB_RET_ASYNC) {
diff --git a/hw/usb-net.c b/hw/usb-net.c
index 6a35f0f..1c4bfd1 100644
--- a/hw/usb-net.c
+++ b/hw/usb-net.c
@@ -1210,7 +1210,7 @@ static int usb_net_handle_data(USBDevice *dev, USBPacket *p)
switch(p->pid) {
case USB_TOKEN_IN:
- switch (p->devep) {
+ switch (p->ep->nr) {
case 1:
ret = usb_net_handle_statusin(s, p);
break;
@@ -1225,7 +1225,7 @@ static int usb_net_handle_data(USBDevice *dev, USBPacket *p)
break;
case USB_TOKEN_OUT:
- switch (p->devep) {
+ switch (p->ep->nr) {
case 2:
ret = usb_net_handle_dataout(s, p);
break;
@@ -1243,7 +1243,7 @@ static int usb_net_handle_data(USBDevice *dev, USBPacket *p)
if (ret == USB_RET_STALL)
fprintf(stderr, "usbnet: failed data transaction: "
"pid 0x%x ep 0x%x len 0x%zx\n",
- p->pid, p->devep, p->iov.size);
+ p->pid, p->ep->nr, p->iov.size);
return ret;
}
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index 4e33638..6d34848 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -657,6 +657,7 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed,
int ret;
int i;
USBDevice *dev;
+ USBEndpoint *ep;
struct ohci_iso_td iso_td;
uint32_t addr;
uint16_t starting_frame;
@@ -796,11 +797,10 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed,
if (completion) {
ret = ohci->usb_packet.result;
} else {
- usb_packet_setup(&ohci->usb_packet, pid,
- OHCI_BM(ed->flags, ED_FA),
- OHCI_BM(ed->flags, ED_EN));
+ dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA));
+ ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN));
+ usb_packet_setup(&ohci->usb_packet, pid, ep);
usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, len);
- dev = ohci_find_device(ohci, ohci->usb_packet.devaddr);
ret = usb_handle_packet(dev, &ohci->usb_packet);
if (ret == USB_RET_ASYNC) {
return 1;
@@ -889,6 +889,7 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
int ret;
int i;
USBDevice *dev;
+ USBEndpoint *ep;
struct ohci_td td;
uint32_t addr;
int flag_r;
@@ -992,11 +993,10 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
#endif
return 1;
}
- usb_packet_setup(&ohci->usb_packet, pid,
- OHCI_BM(ed->flags, ED_FA),
- OHCI_BM(ed->flags, ED_EN));
+ dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA));
+ ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN));
+ usb_packet_setup(&ohci->usb_packet, pid, ep);
usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, pktlen);
- dev = ohci_find_device(ohci, ohci->usb_packet.devaddr);
ret = usb_handle_packet(dev, &ohci->usb_packet);
#ifdef DEBUG_PACKET
DPRINTF("ret=%d\n", ret);
diff --git a/hw/usb-serial.c b/hw/usb-serial.c
index 391f41e..9abfa76 100644
--- a/hw/usb-serial.c
+++ b/hw/usb-serial.c
@@ -353,7 +353,7 @@ static int usb_serial_handle_data(USBDevice *dev, USBPacket *p)
{
USBSerialState *s = (USBSerialState *)dev;
int i, ret = 0;
- uint8_t devep = p->devep;
+ uint8_t devep = p->ep->nr;
struct iovec *iov;
uint8_t header[2];
int first_len, len;
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index 341e112..9c07c47 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -761,6 +761,8 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, uint32_t *in
int len = 0, max_len;
uint8_t pid, isoc;
uint32_t token;
+ USBDevice *dev;
+ USBEndpoint *ep;
/* Is active ? */
if (!(td->ctrl & TD_CTRL_ACTIVE))
@@ -805,23 +807,22 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, uint32_t *in
max_len = ((td->token >> 21) + 1) & 0x7ff;
pid = td->token & 0xff;
- usb_packet_setup(&async->packet, pid, (td->token >> 8) & 0x7f,
- (td->token >> 15) & 0xf);
+ dev = uhci_find_device(s, (td->token >> 8) & 0x7f);
+ ep = usb_ep_get(dev, pid, (td->token >> 15) & 0xf);
+ usb_packet_setup(&async->packet, pid, ep);
qemu_sglist_add(&async->sgl, td->buffer, max_len);
usb_packet_map(&async->packet, &async->sgl);
switch(pid) {
case USB_TOKEN_OUT:
case USB_TOKEN_SETUP:
- len = usb_handle_packet(uhci_find_device(s, async->packet.devaddr),
- &async->packet);
+ len = usb_handle_packet(dev, &async->packet);
if (len >= 0)
len = max_len;
break;
case USB_TOKEN_IN:
- len = usb_handle_packet(uhci_find_device(s, async->packet.devaddr),
- &async->packet);
+ len = usb_handle_packet(dev, &async->packet);
break;
default:
diff --git a/hw/usb-wacom.c b/hw/usb-wacom.c
index 6ebaed1..5b15645 100644
--- a/hw/usb-wacom.c
+++ b/hw/usb-wacom.c
@@ -306,7 +306,7 @@ static int usb_wacom_handle_data(USBDevice *dev, USBPacket *p)
switch (p->pid) {
case USB_TOKEN_IN:
- if (p->devep == 1) {
+ if (p->ep->nr == 1) {
if (!(s->changed || s->idle))
return USB_RET_NAK;
s->changed = 0;
diff --git a/hw/usb-xhci.c b/hw/usb-xhci.c
index a9767e3..15525f4 100644
--- a/hw/usb-xhci.c
+++ b/hw/usb-xhci.c
@@ -1336,15 +1336,17 @@ static int xhci_hle_control(XHCIState *xhci, XHCITransfer *xfer,
}
#endif
-static int xhci_setup_packet(XHCITransfer *xfer, XHCIPort *port, int ep)
+static int xhci_setup_packet(XHCITransfer *xfer, XHCIPort *port, USBDevice *dev)
{
- usb_packet_setup(&xfer->packet,
- xfer->in_xfer ? USB_TOKEN_IN : USB_TOKEN_OUT,
- xfer->xhci->slots[xfer->slotid-1].devaddr,
- ep & 0x7f);
+ USBEndpoint *ep;
+ int dir;
+
+ dir = xfer->in_xfer ? USB_TOKEN_IN : USB_TOKEN_OUT;
+ ep = usb_ep_get(dev, dir, xfer->epid >> 1);
+ usb_packet_setup(&xfer->packet, dir, ep);
usb_packet_addbuf(&xfer->packet, xfer->data, xfer->data_length);
DPRINTF("xhci: setup packet pid 0x%x addr %d ep %d\n",
- xfer->packet.pid, xfer->packet.devaddr, xfer->packet.devep);
+ xfer->packet.pid, dev->addr, ep->nr);
return 0;
}
@@ -1462,7 +1464,7 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
xfer->in_xfer = bmRequestType & USB_DIR_IN;
xfer->iso_xfer = false;
- xhci_setup_packet(xfer, port, 0);
+ xhci_setup_packet(xfer, port, dev);
if (!xfer->in_xfer) {
xhci_xfer_data(xfer, xfer->data, wLength, 0, 1, 0);
}
@@ -1484,12 +1486,8 @@ static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx
int ret;
DPRINTF("xhci_submit(slotid=%d,epid=%d)\n", xfer->slotid, xfer->epid);
- uint8_t ep = xfer->epid>>1;
xfer->in_xfer = epctx->type>>2;
- if (xfer->in_xfer) {
- ep |= 0x80;
- }
if (xfer->data && xfer->data_alloced < xfer->data_length) {
xfer->data_alloced = 0;
@@ -1517,7 +1515,7 @@ static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx
return -1;
}
- xhci_setup_packet(xfer, port, ep);
+ xhci_setup_packet(xfer, port, dev);
switch(epctx->type) {
case ET_INTR_OUT:
@@ -1530,8 +1528,9 @@ static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx
FIXME();
break;
default:
- fprintf(stderr, "xhci: unknown or unhandled EP type %d (ep %02x)\n",
- epctx->type, ep);
+ fprintf(stderr, "xhci: unknown or unhandled EP "
+ "(type %d, in %d, ep %02x)\n",
+ epctx->type, xfer->in_xfer, xfer->epid);
return -1;
}
diff --git a/hw/usb.c b/hw/usb.c
index 73b3ec2..7ee8796 100644
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -144,7 +144,7 @@ static int do_token_in(USBDevice *s, USBPacket *p)
int request, value, index;
int ret = 0;
- assert(p->devep == 0);
+ assert(p->ep->nr == 0);
request = (s->setup_buf[0] << 8) | s->setup_buf[1];
value = (s->setup_buf[3] << 8) | s->setup_buf[2];
@@ -190,7 +190,7 @@ static int do_token_in(USBDevice *s, USBPacket *p)
static int do_token_out(USBDevice *s, USBPacket *p)
{
- assert(p->devep == 0);
+ assert(p->ep->nr == 0);
switch(s->setup_state) {
case SETUP_STATE_ACK:
@@ -296,11 +296,11 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p)
if (dev == NULL) {
return USB_RET_NODEV;
}
- assert(dev->addr == p->devaddr);
+ assert(dev == p->ep->dev);
assert(dev->state == USB_STATE_DEFAULT);
assert(p->state == USB_PACKET_SETUP);
- if (p->devep == 0) {
+ if (p->ep->nr == 0) {
/* control pipe */
switch (p->pid) {
case USB_TOKEN_SETUP:
@@ -322,7 +322,6 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p)
}
if (ret == USB_RET_ASYNC) {
- p->ep = usb_ep_get(dev, p->pid, p->devep);
p->state = USB_PACKET_ASYNC;
}
return ret;
@@ -354,13 +353,12 @@ void usb_packet_init(USBPacket *p)
qemu_iovec_init(&p->iov, 1);
}
-void usb_packet_setup(USBPacket *p, int pid, uint8_t addr, uint8_t ep)
+void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep)
{
assert(!usb_packet_is_inflight(p));
p->state = USB_PACKET_SETUP;
p->pid = pid;
- p->devaddr = addr;
- p->devep = ep;
+ p->ep = ep;
p->result = 0;
qemu_iovec_reset(&p->iov);
}
@@ -471,7 +469,12 @@ void usb_ep_dump(USBDevice *dev)
struct USBEndpoint *usb_ep_get(USBDevice *dev, int pid, int ep)
{
- struct USBEndpoint *eps = pid == USB_TOKEN_IN ? dev->ep_in : dev->ep_out;
+ struct USBEndpoint *eps;
+
+ if (dev == NULL) {
+ return NULL;
+ }
+ eps = (pid == USB_TOKEN_IN) ? dev->ep_in : dev->ep_out;
if (ep == 0) {
return &dev->ep_ctl;
}
diff --git a/hw/usb.h b/hw/usb.h
index 5202f3c..ae30e5c 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -315,8 +315,6 @@ typedef enum USBPacketState {
struct USBPacket {
/* Data fields for use by the driver. */
int pid;
- uint8_t devaddr;
- uint8_t devep;
USBEndpoint *ep;
QEMUIOVector iov;
int result; /* transfer length or USB_RET_* status code */
@@ -325,7 +323,7 @@ struct USBPacket {
};
void usb_packet_init(USBPacket *p);
-void usb_packet_setup(USBPacket *p, int pid, uint8_t addr, uint8_t ep);
+void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep);
void usb_packet_addbuf(USBPacket *p, void *ptr, size_t len);
int usb_packet_map(USBPacket *p, QEMUSGList *sgl);
void usb_packet_unmap(USBPacket *p);
diff --git a/usb-bsd.c b/usb-bsd.c
index 2f34f1b..757804c 100644
--- a/usb-bsd.c
+++ b/usb-bsd.c
@@ -214,7 +214,7 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
int ret, fd, mode;
int one = 1, shortpacket = 0, timeout = 50;
sigset_t new_mask, old_mask;
- uint8_t devep = p->devep;
+ uint8_t devep = p->ep->nr;
/* protect data transfers from SIGALRM signal */
sigemptyset(&new_mask);
diff --git a/usb-linux.c b/usb-linux.c
index 26d1cc4..fea997e 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -137,7 +137,7 @@ static int usb_host_usbfs_type(USBHostDevice *s, USBPacket *p)
[USB_ENDPOINT_XFER_BULK] = USBDEVFS_URB_TYPE_BULK,
[USB_ENDPOINT_XFER_INT] = USBDEVFS_URB_TYPE_INTERRUPT,
};
- uint8_t type = usb_ep_get_type(&s->dev, p->pid, p->devep);
+ uint8_t type = p->ep->type;
assert(type < ARRAY_SIZE(usbfs));
return usbfs[type];
}
@@ -360,7 +360,7 @@ static void async_complete(void *opaque)
break;
case -EPIPE:
- set_halt(s, p->pid, p->devep);
+ set_halt(s, p->pid, p->ep->nr);
p->result = USB_RET_STALL;
break;
@@ -733,16 +733,16 @@ static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in)
int i, j, ret, max_packet_size, offset, len = 0;
uint8_t *buf;
- max_packet_size = usb_ep_get_max_packet_size(&s->dev, p->pid, p->devep);
+ max_packet_size = p->ep->max_packet_size;
if (max_packet_size == 0)
return USB_RET_NAK;
- aurb = get_iso_urb(s, p->pid, p->devep);
+ aurb = get_iso_urb(s, p->pid, p->ep->nr);
if (!aurb) {
- aurb = usb_host_alloc_iso(s, p->pid, p->devep);
+ aurb = usb_host_alloc_iso(s, p->pid, p->ep->nr);
}
- i = get_iso_urb_idx(s, p->pid, p->devep);
+ i = get_iso_urb_idx(s, p->pid, p->ep->nr);
j = aurb[i].iso_frame_idx;
if (j >= 0 && j < ISO_FRAME_DESC_PER_URB) {
if (in) {
@@ -769,7 +769,7 @@ static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in)
}
} else {
len = p->iov.size;
- offset = (j == 0) ? 0 : get_iso_buffer_used(s, p->pid, p->devep);
+ offset = (j == 0) ? 0 : get_iso_buffer_used(s, p->pid, p->ep->nr);
/* Check the frame fits */
if (len > max_packet_size) {
@@ -781,27 +781,27 @@ static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in)
usb_packet_copy(p, aurb[i].urb.buffer + offset, len);
aurb[i].urb.iso_frame_desc[j].length = len;
offset += len;
- set_iso_buffer_used(s, p->pid, p->devep, offset);
+ set_iso_buffer_used(s, p->pid, p->ep->nr, offset);
/* Start the stream once we have buffered enough data */
- if (!is_iso_started(s, p->pid, p->devep) && i == 1 && j == 8) {
- set_iso_started(s, p->pid, p->devep);
+ if (!is_iso_started(s, p->pid, p->ep->nr) && i == 1 && j == 8) {
+ set_iso_started(s, p->pid, p->ep->nr);
}
}
aurb[i].iso_frame_idx++;
if (aurb[i].iso_frame_idx == ISO_FRAME_DESC_PER_URB) {
i = (i + 1) % s->iso_urb_count;
- set_iso_urb_idx(s, p->pid, p->devep, i);
+ set_iso_urb_idx(s, p->pid, p->ep->nr, i);
}
} else {
if (in) {
- set_iso_started(s, p->pid, p->devep);
+ set_iso_started(s, p->pid, p->ep->nr);
} else {
DPRINTF("hubs: iso out error no free buffer, dropping packet\n");
}
}
- if (is_iso_started(s, p->pid, p->devep)) {
+ if (is_iso_started(s, p->pid, p->ep->nr)) {
/* (Re)-submit all fully consumed / filled urbs */
for (i = 0; i < s->iso_urb_count; i++) {
if (aurb[i].iso_frame_idx == ISO_FRAME_DESC_PER_URB) {
@@ -821,7 +821,7 @@ static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in)
break;
}
aurb[i].iso_frame_idx = -1;
- change_iso_inflight(s, p->pid, p->devep, 1);
+ change_iso_inflight(s, p->pid, p->ep->nr, 1);
}
}
}
@@ -840,20 +840,20 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
trace_usb_host_req_data(s->bus_num, s->addr,
p->pid == USB_TOKEN_IN,
- p->devep, p->iov.size);
+ p->ep->nr, p->iov.size);
- if (!is_valid(s, p->pid, p->devep)) {
+ if (!is_valid(s, p->pid, p->ep->nr)) {
trace_usb_host_req_complete(s->bus_num, s->addr, USB_RET_NAK);
return USB_RET_NAK;
}
if (p->pid == USB_TOKEN_IN) {
- ep = p->devep | 0x80;
+ ep = p->ep->nr | 0x80;
} else {
- ep = p->devep;
+ ep = p->ep->nr;
}
- if (is_halted(s, p->pid, p->devep)) {
+ if (is_halted(s, p->pid, p->ep->nr)) {
unsigned int arg = ep;
ret = ioctl(s->fd, USBDEVFS_CLEAR_HALT, &arg);
if (ret < 0) {
@@ -861,10 +861,10 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
trace_usb_host_req_complete(s->bus_num, s->addr, USB_RET_NAK);
return USB_RET_NAK;
}
- clear_halt(s, p->pid, p->devep);
+ clear_halt(s, p->pid, p->ep->nr);
}
- if (is_isoc(s, p->pid, p->devep)) {
+ if (is_isoc(s, p->pid, p->ep->nr)) {
return usb_host_handle_iso_data(s, p, p->pid == USB_TOKEN_IN);
}
@@ -1057,7 +1057,7 @@ static int usb_host_handle_control(USBDevice *dev, USBPacket *p,
urb = &aurb->urb;
urb->type = USBDEVFS_URB_TYPE_CONTROL;
- urb->endpoint = p->devep;
+ urb->endpoint = p->ep->nr;
urb->buffer = &dev->setup_buf;
urb->buffer_length = length + 8;
diff --git a/usb-redir.c b/usb-redir.c
index 459eae8..48af544 100644
--- a/usb-redir.c
+++ b/usb-redir.c
@@ -603,7 +603,7 @@ static int usbredir_handle_data(USBDevice *udev, USBPacket *p)
USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
uint8_t ep;
- ep = p->devep;
+ ep = p->ep->nr;
if (p->pid == USB_TOKEN_IN) {
ep |= USB_DIR_IN;
}
--
1.7.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [Qemu-devel] [PATCH 17/25] usb: maintain async packet list per endpoint
2012-01-23 14:54 [Qemu-devel] [PATCH 00/25] *** SUBJECT HERE *** Gerd Hoffmann
` (15 preceding siblings ...)
2012-01-23 14:55 ` [Qemu-devel] [PATCH 16/25] usb: Set USBEndpoint in usb_packet_setup() Gerd Hoffmann
@ 2012-01-23 14:55 ` Gerd Hoffmann
2012-01-23 14:55 ` [Qemu-devel] [PATCH 18/25] usb: pass USBEndpoint to usb_wakeup Gerd Hoffmann
` (8 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Gerd Hoffmann @ 2012-01-23 14:55 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Maintain a list of async packets per endpoint. With the current code
the list will never receive more than a single item. I think you can
guess what the future plan is though ;)
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb.c | 130 +++++++++++++++++++++++++++++++++++++++++++++++++------------
hw/usb.h | 9 +++-
2 files changed, 111 insertions(+), 28 deletions(-)
diff --git a/hw/usb.c b/hw/usb.c
index 7ee8796..b42fb67 100644
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -286,6 +286,34 @@ USBDevice *usb_find_device(USBPort *port, uint8_t addr)
return NULL;
}
+static int usb_process_one(USBPacket *p)
+{
+ USBDevice *dev = p->ep->dev;
+
+ if (p->ep->nr == 0) {
+ /* control pipe */
+ switch (p->pid) {
+ case USB_TOKEN_SETUP:
+ return do_token_setup(dev, p);
+ case USB_TOKEN_IN:
+ return do_token_in(dev, p);
+ case USB_TOKEN_OUT:
+ return do_token_out(dev, p);
+ default:
+ return USB_RET_STALL;
+ }
+ } else {
+ /* data pipe */
+ return dev->info->handle_data(dev, p);
+ }
+}
+
+#if 0
+static void log_packet_status(USBPacket *p, char *status)
+{
+}
+#endif
+
/* Hand over a packet to a device for processing. Return value
USB_RET_ASYNC indicates the processing isn't finished yet, the
driver will call usb_packet_complete() when done processing it. */
@@ -299,30 +327,21 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p)
assert(dev == p->ep->dev);
assert(dev->state == USB_STATE_DEFAULT);
assert(p->state == USB_PACKET_SETUP);
+ assert(p->ep != NULL);
- if (p->ep->nr == 0) {
- /* control pipe */
- switch (p->pid) {
- case USB_TOKEN_SETUP:
- ret = do_token_setup(dev, p);
- break;
- case USB_TOKEN_IN:
- ret = do_token_in(dev, p);
- break;
- case USB_TOKEN_OUT:
- ret = do_token_out(dev, p);
- break;
- default:
- ret = USB_RET_STALL;
- break;
+ if (QTAILQ_EMPTY(&p->ep->queue)) {
+ ret = usb_process_one(p);
+ if (ret == USB_RET_ASYNC) {
+ usb_packet_set_state(p, USB_PACKET_ASYNC);
+ QTAILQ_INSERT_TAIL(&p->ep->queue, p, queue);
+ } else {
+ p->result = ret;
+ usb_packet_set_state(p, USB_PACKET_COMPLETE);
}
} else {
- /* data pipe */
- ret = dev->info->handle_data(dev, p);
- }
-
- if (ret == USB_RET_ASYNC) {
- p->state = USB_PACKET_ASYNC;
+ ret = USB_RET_ASYNC;
+ usb_packet_set_state(p, USB_PACKET_QUEUED);
+ QTAILQ_INSERT_TAIL(&p->ep->queue, p, queue);
}
return ret;
}
@@ -332,9 +351,27 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p)
handle_packet. */
void usb_packet_complete(USBDevice *dev, USBPacket *p)
{
+ int ret;
+
assert(p->state == USB_PACKET_ASYNC);
- p->state = USB_PACKET_COMPLETE;
+ assert(QTAILQ_FIRST(&p->ep->queue) == p);
+ usb_packet_set_state(p, USB_PACKET_COMPLETE);
+ QTAILQ_REMOVE(&p->ep->queue, p, queue);
dev->port->ops->complete(dev->port, p);
+
+ while (!QTAILQ_EMPTY(&p->ep->queue)) {
+ p = QTAILQ_FIRST(&p->ep->queue);
+ assert(p->state == USB_PACKET_QUEUED);
+ ret = usb_process_one(p);
+ if (ret == USB_RET_ASYNC) {
+ usb_packet_set_state(p, USB_PACKET_ASYNC);
+ break;
+ }
+ p->result = ret;
+ usb_packet_set_state(p, USB_PACKET_COMPLETE);
+ QTAILQ_REMOVE(&p->ep->queue, p, queue);
+ dev->port->ops->complete(dev->port, p);
+ }
}
/* Cancel an active packet. The packed must have been deferred by
@@ -342,9 +379,13 @@ void usb_packet_complete(USBDevice *dev, USBPacket *p)
completed. */
void usb_cancel_packet(USBPacket * p)
{
- assert(p->state == USB_PACKET_ASYNC);
- p->state = USB_PACKET_CANCELED;
- p->ep->dev->info->cancel_packet(p->ep->dev, p);
+ bool callback = (p->state == USB_PACKET_ASYNC);
+ assert(usb_packet_is_inflight(p));
+ usb_packet_set_state(p, USB_PACKET_CANCELED);
+ QTAILQ_REMOVE(&p->ep->queue, p, queue);
+ if (callback) {
+ p->ep->dev->info->cancel_packet(p->ep->dev, p);
+ }
}
@@ -353,14 +394,48 @@ void usb_packet_init(USBPacket *p)
qemu_iovec_init(&p->iov, 1);
}
+void usb_packet_set_state(USBPacket *p, USBPacketState state)
+{
+ static const char *name[] = {
+ [USB_PACKET_UNDEFINED] = "undef",
+ [USB_PACKET_SETUP] = "setup",
+ [USB_PACKET_QUEUED] = "queued",
+ [USB_PACKET_ASYNC] = "async",
+ [USB_PACKET_COMPLETE] = "complete",
+ [USB_PACKET_CANCELED] = "canceled",
+ };
+ static const char *rets[] = {
+ [-USB_RET_NODEV] = "NODEV",
+ [-USB_RET_NAK] = "NAK",
+ [-USB_RET_STALL] = "STALL",
+ [-USB_RET_BABBLE] = "BABBLE",
+ [-USB_RET_ASYNC] = "ASYNC",
+ };
+ char add[16] = "";
+
+ if (state == USB_PACKET_COMPLETE) {
+ if (p->result < 0) {
+ snprintf(add, sizeof(add), " - %s", rets[-p->result]);
+ } else {
+ snprintf(add, sizeof(add), " - %d", p->result);
+ }
+ }
+ fprintf(stderr, "bus %s, port %s, dev %d, ep %d: packet %p: %s -> %s%s\n",
+ p->ep->dev->qdev.parent_bus->name,
+ p->ep->dev->port->path,
+ p->ep->dev->addr, p->ep->nr,
+ p, name[p->state], name[state], add);
+ p->state = state;
+}
+
void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep)
{
assert(!usb_packet_is_inflight(p));
- p->state = USB_PACKET_SETUP;
p->pid = pid;
p->ep = ep;
p->result = 0;
qemu_iovec_reset(&p->iov);
+ usb_packet_set_state(p, USB_PACKET_SETUP);
}
void usb_packet_addbuf(USBPacket *p, void *ptr, size_t len)
@@ -411,6 +486,7 @@ void usb_ep_init(USBDevice *dev)
dev->ep_ctl.type = USB_ENDPOINT_XFER_CONTROL;
dev->ep_ctl.ifnum = 0;
dev->ep_ctl.dev = dev;
+ QTAILQ_INIT(&dev->ep_ctl.queue);
for (ep = 0; ep < USB_MAX_ENDPOINTS; ep++) {
dev->ep_in[ep].nr = ep + 1;
dev->ep_out[ep].nr = ep + 1;
@@ -422,6 +498,8 @@ void usb_ep_init(USBDevice *dev)
dev->ep_out[ep].ifnum = 0;
dev->ep_in[ep].dev = dev;
dev->ep_out[ep].dev = dev;
+ QTAILQ_INIT(&dev->ep_in[ep].queue);
+ QTAILQ_INIT(&dev->ep_out[ep].queue);
}
}
diff --git a/hw/usb.h b/hw/usb.h
index ae30e5c..5063312 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -175,6 +175,7 @@ struct USBEndpoint {
uint8_t ifnum;
int max_packet_size;
USBDevice *dev;
+ QTAILQ_HEAD(, USBPacket) queue;
};
/* definition of a USB device */
@@ -303,15 +304,16 @@ struct USBPort {
typedef void USBCallback(USBPacket * packet, void *opaque);
-/* Structure used to hold information about an active USB packet. */
typedef enum USBPacketState {
USB_PACKET_UNDEFINED = 0,
USB_PACKET_SETUP,
+ USB_PACKET_QUEUED,
USB_PACKET_ASYNC,
USB_PACKET_COMPLETE,
USB_PACKET_CANCELED,
} USBPacketState;
+/* Structure used to hold information about an active USB packet. */
struct USBPacket {
/* Data fields for use by the driver. */
int pid;
@@ -320,9 +322,11 @@ struct USBPacket {
int result; /* transfer length or USB_RET_* status code */
/* Internal use by the USB layer. */
USBPacketState state;
+ QTAILQ_ENTRY(USBPacket) queue;
};
void usb_packet_init(USBPacket *p);
+void usb_packet_set_state(USBPacket *p, USBPacketState state);
void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep);
void usb_packet_addbuf(USBPacket *p, void *ptr, size_t len);
int usb_packet_map(USBPacket *p, QEMUSGList *sgl);
@@ -333,7 +337,8 @@ void usb_packet_cleanup(USBPacket *p);
static inline bool usb_packet_is_inflight(USBPacket *p)
{
- return p->state == USB_PACKET_ASYNC;
+ return (p->state == USB_PACKET_QUEUED ||
+ p->state == USB_PACKET_ASYNC);
}
USBDevice *usb_find_device(USBPort *port, uint8_t addr);
--
1.7.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [Qemu-devel] [PATCH 18/25] usb: pass USBEndpoint to usb_wakeup
2012-01-23 14:54 [Qemu-devel] [PATCH 00/25] *** SUBJECT HERE *** Gerd Hoffmann
` (16 preceding siblings ...)
2012-01-23 14:55 ` [Qemu-devel] [PATCH 17/25] usb: maintain async packet list per endpoint Gerd Hoffmann
@ 2012-01-23 14:55 ` Gerd Hoffmann
2012-01-23 14:55 ` [Qemu-devel] [PATCH 19/25] usb: add USBBusOps->wakeup_endpoint Gerd Hoffmann
` (7 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Gerd Hoffmann @ 2012-01-23 14:55 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Devices must specify which endpoint has data to transfer now.
The plan is to use the usb_wakeup() not only for remove wakeup support,
but for "data ready" signaling in general, so we can move away from
constant polling to event driven usb device emulation.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb-ccid.c | 4 +++-
hw/usb-hid.c | 4 +++-
hw/usb-hub.c | 8 +++++---
hw/usb.c | 4 +++-
hw/usb.h | 2 +-
5 files changed, 15 insertions(+), 7 deletions(-)
diff --git a/hw/usb-ccid.c b/hw/usb-ccid.c
index 504df87..5e39f12 100644
--- a/hw/usb-ccid.c
+++ b/hw/usb-ccid.c
@@ -267,6 +267,7 @@ typedef struct CCIDBus {
*/
typedef struct USBCCIDState {
USBDevice dev;
+ USBEndpoint *intr;
CCIDBus bus;
CCIDCardState *card;
CCIDCardInfo *cardinfo; /* caching the info pointer */
@@ -803,7 +804,7 @@ static void ccid_on_slot_change(USBCCIDState *s, bool full)
s->bmSlotICCState |= SLOT_0_CHANGED_MASK;
}
s->notify_slot_change = true;
- usb_wakeup(&s->dev);
+ usb_wakeup(s->intr);
}
static void ccid_write_data_block_error(
@@ -1168,6 +1169,7 @@ static int ccid_initfn(USBDevice *dev)
usb_desc_init(dev);
qbus_create_inplace(&s->bus.qbus, &ccid_bus_info, &dev->qdev, NULL);
+ s->intr = usb_ep_get(dev, USB_TOKEN_IN, CCID_INT_IN_EP);
s->bus.qbus.allow_hotplug = 1;
s->card = NULL;
s->cardinfo = NULL;
diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index f64eb2d..4433508 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -44,6 +44,7 @@
typedef struct USBHIDState {
USBDevice dev;
+ USBEndpoint *intr;
HIDState hid;
} USBHIDState;
@@ -360,7 +361,7 @@ static void usb_hid_changed(HIDState *hs)
{
USBHIDState *us = container_of(hs, USBHIDState, hid);
- usb_wakeup(&us->dev);
+ usb_wakeup(us->intr);
}
static void usb_hid_handle_reset(USBDevice *dev)
@@ -501,6 +502,7 @@ static int usb_hid_initfn(USBDevice *dev, int kind)
USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
usb_desc_init(dev);
+ us->intr = usb_ep_get(dev, USB_TOKEN_IN, 1);
hid_init(&us->hid, kind, usb_hid_changed);
return 0;
}
diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index 88164f5..7b7f87c 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -37,6 +37,7 @@ typedef struct USBHubPort {
typedef struct USBHubState {
USBDevice dev;
+ USBEndpoint *intr;
USBHubPort ports[NUM_PORTS];
} USBHubState;
@@ -163,7 +164,7 @@ static void usb_hub_attach(USBPort *port1)
} else {
port->wPortStatus &= ~PORT_STAT_LOW_SPEED;
}
- usb_wakeup(&s->dev);
+ usb_wakeup(s->intr);
}
static void usb_hub_detach(USBPort *port1)
@@ -171,7 +172,7 @@ static void usb_hub_detach(USBPort *port1)
USBHubState *s = port1->opaque;
USBHubPort *port = &s->ports[port1->index];
- usb_wakeup(&s->dev);
+ usb_wakeup(s->intr);
/* Let upstream know the device on this port is gone */
s->dev.port->ops->child_detach(s->dev.port, port1->dev);
@@ -199,7 +200,7 @@ static void usb_hub_wakeup(USBPort *port1)
if (port->wPortStatus & PORT_STAT_SUSPEND) {
port->wPortChange |= PORT_STAT_C_SUSPEND;
- usb_wakeup(&s->dev);
+ usb_wakeup(s->intr);
}
}
@@ -481,6 +482,7 @@ static int usb_hub_initfn(USBDevice *dev)
int i;
usb_desc_init(dev);
+ s->intr = usb_ep_get(dev, USB_TOKEN_IN, 1);
for (i = 0; i < NUM_PORTS; i++) {
port = &s->ports[i];
usb_register_port(usb_bus_from_device(dev),
diff --git a/hw/usb.c b/hw/usb.c
index b42fb67..381558d 100644
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -74,8 +74,10 @@ void usb_device_reset(USBDevice *dev)
}
}
-void usb_wakeup(USBDevice *dev)
+void usb_wakeup(USBEndpoint *ep)
{
+ USBDevice *dev = ep->dev;
+
if (dev->remote_wakeup && dev->port && dev->port->ops->wakeup) {
dev->port->ops->wakeup(dev->port);
}
diff --git a/hw/usb.h b/hw/usb.h
index 5063312..6b4684f 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -362,7 +362,7 @@ void usb_attach(USBPort *port);
void usb_detach(USBPort *port);
void usb_port_reset(USBPort *port);
void usb_device_reset(USBDevice *dev);
-void usb_wakeup(USBDevice *dev);
+void usb_wakeup(USBEndpoint *ep);
void usb_generic_async_ctrl_complete(USBDevice *s, USBPacket *p);
int set_usb_string(uint8_t *buf, const char *str);
--
1.7.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [Qemu-devel] [PATCH 19/25] usb: add USBBusOps->wakeup_endpoint
2012-01-23 14:54 [Qemu-devel] [PATCH 00/25] *** SUBJECT HERE *** Gerd Hoffmann
` (17 preceding siblings ...)
2012-01-23 14:55 ` [Qemu-devel] [PATCH 18/25] usb: pass USBEndpoint to usb_wakeup Gerd Hoffmann
@ 2012-01-23 14:55 ` Gerd Hoffmann
2012-01-23 14:55 ` [Qemu-devel] [PATCH 20/25] xhci: signal low- and fullspeed support Gerd Hoffmann
` (6 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Gerd Hoffmann @ 2012-01-23 14:55 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Add usb bus op which is called whenever a usb endpoint becomes ready,
so the host adapter emulation can react on that event.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb.c | 4 ++++
hw/usb.h | 1 +
2 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/hw/usb.c b/hw/usb.c
index 381558d..2d7088d 100644
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -77,10 +77,14 @@ void usb_device_reset(USBDevice *dev)
void usb_wakeup(USBEndpoint *ep)
{
USBDevice *dev = ep->dev;
+ USBBus *bus = usb_bus_from_device(dev);
if (dev->remote_wakeup && dev->port && dev->port->ops->wakeup) {
dev->port->ops->wakeup(dev->port);
}
+ if (bus->ops->wakeup_endpoint) {
+ bus->ops->wakeup_endpoint(bus, ep);
+ }
}
/**********************/
diff --git a/hw/usb.h b/hw/usb.h
index 6b4684f..0dd6b88 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -419,6 +419,7 @@ struct USBBus {
struct USBBusOps {
int (*register_companion)(USBBus *bus, USBPort *ports[],
uint32_t portcount, uint32_t firstport);
+ void (*wakeup_endpoint)(USBBus *bus, USBEndpoint *ep);
};
void usb_bus_new(USBBus *bus, USBBusOps *ops, DeviceState *host);
--
1.7.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [Qemu-devel] [PATCH 20/25] xhci: signal low- and fullspeed support
2012-01-23 14:54 [Qemu-devel] [PATCH 00/25] *** SUBJECT HERE *** Gerd Hoffmann
` (18 preceding siblings ...)
2012-01-23 14:55 ` [Qemu-devel] [PATCH 19/25] usb: add USBBusOps->wakeup_endpoint Gerd Hoffmann
@ 2012-01-23 14:55 ` Gerd Hoffmann
2012-01-23 14:55 ` [Qemu-devel] [PATCH 21/25] xhci: add trb type name lookup support Gerd Hoffmann
` (5 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Gerd Hoffmann @ 2012-01-23 14:55 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb-xhci.c | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/hw/usb-xhci.c b/hw/usb-xhci.c
index 15525f4..99e08e3 100644
--- a/hw/usb-xhci.c
+++ b/hw/usb-xhci.c
@@ -2672,7 +2672,10 @@ static void usb_xhci_init(XHCIState *xhci, DeviceState *dev)
for (i = 0; i < MAXPORTS; i++) {
memset(&xhci->ports[i], 0, sizeof(xhci->ports[i]));
usb_register_port(&xhci->bus, &xhci->ports[i].port, xhci, i,
- &xhci_port_ops, USB_SPEED_MASK_HIGH);
+ &xhci_port_ops,
+ USB_SPEED_MASK_LOW |
+ USB_SPEED_MASK_FULL |
+ USB_SPEED_MASK_HIGH);
}
for (i = 0; i < MAXSLOTS; i++) {
xhci->slots[i].enabled = 0;
--
1.7.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [Qemu-devel] [PATCH 21/25] xhci: add trb type name lookup support.
2012-01-23 14:54 [Qemu-devel] [PATCH 00/25] *** SUBJECT HERE *** Gerd Hoffmann
` (19 preceding siblings ...)
2012-01-23 14:55 ` [Qemu-devel] [PATCH 20/25] xhci: signal low- and fullspeed support Gerd Hoffmann
@ 2012-01-23 14:55 ` Gerd Hoffmann
2012-01-23 14:55 ` [Qemu-devel] [PATCH 22/25] xhci: stop on errors Gerd Hoffmann
` (4 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Gerd Hoffmann @ 2012-01-23 14:55 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
When logging TRBs add a the type name for more readable debug output.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb-xhci.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 58 insertions(+), 4 deletions(-)
diff --git a/hw/usb-xhci.c b/hw/usb-xhci.c
index 99e08e3..3cd5374 100644
--- a/hw/usb-xhci.c
+++ b/hw/usb-xhci.c
@@ -420,6 +420,58 @@ typedef struct XHCIEvRingSeg {
uint32_t rsvd;
} XHCIEvRingSeg;
+static const char *TRBType_names[] = {
+ [TRB_RESERVED] = "TRB_RESERVED",
+ [TR_NORMAL] = "TR_NORMAL",
+ [TR_SETUP] = "TR_SETUP",
+ [TR_DATA] = "TR_DATA",
+ [TR_STATUS] = "TR_STATUS",
+ [TR_ISOCH] = "TR_ISOCH",
+ [TR_LINK] = "TR_LINK",
+ [TR_EVDATA] = "TR_EVDATA",
+ [TR_NOOP] = "TR_NOOP",
+ [CR_ENABLE_SLOT] = "CR_ENABLE_SLOT",
+ [CR_DISABLE_SLOT] = "CR_DISABLE_SLOT",
+ [CR_ADDRESS_DEVICE] = "CR_ADDRESS_DEVICE",
+ [CR_CONFIGURE_ENDPOINT] = "CR_CONFIGURE_ENDPOINT",
+ [CR_EVALUATE_CONTEXT] = "CR_EVALUATE_CONTEXT",
+ [CR_RESET_ENDPOINT] = "CR_RESET_ENDPOINT",
+ [CR_STOP_ENDPOINT] = "CR_STOP_ENDPOINT",
+ [CR_SET_TR_DEQUEUE] = "CR_SET_TR_DEQUEUE",
+ [CR_RESET_DEVICE] = "CR_RESET_DEVICE",
+ [CR_FORCE_EVENT] = "CR_FORCE_EVENT",
+ [CR_NEGOTIATE_BW] = "CR_NEGOTIATE_BW",
+ [CR_SET_LATENCY_TOLERANCE] = "CR_SET_LATENCY_TOLERANCE",
+ [CR_GET_PORT_BANDWIDTH] = "CR_GET_PORT_BANDWIDTH",
+ [CR_FORCE_HEADER] = "CR_FORCE_HEADER",
+ [CR_NOOP] = "CR_NOOP",
+ [ER_TRANSFER] = "ER_TRANSFER",
+ [ER_COMMAND_COMPLETE] = "ER_COMMAND_COMPLETE",
+ [ER_PORT_STATUS_CHANGE] = "ER_PORT_STATUS_CHANGE",
+ [ER_BANDWIDTH_REQUEST] = "ER_BANDWIDTH_REQUEST",
+ [ER_DOORBELL] = "ER_DOORBELL",
+ [ER_HOST_CONTROLLER] = "ER_HOST_CONTROLLER",
+ [ER_DEVICE_NOTIFICATION] = "ER_DEVICE_NOTIFICATION",
+ [ER_MFINDEX_WRAP] = "ER_MFINDEX_WRAP",
+ [CR_VENDOR_VIA_CHALLENGE_RESPONSE] = "CR_VENDOR_VIA_CHALLENGE_RESPONSE",
+ [CR_VENDOR_NEC_FIRMWARE_REVISION] = "CR_VENDOR_NEC_FIRMWARE_REVISION",
+ [CR_VENDOR_NEC_CHALLENGE_RESPONSE] = "CR_VENDOR_NEC_CHALLENGE_RESPONSE",
+};
+
+static const char *lookup_name(uint32_t index, const char **list, uint32_t llen)
+{
+ if (index >= llen || list[index] == NULL) {
+ return "???";
+ }
+ return list[index];
+}
+
+static const char *trb_name(XHCITRB *trb)
+{
+ return lookup_name(TRB_TYPE(*trb), TRBType_names,
+ ARRAY_SIZE(TRBType_names));
+}
+
static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid,
unsigned int epid);
@@ -487,8 +539,9 @@ static void xhci_write_event(XHCIState *xhci, XHCIEvent *event)
}
ev_trb.control = cpu_to_le32(ev_trb.control);
- DPRINTF("xhci_write_event(): [%d] %016"PRIx64" %08x %08x\n",
- xhci->er_ep_idx, ev_trb.parameter, ev_trb.status, ev_trb.control);
+ DPRINTF("xhci_write_event(): [%d] %016"PRIx64" %08x %08x %s\n",
+ xhci->er_ep_idx, ev_trb.parameter, ev_trb.status, ev_trb.control,
+ trb_name(&ev_trb));
addr = xhci->er_start + TRB_SIZE*xhci->er_ep_idx;
cpu_physical_memory_write(addr, (uint8_t *) &ev_trb, TRB_SIZE);
@@ -649,8 +702,9 @@ static TRBType xhci_ring_fetch(XHCIState *xhci, XHCIRing *ring, XHCITRB *trb,
le32_to_cpus(&trb->control);
DPRINTF("xhci: TRB fetched [" TARGET_FMT_plx "]: "
- "%016" PRIx64 " %08x %08x\n",
- ring->dequeue, trb->parameter, trb->status, trb->control);
+ "%016" PRIx64 " %08x %08x %s\n",
+ ring->dequeue, trb->parameter, trb->status, trb->control,
+ trb_name(trb));
if ((trb->control & TRB_C) != ring->ccs) {
return 0;
--
1.7.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [Qemu-devel] [PATCH 22/25] xhci: stop on errors
2012-01-23 14:54 [Qemu-devel] [PATCH 00/25] *** SUBJECT HERE *** Gerd Hoffmann
` (20 preceding siblings ...)
2012-01-23 14:55 ` [Qemu-devel] [PATCH 21/25] xhci: add trb type name lookup support Gerd Hoffmann
@ 2012-01-23 14:55 ` Gerd Hoffmann
2012-01-23 14:55 ` [Qemu-devel] [PATCH 23/25] xhci: kill port arg from xhci_setup_packet Gerd Hoffmann
` (3 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Gerd Hoffmann @ 2012-01-23 14:55 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
When some error happened we'll have to stop processing the endpoint.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb-xhci.c | 8 ++++++--
1 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/hw/usb-xhci.c b/hw/usb-xhci.c
index 3cd5374..1e8836f 100644
--- a/hw/usb-xhci.c
+++ b/hw/usb-xhci.c
@@ -1719,10 +1719,14 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid
}
}
+ if (epctx->state == EP_HALTED) {
+ DPRINTF("xhci: ep halted, stopping schedule\n");
+ break;
+ }
+
/*
* Qemu usb can't handle multiple in-flight xfers.
- * Also xfers might be finished here already,
- * possibly with an error. Stop here for now.
+ * Stop here for now.
*/
break;
}
--
1.7.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [Qemu-devel] [PATCH 23/25] xhci: kill port arg from xhci_setup_packet
2012-01-23 14:54 [Qemu-devel] [PATCH 00/25] *** SUBJECT HERE *** Gerd Hoffmann
` (21 preceding siblings ...)
2012-01-23 14:55 ` [Qemu-devel] [PATCH 22/25] xhci: stop on errors Gerd Hoffmann
@ 2012-01-23 14:55 ` Gerd Hoffmann
2012-01-23 14:55 ` [Qemu-devel] [PATCH 24/25] xhci: remote wakeup support Gerd Hoffmann
` (2 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Gerd Hoffmann @ 2012-01-23 14:55 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Unused argument, remove it.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb-xhci.c | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/hw/usb-xhci.c b/hw/usb-xhci.c
index 1e8836f..cd88c76 100644
--- a/hw/usb-xhci.c
+++ b/hw/usb-xhci.c
@@ -1390,7 +1390,7 @@ static int xhci_hle_control(XHCIState *xhci, XHCITransfer *xfer,
}
#endif
-static int xhci_setup_packet(XHCITransfer *xfer, XHCIPort *port, USBDevice *dev)
+static int xhci_setup_packet(XHCITransfer *xfer, USBDevice *dev)
{
USBEndpoint *ep;
int dir;
@@ -1518,7 +1518,7 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
xfer->in_xfer = bmRequestType & USB_DIR_IN;
xfer->iso_xfer = false;
- xhci_setup_packet(xfer, port, dev);
+ xhci_setup_packet(xfer, dev);
if (!xfer->in_xfer) {
xhci_xfer_data(xfer, xfer->data, wLength, 0, 1, 0);
}
@@ -1569,7 +1569,7 @@ static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx
return -1;
}
- xhci_setup_packet(xfer, port, dev);
+ xhci_setup_packet(xfer, dev);
switch(epctx->type) {
case ET_INTR_OUT:
--
1.7.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [Qemu-devel] [PATCH 24/25] xhci: remote wakeup support
2012-01-23 14:54 [Qemu-devel] [PATCH 00/25] *** SUBJECT HERE *** Gerd Hoffmann
` (22 preceding siblings ...)
2012-01-23 14:55 ` [Qemu-devel] [PATCH 23/25] xhci: kill port arg from xhci_setup_packet Gerd Hoffmann
@ 2012-01-23 14:55 ` Gerd Hoffmann
2012-01-23 14:55 ` [Qemu-devel] [PATCH 25/25] xhci: handle USB_RET_NAK Gerd Hoffmann
2012-01-23 15:00 ` [Qemu-devel] [PATCH 00/25] *** SUBJECT HERE *** Gerd Hoffmann
25 siblings, 0 replies; 27+ messages in thread
From: Gerd Hoffmann @ 2012-01-23 14:55 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb-xhci.c | 21 +++++++++++++++++++++
1 files changed, 21 insertions(+), 0 deletions(-)
diff --git a/hw/usb-xhci.c b/hw/usb-xhci.c
index cd88c76..a42bb96 100644
--- a/hw/usb-xhci.c
+++ b/hw/usb-xhci.c
@@ -2696,6 +2696,26 @@ static void xhci_detach(USBPort *usbport)
xhci_update_port(xhci, port, 1);
}
+static void xhci_wakeup(USBPort *usbport)
+{
+ XHCIState *xhci = usbport->opaque;
+ XHCIPort *port = &xhci->ports[usbport->index];
+ int nr = port->port.index + 1;
+ XHCIEvent ev = { ER_PORT_STATUS_CHANGE, CC_SUCCESS, nr << 24};
+ uint32_t pls;
+
+ pls = (port->portsc >> PORTSC_PLS_SHIFT) & PORTSC_PLS_MASK;
+ if (pls != 3) {
+ return;
+ }
+ port->portsc |= 0xf << PORTSC_PLS_SHIFT;
+ if (port->portsc & PORTSC_PLC) {
+ return;
+ }
+ port->portsc |= PORTSC_PLC;
+ xhci_event(xhci, &ev);
+}
+
static void xhci_complete(USBPort *port, USBPacket *packet)
{
XHCITransfer *xfer = container_of(packet, XHCITransfer, packet);
@@ -2712,6 +2732,7 @@ static void xhci_child_detach(USBPort *port, USBDevice *child)
static USBPortOps xhci_port_ops = {
.attach = xhci_attach,
.detach = xhci_detach,
+ .wakeup = xhci_wakeup,
.complete = xhci_complete,
.child_detach = xhci_child_detach,
};
--
1.7.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [Qemu-devel] [PATCH 25/25] xhci: handle USB_RET_NAK
2012-01-23 14:54 [Qemu-devel] [PATCH 00/25] *** SUBJECT HERE *** Gerd Hoffmann
` (23 preceding siblings ...)
2012-01-23 14:55 ` [Qemu-devel] [PATCH 24/25] xhci: remote wakeup support Gerd Hoffmann
@ 2012-01-23 14:55 ` Gerd Hoffmann
2012-01-23 15:00 ` [Qemu-devel] [PATCH 00/25] *** SUBJECT HERE *** Gerd Hoffmann
25 siblings, 0 replies; 27+ messages in thread
From: Gerd Hoffmann @ 2012-01-23 14:55 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Add a field to XHCITransfer to correctly keep track of NAK'ed usb
packets. Retry transfers when the endpoint is kicked again. Implement
wakeup_endpoint bus op so we can kick the endpoint when needed.
With this patch applied the emulated hid devices are working correctly
when hooked up to xhci. usb-tabled without polling, yay!
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb-xhci.c | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++------
1 files changed, 96 insertions(+), 11 deletions(-)
diff --git a/hw/usb-xhci.c b/hw/usb-xhci.c
index a42bb96..ca6a7ce 100644
--- a/hw/usb-xhci.c
+++ b/hw/usb-xhci.c
@@ -307,7 +307,8 @@ typedef struct XHCIState XHCIState;
typedef struct XHCITransfer {
XHCIState *xhci;
USBPacket packet;
- bool running;
+ bool running_async;
+ bool running_retry;
bool cancelled;
bool complete;
bool backgrounded;
@@ -338,6 +339,7 @@ typedef struct XHCIEPContext {
unsigned int next_xfer;
unsigned int comp_xfer;
XHCITransfer transfers[TD_QUEUE];
+ XHCITransfer *retry;
bool bg_running;
bool bg_updating;
unsigned int next_bg;
@@ -913,12 +915,17 @@ static int xhci_ep_nuke_xfers(XHCIState *xhci, unsigned int slotid,
xferi = epctx->next_xfer;
for (i = 0; i < TD_QUEUE; i++) {
XHCITransfer *t = &epctx->transfers[xferi];
- if (t->running) {
+ if (t->running_async) {
+ usb_cancel_packet(&t->packet);
+ t->running_async = 0;
t->cancelled = 1;
- /* libusb_cancel_transfer(t->usbxfer) */
DPRINTF("xhci: cancelling transfer %d, waiting for it to complete...\n", i);
killed++;
}
+ if (t->running_retry) {
+ t->running_retry = 0;
+ epctx->retry = NULL;
+ }
if (t->backgrounded) {
t->backgrounded = 0;
}
@@ -939,9 +946,10 @@ static int xhci_ep_nuke_xfers(XHCIState *xhci, unsigned int slotid,
xferi = epctx->next_bg;
for (i = 0; i < BG_XFERS; i++) {
XHCITransfer *t = &epctx->bg_transfers[xferi];
- if (t->running) {
+ if (t->running_async) {
+ usb_cancel_packet(&t->packet);
+ t->running_async = 0;
t->cancelled = 1;
- /* libusb_cancel_transfer(t->usbxfer); */
DPRINTF("xhci: cancelling bg transfer %d, waiting for it to complete...\n", i);
killed++;
}
@@ -1407,12 +1415,20 @@ static int xhci_setup_packet(XHCITransfer *xfer, USBDevice *dev)
static int xhci_complete_packet(XHCITransfer *xfer, int ret)
{
if (ret == USB_RET_ASYNC) {
- xfer->running = 1;
+ xfer->running_async = 1;
+ xfer->running_retry = 0;
+ xfer->complete = 0;
+ xfer->cancelled = 0;
+ return 0;
+ } else if (ret == USB_RET_NAK) {
+ xfer->running_async = 0;
+ xfer->running_retry = 1;
xfer->complete = 0;
xfer->cancelled = 0;
return 0;
} else {
- xfer->running = 0;
+ xfer->running_async = 0;
+ xfer->running_retry = 0;
xfer->complete = 1;
}
@@ -1527,7 +1543,7 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
wValue, wIndex, wLength, xfer->data);
xhci_complete_packet(xfer, ret);
- if (!xfer->running) {
+ if (!xfer->running_async && !xfer->running_retry) {
xhci_kick_ep(xhci, xfer->slotid, xfer->epid);
}
return 0;
@@ -1594,7 +1610,7 @@ static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx
ret = usb_handle_packet(dev, &xfer->packet);
xhci_complete_packet(xfer, ret);
- if (!xfer->running) {
+ if (!xfer->running_async && !xfer->running_retry) {
xhci_kick_ep(xhci, xfer->slotid, xfer->epid);
}
return 0;
@@ -1665,6 +1681,25 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid
return;
}
+ if (epctx->retry) {
+ /* retry nak'ed transfer */
+ XHCITransfer *xfer = epctx->retry;
+ int result;
+
+ DPRINTF("xhci: retry nack'ed transfer ...\n");
+ assert(xfer->running_retry);
+ xhci_setup_packet(xfer, xfer->packet.ep->dev);
+ result = usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);
+ if (result == USB_RET_NAK) {
+ DPRINTF("xhci: ... xfer still nacked\n");
+ return;
+ }
+ DPRINTF("xhci: ... result %d\n", result);
+ xhci_complete_packet(xfer, result);
+ assert(!xfer->running_retry);
+ epctx->retry = NULL;
+ }
+
if (epctx->state == EP_HALTED) {
DPRINTF("xhci: ep halted, not running schedule\n");
return;
@@ -1674,9 +1709,13 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid
while (1) {
XHCITransfer *xfer = &epctx->transfers[epctx->next_xfer];
- if (xfer->running || xfer->backgrounded) {
- DPRINTF("xhci: ep is busy\n");
+ if (xfer->running_async || xfer->running_retry || xfer->backgrounded) {
+ DPRINTF("xhci: ep is busy (#%d,%d,%d,%d)\n",
+ epctx->next_xfer, xfer->running_async,
+ xfer->running_retry, xfer->backgrounded);
break;
+ } else {
+ DPRINTF("xhci: ep: using #%d\n", epctx->next_xfer);
}
length = xhci_ring_chain_length(xhci, &epctx->ring);
if (length < 0) {
@@ -1723,6 +1762,11 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid
DPRINTF("xhci: ep halted, stopping schedule\n");
break;
}
+ if (xfer->running_retry) {
+ DPRINTF("xhci: xfer nacked, stopping schedule\n");
+ epctx->retry = xfer;
+ break;
+ }
/*
* Qemu usb can't handle multiple in-flight xfers.
@@ -2737,7 +2781,48 @@ static USBPortOps xhci_port_ops = {
.child_detach = xhci_child_detach,
};
+static int xhci_find_slotid(XHCIState *xhci, USBDevice *dev)
+{
+ XHCISlot *slot;
+ int slotid;
+
+ for (slotid = 1; slotid <= MAXSLOTS; slotid++) {
+ slot = &xhci->slots[slotid-1];
+ if (slot->devaddr == dev->addr) {
+ return slotid;
+ }
+ }
+ return 0;
+}
+
+static int xhci_find_epid(USBEndpoint *ep)
+{
+ if (ep->nr == 0) {
+ return 1;
+ }
+ if (ep->pid == USB_TOKEN_IN) {
+ return ep->nr * 2 + 1;
+ } else {
+ return ep->nr * 2;
+ }
+}
+
+static void xhci_wakeup_endpoint(USBBus *bus, USBEndpoint *ep)
+{
+ XHCIState *xhci = container_of(bus, XHCIState, bus);
+ int slotid;
+
+ DPRINTF("%s\n", __func__);
+ slotid = xhci_find_slotid(xhci, ep->dev);
+ if (slotid == 0 || !xhci->slots[slotid-1].enabled) {
+ DPRINTF("%s: oops, no slot for dev %d\n", __func__, ep->dev->addr);
+ return;
+ }
+ xhci_kick_ep(xhci, slotid, xhci_find_epid(ep));
+}
+
static USBBusOps xhci_bus_ops = {
+ .wakeup_endpoint = xhci_wakeup_endpoint,
};
static void usb_xhci_init(XHCIState *xhci, DeviceState *dev)
--
1.7.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* Re: [Qemu-devel] [PATCH 00/25] *** SUBJECT HERE ***
2012-01-23 14:54 [Qemu-devel] [PATCH 00/25] *** SUBJECT HERE *** Gerd Hoffmann
` (24 preceding siblings ...)
2012-01-23 14:55 ` [Qemu-devel] [PATCH 25/25] xhci: handle USB_RET_NAK Gerd Hoffmann
@ 2012-01-23 15:00 ` Gerd Hoffmann
25 siblings, 0 replies; 27+ messages in thread
From: Gerd Hoffmann @ 2012-01-23 15:00 UTC (permalink / raw)
To: Gerd Hoffmann; +Cc: qemu-devel
On 01/23/12 15:54, Gerd Hoffmann wrote:
> *** BLURB HERE ***
Oops, that wasn't supposed to happen ...
This patch series revamps the usb packet workflow to move the whole
thing to a event-based workflow. xhci emulation needs this, and we also
might be able to use this with the other host adapters to reduce
emulation cpu overhead, although it is much harder there due to the way
the hardware is designed ...
please review,
Gerd
^ permalink raw reply [flat|nested] 27+ messages in thread
end of thread, other threads:[~2012-01-23 15:00 UTC | newest]
Thread overview: 27+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-01-23 14:54 [Qemu-devel] [PATCH 00/25] *** SUBJECT HERE *** Gerd Hoffmann
2012-01-23 14:54 ` [Qemu-devel] [PATCH 01/25] usb: kill USB_MSG_{ATTACH,DETACH} Gerd Hoffmann
2012-01-23 14:54 ` [Qemu-devel] [PATCH 02/25] usb: kill USB_MSG_RESET Gerd Hoffmann
2012-01-23 14:54 ` [Qemu-devel] [PATCH 03/25] usb: kill usb_send_msg Gerd Hoffmann
2012-01-23 14:54 ` [Qemu-devel] [PATCH 04/25] usb: add usb_find_device() Gerd Hoffmann
2012-01-23 14:54 ` [Qemu-devel] [PATCH 05/25] usb-hub: implement find_device Gerd Hoffmann
2012-01-23 14:54 ` [Qemu-devel] [PATCH 06/25] usb: handle dev == NULL in usb_handle_packet() Gerd Hoffmann
2012-01-23 14:54 ` [Qemu-devel] [PATCH 07/25] usb-uhci: switch to usb_find_device() Gerd Hoffmann
2012-01-23 14:54 ` [Qemu-devel] [PATCH 08/25] usb-ehci: " Gerd Hoffmann
2012-01-23 14:54 ` [Qemu-devel] [PATCH 09/25] usb-ohci: " Gerd Hoffmann
2012-01-23 14:54 ` [Qemu-devel] [PATCH 10/25] usb-musb: " Gerd Hoffmann
2012-01-23 14:54 ` [Qemu-devel] [PATCH 11/25] usb-xhci: " Gerd Hoffmann
2012-01-23 14:54 ` [Qemu-devel] [PATCH 12/25] usb: kill handle_packet callback Gerd Hoffmann
2012-01-23 14:54 ` [Qemu-devel] [PATCH 13/25] usb: fold usb_generic_handle_packet into usb_handle_packet Gerd Hoffmann
2012-01-23 14:55 ` [Qemu-devel] [PATCH 14/25] usb: USBPacket: add status, rename owner -> ep Gerd Hoffmann
2012-01-23 14:55 ` [Qemu-devel] [PATCH 15/25] usb: add USBEndpoint->{nr,pid} Gerd Hoffmann
2012-01-23 14:55 ` [Qemu-devel] [PATCH 16/25] usb: Set USBEndpoint in usb_packet_setup() Gerd Hoffmann
2012-01-23 14:55 ` [Qemu-devel] [PATCH 17/25] usb: maintain async packet list per endpoint Gerd Hoffmann
2012-01-23 14:55 ` [Qemu-devel] [PATCH 18/25] usb: pass USBEndpoint to usb_wakeup Gerd Hoffmann
2012-01-23 14:55 ` [Qemu-devel] [PATCH 19/25] usb: add USBBusOps->wakeup_endpoint Gerd Hoffmann
2012-01-23 14:55 ` [Qemu-devel] [PATCH 20/25] xhci: signal low- and fullspeed support Gerd Hoffmann
2012-01-23 14:55 ` [Qemu-devel] [PATCH 21/25] xhci: add trb type name lookup support Gerd Hoffmann
2012-01-23 14:55 ` [Qemu-devel] [PATCH 22/25] xhci: stop on errors Gerd Hoffmann
2012-01-23 14:55 ` [Qemu-devel] [PATCH 23/25] xhci: kill port arg from xhci_setup_packet Gerd Hoffmann
2012-01-23 14:55 ` [Qemu-devel] [PATCH 24/25] xhci: remote wakeup support Gerd Hoffmann
2012-01-23 14:55 ` [Qemu-devel] [PATCH 25/25] xhci: handle USB_RET_NAK Gerd Hoffmann
2012-01-23 15:00 ` [Qemu-devel] [PATCH 00/25] *** SUBJECT HERE *** Gerd Hoffmann
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).