From f47dd59ee594e62029a919b20fc048ce8421b0c2 Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Sat, 15 Mar 2014 17:51:06 +0100 Subject: usbdump: initial API extension for handle_data Signed-off-by: Peter Wu --- hw/usb/dump.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ hw/usb/dump.h | 28 +++++++++++++++++++++++++++- 2 files changed, 83 insertions(+), 1 deletion(-) (limited to 'hw') 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); -- cgit v1.2.1