summaryrefslogtreecommitdiff
path: root/hw/usb/dump.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/usb/dump.c')
-rw-r--r--hw/usb/dump.c27
1 files changed, 19 insertions, 8 deletions
diff --git a/hw/usb/dump.c b/hw/usb/dump.c
index b0209c1f02..3f2fef1b1e 100644
--- a/hw/usb/dump.c
+++ b/hw/usb/dump.c
@@ -298,11 +298,17 @@ void usb_dump_submit(UsbDumpState *s, const USBPacket *p)
}
if (ep_type == USB_ENDPOINT_XFER_CONTROL) {
- /* PID is IN because this is the status stage for OUT, it cannot get
- * called for OUT (that would be the data packet themselves) */
- assert(pid == USB_TOKEN_IN || pid == USB_TOKEN_SETUP);
-
- if (pid == USB_TOKEN_IN) {
+ /**
+ * Two moments where an out transfer happens.
+ * (1) Via the normal do_token_setup()/do_token_out()/do_token_in()
+ * sequence. As handle_control() is only called in do_token_in()
+ * (the status stage), the PID will be IN.
+ * (2) Via do_parameter (as used by XHCI), all setup/data/status stages
+ * are done at once, and the PID will be OUT.
+ * (3) Via xhci_address_slot(), the PID will be OUT. As there is no
+ * data, this case does not really provide data.
+ */
+ if (pid == USB_TOKEN_IN || (pid == USB_TOKEN_OUT && p->parameter)) {
/* ctrl: device should set data in setup stage */
datalen = dev->setup_len;
}
@@ -332,9 +338,14 @@ void usb_dump_complete(UsbDumpState *s, const USBPacket *p)
}
if (ep_type == USB_ENDPOINT_XFER_CONTROL) {
- assert(pid == USB_TOKEN_IN || pid == USB_TOKEN_SETUP);
-
- if (pid == USB_TOKEN_SETUP) {
+ /* Two modes of operation where data is available:
+ * (1) Via the normal do_token_setup() sequence. Data is provided by the
+ * device, but since handle_control() is called in do_token_setup(),
+ * the PID will be SETUP.
+ * (2) Via do_parameter (as used by XHCI), all setup/data/status stages
+ * are done at once, and the PID will be IN when data was requested.
+ */
+ if (pid == USB_TOKEN_SETUP || (pid == USB_TOKEN_IN && p->parameter)) {
/* this was an IN request, data is now available. */
assert(dev->setup_buf[0] & USB_DIR_IN);
datalen = p->actual_length;