aboutsummaryrefslogtreecommitdiff
path: root/atmel-samd/asf4/samd51/hal/include/hpl_usb_host.h
diff options
context:
space:
mode:
Diffstat (limited to 'atmel-samd/asf4/samd51/hal/include/hpl_usb_host.h')
-rw-r--r--atmel-samd/asf4/samd51/hal/include/hpl_usb_host.h628
1 files changed, 628 insertions, 0 deletions
diff --git a/atmel-samd/asf4/samd51/hal/include/hpl_usb_host.h b/atmel-samd/asf4/samd51/hal/include/hpl_usb_host.h
new file mode 100644
index 000000000..ee48ecc3a
--- /dev/null
+++ b/atmel-samd/asf4/samd51/hal/include/hpl_usb_host.h
@@ -0,0 +1,628 @@
+/**
+ * \file
+ *
+ * \brief SAM USB host HPL
+ *
+ * Copyright (C) 2016 - 2017 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * 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 Atmel may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ * Atmel microcontroller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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.
+ *
+ * \asf_license_stop
+ *
+ */
+
+#ifndef _HPL_USB_HOST_H_INCLUDED
+#define _HPL_USB_HOST_H_INCLUDED
+
+#include <hpl_usb.h>
+#include <hpl_irq.h>
+#include "hpl_usb_config.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Driver version */
+#define USB_H_VERSION 0x00000001
+
+/**
+ * @brief USB HCD callback types
+ */
+enum usb_h_cb_type {
+ /** SOF generated */
+ USB_H_CB_SOF,
+ /** Root Hub change detected */
+ USB_H_CB_ROOTHUB_CHANGE,
+ /** Number of USB HCD callback types */
+ USB_H_CB_N
+};
+
+/**
+ * @brief USB HCD resource strategy
+ */
+enum usb_h_rsc_strategy {
+ /** Normal resource allocation, e.g.,
+ * 1 bank for interrupt endpoint,
+ * 2 bank for bulk endpoint and normal iso endpoint,
+ * 3 bank for iso high bandwidth endpoint.
+ */
+ USB_H_RSC_NORMAL = false,
+ /** Minimal resource allocation, e.g., only 1 bank for bulk endpoints */
+ USB_H_RSC_MINIMAL = true
+};
+
+/**
+ * @brief USB HCD pipe states
+ */
+enum usb_h_pipe_state {
+ /** Pipe is free to allocate */
+ USB_H_PIPE_S_FREE = 0x00,
+ /** Pipe is in configuration */
+ USB_H_PIPE_S_CFG = 0x01,
+ /** Pipe is allocated and idle */
+ USB_H_PIPE_S_IDLE = 0x02,
+ /** Pipe in control setup stage */
+ USB_H_PIPE_S_SETUP = 0x03,
+ /** Pipe in data IN stage */
+ USB_H_PIPE_S_DATI = 0x05,
+ /** Pipe in data OUT stage */
+ USB_H_PIPE_S_DATO = 0x06,
+ /** Pipe in data IN ZLP stage */
+ USB_H_PIPE_S_ZLPI = 0x07,
+ /** Pipe in data OUT ZLP stage */
+ USB_H_PIPE_S_ZLPO = 0x08,
+ /** Pipe in control status IN stage */
+ USB_H_PIPE_S_STATI = 0x09,
+ /** Pipe in control status OUT stage */
+ USB_H_PIPE_S_STATO = 0x0A,
+ /** Taken by physical pipe (in process) */
+ USB_H_PIPE_S_TAKEN = 0x10
+};
+
+/**
+ * @brief USB HCD status code
+ */
+enum usb_h_status {
+ /** OK */
+ USB_H_OK = ERR_NONE,
+ /** Busy */
+ USB_H_BUSY = ERR_BUSY,
+ /** Denied */
+ USB_H_DENIED = ERR_DENIED,
+ /** Timeout */
+ USB_H_TIMEOUT = ERR_TIMEOUT,
+ /** Abort */
+ USB_H_ABORT = ERR_ABORTED,
+ /** Stall protocol */
+ USB_H_STALL = ERR_PROTOCOL,
+ /** Transfer reset by pipe re-configure */
+ USB_H_RESET = ERR_REQ_FLUSHED,
+ /** Argument error */
+ USB_H_ERR_ARG = ERR_INVALID_ARG,
+ /** Operation not supported */
+ USB_H_ERR_UNSP_OP = ERR_UNSUPPORTED_OP,
+ /** No resource */
+ USB_H_ERR_NO_RSC = ERR_NO_RESOURCE,
+ /** Not initialized */
+ USB_H_ERR_NOT_INIT = ERR_NOT_INITIALIZED,
+ /** Some general error */
+ USB_H_ERR = ERR_IO
+};
+
+/** Forward declare for pipe structure */
+struct usb_h_pipe;
+
+/** Forward declare for driver descriptor structure */
+struct usb_h_desc;
+
+/**
+ * \brief Prototyping USB HCD callback of SOF
+ */
+typedef void (*usb_h_cb_sof_t)(struct usb_h_desc *drv);
+
+/**
+ * \brief Prototyping USB HCD callback of root hub changing.
+ * According to the bitmap size, max port number is 31.
+ */
+typedef void (*usb_h_cb_roothub_t)(struct usb_h_desc *drv, uint8_t port, uint8_t ftr);
+
+/**
+ * Prototyping USB HCD callback of pipe transfer done.
+ * For control pipe, it's forced to call even if there is no transfer
+ * in progress, since the pipe size could be changed at run time.
+ */
+typedef void (*usb_h_pipe_cb_xfer_t)(struct usb_h_pipe *pipe);
+
+/** Access to max packet size of a pipe */
+#define usb_h_pipe_max_pkt_size(p) (p->max_pkt_size)
+
+/** Access to device address of a pipe */
+#define usb_h_pipe_dev_addr(p) (p->dev)
+
+/** Access to endpoint address of a pipe */
+#define usb_h_pipe_ep_addr(p) (p->ep)
+
+/** Access to state of a pipe */
+#define usb_h_pipe_state(p) (p->x.general.state)
+
+/** Access to status of a pipe */
+#define usb_h_pipe_status(p) (p->x.general.status)
+
+/**
+ * @brief USB Host Controller device structure
+ */
+struct usb_h_desc {
+ /** Pointer to hardware base */
+ void *hw;
+ /** Pointer to private data for Host Controller driver */
+ void *prvt;
+ /** Interrupt handling descriptor */
+ struct _irq_descriptor irq;
+ /** Callback of SOF */
+ usb_h_cb_sof_t sof_cb;
+ /** Callback of root hub change */
+ usb_h_cb_roothub_t rh_cb;
+#if CONF_USB_H_INST_OWNER_SP
+ /** Extension for the driver owner (upper layer user) */
+ void *owner;
+#endif
+};
+
+/**
+ * @brief Transfer descriptor for control transfer
+ *
+ * Timing in USB 2.0 spec.:
+ * - 9.2.6.1 : USB sets an upper limit of 5 seconds as the upper limit for any
+ * command to be processed.
+ * - 9.2.6.3 : if a device receives a SetAddress() request, the device must be
+ * able to complete processing of the request and be able to
+ * successfully complete the Status stage of the request within
+ * 50 ms.
+ * After successful completion of the Status stage, the device is
+ * allowed a SetAddress() recovery interval of 2 ms. At the end of
+ * this interval, the device must be able to accept Setup packets
+ * addressed to the new address.
+ * - 9.2.6.4 : For standard device requests that require no Data stage, a device
+ * must be able to complete the request and be able to successfully
+ * complete the Status stage of the request within 50 ms of receipt
+ * of the request. This limitation applies to requests to the
+ * device, interface, or endpoint.
+ * For standard device requests that require data stage transfer to
+ * the host, the device must be able to return the first data packet
+ * to the host within 500 ms of receipt of the request. For
+ * subsequent data packets, if any, the device must be able to
+ * return them within 500 ms of successful completion of the
+ * transmission of the previous packet. The device must then be
+ * able to successfully complete the status stage within 50 ms after
+ * returning the last data packet.
+ * For standard device requests that require a data stage transfer
+ * to the device, the 5-second limit applies.
+ * - 9.2.6.5 : Unless specifically exempted in the class document, all
+ * class-specific requests must meet the timing limitations for
+ * standard device requests.
+ *
+ * Conclusion:
+ * 1. Whole request with data: 5 seconds
+ * 2. Whole request without data: 50 ms
+ * 3. Data packets: 500 ms
+ */
+struct usb_h_ctrl_xfer {
+ /** Pointer to transfer data */
+ uint8_t *data;
+ /** Pointer to setup packet */
+ uint8_t *setup;
+ /** Expected transfer size */
+ uint16_t size;
+ /** Transfer count */
+ uint16_t count;
+ /** Timeout for request, -1 if disable timeout */
+ int16_t req_timeout;
+ /** Timeout between packets
+ * (500ms for data and 50ms for status), -1 if disabled */
+ int16_t pkt_timeout;
+ /** Packet size during transfer (<= allocate max packet size) */
+ uint16_t pkt_size;
+
+ /** Transfer state */
+ uint8_t state;
+ /** Last transfer status */
+ int8_t status;
+};
+
+/**
+ * @brief Transfer descriptor for bulk / interrupt / iso transfer
+ */
+struct usb_h_bulk_int_iso_xfer {
+ /** Expected transfer size */
+ uint32_t size;
+ /** Transfer count */
+ uint32_t count;
+ /** Pointer to transfer data */
+ uint8_t *data;
+ /** Reserved */
+ uint16_t reserved[3];
+
+ /** Transfer state */
+ uint8_t state;
+ /** Last transfer status */
+ int8_t status;
+};
+
+/**
+ * @brief Transfer descriptor for periodic high bandwidth transfer
+ */
+struct usb_h_high_bw_xfer {
+ /** Expected transfer size */
+ uint32_t size;
+ /** Transfer count */
+ uint32_t count;
+ /** Pointer to transfer data */
+ uint8_t *data;
+ /** Micro frame packet sizes */
+ uint16_t pkt_size[3];
+
+ /** Transfer state */
+ uint8_t state;
+ /** Last transfer status */
+ int8_t status;
+};
+
+/**
+ * @brief General transfer descriptor
+ */
+struct usb_h_xfer {
+ /** Reserved for different transfer */
+ union {
+ uint16_t u16[9];
+ uint8_t u8[18];
+ } reserved;
+ /** Transfer state */
+ uint8_t state;
+ /** Last transfer status */
+ int8_t status;
+};
+
+/**
+ * @brief USB Host Controller Driver Pipe structure
+ */
+struct usb_h_pipe {
+ /** Pointer to the USB Host Controller Driver */
+ struct usb_h_desc *hcd;
+ /** Pointer to the callback for transfer done */
+ usb_h_pipe_cb_xfer_t done;
+#if CONF_USB_H_INST_OWNER_SP
+ /** Pointer to the pipe owner */
+ void *owner;
+#endif
+
+ /** Endpoint max packet size (bits 10..0) */
+ uint16_t max_pkt_size;
+ /** Device address */
+ uint8_t dev;
+ /** Endpoint address */
+ uint8_t ep;
+
+ /** Endpoint interval */
+ uint8_t interval;
+ /** Endpoint type: Control, Isochronous, Bulk or Interrupt */
+ uint8_t type;
+ /** Current toggle (driver dependent) */
+ uint8_t toggle;
+ /** Endpoint number of banks (HW dependent) */
+ uint8_t bank : 2;
+ /** Transfer speed (HW dependent) */
+ uint8_t speed : 2;
+ /** High bandwidth periodic out */
+ uint8_t high_bw_out : 1;
+ /** Uses DMA (on transfer) */
+ uint8_t dma : 1;
+ /** Transfer ZLP support */
+ uint8_t zlp : 1;
+ /** Transfer periodic */
+ uint8_t periodic_start : 1;
+
+ /** Transfer status */
+ union {
+ /** General transfer info */
+ struct usb_h_xfer general;
+ /** Control transfer status */
+ struct usb_h_ctrl_xfer ctrl;
+ /** Bulk interrupt iso transfer status */
+ struct usb_h_bulk_int_iso_xfer bii;
+ /** Periodic high bandwidth transfer status */
+ struct usb_h_high_bw_xfer hbw;
+ } x;
+};
+
+/**
+ * @brief USB HCD Initialization
+ *
+ * @param drv Pointer to the HCD driver instance
+ * @param[in] hw Pointer to hardware base
+ * @param[in] prvt The private driver data (implement specific)
+ *
+ * @return Operation result status
+ * @retval ERR_DENIED Hardware has been enabled
+ * @retval ERR_NONE Operation done successfully
+ */
+int32_t _usb_h_init(struct usb_h_desc *drv, void *hw, void *prvt);
+
+/**
+ * @brief USB HCD de-initialization
+ *
+ * @param drv The driver
+ */
+void _usb_h_deinit(struct usb_h_desc *drv);
+
+/**
+ * @brief USB HCD enable
+ *
+ * @param drv The driver
+ */
+void _usb_h_enable(struct usb_h_desc *drv);
+
+/**
+ * @brief USB HCD disable
+ *
+ * @param drv The driver
+ */
+void _usb_h_disable(struct usb_h_desc *drv);
+
+/**
+ * @brief Register callbacks for USB HCD
+ *
+ * @param drv The driver
+ * @param[in] type The callback type
+ * @param[in] cb The callback function entry
+ *
+ * @return Operation result status
+ * @retval ERR_INVALID_ARG Argument error
+ * @retval ERR_NONE Operation done successfully
+ */
+int32_t _usb_h_register_callback(struct usb_h_desc *drv, enum usb_h_cb_type type, FUNC_PTR cb);
+
+/**
+ * @brief Return current frame number
+ *
+ * @param drv The driver
+ *
+ * @return current frame number
+ */
+uint16_t _usb_h_get_frame_n(struct usb_h_desc *drv);
+
+/**
+ * @brief Return current micro frame number
+ *
+ * @param drv The driver
+ *
+ * @return current micro frame number
+ */
+uint8_t _usb_h_get_microframe_n(struct usb_h_desc *drv);
+
+/**
+ * @brief Suspend the USB bus
+ *
+ * @param drv The driver
+ */
+void _usb_h_suspend(struct usb_h_desc *drv);
+
+/**
+ * @brief Resume the USB bus
+ *
+ * @param drv The driver
+ */
+void _usb_h_resume(struct usb_h_desc *drv);
+
+/* Root hub related APIs */
+
+/**
+ * \brief Reset the root hub port
+ *
+ * \param[in,out] drv Pointer to the USB HCD driver
+ * \param[in] port Root hub port, ignored if there is only one port
+ */
+void _usb_h_rh_reset(struct usb_h_desc *drv, uint8_t port);
+
+/**
+ * \brief Suspend the root hub port
+ *
+ * \param[in,out] drv Pointer to the USB HCD driver
+ * \param[in] port Root hub port, ignored if there is only one port
+ */
+void _usb_h_rh_suspend(struct usb_h_desc *drv, uint8_t port);
+
+/**
+ * \brief Resume the root hub port
+ *
+ * \param[in,out] drv Pointer to the USB HCD driver
+ * \param[in] port Root hub port, ignored if there is only one port
+ */
+void _usb_h_rh_resume(struct usb_h_desc *drv, uint8_t port);
+
+/**
+ * \brief Root hub or port feature status check
+ *
+ * Check USB Spec. for hub status and feature selectors.
+ *
+ * \param[in] drv Pointer to the USB HCD driver
+ * \param[in] port Set to 0 to get hub status, otherwise to get port status
+ * \param[in] ftr Hub feature/status selector
+ * (0: connection, 2: suspend, 4: reset, 9: LS, 10: HS)
+ *
+ * \return \c true if the status bit is 1
+ */
+bool _usb_h_rh_check_status(struct usb_h_desc *drv, uint8_t port, uint8_t ftr);
+
+/* Pipe transfer functions */
+
+/**
+ * @brief Allocate a pipe for USB host communication
+ *
+ * @param drv The USB HCD driver
+ * @param[in] dev The device address
+ * @param[in] ep The endpoint address
+ * @param[in] max_pkt_size The endpoint maximum packet size
+ * @param[in] attr The endpoint attribute
+ * @param[in] interval The endpoint interval
+ * (bInterval of USB Endpoint Descriptor)
+ * @param[in] speed The transfer speed of the endpoint
+ * @param[in] minimum_rsc Minimum the resource usage, \sa usb_h_rsc_strategy
+ *
+ * @return Pointer to allocated pipe structure instance
+ * @retval NULL allocation fail
+ */
+struct usb_h_pipe *_usb_h_pipe_allocate(struct usb_h_desc *drv, uint8_t dev, uint8_t ep, uint16_t max_pkt_size,
+ uint8_t attr, uint8_t interval, uint8_t speed, bool minimum_rsc);
+
+/**
+ * @brief Free an allocated pipe
+ *
+ * @param pipe The pipe
+ *
+ * @return Operation result status
+ * @retval ERR_BUSY Pipe is busy, use \ref _usb_h_pipe_abort to abort
+ * @retval ERR_NONE Operation done successfully
+ */
+int32_t _usb_h_pipe_free(struct usb_h_pipe *pipe);
+
+/**
+ * @brief Modify parameters of an allocated control pipe
+ *
+ * @param pipe The pipe
+ * @param[in] dev The device address
+ * @param[in] ep The endpoint address
+ * @param[in] max_pkt_size The maximum packet size, must be equal or
+ * less than allocated size
+ * @param[in] speed The working speed
+ *
+ * @return Operation result status
+ * @retval ERR_NOT_INITIALIZED Pipe is not allocated
+ * @retval ERR_BUSY Pipe is busy transferring
+ * @retval ERR_INVALID_ARG Argument error
+ * @retval ERR_UNSUPPORTED_OP Pipe is not control pipe
+ * @retval ERR_NONE Operation done successfully
+ */
+int32_t _usb_h_pipe_set_control_param(struct usb_h_pipe *pipe, uint8_t dev, uint8_t ep, uint16_t max_pkt_size,
+ uint8_t speed);
+
+/**
+ * @brief Register transfer callback on a pipe
+ *
+ * @param pipe The pipe
+ * @param[in] cb Transfer callback function
+ *
+ * @return Operation result status
+ * @retval ERR_INVALID_ARG Argument error
+ * @retval ERR_NONE Operation done successfully
+ */
+int32_t _usb_h_pipe_register_callback(struct usb_h_pipe *pipe, usb_h_pipe_cb_xfer_t cb);
+
+/**
+ * @brief Issue a control transfer (request) on a pipe
+ *
+ * \note When there is data stage, timeout between data packets is 500ms, the
+ * timeout between last data packet and the status packet is 50ms.
+ *
+ * @param pipe The pipe
+ * @param[in] setup Pointer to the setup packet
+ * @param[in,out] data Pointer to the data buffer
+ * @param[in] length The data length
+ * @param[in] timeout Timeout for whole request in ms
+ *
+ * @return Operation result status
+ * @retval ERR_NOT_INITIALIZED Pipe is not allocated
+ * @retval ERR_BUSY Pipe is busy transferring
+ * @retval ERR_INVALID_ARG Argument error
+ * @retval ERR_UNSUPPORTED_OP Pipe is not control pipe
+ * @retval ERR_NONE Operation done successfully
+ */
+int32_t _usb_h_control_xfer(struct usb_h_pipe *pipe, uint8_t *setup, uint8_t *data, uint16_t length, int16_t timeout);
+
+/**
+ * @brief Issue a bulk / interrupt / iso transfer on a pipe
+ *
+ * @param pipe The pipe
+ * @param[in,out] data Pointer to the data buffer
+ * @param[in] length The data length
+ * @param[in] auto_zlp Auto append ZLP for OUT
+ *
+ * @return Operation result status
+ * @retval ERR_NOT_INITIALIZED Pipe is not allocated
+ * @retval ERR_BUSY Pipe is busy transferring
+ * @retval ERR_INVALID_ARG Argument error
+ * @retval ERR_UNSUPPORTED_OP Pipe is control pipe
+ * @retval ERR_NONE Operation done successfully
+ */
+int32_t _usb_h_bulk_int_iso_xfer(struct usb_h_pipe *pipe, uint8_t *data, uint32_t length, bool auto_zlp);
+
+/**
+ * @brief Issue a periodic high bandwidth output on a pipe
+ *
+ * @param pipe The pipe
+ * @param[in,out] data Pointer to the data buffer
+ * @param[in] length The data length
+ * @param[in] trans_pkt_size The transaction packet sizes in a micro frame,
+ * 0 to use endpoint max packet size
+ *
+ * @return Operation result status
+ * @retval ERR_NOT_INITIALIZED Pipe is not allocated
+ * @retval ERR_BUSY Pipe is busy transferring
+ * @retval ERR_INVALID_ARG Argument error
+ * @retval ERR_UNSUPPORTED_OP Pipe is not high bandwidth periodic pipe, or
+ * DMA feature not enabled, or
+ * high bandwidth not enabled
+ * @retval ERR_NONE Operation done successfully
+ */
+int32_t _usb_h_high_bw_out(struct usb_h_pipe *pipe, uint8_t *data, uint32_t length, uint16_t trans_pkt_size[3]);
+
+/**
+ * @brief Check if pipe is busy transferring
+ *
+ * @param pipe The pipe
+ *
+ * @return \c true if pipe is busy
+ */
+bool _usb_h_pipe_is_busy(struct usb_h_pipe *pipe);
+
+/**
+ * @brief Abort pending transfer on a pipe
+ *
+ * @param pipe The pipe
+ */
+void _usb_h_pipe_abort(struct usb_h_pipe *pipe);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _HPL_USB_HOST_H_INCLUDED */