/* ----------------------------------------------------------------------------
 *         ATMEL Microcontroller Software Support
 * ----------------------------------------------------------------------------
 * Copyright (c) 2008, Atmel Corporation
 *
 * 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 disclaimer below.
 *
 * Atmel's name may not be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * DISCLAIMER: 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
 * 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.
 * ----------------------------------------------------------------------------
 */
/*
 * $Id: USBD.h 23837 2010-10-13 13:45:05Z mahendran.p $
 */

//------------------------------------------------------------------------------
/// \unit
///
/// !!!Purpose
///
/// Collection of methods for using the USB device controller on AT91
/// microcontrollers.
///
/// !!!Usage
///
/// Please refer to the corresponding application note.
/// - "AT91 USB device framework"
/// - "USBD API" . "USBD API Methods"
//------------------------------------------------------------------------------

#ifndef USBD_H
#define USBD_H

/*----------------------------------------------------------------------------
 *         Headers
 *----------------------------------------------------------------------------*/

/* These headers were introduced in C99 by working group
 * ISO/IEC JTC1/SC22/WG14.
 */
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>

#include <usb/common/core/USBEndpointDescriptor.h>
#include <usb/common/core/USBGenericRequest.h>

/*----------------------------------------------------------------------------
 *      Compile Options
 *----------------------------------------------------------------------------*/

/* Compile option for HS or OTG, use DMA. Remove this define for not use DMA. */
/*#if defined(CHIP_USB_OTGHS) || defined(CHIP_USB_UDPHS)*/
/*#define DMA*/
/*#endif*/

/*------------------------------------------------------------------------------
 *      Definitions
 *------------------------------------------------------------------------------*/

/** \addtogroup usbd_interface
 *@{*/

/**
 * \addtogroup usbd_rc USB device API return codes
 *  @{
 * This section lists the return codes for the USB device driver API
 * - \ref USBD_STATUS_SUCCESS
 * - \ref USBD_STATUS_LOCKED
 * - \ref USBD_STATUS_ABORTED
 * - \ref USBD_STATUS_RESET
 */

/** Indicates the operation was successful. */
#define USBD_STATUS_SUCCESS             0
/** Endpoint/device is already busy. */
#define USBD_STATUS_LOCKED              1
/** Operation has been aborted (error or stall). */
#define USBD_STATUS_ABORTED             2
/** Operation has been canceled (by user). */
#define USBD_STATUS_CANCELED            3
/** Operation has been aborted because the device init/reset/un-configure. */
#define USBD_STATUS_RESET               4
/** Part ot operation successfully done. */
#define USBD_STATUS_PARTIAL_DONE        5
/** Operation failed because parameter error */
#define USBD_STATUS_INVALID_PARAMETER   6
/** Operation failed because in unexpected state */
#define USBD_STATUS_WRONG_STATE         7
/** Operation failed because HW not supported */
#define USBD_STATUS_HW_NOT_SUPPORTED    0xFE
/** @}*/

/** \addtogroup usbd_states USB device states
 *  @{
 * This section lists the device states of the USB device driver.
 * - \ref USBD_STATE_SUSPENDED
 * - \ref USBD_STATE_ATTACHED
 * - \ref USBD_STATE_POWERED
 * - \ref USBD_STATE_DEFAULT
 * - \ref USBD_STATE_ADDRESS
 * - \ref USBD_STATE_CONFIGURED
 */

/** The device is currently suspended. */
#define USBD_STATE_SUSPENDED            0
/** USB cable is plugged into the device. */
#define USBD_STATE_ATTACHED             1
/** Host is providing +5V through the USB cable. */
#define USBD_STATE_POWERED              2
/** Device has been reset. */
#define USBD_STATE_DEFAULT              3
/** The device has been given an address on the bus. */
#define USBD_STATE_ADDRESS              4
/** A valid configuration has been selected. */
#define USBD_STATE_CONFIGURED           5
/**  @}*/

/*----------------------------------------------------------------------------
 *         Types
 *----------------------------------------------------------------------------*/

/**
 * \brief Buffer struct used for multi-buffer-listed transfer.
 *
 * The driver can process 255 bytes of buffers or buffer list window.
 */
