summaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorPeter Wu <peter@lekensteyn.nl>2014-03-15 17:51:06 +0100
committerPeter Wu <peter@lekensteyn.nl>2014-03-16 00:10:06 +0100
commitf47dd59ee594e62029a919b20fc048ce8421b0c2 (patch)
treef1699dfa7a8643256695012fd7309acbe2e36ad6 /hw
parent43d6464d410136f1c083a6df263bb71319eb2244 (diff)
downloadqemu-f47dd59ee594e62029a919b20fc048ce8421b0c2.tar.gz
usbdump: initial API extension for handle_data
Signed-off-by: Peter Wu <peter@lekensteyn.nl>
Diffstat (limited to 'hw')
-rw-r--r--hw/usb/dump.c56
-rw-r--r--hw/usb/dump.h28
2 files changed, 83 insertions, 1 deletions
diff --git a/hw/usb/dump.c b/hw/usb/dump.c
index eb4ce336e4..bff9bcd601 100644
--- a/hw/usb/dump.c
+++ b/hw/usb/dump.c
@@ -258,6 +258,9 @@ static void init_from_usbpacket(UsbDumpState *s, struct usbmon_packet *u,
}
+
+/* control transfers; data request for interrupt, bulk, isochronous transfers */
+
void usb_dump_submit(UsbDumpState *s, USBPacket *p)
{
struct usbmon_packet u;
@@ -283,6 +286,8 @@ void usb_dump_submit(UsbDumpState *s, USBPacket *p)
assert(ep_type == USB_ENDPOINT_XFER_ISOC ||
ep_type == USB_ENDPOINT_XFER_BULK ||
ep_type == USB_ENDPOINT_XFER_INT);
+ /* no data submitted, must be a IN request */
+ assert(pid == USB_TOKEN_IN);
}
init_from_usbpacket(s, &u, p, 'S', datalen);
@@ -313,12 +318,63 @@ void usb_dump_complete(UsbDumpState *s, USBPacket *p)
assert(ep_type == USB_ENDPOINT_XFER_ISOC ||
ep_type == USB_ENDPOINT_XFER_BULK ||
ep_type == USB_ENDPOINT_XFER_INT);
+ /* no ack of data, must have received data for processing.
+ * Alternative: no data could be created due to an error. */
+ assert(pid == USB_TOKEN_OUT ||
+ (pid == USB_TOKEN_IN && p->status != USB_RET_SUCCESS));
}
init_from_usbpacket(s, &u, p, 'C', datalen);
usb_dump_packet(s, &u, dev->data_buf);
}
+
+/* data for interrupt, bulk, isochronous transfers */
+
+void usb_dump_submit_data(UsbDumpState *s, USBPacket *p,
+ uint8_t *data, size_t len)
+{
+ struct usbmon_packet u;
+ uint8_t pid = p->pid;
+ uint8_t ep_type = p->ep->type;
+
+ /* fail early if not configured */
+ if (!s || s->fd < 0) {
+ return;
+ }
+
+ assert(ep_type == USB_ENDPOINT_XFER_ISOC ||
+ ep_type == USB_ENDPOINT_XFER_BULK ||
+ ep_type == USB_ENDPOINT_XFER_INT);
+ /* got data for device, must be an OUT request */
+ assert(pid == USB_TOKEN_OUT);
+
+ init_from_usbpacket(s, &u, p, 'S', len);
+ usb_dump_packet(s, &u, data);
+}
+
+void usb_dump_complete_data(UsbDumpState *s, USBPacket *p,
+ uint8_t *data, size_t len)
+{
+ struct usbmon_packet u;
+ uint8_t pid = p->pid;
+ uint8_t ep_type = p->ep->type;
+
+ /* fail early if not configured */
+ if (!s || s->fd < 0) {
+ return;
+ }
+
+ assert(ep_type == USB_ENDPOINT_XFER_ISOC ||
+ ep_type == USB_ENDPOINT_XFER_BULK ||
+ ep_type == USB_ENDPOINT_XFER_INT);
+ /* device made some data for host */
+ assert(pid == USB_TOKEN_IN);
+
+ init_from_usbpacket(s, &u, p, 'C', len);
+ usb_dump_packet(s, &u, data);
+}
+
void usb_dump_cleanup(UsbDumpState *s)
{
if (s->fd >= 0) {
diff --git a/hw/usb/dump.h b/hw/usb/dump.h
index 08134e82e3..1fb8389b60 100644
--- a/hw/usb/dump.h
+++ b/hw/usb/dump.h
@@ -31,7 +31,7 @@ typedef struct UsbDumpState UsbDumpState;
/*
* p->pid shows whether a packet is IN, OUT or SETUP.
*
- * handle_ctrl is called for:
+ * handle_control is called for:
* - SETUP (setup dir IN): setup_buf provided, data ptr is data (setup_len > 0)
* - IN: setup_len > 0 (data): callback for OUT
* - (same code path: IN: setup_len == 0 (!data): Called iff dir is OUT
@@ -52,6 +52,11 @@ typedef struct UsbDumpState UsbDumpState;
* - setup(setup_len == 0, IN) / status^SC,(IN) - Same as above (with
* status(IN)), but there is no data for both submission and callback.
* - setup(setup_len == 0, OUT) / status(OUT) (BROKEN!)
+ *
+ * handle_data is called for all non-EP0 transfers. PID is either IN or OUT.
+ * Sequence for the PID cases:
+ * - IN: submit(); make data; complete(data); usb_packet_copy(data)
+ * - OUT: usb_packet_copy(data); submit(data); process data; complete()
*/
/*
@@ -60,6 +65,8 @@ typedef struct UsbDumpState UsbDumpState;
* data is of length setup_len. PID == OUT is not possible because handle_ctrl
* is never called from that point.
*
+ * submit (data): IN request (host wants data from dev), so no data attached.
+ *
* If s is NULL or if no dump file is available, no action is performed.
*/
void usb_dump_submit(UsbDumpState *s, USBPacket *p);
@@ -69,10 +76,29 @@ void usb_dump_submit(UsbDumpState *s, USBPacket *p);
* inserted by the "device" in handle_ctrl. Length is actual_length. If PID ==
* IN, then data is empty. PID == OUT is again not possible (see submit).
*
+ * complete (data): OUT status (device has received data), so no data attached.
+ * Also called for pid == IN if an error occured (p->status != USB_RET_SUCCESS)
+ * and no data is available.
+ *
* If s is NULL or if no dump file is available, no action is performed.
*/
void usb_dump_complete(UsbDumpState *s, USBPacket *p);
+/*
+ * submit (data): OUT request, host has data for device.
+ *
+ * If s is NULL or if no dump file is available, no action is performed.
+ */
+void usb_dump_submit_data(UsbDumpState *s, USBPacket *p,
+ uint8_t *data, size_t len);
+/*
+ * complete (data): IN status, device has data for device.
+ *
+ * If s is NULL or if no dump file is available, no action is performed.
+ */
+void usb_dump_complete_data(UsbDumpState *s, USBPacket *p,
+ uint8_t *data, size_t len);
+
void usb_dump_cleanup(UsbDumpState *s);