|
|
@@ -0,0 +1,402 @@
|
|
|
+/*
|
|
|
+ * LPCUSB, an USB device driver for LPC microcontrollers
|
|
|
+ * Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
|
|
|
+ * Copyright (c) 2016 Intel Corporation
|
|
|
+ *
|
|
|
+ * Redistribution and use in source and binary forms, with or without
|
|
|
+ * modification, are permitted provided that the following conditions are met:
|
|
|
+ *
|
|
|
+ * 1. Redistributions of source code must retain the above copyright
|
|
|
+ * notice, this list of conditions and the following disclaimer.
|
|
|
+ * 2. 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.
|
|
|
+ * 3. 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.
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @file
|
|
|
+ * @brief USB device core layer APIs and structures
|
|
|
+ *
|
|
|
+ * This file contains the USB device core layer APIs and structures.
|
|
|
+ */
|
|
|
+
|
|
|
+#pragma once
|
|
|
+
|
|
|
+#include <stddef.h>
|
|
|
+#include <sys/cdefs.h>
|
|
|
+#include "usb_dc.h"
|
|
|
+
|
|
|
+#ifdef __cplusplus
|
|
|
+extern "C" {
|
|
|
+#endif
|
|
|
+
|
|
|
+/*************************************************************************
|
|
|
+ * USB configuration
|
|
|
+ **************************************************************************/
|
|
|
+
|
|
|
+#define MAX_PACKET_SIZE0 64 /**< maximum packet size for EP 0 */
|
|
|
+//Note: for FS this should be 8, 16, 32, 64 bytes. HS can go up to 512.
|
|
|
+
|
|
|
+/*************************************************************************
|
|
|
+ * USB application interface
|
|
|
+ **************************************************************************/
|
|
|
+
|
|
|
+/** setup packet definitions */
|
|
|
+struct usb_setup_packet {
|
|
|
+ uint8_t bmRequestType; /**< characteristics of the specific request */
|
|
|
+ uint8_t bRequest; /**< specific request */
|
|
|
+ uint16_t wValue; /**< request specific parameter */
|
|
|
+ uint16_t wIndex; /**< request specific parameter */
|
|
|
+ uint16_t wLength; /**< length of data transferred in data phase */
|
|
|
+} __packed;
|
|
|
+
|
|
|
+
|
|
|
+_Static_assert(sizeof(struct usb_setup_packet) == 8, "USB setup packet struct size error");
|
|
|
+
|
|
|
+/**
|
|
|
+ * Callback function signature for the device
|
|
|
+ */
|
|
|
+typedef void (*usb_status_callback)(enum usb_dc_status_code status_code,
|
|
|
+ uint8_t *param);
|
|
|
+
|
|
|
+/**
|
|
|
+ * Callback function signature for the USB Endpoint status
|
|
|
+ */
|
|
|
+typedef void (*usb_ep_callback)(uint8_t ep,
|
|
|
+ enum usb_dc_ep_cb_status_code cb_status);
|
|
|
+
|
|
|
+/**
|
|
|
+ * Function which handles Class specific requests corresponding to an
|
|
|
+ * interface number specified in the device descriptor table
|
|
|
+ */
|
|
|
+typedef int (*usb_request_handler) (struct usb_setup_packet *detup,
|
|
|
+ int32_t *transfer_len, uint8_t **payload_data);
|
|
|
+
|
|
|
+/**
|
|
|
+ * Function for interface runtime configuration
|
|
|
+ */
|
|
|
+typedef void (*usb_interface_config)(uint8_t bInterfaceNumber);
|
|
|
+
|
|
|
+/*
|
|
|
+ * USB Endpoint Configuration
|
|
|
+ */
|
|
|
+struct usb_ep_cfg_data {
|
|
|
+ /**
|
|
|
+ * Callback function for notification of data received and
|
|
|
+ * available to application or transmit done, NULL if callback
|
|
|
+ * not required by application code
|
|
|
+ */
|
|
|
+ usb_ep_callback ep_cb;
|
|
|
+ /**
|
|
|
+ * The number associated with the EP in the device configuration
|
|
|
+ * structure
|
|
|
+ * IN EP = 0x80 | \<endpoint number\>
|
|
|
+ * OUT EP = 0x00 | \<endpoint number\>
|
|
|
+ */
|
|
|
+ uint8_t ep_addr;
|
|
|
+};
|
|
|
+
|
|
|
+/**
|
|
|
+ * USB Interface Configuration
|
|
|
+ */
|
|
|
+struct usb_interface_cfg_data {
|
|
|
+ /** Handler for USB Class specific Control (EP 0) communications */
|
|
|
+ usb_request_handler class_handler;
|
|
|
+ /** Handler for USB Vendor specific commands */
|
|
|
+ usb_request_handler vendor_handler;
|
|
|
+ /**
|
|
|
+ * The custom request handler gets a first chance at handling
|
|
|
+ * the request before it is handed over to the 'chapter 9' request
|
|
|
+ * handler
|
|
|
+ */
|
|
|
+ usb_request_handler custom_handler;
|
|
|
+ /**
|
|
|
+ * This data area, allocated by the application, is used to store
|
|
|
+ * Class specific command data and must be large enough to store the
|
|
|
+ * largest payload associated with the largest supported Class'
|
|
|
+ * command set. This data area may be used for USB IN or OUT
|
|
|
+ * communications
|
|
|
+ */
|
|
|
+ uint8_t *payload_data;
|
|
|
+ /**
|
|
|
+ * This data area, allocated by the application, is used to store
|
|
|
+ * Vendor specific payload
|
|
|
+ */
|
|
|
+ uint8_t *vendor_data;
|
|
|
+};
|
|
|
+
|
|
|
+/*
|
|
|
+ * @brief USB device configuration
|
|
|
+ *
|
|
|
+ * The Application instantiates this with given parameters added
|
|
|
+ * using the "usb_set_config" function. Once this function is called
|
|
|
+ * changes to this structure will result in undefined behaviour. This structure
|
|
|
+ * may only be updated after calls to usb_deconfig
|
|
|
+ */
|
|
|
+struct usb_cfg_data {
|
|
|
+ /**
|
|
|
+ * USB device description, see
|
|
|
+ * http://www.beyondlogic.org/usbnutshell/usb5.shtml#DeviceDescriptors
|
|
|
+ */
|
|
|
+ const uint8_t *usb_device_description;
|
|
|
+ /** Pointer to interface descriptor */
|
|
|
+ const void *interface_descriptor;
|
|
|
+ /** Function for interface runtime configuration */
|
|
|
+ usb_interface_config interface_config;
|
|
|
+ /** Callback to be notified on USB connection status change */
|
|
|
+ usb_status_callback cb_usb_status;
|
|
|
+ /** USB interface (Class) handler and storage space */
|
|
|
+ struct usb_interface_cfg_data interface;
|
|
|
+ /** Number of individual endpoints in the device configuration */
|
|
|
+ uint8_t num_endpoints;
|
|
|
+ /**
|
|
|
+ * Pointer to an array of endpoint structs of length equal to the
|
|
|
+ * number of EP associated with the device description,
|
|
|
+ * not including control endpoints
|
|
|
+ */
|
|
|
+ struct usb_ep_cfg_data *endpoint;
|
|
|
+};
|
|
|
+
|
|
|
+/*
|
|
|
+ * @brief configure USB controller
|
|
|
+ *
|
|
|
+ * Function to configure USB controller.
|
|
|
+ * Configuration parameters must be valid or an error is returned
|
|
|
+ *
|
|
|
+ * @param[in] config Pointer to configuration structure
|
|
|
+ *
|
|
|
+ * @return 0 on success, negative errno code on fail
|
|
|
+ */
|
|
|
+int usb_set_config(struct usb_cfg_data *config);
|
|
|
+
|
|
|
+/*
|
|
|
+ * @brief return the USB device to it's initial state
|
|
|
+ *
|
|
|
+ * @return 0 on success, negative errno code on fail
|
|
|
+ */
|
|
|
+int usb_deconfig(void);
|
|
|
+
|
|
|
+/*
|
|
|
+ * @brief enable USB for host/device connection
|
|
|
+ *
|
|
|
+ * Function to enable USB for host/device connection.
|
|
|
+ * Upon success, the USB module is no longer clock gated in hardware,
|
|
|
+ * it is now capable of transmitting and receiving on the USB bus and
|
|
|
+ * of generating interrupts.
|
|
|
+ *
|
|
|
+ * @return 0 on success, negative errno code on fail.
|
|
|
+ */
|
|
|
+int usb_enable(struct usb_cfg_data *config);
|
|
|
+
|
|
|
+/*
|
|
|
+ * @brief disable the USB device.
|
|
|
+ *
|
|
|
+ * Function to disable the USB device.
|
|
|
+ * Upon success, the specified USB interface is clock gated in hardware,
|
|
|
+ * it is no longer capable of generating interrupts.
|
|
|
+ *
|
|
|
+ * @return 0 on success, negative errno code on fail
|
|
|
+ */
|
|
|
+int usb_disable(void);
|
|
|
+
|
|
|
+/*
|
|
|
+ * @brief Check if a write to an in ep would block until there is enough space
|
|
|
+ * in the fifo
|
|
|
+ *
|
|
|
+ * @param[in] ep Endpoint address corresponding to the one listed in the
|
|
|
+ * device configuration table
|
|
|
+ *
|
|
|
+ * @return 0 if free to write, 1 if a write would block, negative errno code on fail
|
|
|
+ */
|
|
|
+int usb_write_would_block(uint8_t ep);
|
|
|
+
|
|
|
+/*
|
|
|
+ * @brief write data to the specified endpoint
|
|
|
+ *
|
|
|
+ * Function to write data to the specified endpoint. The supplied
|
|
|
+ * usb_ep_callback will be called when transmission is done.
|
|
|
+ *
|
|
|
+ * @param[in] ep Endpoint address corresponding to the one listed in the
|
|
|
+ * device configuration table
|
|
|
+ * @param[in] data Pointer to data to write
|
|
|
+ * @param[in] data_len Length of data requested to write. This may be zero for
|
|
|
+ * a zero length status packet.
|
|
|
+ * @param[out] bytes_ret Bytes written to the EP FIFO. This value may be NULL if
|
|
|
+ * the application expects all bytes to be written
|
|
|
+ *
|
|
|
+ * @return 0 on success, negative errno code on fail
|
|
|
+ */
|
|
|
+int usb_write(uint8_t ep, const uint8_t *data, uint32_t data_len,
|
|
|
+ uint32_t *bytes_ret);
|
|
|
+
|
|
|
+/*
|
|
|
+ * @brief read data from the specified endpoint
|
|
|
+ *
|
|
|
+ * This function is called by the Endpoint handler function, after an
|
|
|
+ * OUT interrupt has been received for that EP. The application must
|
|
|
+ * only call this function through the supplied usb_ep_callback function.
|
|
|
+ *
|
|
|
+ * @param[in] ep Endpoint address corresponding to the one listed in
|
|
|
+ * the device configuration table
|
|
|
+ * @param[in] data Pointer to data buffer to write to
|
|
|
+ * @param[in] max_data_len Max length of data to read
|
|
|
+ * @param[out] ret_bytes Number of bytes read. If data is NULL and
|
|
|
+ * max_data_len is 0 the number of bytes available
|
|
|
+ * for read is returned.
|
|
|
+ *
|
|
|
+ * @return 0 on success, negative errno code on fail
|
|
|
+ */
|
|
|
+int usb_read(uint8_t ep, uint8_t *data, uint32_t max_data_len,
|
|
|
+ uint32_t *ret_bytes);
|
|
|
+
|
|
|
+/*
|
|
|
+ * @brief set STALL condition on the specified endpoint
|
|
|
+ *
|
|
|
+ * This function is called by USB device class handler code to set stall
|
|
|
+ * conditionin on endpoint.
|
|
|
+ *
|
|
|
+ * @param[in] ep Endpoint address corresponding to the one listed in
|
|
|
+ * the device configuration table
|
|
|
+ *
|
|
|
+ * @return 0 on success, negative errno code on fail
|
|
|
+ */
|
|
|
+int usb_ep_set_stall(uint8_t ep);
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+ * @brief clears STALL condition on the specified endpoint
|
|
|
+ *
|
|
|
+ * This function is called by USB device class handler code to clear stall
|
|
|
+ * conditionin on endpoint.
|
|
|
+ *
|
|
|
+ * @param[in] ep Endpoint address corresponding to the one listed in
|
|
|
+ * the device configuration table
|
|
|
+ *
|
|
|
+ * @return 0 on success, negative errno code on fail
|
|
|
+ */
|
|
|
+int usb_ep_clear_stall(uint8_t ep);
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief read data from the specified endpoint
|
|
|
+ *
|
|
|
+ * This is similar to usb_ep_read, the difference being that, it doesn't
|
|
|
+ * clear the endpoint NAKs so that the consumer is not bogged down by further
|
|
|
+ * upcalls till he is done with the processing of the data. The caller should
|
|
|
+ * reactivate ep by invoking usb_ep_read_continue() do so.
|
|
|
+ *
|
|
|
+ * @param[in] ep Endpoint address corresponding to the one
|
|
|
+ * listed in the device configuration table
|
|
|
+ * @param[in] data pointer to data buffer to write to
|
|
|
+ * @param[in] max_data_len max length of data to read
|
|
|
+ * @param[out] read_bytes Number of bytes read. If data is NULL and
|
|
|
+ * max_data_len is 0 the number of bytes
|
|
|
+ * available for read should be returned.
|
|
|
+ *
|
|
|
+ * @return 0 on success, negative errno code on fail.
|
|
|
+ */
|
|
|
+int usb_ep_read_wait(uint8_t ep, uint8_t *data, uint32_t max_data_len,
|
|
|
+ uint32_t *read_bytes);
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief Continue reading data from the endpoint
|
|
|
+ *
|
|
|
+ * Clear the endpoint NAK and enable the endpoint to accept more data
|
|
|
+ * from the host. Usually called after usb_ep_read_wait() when the consumer
|
|
|
+ * is fine to accept more data. Thus these calls together acts as flow control
|
|
|
+ * mechanism.
|
|
|
+ *
|
|
|
+ * @param[in] ep Endpoint address corresponding to the one
|
|
|
+ * listed in the device configuration table
|
|
|
+ *
|
|
|
+ * @return 0 on success, negative errno code on fail.
|
|
|
+ */
|
|
|
+int usb_ep_read_continue(uint8_t ep);
|
|
|
+
|
|
|
+/**
|
|
|
+ * Callback function signature for transfer completion.
|
|
|
+ */
|
|
|
+typedef void (*usb_transfer_callback)(uint8_t ep, int tsize, void *priv);
|
|
|
+
|
|
|
+/* USB transfer flags */
|
|
|
+#define USB_TRANS_READ BIT(0) /** Read transfer flag */
|
|
|
+#define USB_TRANS_WRITE BIT(1) /** Write transfer flag */
|
|
|
+#define USB_TRANS_NO_ZLP BIT(2) /** No zero-length packet flag */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief Transfer management endpoint callback
|
|
|
+ *
|
|
|
+ * If a USB class driver wants to use high-level transfer functions, driver
|
|
|
+ * needs to register this callback as usb endpoint callback.
|
|
|
+ */
|
|
|
+void usb_transfer_ep_callback(uint8_t ep, enum usb_dc_ep_cb_status_code);
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief Start a transfer
|
|
|
+ *
|
|
|
+ * Start a usb transfer to/from the data buffer. This function is asynchronous
|
|
|
+ * and can be executed in IRQ context. The provided callback will be called
|
|
|
+ * on transfer completion (or error) in thread context.
|
|
|
+ *
|
|
|
+ * @param[in] ep Endpoint address corresponding to the one
|
|
|
+ * listed in the device configuration table
|
|
|
+ * @param[in] data Pointer to data buffer to write-to/read-from
|
|
|
+ * @param[in] dlen Size of data buffer
|
|
|
+ * @param[in] flags Transfer flags (USB_TRANS_READ, USB_TRANS_WRITE...)
|
|
|
+ * @param[in] cb Function called on transfer completion/failure
|
|
|
+ * @param[in] priv Data passed back to the transfer completion callback
|
|
|
+ *
|
|
|
+ * @return 0 on success, negative errno code on fail.
|
|
|
+ */
|
|
|
+int usb_transfer(uint8_t ep, uint8_t *data, size_t dlen, unsigned int flags,
|
|
|
+ usb_transfer_callback cb, void *priv);
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief Start a transfer and block-wait for completion
|
|
|
+ *
|
|
|
+ * Synchronous version of usb_transfer, wait for transfer completion before
|
|
|
+ * returning.
|
|
|
+ *
|
|
|
+ * @param[in] ep Endpoint address corresponding to the one
|
|
|
+ * listed in the device configuration table
|
|
|
+ * @param[in] data Pointer to data buffer to write-to/read-from
|
|
|
+ * @param[in] dlen Size of data buffer
|
|
|
+ * @param[in] flags Transfer flags
|
|
|
+
|
|
|
+ *
|
|
|
+ * @return number of bytes transferred on success, negative errno code on fail.
|
|
|
+ */
|
|
|
+int usb_transfer_sync(uint8_t ep, uint8_t *data, size_t dlen, unsigned int flags);
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief Cancel any ongoing transfer on the specified endpoint
|
|
|
+ *
|
|
|
+ * @param[in] ep Endpoint address corresponding to the one
|
|
|
+ * listed in the device configuration table
|
|
|
+ *
|
|
|
+ * @return 0 on success, negative errno code on fail.
|
|
|
+ */
|
|
|
+void usb_cancel_transfer(uint8_t ep);
|
|
|
+
|
|
|
+
|
|
|
+void usb_dev_resume(int configuration);
|
|
|
+int usb_dev_get_configuration(void);
|
|
|
+
|
|
|
+
|
|
|
+#ifdef __cplusplus
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|