/* * Copyright (c) 2010 Vojtech Horky * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @addtogroup libusbvirt usb * @{ */ /** @file * @brief Virtual USB device. */ #ifndef LIBUSBVIRT_DEVICE_H_ #define LIBUSBVIRT_DEVICE_H_ #include #include #include typedef struct usbvirt_device usbvirt_device_t; struct usbvirt_control_transfer; typedef int (*usbvirt_on_device_request_t)(usbvirt_device_t *dev, usb_device_request_setup_packet_t *request, uint8_t *data); /** Callbacks for standard device requests. * When these functions are NULL or return EFORWARD, this * framework will try to satisfy the request by itself. */ typedef struct { usbvirt_on_device_request_t on_get_status; usbvirt_on_device_request_t on_clear_feature; usbvirt_on_device_request_t on_set_feature; usbvirt_on_device_request_t on_set_address; usbvirt_on_device_request_t on_get_descriptor; usbvirt_on_device_request_t on_set_descriptor; usbvirt_on_device_request_t on_get_configuration; usbvirt_on_device_request_t on_set_configuration; usbvirt_on_device_request_t on_get_interface; usbvirt_on_device_request_t on_set_interface; usbvirt_on_device_request_t on_synch_frame; } usbvirt_standard_device_request_ops_t; /** Device operations. */ typedef struct { /** Callbacks for standard deivce requests. */ usbvirt_standard_device_request_ops_t *standard_request_ops; /** Callback for class-specific USB request. */ usbvirt_on_device_request_t on_class_device_request; int (*on_control_transfer)(usbvirt_device_t *dev, usb_endpoint_t endpoint, struct usbvirt_control_transfer *transfer); /** Callback for all other incoming data. */ int (*on_data)(usbvirt_device_t *dev, usb_endpoint_t endpoint, void *buffer, size_t size); /** Callback for host request for data. */ int (*on_data_request)(usbvirt_device_t *dev, usb_endpoint_t endpoint, void *buffer, size_t size, size_t *actual_size); /** Decides direction of control transfer. */ usb_direction_t (*decide_control_transfer_direction)( usb_endpoint_t endpoint, void *buffer, size_t size); } usbvirt_device_ops_t; /** Extra configuration data for GET_CONFIGURATION request. */ typedef struct { /** Actual data. */ uint8_t *data; /** Data length. */ size_t length; } usbvirt_device_configuration_extras_t; /** Single device configuration. */ typedef struct { /** Standard configuration descriptor. */ usb_standard_configuration_descriptor_t *descriptor; /** Array of extra data. */ usbvirt_device_configuration_extras_t *extra; /** Length of @c extra array. */ size_t extra_count; } usbvirt_device_configuration_t; /** Standard USB descriptors. */ typedef struct { /** Standard device descriptor. * There is always only one such descriptor for the device. */ usb_standard_device_descriptor_t *device; /** Configurations. */ usbvirt_device_configuration_t *configuration; /** Number of configurations. */ size_t configuration_count; /** Index of currently selected configuration. */ uint8_t current_configuration; } usbvirt_descriptors_t; /** Possible states of virtual USB device. * Notice that these are not 1:1 mappings to those in USB specification. */ typedef enum { USBVIRT_STATE_DEFAULT, USBVIRT_STATE_ADDRESS, USBVIRT_STATE_CONFIGURED } usbvirt_device_state_t; /** Information about on-going control transfer. */ typedef struct usbvirt_control_transfer { /** Transfer direction (read/write control transfer). */ usb_direction_t direction; /** Request data. */ void *request; /** Size of request data. */ size_t request_size; /** Payload. */ void *data; /** Size of payload. */ size_t data_size; } usbvirt_control_transfer_t; typedef enum { USBVIRT_DEBUGTAG_BASE = 1, USBVIRT_DEBUGTAG_TRANSACTION = 2, USBVIRT_DEBUGTAG_CONTROL_PIPE_ZERO = 4, USBVIRT_DEBUGTAG_ALL = 255 } usbvirt_debug_tags_t; /** Virtual USB device. */ struct usbvirt_device { /** Callback device operations. */ usbvirt_device_ops_t *ops; /** Reply onto control transfer. */ int (*control_transfer_reply)(usbvirt_device_t *dev, usb_endpoint_t endpoint, void *buffer, size_t size); /** Device name. * Used in debug prints and sent to virtual host controller. */ const char *name; /** Standard descriptors. */ usbvirt_descriptors_t *descriptors; /** Current device state. */ usbvirt_device_state_t state; /** Device address. */ usb_address_t address; /** New device address. * This field is used during SET_ADDRESS request. * On all other occasions, it holds invalid address (e.g. -1). */ usb_address_t new_address; /** Process OUT transaction. */ int (*transaction_out)(usbvirt_device_t *dev, usb_endpoint_t endpoint, void *buffer, size_t size); /** Process SETUP transaction. */ int (*transaction_setup)(usbvirt_device_t *dev, usb_endpoint_t endpoint, void *buffer, size_t size); /** Process IN transaction. */ int (*transaction_in)(usbvirt_device_t *dev, usb_endpoint_t endpoint, void *buffer, size_t size, size_t *data_size); /** State information on control-transfer endpoints. */ usbvirt_control_transfer_t current_control_transfers[USB11_ENDPOINT_MAX]; /* User debugging. */ /** Debug print. */ void (*debug)(usbvirt_device_t *dev, int level, uint8_t tag, const char *format, ...); /** Current debug level. */ int debug_level; /** Bitmap of currently enabled tags. */ uint8_t debug_enabled_tags; /* Library debugging. */ /** Debug print. */ void (*lib_debug)(usbvirt_device_t *dev, int level, uint8_t tag, const char *format, ...); /** Current debug level. */ int lib_debug_level; /** Bitmap of currently enabled tags. */ uint8_t lib_debug_enabled_tags; }; #endif /** * @} */