/* * USB capture helper. * * Copyright (c) 2014 Peter Wu * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef QEMU_HW_USB_DUMP_H #define QEMU_HW_USB_DUMP_H #include "qapi-types.h" typedef struct UsbDumpState UsbDumpState; /* * p->pid shows whether a packet is IN, OUT or SETUP. * * 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 * (otherwise BROKEN!)) * - Note: never called in OUT (via do_token_out), but do_parameter may call * with OUT as does XHCI. * * Possible combinations (^X,Y = handle_ctrl called, X and Y are Submission or * Callback where X is called before processing the data in handle_ctrl, and Y * must be called right before returning because data is modified. If order does * not matter (e.g. XY, then the order is still recommended to be X,Y for timing * considerations)): * - setup^S,C(setup_len > 0, IN) / data(IN) / status(OUT) - Submission contains * setup packet with no data (actual_length == 0), callback contains data (len * actual_length). * - setup(setup_len > 0, OUT) / data(OUT) / status^SC,(IN) - Submission * contains setup packet and data (len setup_len), callback contains no data * (just success). * - 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!) * - NOTE: do_parameter() is not taken into account in the above description. * * handle_data is called for all non-EP0 transfers. PID is either IN or OUT. * Sequence for the PID cases (interrupt): * - IN: make data; complete(data); usb_packet_copy(data); submit() * - OUT: usb_packet_copy(data); submit(data); process data; complete() * * If there is no data for IN, just return NAK without dumping to avoid log * flood (due to the periodic polling by interrupts and isoc). * Isoc has probably the same sequence as interrupt; bulk less so. * In the IN sequence, note that complete(data) is called before submit. See the * below diagram for the reason. * ___________ * _____ \ ev_type / * | dir \ | S | C | * | +---+---+ * | IN | n | y | (whether the packet has data for this * | OUT | y | n | combination of ev_type and direction) * --------+---+---+ * * Control: DONE * Int: DONE * Bulk: TODO * Isoc: TODO */ /* * submit (ctrl): always log setup_buf, do not use PID for determining * direction, but setup_buf[0]. data is empty for PID == SETUP; for PID == IN, * 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, const USBPacket *p); /* * complete (ctrl): setup_is irrelevant. If PID == SETUP, then the data was just * 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, const 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, const USBPacket *p, const 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, const USBPacket *p, const uint8_t *data, size_t len); void usb_dump_cleanup(UsbDumpState *s); int usb_dump_init(UsbDumpState *s, const char *filename); UsbDumpState *usb_dump_init_alloc(const char *filename); #endif