2017-12-21 06:42:46 +01:00
|
|
|
/**
|
|
|
|
* \file
|
|
|
|
*
|
|
|
|
* \brief Common API for USB Device Drivers (UDD)
|
|
|
|
*
|
|
|
|
* Copyright (c) 2009-2015 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
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
/*
|
2020-07-24 03:59:43 +02:00
|
|
|
* Support and FAQ: visit <a href="https://www.atmel.com/design-support/">Atmel Support</a>
|
2017-12-21 06:42:46 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef _UDD_H_
|
|
|
|
#define _UDD_H_
|
|
|
|
|
|
|
|
#include "usb_protocol.h"
|
|
|
|
#include "udc_desc.h"
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \ingroup usb_device_group
|
|
|
|
* \defgroup udd_group USB Device Driver (UDD)
|
|
|
|
*
|
|
|
|
* The UDD driver provides a low-level abstraction of the device
|
|
|
|
* controller hardware. Most events coming from the hardware such as
|
|
|
|
* interrupts, which may cause the UDD to call into the UDC and UDI.
|
|
|
|
*
|
|
|
|
* @{
|
|
|
|
*/
|
|
|
|
|
|
|
|
//! \brief Endpoint identifier
|
|
|
|
typedef uint8_t udd_ep_id_t;
|
|
|
|
|
|
|
|
//! \brief Endpoint transfer status
|
|
|
|
//! Returned in parameters of callback register via udd_ep_run routine.
|
|
|
|
typedef enum {
|
|
|
|
UDD_EP_TRANSFER_OK = 0,
|
|
|
|
UDD_EP_TRANSFER_ABORT = 1,
|
|
|
|
} udd_ep_status_t;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Global variable to give and record information of the setup request management
|
|
|
|
*
|
|
|
|
* This global variable allows to decode and response a setup request.
|
|
|
|
* It can be updated by udc_process_setup() from UDC or *setup() from UDIs.
|
|
|
|
*/
|
|
|
|
typedef struct {
|
|
|
|
//! Data received in USB SETUP packet
|
|
|
|
//! Note: The swap of "req.wValues" from uin16_t to le16_t is done by UDD.
|
|
|
|
usb_setup_req_t req;
|
|
|
|
|
|
|
|
//! Point to buffer to send or fill with data following SETUP packet
|
|
|
|
//! This buffer must be word align for DATA IN phase (use prefix COMPILER_WORD_ALIGNED for buffer)
|
|
|
|
uint8_t *payload;
|
|
|
|
|
|
|
|
//! Size of buffer to send or fill, and content the number of byte transfered
|
|
|
|
uint16_t payload_size;
|
|
|
|
|
|
|
|
//! Callback called after reception of ZLP from setup request
|
2019-09-27 21:02:35 +02:00
|
|
|
void (*callback)(void);
|
2017-12-21 06:42:46 +01:00
|
|
|
|
|
|
|
//! Callback called when the buffer given (.payload) is full or empty.
|
|
|
|
//! This one return false to abort data transfer, or true with a new buffer in .payload.
|
2019-09-27 21:02:35 +02:00
|
|
|
bool (*over_under_run)(void);
|
2017-12-21 06:42:46 +01:00
|
|
|
} udd_ctrl_request_t;
|
|
|
|
extern udd_ctrl_request_t udd_g_ctrlreq;
|
|
|
|
|
|
|
|
//! Return true if the setup request \a udd_g_ctrlreq indicates IN data transfer
|
|
|
|
#define Udd_setup_is_in() \
|
|
|
|
(USB_REQ_DIR_IN == (udd_g_ctrlreq.req.bmRequestType & USB_REQ_DIR_MASK))
|
|
|
|
|
|
|
|
//! Return true if the setup request \a udd_g_ctrlreq indicates OUT data transfer
|
|
|
|
#define Udd_setup_is_out() \
|
|
|
|
(USB_REQ_DIR_OUT == (udd_g_ctrlreq.req.bmRequestType & USB_REQ_DIR_MASK))
|
|
|
|
|
|
|
|
//! Return the type of the SETUP request \a udd_g_ctrlreq. \see usb_reqtype.
|
|
|
|
#define Udd_setup_type() \
|
|
|
|
(udd_g_ctrlreq.req.bmRequestType & USB_REQ_TYPE_MASK)
|
|
|
|
|
|
|
|
//! Return the recipient of the SETUP request \a udd_g_ctrlreq. \see usb_recipient
|
|
|
|
#define Udd_setup_recipient() \
|
|
|
|
(udd_g_ctrlreq.req.bmRequestType & USB_REQ_RECIP_MASK)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief End of halt callback function type.
|
|
|
|
* Registered by routine udd_ep_wait_stall_clear()
|
|
|
|
* Callback called when endpoint stall is cleared.
|
|
|
|
*/
|
2019-09-27 21:02:35 +02:00
|
|
|
typedef void (*udd_callback_halt_cleared_t)(void);
|
2017-12-21 06:42:46 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief End of transfer callback function type.
|
|
|
|
* Registered by routine udd_ep_run()
|
|
|
|
* Callback called by USB interrupt after data transfer or abort (reset,...).
|
|
|
|
*
|
|
|
|
* \param status UDD_EP_TRANSFER_OK, if transfer is complete
|
|
|
|
* \param status UDD_EP_TRANSFER_ABORT, if transfer is aborted
|
|
|
|
* \param n number of data transfered
|
|
|
|
*/
|
|
|
|
typedef void (*udd_callback_trans_t) (udd_ep_status_t status,
|
|
|
|
iram_size_t nb_transfered, udd_ep_id_t ep);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Authorizes the VBUS event
|
|
|
|
*
|
|
|
|
* \return true, if the VBUS monitoring is possible.
|
|
|
|
*/
|
2019-09-27 21:02:35 +02:00
|
|
|
bool udd_include_vbus_monitoring(void);
|
2017-12-21 06:42:46 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Enables the USB Device mode
|
|
|
|
*/
|
2019-09-27 21:02:35 +02:00
|
|
|
void udd_enable(void);
|
2017-12-21 06:42:46 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Disables the USB Device mode
|
|
|
|
*/
|
2019-09-27 21:02:35 +02:00
|
|
|
void udd_disable(void);
|
2017-12-21 06:42:46 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Attach device to the bus when possible
|
|
|
|
*
|
|
|
|
* \warning If a VBus control is included in driver,
|
|
|
|
* then it will attach device when an acceptable Vbus
|
|
|
|
* level from the host is detected.
|
|
|
|
*/
|
2019-09-27 21:02:35 +02:00
|
|
|
void udd_attach(void);
|
2017-12-21 06:42:46 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Detaches the device from the bus
|
|
|
|
*
|
|
|
|
* The driver must remove pull-up on USB line D- or D+.
|
|
|
|
*/
|
2019-09-27 21:02:35 +02:00
|
|
|
void udd_detach(void);
|
2017-12-21 06:42:46 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Test whether the USB Device Controller is running at high
|
|
|
|
* speed or not.
|
|
|
|
*
|
|
|
|
* \return \c true if the Device is running at high speed mode, otherwise \c false.
|
|
|
|
*/
|
2019-09-27 21:02:35 +02:00
|
|
|
bool udd_is_high_speed(void);
|
2017-12-21 06:42:46 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Changes the USB address of device
|
|
|
|
*
|
|
|
|
* \param address New USB address
|
|
|
|
*/
|
|
|
|
void udd_set_address(uint8_t address);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Returns the USB address of device
|
|
|
|
*
|
|
|
|
* \return USB address
|
|
|
|
*/
|
2019-09-27 21:02:35 +02:00
|
|
|
uint8_t udd_getaddress(void);
|
2017-12-21 06:42:46 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Returns the current start of frame number
|
|
|
|
*
|
|
|
|
* \return current start of frame number.
|
|
|
|
*/
|
2019-09-27 21:02:35 +02:00
|
|
|
uint16_t udd_get_frame_number(void);
|
2017-12-21 06:42:46 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Returns the current micro start of frame number
|
|
|
|
*
|
|
|
|
* \return current micro start of frame number required in high speed mode.
|
|
|
|
*/
|
2019-09-27 21:02:35 +02:00
|
|
|
uint16_t udd_get_micro_frame_number(void);
|
2017-12-21 06:42:46 +01:00
|
|
|
|
|
|
|
/*! \brief The USB driver sends a resume signal called Upstream Resume
|
|
|
|
*/
|
2019-09-27 21:02:35 +02:00
|
|
|
void udd_send_remotewakeup(void);
|
2017-12-21 06:42:46 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Load setup payload
|
|
|
|
*
|
|
|
|
* \param payload Pointer on payload
|
|
|
|
* \param payload_size Size of payload
|
|
|
|
*/
|
|
|
|
void udd_set_setup_payload( uint8_t *payload, uint16_t payload_size );
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \name Endpoint Management
|
|
|
|
*
|
|
|
|
* The following functions allow drivers to create and remove
|
|
|
|
* endpoints, as well as set, clear and query their "halted" and
|
|
|
|
* "wedged" states.
|
|
|
|
*/
|
|
|
|
//@{
|
|
|
|
|
|
|
|
#if (USB_DEVICE_MAX_EP != 0)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Configures and enables an endpoint
|
|
|
|
*
|
|
|
|
* \param ep Endpoint number including direction (USB_EP_DIR_IN/USB_EP_DIR_OUT).
|
|
|
|
* \param bmAttributes Attributes of endpoint declared in the descriptor.
|
|
|
|
* \param MaxEndpointSize Endpoint maximum size
|
|
|
|
*
|
|
|
|
* \return \c 1 if the endpoint is enabled, otherwise \c 0.
|
|
|
|
*/
|
|
|
|
bool udd_ep_alloc(udd_ep_id_t ep, uint8_t bmAttributes,
|
|
|
|
uint16_t MaxEndpointSize);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Disables an endpoint
|
|
|
|
*
|
|
|
|
* \param ep Endpoint number including direction (USB_EP_DIR_IN/USB_EP_DIR_OUT).
|
|
|
|
*/
|
|
|
|
void udd_ep_free(udd_ep_id_t ep);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Check if the endpoint \a ep is halted.
|
|
|
|
*
|
|
|
|
* \param ep The ID of the endpoint to check.
|
|
|
|
*
|
|
|
|
* \return \c 1 if \a ep is halted, otherwise \c 0.
|
|
|
|
*/
|
|
|
|
bool udd_ep_is_halted(udd_ep_id_t ep);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Set the halted state of the endpoint \a ep
|
|
|
|
*
|
|
|
|
* After calling this function, any transaction on \a ep will result
|
|
|
|
* in a STALL handshake being sent. Any pending transactions will be
|
|
|
|
* performed first, however.
|
|
|
|
*
|
|
|
|
* \param ep The ID of the endpoint to be halted
|
|
|
|
*
|
|
|
|
* \return \c 1 if \a ep is halted, otherwise \c 0.
|
|
|
|
*/
|
|
|
|
bool udd_ep_set_halt(udd_ep_id_t ep);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Clear the halted state of the endpoint \a ep
|
|
|
|
*
|
|
|
|
* After calling this function, any transaction on \a ep will
|
|
|
|
* be handled normally, i.e. a STALL handshake will not be sent, and
|
|
|
|
* the data toggle sequence will start at DATA0.
|
|
|
|
*
|
|
|
|
* \param ep The ID of the endpoint to be un-halted
|
|
|
|
*
|
|
|
|
* \return \c 1 if function was successfully done, otherwise \c 0.
|
|
|
|
*/
|
|
|
|
bool udd_ep_clear_halt(udd_ep_id_t ep);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Registers a callback to call when endpoint halt is cleared
|
|
|
|
*
|
|
|
|
* \param ep The ID of the endpoint to use
|
|
|
|
* \param callback NULL or function to call when endpoint halt is cleared
|
|
|
|
*
|
|
|
|
* \warning if the endpoint is not halted then the \a callback is called immediately.
|
|
|
|
*
|
|
|
|
* \return \c 1 if the register is accepted, otherwise \c 0.
|
|
|
|
*/
|
|
|
|
bool udd_ep_wait_stall_clear(udd_ep_id_t ep,
|
|
|
|
udd_callback_halt_cleared_t callback);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Allows to receive or send data on an endpoint
|
|
|
|
*
|
|
|
|
* The driver uses a specific DMA USB to transfer data
|
|
|
|
* from internal RAM to endpoint, if this one is available.
|
|
|
|
* When the transfer is finished or aborted (stall, reset, ...), the \a callback is called.
|
|
|
|
* The \a callback returns the transfer status and eventually the number of byte transfered.
|
|
|
|
* Note: The control endpoint is not authorized.
|
|
|
|
*
|
|
|
|
* \param ep The ID of the endpoint to use
|
|
|
|
* \param b_shortpacket Enabled automatic short packet
|
|
|
|
* \param buf Buffer on Internal RAM to send or fill.
|
|
|
|
* It must be align, then use COMPILER_WORD_ALIGNED.
|
|
|
|
* \param buf_size Buffer size to send or fill
|
|
|
|
* \param callback NULL or function to call at the end of transfer
|
|
|
|
*
|
|
|
|
* \warning About \a b_shortpacket, for IN endpoint it means that a short packet
|
|
|
|
* (or a Zero Length Packet) will be sent to the USB line to properly close the usb
|
|
|
|
* transfer at the end of the data transfer.
|
|
|
|
* For Bulk and Interrupt OUT endpoint, it will automatically stop the transfer
|
|
|
|
* at the end of the data transfer (received short packet).
|
|
|
|
*
|
|
|
|
* \return \c 1 if function was successfully done, otherwise \c 0.
|
|
|
|
*/
|
|
|
|
bool udd_ep_run(udd_ep_id_t ep, bool b_shortpacket,
|
|
|
|
uint8_t * buf, iram_size_t buf_size,
|
|
|
|
udd_callback_trans_t callback);
|
|
|
|
/**
|
|
|
|
* \brief Aborts transfer on going on endpoint
|
|
|
|
*
|
|
|
|
* If a transfer is on going, then it is stopped and
|
|
|
|
* the callback registered is called to signal the end of transfer.
|
|
|
|
* Note: The control endpoint is not authorized.
|
|
|
|
*
|
|
|
|
* \param ep Endpoint to abort
|
|
|
|
*/
|
|
|
|
void udd_ep_abort(udd_ep_id_t ep);
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
//@}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \name High speed test mode management
|
|
|
|
*
|
|
|
|
* The following functions allow the device to jump to a specific test mode required in high speed mode.
|
|
|
|
*/
|
|
|
|
//@{
|
2019-09-27 21:02:35 +02:00
|
|
|
void udd_test_mode_j(void);
|
|
|
|
void udd_test_mode_k(void);
|
|
|
|
void udd_test_mode_se0_nak(void);
|
|
|
|
void udd_test_mode_packet(void);
|
2017-12-21 06:42:46 +01:00
|
|
|
//@}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \name UDC callbacks to provide for UDD
|
|
|
|
*
|
|
|
|
* The following callbacks are used by UDD.
|
|
|
|
*/
|
|
|
|
//@{
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Decodes and manages a setup request
|
|
|
|
*
|
|
|
|
* The driver call it when a SETUP packet is received.
|
|
|
|
* The \c udd_g_ctrlreq contains the data of SETUP packet.
|
|
|
|
* If this callback accepts the setup request then it must
|
|
|
|
* return \c 1 and eventually update \c udd_g_ctrlreq to send or receive data.
|
|
|
|
*
|
|
|
|
* \return \c 1 if the request is accepted, otherwise \c 0.
|
|
|
|
*/
|
2019-09-27 21:02:35 +02:00
|
|
|
extern bool udc_process_setup(void);
|
2017-12-21 06:42:46 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Reset the UDC
|
|
|
|
*
|
|
|
|
* The UDC must reset all configuration.
|
|
|
|
*/
|
2019-09-27 21:02:35 +02:00
|
|
|
extern void udc_reset(void);
|
2017-12-21 06:42:46 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief To signal that a SOF is occurred
|
|
|
|
*
|
|
|
|
* The UDC must send the signal to all UDIs enabled
|
|
|
|
*/
|
2019-09-27 21:02:35 +02:00
|
|
|
extern void udc_sof_notify(void);
|
2017-12-21 06:42:46 +01:00
|
|
|
|
|
|
|
//@}
|
|
|
|
|
|
|
|
//@}
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif // _UDD_H_
|