typedef struct _USBDTransferBuffer {
    /** Pointer to frame buffer */
    uint8_t * pBuffer;
    /** Size of the frame (up to 64K-1) */
    uint16_t size;
    /** Bytes transferred */
    uint16_t transferred;
    /** Bytes in FIFO */
    uint16_t buffered;
    /** Bytes remaining */
    uint16_t remaining;
} USBDTransferBuffer;

#ifdef __ICCARM__          /* IAR*/
#define __attribute__(...) /* IAR*/
#endif                     /* IAR*/

/**
 * \brief Struct used for USBD DMA Link List Transfer Descriptor, must be 16-bytes
 * aligned.
 *
 * (For USB, DMA transfer is linked to EPs and FIFO address is EP defined)
 */
typedef struct _USBDDmaDescriptor {
    /** Pointer to Next Descriptor */
    void* pNxtDesc;
    /** Pointer to data buffer address */
    void* pDataAddr;
    /** DMA Control setting register value */
    uint32_t   ctrlSettings:8,      /** Control settings */
                   reserved:8,      /** Not used */
                   bufferLength:16; /** Length of buffer */
    /** Loaded to DMA register, OK to modify */
    uint32_t used;
} __attribute__((aligned(16))) USBDDmaDescriptor;

#ifdef __ICCARM__          /* IAR*/
#pragma pack()             /* IAR*/
#endif                     /* IAR*/

/**
 * Callback used by transfer functions (USBD_Read & USBD_Write) to notify
 * that a transaction is complete.
 */
typedef void (*TransferCallback)(void *pArg,
                                 uint8_t status,
                                 uint32_t transferred,
                                 uint32_t remaining);

/**
 * Callback used by MBL transfer functions (USBD_Read & USBD_Write) to notify
 * that a transaction is complete.
 * \param pArg     Pointer to callback arguments.
 * \param status   USBD status.
 * \param nbFreed  Number of buffers that is freed since last callback.
 */
typedef void (*MblTransferCallback)(void *pArg,
                                    uint8_t status,
                                    uint32_t nbFreed);

/**@}*/

/*------------------------------------------------------------------------------
 *         Exported functions
 *------------------------------------------------------------------------------*/

extern void USBD_IrqHandler(void);

extern void USBD_Init(void);

extern void USBD_ConfigureSpeed(uint8_t forceFS);

extern void USBD_Connect(void);

extern void USBD_Disconnect(void);

extern uint8_t USBD_Write(
    uint8_t bEndpoint,
    const void *pData,
    uint32_t size,
    TransferCallback callback,
    void *pArg);

extern uint8_t USBD_MblWrite(
    uint8_t bEndpoint,
    void * pMbl,
    uint16_t wListSize,
    uint8_t bCircList,
    uint16_t wStartNdx,
    MblTransferCallback fCallback,
    void * pArgument);

extern uint8_t USBD_MblReuse(
    uint8_t bEndpoint,
    uint8_t * pNewBuffer,
    uint16_t wNewSize);

extern uint8_t USBD_Read(
    uint8_t bEndpoint,
    void *pData,
    uint32_t dLength,
    TransferCallback fCallback,
    void *pArg);

extern uint8_t USBD_Stall(uint8_t bEndpoint);

extern void USBD_Halt(uint8_t bEndpoint);

extern void USBD_Unhalt(uint8_t bEndpoint);

extern void USBD_ConfigureEndpoint(const USBEndpointDescriptor *pDescriptor);

extern uint8_t USBD_IsHalted(uint8_t bEndpoint);

extern void USBD_RemoteWakeUp(void);

extern void USBD_SetAddress(uint8_t address);

extern void USBD_SetConfiguration(uint8_t cfgnum);

extern uint8_t USBD_GetState(void);

extern uint8_t USBD_IsHighSpeed(void);

extern void USBD_Test(uint8_t bIndex);

extern void USBD_SuspendHandler(void);
extern void USBD_ResumeHandler(void);
extern void USBD_ResetHandler(void);
extern void USBD_RequestHandler(uint8_t bEndpoint,
                                const USBGenericRequest * pRequest);


#endif /*#ifndef USBD_H*/

