HelenOS sources

root/uspace/lib/usbvirt/include/usbvirt/device.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


/*
 * Copyright (c) 2011 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
 * @{
 */
/** @file
 * Virtual USB device.
 */

#ifndef LIBUSBVIRT_DEVICE_H_
#define LIBUSBVIRT_DEVICE_H_

#include <usb/usb.h>
#include <usb/dev/request.h>
#include <async.h>
#include <errno.h>

/** Maximum number of endpoints supported by virtual USB. */
#define USBVIRT_ENDPOINT_MAX 16

typedef struct usbvirt_device usbvirt_device_t;

/** Callback for data to device (OUT transaction).
 *
 * @param dev Virtual device to which the transaction belongs.
 * @param endpoint Target endpoint number.
 * @param transfer_type Transfer type.
 * @param buffer Data buffer.
 * @param buffer_size Size of the buffer in bytes.
 * @return Error code.
 */
typedef errno_t (*usbvirt_on_data_to_device_t)(usbvirt_device_t *dev,
    usb_endpoint_t endpoint, usb_transfer_type_t transfer_type,
    const void *buffer, size_t buffer_size);

/** Callback for data from device (IN transaction).
 *
 * @param dev Virtual device to which the transaction belongs.
 * @param endpoint Target endpoint number.
 * @param transfer_type Transfer type.
 * @param buffer Data buffer to write answer to.
 * @param buffer_size Size of the buffer in bytes.
 * @param act_buffer_size Write here how many bytes were actually written.
 * @return Error code.
 */
typedef errno_t (*usbvirt_on_data_from_device_t)(usbvirt_device_t *dev,
    usb_endpoint_t endpoint, usb_transfer_type_t transfer_type,
    void *buffer, size_t buffer_size, size_t *act_buffer_size);

/** Callback for control transfer on endpoint zero.
 *
 * Notice that size of the data buffer is expected to be read from the
 * setup packet.
 *
 * @param dev Virtual device to which the transaction belongs.
 * @param setup_packet Standard setup packet.
 * @param data Data (might be NULL).
 * @param act_data_size Size of returned data in bytes.
 * @return Error code.
 */
typedef errno_t (*usbvirt_on_control_t)(usbvirt_device_t *dev,
    const usb_device_request_setup_packet_t *setup_packet,
    uint8_t *data, size_t *act_data_size);

/** Create a class request to get data from device
 *
 * @param rec Request recipient.
 * @param req Request code.
 */
#define CLASS_REQ_IN(rec, req) \
        .request_type = SETUP_REQUEST_TO_HOST(USB_REQUEST_TYPE_CLASS, rec), \
        .request = req

/** Create a class request to send data to device
 *
 * @param rec Request recipient.
 * @param req Request code.
 */
#define CLASS_REQ_OUT(rec, req) \
        .request_type = SETUP_REQUEST_TO_DEVICE(USB_REQUEST_TYPE_CLASS, rec), \
        .request = req

/** Create a standard request to get data from device
 *
 * @param rec Request recipient.
 * @param req Request code.
 */
#define STD_REQ_IN(rec, req) \
        .request_type = SETUP_REQUEST_TO_HOST(USB_REQUEST_TYPE_STANDARD, rec), \
        .request = req

/** Create a standard request to send data to device
 *
 * @param rec Request recipient.
 * @param req Request code.
 */
#define STD_REQ_OUT(rec, req) \
        .request_type = SETUP_REQUEST_TO_DEVICE(USB_REQUEST_TYPE_STANDARD, rec), \
        .request = req

/** Callback for control request on a virtual USB device.
 *
 * See usbvirt_control_reply_helper() for simple way of answering
 * control read requests.
 */
typedef struct {
        /* Request type. See usb/request.h */
        uint8_t request_type;
        /** Actual request code. */
        uint8_t request;
        /** Request handler name for debugging purposes. */
        const char *name;
        /** Callback to be executed on matching request. */
        usbvirt_on_control_t callback;
} usbvirt_control_request_handler_t;

/** Extra configuration data for GET_CONFIGURATION request. */
typedef struct {
        /** Actual data. */
        const 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 for virtual device. */
typedef struct {
        /** Standard device descriptor.
         * There is always only one such descriptor for the device.
         */
        const usb_standard_device_descriptor_t *device;

        /** Configurations. */
        usbvirt_device_configuration_t *configuration;
        /** Number of configurations. */
        size_t configuration_count;
} usbvirt_descriptors_t;

/** Possible states of virtual USB device.
 * Notice that these are not 1:1 mappings to those in USB specification.
 */
typedef enum {
        /** Default state, device listens at default address. */
        USBVIRT_STATE_DEFAULT,
        /** Device has non-default address assigned. */
        USBVIRT_STATE_ADDRESS,
        /** Device is configured. */
        USBVIRT_STATE_CONFIGURED
} usbvirt_device_state_t;

/** Ops structure for virtual USB device. */
typedef struct {
        /** Callbacks for data to device.
         * Index zero is ignored.
         */
        usbvirt_on_data_to_device_t data_out[USBVIRT_ENDPOINT_MAX];
        /** Callbacks for data from device.
         * Index zero is ignored.
         */
        usbvirt_on_data_from_device_t data_in[USBVIRT_ENDPOINT_MAX];
        /** Array of control handlers.
         * Last handler is expected to have the @c callback field set to NULL
         */
        const usbvirt_control_request_handler_t *control;
        /** Callback when device changes state.
         *
         * The value of @c state attribute of @p dev device is not
         * defined during call of this function.
         *
         * @param dev The virtual USB device.
         * @param old_state Old device state.
         * @param new_state New device state.
         */
        void (*state_changed)(usbvirt_device_t *dev,
            usbvirt_device_state_t old_state, usbvirt_device_state_t new_state);
} usbvirt_device_ops_t;

/** Virtual USB device. */
struct usbvirt_device {
        /** Device does not require USB bus power */
        bool self_powered;
        /** Device is allowed to signal remote wakeup */
        bool remote_wakeup;
        /** Name for debugging purposes. */
        const char *name;
        /** Custom device data. */
        void *device_data;
        /** Device ops. */
        usbvirt_device_ops_t *ops;
        /** Device descriptors. */
        const usbvirt_descriptors_t *descriptors;
        /** Current device address.
         * You shall treat this field as read only in your code.
         */
        usb_address_t address;
        /** Current device state.
         * You shall treat this field as read only in your code.
         */
        usbvirt_device_state_t state;
        /** Session to the host controller.
         * You shall treat this field as read only in your code.
         */
        async_sess_t *vhc_sess;
};

extern errno_t req_nop(usbvirt_device_t *device,
    const usb_device_request_setup_packet_t *setup_packet,
    uint8_t *data, size_t *act_size);

extern errno_t usbvirt_device_plug(usbvirt_device_t *, const char *);
extern void usbvirt_device_unplug(usbvirt_device_t *);

extern void usbvirt_control_reply_helper(
    const usb_device_request_setup_packet_t *, uint8_t *, size_t *,
    const void *, size_t);

extern errno_t usbvirt_control_write(usbvirt_device_t *, const void *, size_t,
    void *, size_t);
extern errno_t usbvirt_control_read(usbvirt_device_t *, const void *, size_t,
    void *, size_t, size_t *);
extern errno_t usbvirt_data_out(usbvirt_device_t *, usb_transfer_type_t,
    usb_endpoint_t, const void *, size_t);
extern errno_t usbvirt_data_in(usbvirt_device_t *, usb_transfer_type_t,
    usb_endpoint_t, void *, size_t, size_t *);

#endif

/**
 * @}
 */

/* [<][>][^][v][top][bottom][index][help] */
HelenOS homepage, sources at GitHub