/*******************************************************************************
* File Name: USBFS_1.c
* Version 2.11
*
* Description:
*  API for USBFS Component.
*
* Note:
*  Many of the functions use endpoint number.  RAM arrays are sized with 9
*  elements so they are indexed directly by epNumber.  The SIE and ARB
*  registers are indexed by variations of epNumber - 1.
*
********************************************************************************
* Copyright 2008-2011, Cypress Semiconductor Corporation.  All rights reserved.
* You may use this file only in accordance with the license, terms, conditions,
* disclaimers, and limitations in the end user license agreement accompanying
* the software package with which this file was provided.
*******************************************************************************/

#include <CyDmac.h>
#include "USBFS_1.h"
#include "USBFS_1_hid.h"
#if(USBFS_1_DMA1_REMOVE == 0u)
    #include "USBFS_1_ep1_dma.h"
#endif   /* End USBFS_1_DMA1_REMOVE */
#if(USBFS_1_DMA2_REMOVE == 0u)
    #include "USBFS_1_ep2_dma.h"
#endif   /* End USBFS_1_DMA2_REMOVE */
#if(USBFS_1_DMA3_REMOVE == 0u)
    #include "USBFS_1_ep3_dma.h"
#endif   /* End USBFS_1_DMA3_REMOVE */
#if(USBFS_1_DMA4_REMOVE == 0u)
    #include "USBFS_1_ep4_dma.h"
#endif   /* End USBFS_1_DMA4_REMOVE */
#if(USBFS_1_DMA5_REMOVE == 0u)
    #include "USBFS_1_ep5_dma.h"
#endif   /* End USBFS_1_DMA5_REMOVE */
#if(USBFS_1_DMA6_REMOVE == 0u)
    #include "USBFS_1_ep6_dma.h"
#endif   /* End USBFS_1_DMA6_REMOVE */
#if(USBFS_1_DMA7_REMOVE == 0u)
    #include "USBFS_1_ep7_dma.h"
#endif   /* End USBFS_1_DMA7_REMOVE */
#if(USBFS_1_DMA8_REMOVE == 0u)
    #include "USBFS_1_ep8_dma.h"
#endif   /* End USBFS_1_DMA8_REMOVE */


/***************************************
* External data references
***************************************/

extern volatile uint8 USBFS_1_configuration;
extern volatile uint8 USBFS_1_configurationChanged;
extern volatile uint8 USBFS_1_interfaceSetting[];
extern volatile uint8 USBFS_1_interfaceSetting_last[];
extern volatile uint8 USBFS_1_deviceAddress;
extern volatile uint8 USBFS_1_deviceStatus;
extern volatile uint8 USBFS_1_device;
extern volatile uint8 USBFS_1_transferState;
extern volatile uint8 USBFS_1_lastPacketSize;

extern volatile T_USBFS_1_EP_CTL_BLOCK USBFS_1_EP[];

#if defined(USBFS_1_ENABLE_HID_CLASS)
    extern volatile uint8 USBFS_1_hidProtocol[];  
#endif /* USBFS_1_ENABLE_HID_CLASS */    


/***************************************
* External function references
***************************************/

CY_ISR_PROTO(USBFS_1_EP_0_ISR);
#if(USBFS_1_EP1_ISR_REMOVE == 0u)
    CY_ISR_PROTO(USBFS_1_EP_1_ISR);
#endif /* End USBFS_1_EP1_ISR_REMOVE */
#if(USBFS_1_EP2_ISR_REMOVE == 0u)
    CY_ISR_PROTO(USBFS_1_EP_2_ISR);
#endif /* End USBFS_1_EP2_ISR_REMOVE */
#if(USBFS_1_EP3_ISR_REMOVE == 0u)
    CY_ISR_PROTO(USBFS_1_EP_3_ISR);
#endif /* End USBFS_1_EP3_ISR_REMOVE */
#if(USBFS_1_EP4_ISR_REMOVE == 0u)
    CY_ISR_PROTO(USBFS_1_EP_4_ISR);
#endif /* End USBFS_1_EP4_ISR_REMOVE */
#if(USBFS_1_EP5_ISR_REMOVE == 0u)
    CY_ISR_PROTO(USBFS_1_EP_5_ISR);
#endif /* End USBFS_1_EP5_ISR_REMOVE */
#if(USBFS_1_EP6_ISR_REMOVE == 0u)
    CY_ISR_PROTO(USBFS_1_EP_6_ISR);
#endif /* End USBFS_1_EP6_ISR_REMOVE */
#if(USBFS_1_EP7_ISR_REMOVE == 0u)
    CY_ISR_PROTO(USBFS_1_EP_7_ISR);
#endif /* End USBFS_1_EP7_ISR_REMOVE */
#if(USBFS_1_EP8_ISR_REMOVE == 0u)
    CY_ISR_PROTO(USBFS_1_EP_8_ISR);
#endif /* End USBFS_1_EP8_ISR_REMOVE */
CY_ISR_PROTO(USBFS_1_BUS_RESET_ISR);
#if(USBFS_1_SOF_ISR_REMOVE == 0u)
    CY_ISR_PROTO(USBFS_1_SOF_ISR);
#endif /* End USBFS_1_SOF_ISR_REMOVE */
#if(USBFS_1_EP_MM != USBFS_1__EP_MANUAL)
    CY_ISR_PROTO(USBFS_1_ARB_ISR);
#endif /* End USBFS_1_EP_MM */


/***************************************
* Forward function references
***************************************/

#if(USBFS_1_EP_MM != USBFS_1__EP_MANUAL)
    void USBFS_1_Stop_DMA(uint8 epNumber);
#endif   /* End USBFS_1_EP_MM != USBFS_1__EP_MANUAL */


/***************************************
* Global data allocation
***************************************/

uint8 USBFS_1_initVar = 0u;
#if(USBFS_1_EP_MM != USBFS_1__EP_MANUAL)
    uint8 USBFS_1_DmaChan[USBFS_1_MAX_EP];
    uint8 USBFS_1_DmaTd[USBFS_1_MAX_EP];
#endif /* End USBFS_1_EP_MM */


/*******************************************************************************
* Function Name: USBFS_1_Start
********************************************************************************
*
* Summary:
*  This function initialize the USB SIE, arbiter and the
*  endpoint APIs, including setting the D+ Pullup
*
* Parameters:
*  device: Contains the device number from the desired device descriptor set 
*          entered with the USBFS customizer.
*  mode: The operating voltage. This determines whether the voltage regulator 
*        is enabled for 5V operation or if pass through mode is used for 3.3V 
*        operation. Symbolic names and their associated values are given in the 
*        following table.
*       USBFS_1_3V_OPERATION - Disable voltage regulator and pass-thru 
*                                       Vcc for pull-up
*       USBFS_1_5V_OPERATION - Enable voltage regulator and use 
*                                       regulator for pull-up
*       USBFS_1_DWR_VDDD_OPERATION - Enable or Disable voltage 
*                         regulator depend on Vddd Voltage configuration in DWR.
*
* Return:
*   None.
*
* Global variables:
*  The USBFS_1_intiVar variable is used to indicate initial 
*  configuration of this component. The variable is initialized to zero (0u) 
*  and set to one (1u) the first time USBFS_1_Start() is called. 
*  This allows for component Re-Start without unnecessary re-initialization 
*  in all subsequent calls to the USBFS_1_Start() routine. 
*  If re-initialization of the component is required the variable should be set 
*  to zero before call of UART_Start() routine, or the user may call 
*  USBFS_1_Init() and USBFS_1_InitComponent() as done 
*  in the USBFS_1_Start() routine.
*
* Side Effects:
*   This function will reset all communication states to default.
*
* Reentrant:
*  No.
*
*******************************************************************************/
void USBFS_1_Start(uint8 device, uint8 mode) 
{
    /* If not Initialized then initialize all required hardware and software */
    if(USBFS_1_initVar == 0u)
    {
        USBFS_1_Init();
        USBFS_1_initVar = 1u;
    }
    USBFS_1_InitComponent(device, mode);
}


/*******************************************************************************
* Function Name: USBFS_1_Init
********************************************************************************
*
* Summary:
*  Initialize component's hardware. Usually called in USBFS_1_Start().
*
* Parameters:
*  None.
*
* Return:
*  None.
*
* Reentrant:
*  No.
*
*******************************************************************************/
void USBFS_1_Init(void) 
{
    uint8 enableInterrupts;
    #if(USBFS_1_EP_MM != USBFS_1__EP_MANUAL)
        uint16 i;
    #endif   /* End USBFS_1_EP_MM != USBFS_1__EP_MANUAL */

    enableInterrupts = CyEnterCriticalSection();

    /* Enable USB block  */
    USBFS_1_PM_ACT_CFG_REG |= USBFS_1_PM_ACT_EN_FSUSB;
    /* Enable USB block for Standby Power Mode */
    USBFS_1_PM_STBY_CFG_REG |= USBFS_1_PM_STBY_EN_FSUSB;
    
    #if(CY_PSOC3_ES2 || CY_PSOC5_ES1)
        /* Disable USBIO for TO3 */
        USBFS_1_PM_AVAIL_CR_REG &= ~USBFS_1_PM_AVAIL_EN_FSUSBIO;
    #endif /* End CY_PSOC3_ES2 || CY_PSOC5_ES1 */

    /* Enable core clock */
    USBFS_1_USB_CLK_EN_REG = USBFS_1_USB_CLK_ENABLE;

    USBFS_1_CR1_REG = USBFS_1_CR1_ENABLE_LOCK;

    #if(CY_PSOC3_ES2 || CY_PSOC5_ES1)
        /* Disable USBIO for TO3 */
        USBFS_1_PM_AVAIL_CR_REG |= USBFS_1_PM_AVAIL_EN_FSUSBIO;
        /* Bus Reset Length, It has correct default value in ES3 */
        USBFS_1_BUS_RST_CNT_REG = USBFS_1_BUS_RST_COUNT;
    #endif /* End CY_PSOC3_ES2 || CY_PSOC5_ES1 */

    /* ENABLING USBIO PADS IN USB MODE FROM I/O MODE */
    #if(CY_PSOC3_ES3 || CY_PSOC5_ES2)
        /* Ensure USB transmit enable is low (USB_USBIO_CR0.ten). - Manual Transmission - Disabled */
        USBFS_1_USBIO_CR0_REG &= ~USBFS_1_USBIO_CR0_TEN;
        CyDelayUs(0);  /*~50ns delay */
        /* Disable the USBIO by asserting PM.USB_CR0.fsusbio_pd_n(Inverted) 
        *  high. This will have been set low by the power manger out of reset. 
        *  Also confirm USBIO pull-up disabled 
        */
        USBFS_1_PM_USB_CR0_REG &= ~(USBFS_1_PM_USB_CR0_PD_N |USBFS_1_PM_USB_CR0_PD_PULLUP_N);
        /* Enable the USBIO reference by setting PM.USB_CR0.fsusbio_ref_en.*/
        USBFS_1_PM_USB_CR0_REG |= USBFS_1_PM_USB_CR0_REF_EN;
        /* The reference will be available 1 us after the regulator is enabled */
        CyDelayUs(1); 
        /* OR 40us after power restored */
        CyDelayUs(40); 
        /* Ensure the single ended disable bits are low (PRT15.INP_DIS[7:6])(input receiver enabled). */
        USBFS_1_DM_INP_DIS_REG &= ~USBFS_1_DM_MASK;
        USBFS_1_DP_INP_DIS_REG &= ~USBFS_1_DP_MASK;
        
        /* Enable USBIO */
        USBFS_1_PM_USB_CR0_REG |= USBFS_1_PM_USB_CR0_PD_N;
        CyDelayUs(2); 
        /* Set the USBIO pull-up enable */
        USBFS_1_PM_USB_CR0_REG |= USBFS_1_PM_USB_CR0_PD_PULLUP_N;
    
    #endif /* End CY_PSOC3_ES3 || CY_PSOC5_ES2 */

    /* Write WAx */
    CY_SET_REG8(&USBFS_1_ARB_RW1_WA_PTR[0u],     0u);
    CY_SET_REG8(&USBFS_1_ARB_RW1_WA_MSB_PTR[0u], 0u);

    #if(USBFS_1_EP_MM != USBFS_1__EP_MANUAL)
        /* Init transfer descriptor. This will be used to detect the DMA state - initialized or not. */
        for (i = 0u; i < USBFS_1_MAX_EP; i++)
        {
            USBFS_1_DmaTd[i] = DMA_INVALID_TD;
        }
    #endif   /* End USBFS_1_EP_MM != USBFS_1__EP_MANUAL */
    
    CyExitCriticalSection(enableInterrupts);


    /* Set the bus reset Interrupt. */
    CyIntSetVector(USBFS_1_BUS_RESET_VECT_NUM,   USBFS_1_BUS_RESET_ISR);
    CyIntSetPriority(USBFS_1_BUS_RESET_VECT_NUM, USBFS_1_BUS_RESET_PRIOR);

    /* Set the SOF Interrupt. */
    #if(USBFS_1_SOF_ISR_REMOVE == 0u)
        CyIntSetVector(USBFS_1_SOF_VECT_NUM,   USBFS_1_SOF_ISR);
        CyIntSetPriority(USBFS_1_SOF_VECT_NUM, USBFS_1_SOF_PRIOR);
    #endif   /* End USBFS_1_SOF_ISR_REMOVE */

    /* Set the Control Endpoint Interrupt. */
    CyIntSetVector(USBFS_1_EP_0_VECT_NUM,   USBFS_1_EP_0_ISR);
    CyIntSetPriority(USBFS_1_EP_0_VECT_NUM, USBFS_1_EP_0_PRIOR);

    /* Set the Data Endpoint 1 Interrupt. */
    #if(USBFS_1_EP1_ISR_REMOVE == 0u)
        CyIntSetVector(USBFS_1_EP_1_VECT_NUM,   USBFS_1_EP_1_ISR);
        CyIntSetPriority(USBFS_1_EP_1_VECT_NUM, USBFS_1_EP_1_PRIOR);
    #endif   /* End USBFS_1_EP1_ISR_REMOVE */

    /* Set the Data Endpoint 2 Interrupt. */
    #if(USBFS_1_EP2_ISR_REMOVE == 0u)
        CyIntSetVector(USBFS_1_EP_2_VECT_NUM,   USBFS_1_EP_2_ISR);
        CyIntSetPriority(USBFS_1_EP_2_VECT_NUM, USBFS_1_EP_2_PRIOR);
    #endif   /* End USBFS_1_EP2_ISR_REMOVE */

    /* Set the Data Endpoint 3 Interrupt. */
    #if(USBFS_1_EP3_ISR_REMOVE == 0u)
        CyIntSetVector(USBFS_1_EP_3_VECT_NUM,   USBFS_1_EP_3_ISR);
        CyIntSetPriority(USBFS_1_EP_3_VECT_NUM, USBFS_1_EP_3_PRIOR);
    #endif   /* End USBFS_1_EP3_ISR_REMOVE */

    /* Set the Data Endpoint 4 Interrupt. */
    #if(USBFS_1_EP4_ISR_REMOVE == 0u)
        CyIntSetVector(USBFS_1_EP_4_VECT_NUM,   USBFS_1_EP_4_ISR);
        CyIntSetPriority(USBFS_1_EP_4_VECT_NUM, USBFS_1_EP_4_PRIOR);
    #endif   /* End USBFS_1_EP4_ISR_REMOVE */

    /* Set the Data Endpoint 5 Interrupt. */
    #if(USBFS_1_EP5_ISR_REMOVE == 0u)
        CyIntSetVector(USBFS_1_EP_5_VECT_NUM,   USBFS_1_EP_5_ISR);
        CyIntSetPriority(USBFS_1_EP_5_VECT_NUM, USBFS_1_EP_5_PRIOR);
    #endif   /* End USBFS_1_EP5_ISR_REMOVE */

    /* Set the Data Endpoint 6 Interrupt. */
    #if(USBFS_1_EP6_ISR_REMOVE == 0u)
        CyIntSetVector(USBFS_1_EP_6_VECT_NUM,   USBFS_1_EP_6_ISR);
        CyIntSetPriority(USBFS_1_EP_6_VECT_NUM, USBFS_1_EP_6_PRIOR);
    #endif   /* End USBFS_1_EP6_ISR_REMOVE */

     /* Set the Data Endpoint 7 Interrupt. */
    #if(USBFS_1_EP7_ISR_REMOVE == 0u)
        CyIntSetVector(USBFS_1_EP_7_VECT_NUM,   USBFS_1_EP_7_ISR);
        CyIntSetPriority(USBFS_1_EP_7_VECT_NUM, USBFS_1_EP_7_PRIOR);
    #endif   /* End USBFS_1_EP7_ISR_REMOVE */

    /* Set the Data Endpoint 8 Interrupt. */
    #if(USBFS_1_EP8_ISR_REMOVE == 0u)
        CyIntSetVector(USBFS_1_EP_8_VECT_NUM,   USBFS_1_EP_8_ISR);
        CyIntSetPriority(USBFS_1_EP_8_VECT_NUM, USBFS_1_EP_8_PRIOR);
    #endif   /* End USBFS_1_EP8_ISR_REMOVE */
    
    #if((USBFS_1_EP_MM != USBFS_1__EP_MANUAL) && (USBFS_1_ARB_ISR_REMOVE == 0u))
        /* Set the ARB Interrupt. */
        CyIntSetVector(USBFS_1_ARB_VECT_NUM,   USBFS_1_ARB_ISR);
        CyIntSetPriority(USBFS_1_ARB_VECT_NUM, USBFS_1_ARB_PRIOR);
    #endif   /* End USBFS_1_EP_MM != USBFS_1__EP_MANUAL */
    
}


/*******************************************************************************
* Function Name: USBFS_1_InitComponent
********************************************************************************
*
* Summary:
*  Initialize the component, except for the HW which is done one time in
*  the Start function.  This function pulls up D+.
*
* Parameters:
*  device: Contains the device number from the desired device descriptor set 
*          entered with the USBFS customizer.
*  mode: The operating voltage. This determines whether the voltage regulator 
*        is enabled for 5V operation or if pass through mode is used for 3.3V 
*        operation. Symbolic names and their associated values are given in the 
*        following table.
*       USBFS_1_3V_OPERATION - Disable voltage regulator and pass-thru 
*                                       Vcc for pull-up
*       USBFS_1_5V_OPERATION - Enable voltage regulator and use 
*                                       regulator for pull-up
*       USBFS_1_DWR_VDDD_OPERATION - Enable or Disable voltage 
*                         regulator depend on Vddd Voltage configuration in DWR.
*
* Return:
*   None.
*
* Global variables:
*   USBFS_1_device: Contains the started device number from the 
*       desired device descriptor set entered with the USBFS customizer.
*   USBFS_1_transferState: This variable used by the communication 
*       functions to handle current transfer state. Initialized to 
*       TRANS_STATE_IDLE in this API. 
*   USBFS_1_configuration: Contains current configuration number 
*       which is set by the Host using SET_CONFIGURATION request. 
*       Initialized to zero in this API.
*   USBFS_1_deviceAddress: Contains current device address. This 
*       variable is initialized to zero in this API. Host starts to communicate 
*      to device with address 0 and then set it to whatever value using 
*      SET_ADDRESS request.  
*   USBFS_1_deviceStatus: initialized to 0.
*       This is two bit variable which contain power status in first bit 
*       (DEVICE_STATUS_BUS_POWERED or DEVICE_STATUS_SELF_POWERED) and remote 
*       wakeup status (DEVICE_STATUS_REMOTE_WAKEUP) in second bit. 
*   USBFS_1_lastPacketSize initialized to 0;
*
* Reentrant:
*  No.
*
*******************************************************************************/
void USBFS_1_InitComponent(uint8 device, uint8 mode) 
{
    /* Initialize _hidProtocol variable to comply with 
    *  HID 7.2.6 Set_Protocol Request: 
    *  "When initialized, all devices default to report protocol." 
    */
    #if defined(USBFS_1_ENABLE_HID_CLASS)
        uint8 interface;
        
        for (interface = 0u; interface < USBFS_1_MAX_INTERFACES_NUMBER; interface++)
        {
            USBFS_1_hidProtocol[interface] = USBFS_1_PROTOCOL_REPORT;
        }
    #endif /* USBFS_1_ENABLE_HID_CLASS */    

    /* Enable Interrupts. */
    CyIntEnable(USBFS_1_BUS_RESET_VECT_NUM);
    CyIntEnable(USBFS_1_EP_0_VECT_NUM);
    #if(USBFS_1_EP1_ISR_REMOVE == 0u)
        CyIntEnable(USBFS_1_EP_1_VECT_NUM);
    #endif   /* End USBFS_1_EP1_ISR_REMOVE */
    #if(USBFS_1_EP2_ISR_REMOVE == 0u)
        CyIntEnable(USBFS_1_EP_2_VECT_NUM);
    #endif   /* End USBFS_1_EP2_ISR_REMOVE */
    #if(USBFS_1_EP3_ISR_REMOVE == 0u)
        CyIntEnable(USBFS_1_EP_3_VECT_NUM);
    #endif   /* End USBFS_1_EP3_ISR_REMOVE */
    #if(USBFS_1_EP4_ISR_REMOVE == 0u)
        CyIntEnable(USBFS_1_EP_4_VECT_NUM);
    #endif   /* End USBFS_1_EP4_ISR_REMOVE */
    #if(USBFS_1_EP5_ISR_REMOVE == 0u)
        CyIntEnable(USBFS_1_EP_5_VECT_NUM);
    #endif   /* End USBFS_1_EP5_ISR_REMOVE */
    #if(USBFS_1_EP6_ISR_REMOVE == 0u)
        CyIntEnable(USBFS_1_EP_6_VECT_NUM);
    #endif   /* End USBFS_1_EP6_ISR_REMOVE */
    #if(USBFS_1_EP7_ISR_REMOVE == 0u)
        CyIntEnable(USBFS_1_EP_7_VECT_NUM);
    #endif   /* End USBFS_1_EP7_ISR_REMOVE */
    #if(USBFS_1_EP8_ISR_REMOVE == 0u)
        CyIntEnable(USBFS_1_EP_8_VECT_NUM);
    #endif   /* End USBFS_1_EP8_ISR_REMOVE */
    #if((USBFS_1_EP_MM != USBFS_1__EP_MANUAL) && (USBFS_1_ARB_ISR_REMOVE == 0u))
        /* usb arb interrupt enable */
        USBFS_1_ARB_INT_EN_REG = USBFS_1_ARB_INT_MASK;   
        CyIntEnable(USBFS_1_ARB_VECT_NUM);
    #endif   /* End USBFS_1_EP_MM != USBFS_1__EP_MANUAL */
    
    /* Arbiter congiguration for DMA transfers */
    #if(USBFS_1_EP_MM != USBFS_1__EP_MANUAL)

        #if(USBFS_1_EP_MM == USBFS_1__EP_DMAMANUAL)
            USBFS_1_ARB_CFG_REG = USBFS_1_ARB_CFG_MANUAL_DMA;
        #endif   /* End USBFS_1_EP_MM == USBFS_1__EP_DMAMANUAL */
        #if(USBFS_1_EP_MM == USBFS_1__EP_DMAAUTO)
            /*Set cfg cmplt this rises DMA request when the full configuration is done */
            USBFS_1_ARB_CFG_REG = USBFS_1_ARB_CFG_AUTO_DMA | USBFS_1_ARB_CFG_AUTO_MEM;
        #endif   /* End USBFS_1_EP_MM == USBFS_1__EP_DMAAUTO */
    #endif   /* End USBFS_1_EP_MM != USBFS_1__EP_MANUAL */

    USBFS_1_transferState = USBFS_1_TRANS_STATE_IDLE;

    /* USB Locking: Enabled, VRegulator: depend on mode or DWR Voltage configuration*/
    switch(mode)
    {
        case USBFS_1_3V_OPERATION:
            USBFS_1_CR1_REG = USBFS_1_CR1_ENABLE_LOCK;
            break;
        case USBFS_1_5V_OPERATION:
            USBFS_1_CR1_REG = USBFS_1_CR1_ENABLE_LOCK | USBFS_1_CR1_REG_ENABLE;
            break;
        default:   /*USBFS_1_DWR_VDDD_OPERATION */    
            #if(USBFS_1_VDDD_MV < USBFS_1_3500MV)
                USBFS_1_CR1_REG = USBFS_1_CR1_ENABLE_LOCK;
            #else
                USBFS_1_CR1_REG = USBFS_1_CR1_ENABLE_LOCK | USBFS_1_CR1_REG_ENABLE;
            #endif /* End USBFS_1_VDDD_MV < USBFS_1_3500MV */
            break;    
    }

    /* Record the descriptor selection */
    USBFS_1_device = device;

    /* Clear all of the component data */
    USBFS_1_configuration = 0u;
    USBFS_1_configurationChanged = 0u;
    USBFS_1_deviceAddress  = 0u;
    USBFS_1_deviceStatus = 0u;

    USBFS_1_lastPacketSize = 0u;

    /*  ACK Setup, Stall IN/OUT */
    CY_SET_REG8(USBFS_1_EP0_CR_PTR, USBFS_1_MODE_STALL_IN_OUT);

    /* Enable the SIE with an address 0 */
    CY_SET_REG8(USBFS_1_CR0_PTR, USBFS_1_CR0_ENABLE);

    /* Finally, Enable d+ pullup and select iomode to USB mode*/
    CY_SET_REG8(USBFS_1_USBIO_CR1_PTR, USBFS_1_USBIO_CR1_USBPUEN);
}


/*******************************************************************************
* Function Name: USBFS_1_ReInitComponent
********************************************************************************
*
* Summary:
*  This function reinitialize the component configuration and is 
*  intend to be called from the Reset interrupt.
*
* Parameters:
*  None.
*
* Return:
*   None.
*
* Global variables:
*   USBFS_1_device: Contains the started device number from the 
*       desired device descriptor set entered with the USBFS customizer.
*   USBFS_1_transferState: This variable used by the communication 
*       functions to handle current transfer state. Initialized to 
*       TRANS_STATE_IDLE in this API. 
*   USBFS_1_configuration: Contains current configuration number 
*       which is set by the Host using SET_CONFIGURATION request. 
*       Initialized to zero in this API.
*   USBFS_1_deviceAddress: Contains current device address. This 
*       variable is initialized to zero in this API. Host starts to communicate 
*      to device with address 0 and then set it to whatever value using 
*      SET_ADDRESS request.  
*   USBFS_1_deviceStatus: initialized to 0.
*       This is two bit variable which contain power status in first bit 
*       (DEVICE_STATUS_BUS_POWERED or DEVICE_STATUS_SELF_POWERED) and remote 
*       wakeup status (DEVICE_STATUS_REMOTE_WAKEUP) in second bit. 
*   USBFS_1_lastPacketSize initialized to 0;
*
* Reentrant:
*  No.
*
*******************************************************************************/
void USBFS_1_ReInitComponent() 
{
    /* Initialize _hidProtocol variable to comply with HID 7.2.6 Set_Protocol 
    *  Request: "When initialized, all devices default to report protocol." 
    */
    #if defined(USBFS_1_ENABLE_HID_CLASS)
        uint8 interface;
        
        for (interface = 0u; interface < USBFS_1_MAX_INTERFACES_NUMBER; interface++)
        {
            USBFS_1_hidProtocol[interface] = USBFS_1_PROTOCOL_REPORT;
        }
    #endif /* USBFS_1_ENABLE_HID_CLASS */    

    USBFS_1_transferState = USBFS_1_TRANS_STATE_IDLE;

    /* Clear all of the component data */
    USBFS_1_configuration = 0u;
    USBFS_1_configurationChanged = 0u;
    USBFS_1_deviceAddress  = 0u;
    USBFS_1_deviceStatus = 0u;

    USBFS_1_lastPacketSize = 0u;
    

    /*  ACK Setup, Stall IN/OUT */
    CY_SET_REG8(USBFS_1_EP0_CR_PTR, USBFS_1_MODE_STALL_IN_OUT);

    /* Enable the SIE with an address 0 */
    CY_SET_REG8(USBFS_1_CR0_PTR, USBFS_1_CR0_ENABLE);

}


/*******************************************************************************
* Function Name: USBFS_1_Stop
********************************************************************************
*
* Summary:
*  This function shuts down the USB function including to release
*  the D+ Pullup and disabling the SIE.
*
* Parameters:
*  None.
*
* Return:
*  None.
*
* Global variables:
*   USBFS_1_configuration: Contains current configuration number 
*       which is set by the Host using SET_CONFIGURATION request. 
*       Initialized to zero in this API.
*   USBFS_1_deviceAddress: Contains current device address. This 
*       variable is initialized to zero in this API. Host starts to communicate 
*      to device with address 0 and then set it to whatever value using 
*      SET_ADDRESS request.  
*   USBFS_1_deviceStatus: initialized to 0.
*       This is two bit variable which contain power status in first bit 
*       (DEVICE_STATUS_BUS_POWERED or DEVICE_STATUS_SELF_POWERED) and remote 
*       wakeup status (DEVICE_STATUS_REMOTE_WAKEUP) in second bit. 
*   USBFS_1_configurationChanged: This variable is set to one after 
*       SET_CONFIGURATION request and cleared in this function. 
*   USBFS_1_intiVar variable is set to zero 
*
*******************************************************************************/
void USBFS_1_Stop(void) 
{

    #if(USBFS_1_EP_MM != USBFS_1__EP_MANUAL)
        USBFS_1_Stop_DMA(USBFS_1_MAX_EP);     /* Stop all DMAs */
    #endif   /* End USBFS_1_EP_MM != USBFS_1__EP_MANUAL */

    /* Disable the SIE */
    USBFS_1_CR0_REG &= ~USBFS_1_CR0_ENABLE;
    /* Disable the d+ pullup */
    USBFS_1_USBIO_CR1_REG &= ~USBFS_1_USBIO_CR1_USBPUEN;
    /* Disable USB in ACT PM */
    USBFS_1_PM_ACT_CFG_REG &= ~USBFS_1_PM_ACT_EN_FSUSB;
    /* Disable USB block for Standby Power Mode */
    USBFS_1_PM_STBY_CFG_REG &= ~USBFS_1_PM_STBY_EN_FSUSB;
    
    /* Disable the reset and EP interrupts */
    CyIntDisable(USBFS_1_BUS_RESET_VECT_NUM);
    CyIntDisable(USBFS_1_EP_0_VECT_NUM);
    #if(USBFS_1_EP1_ISR_REMOVE == 0u)
        CyIntDisable(USBFS_1_EP_1_VECT_NUM);
    #endif   /* End USBFS_1_EP1_ISR_REMOVE */
    #if(USBFS_1_EP2_ISR_REMOVE == 0u)
        CyIntDisable(USBFS_1_EP_2_VECT_NUM);
    #endif   /* End USBFS_1_EP2_ISR_REMOVE */
    #if(USBFS_1_EP3_ISR_REMOVE == 0u)
        CyIntDisable(USBFS_1_EP_3_VECT_NUM);
    #endif   /* End USBFS_1_EP3_ISR_REMOVE */
    #if(USBFS_1_EP4_ISR_REMOVE == 0u)
        CyIntDisable(USBFS_1_EP_4_VECT_NUM);
    #endif   /* End USBFS_1_EP4_ISR_REMOVE */
    #if(USBFS_1_EP5_ISR_REMOVE == 0u)
        CyIntDisable(USBFS_1_EP_5_VECT_NUM);
    #endif   /* End USBFS_1_EP5_ISR_REMOVE */
    #if(USBFS_1_EP6_ISR_REMOVE == 0u)
        CyIntDisable(USBFS_1_EP_6_VECT_NUM);
    #endif   /* End USBFS_1_EP6_ISR_REMOVE */
    #if(USBFS_1_EP7_ISR_REMOVE == 0u)
        CyIntDisable(USBFS_1_EP_7_VECT_NUM);
    #endif   /* End USBFS_1_EP7_ISR_REMOVE */
    #if(USBFS_1_EP8_ISR_REMOVE == 0u)
        CyIntDisable(USBFS_1_EP_8_VECT_NUM);
    #endif   /* End USBFS_1_EP8_ISR_REMOVE */
    
    /* Clear all of the component data */
    USBFS_1_configuration = 0u;
    USBFS_1_configurationChanged = 0u;
    USBFS_1_deviceAddress  = 0u;
    USBFS_1_deviceStatus = 0u;
    USBFS_1_initVar = 0u;
    
}


/*******************************************************************************
* Function Name: USBFS_1_CheckActivity
********************************************************************************
*
* Summary:
*  Returns the activity status of the bus.  Clears the status hardware to
*  provide fresh activity status on the next call of this routine.
*
* Parameters:
*  None.
*
* Return:
*  1 - If bus activity was detected since the last call to this function
*  0 - If bus activity not was detected since the last call to this function
*
*******************************************************************************/
uint8 USBFS_1_CheckActivity(void) 
{
    uint8 r;
    
    r = CY_GET_REG8(USBFS_1_CR1_PTR);
    CY_SET_REG8(USBFS_1_CR1_PTR, (r & ~USBFS_1_CR1_BUS_ACTIVITY));

    return((r & USBFS_1_CR1_BUS_ACTIVITY) >> USBFS_1_CR1_BUS_ACTIVITY_SHIFT);
}


/*******************************************************************************
* Function Name: USBFS_1_GetConfiguration
********************************************************************************
*
* Summary:
*  Returns the current configuration setting
*
* Parameters:
*  None.
*
* Return:
*  configuration.
*
*******************************************************************************/
uint8 USBFS_1_GetConfiguration(void) 
{
    return(USBFS_1_configuration);
}


/*******************************************************************************
* Function Name: USBFS_1_IsConfigurationChanged
********************************************************************************
*
* Summary:
*  Returns the clear on read configuration state. It is usefull when PC send 
*  double SET_CONFIGURATION request with same configuration number. 
*
* Parameters:
*  None.
*
* Return:
*  Not zero value when new configuration has been changed, otherwise zero is 
*  returned.
*
* Global variables:
*   USBFS_1_configurationChanged: This variable is set to one after 
*       SET_CONFIGURATION request and cleared in this function. 
*
*******************************************************************************/
uint8 USBFS_1_IsConfigurationChanged(void) 
{
    uint8 res = 0u;
    
    if(USBFS_1_configurationChanged != 0u)
    {
        res = USBFS_1_configurationChanged;
        USBFS_1_configurationChanged = 0u;
    }
    
    return(res);
}


/*******************************************************************************
* Function Name: USBFS_1_GetInterfaceSetting
********************************************************************************
*
* Summary:
*  Returns the alternate setting from current interface
*
* Parameters:
*  uint8 interfaceNumber, interface number
*
* Return:
*  Alternate setting.
*
*******************************************************************************/
uint8  USBFS_1_GetInterfaceSetting(uint8 interfaceNumber)
                                                    
{
    return(USBFS_1_interfaceSetting[interfaceNumber]);
}


/*******************************************************************************
* Function Name: USBFS_1_GetEPState
********************************************************************************
*
* Summary:
*  Returned the state of the requested endpoint.
*
* Parameters:
*  epNumber: Endpoint Number
*
* Return:
*  State of the requested endpoint.
*
*******************************************************************************/
uint8 USBFS_1_GetEPState(uint8 epNumber) 
{
    return(USBFS_1_EP[epNumber].apiEpState);
}


/*******************************************************************************
* Function Name: USBFS_1_GetEPCount
********************************************************************************
*
* Summary:
*  This function supports Data Endpoints only(EP1-EP8).
*  Returns the transfer count for the requested endpoint.  The value from
*  the count registers includes 2 counts for the two byte checksum of the
*  packet.  This function subtracts the two counts. 
*
* Parameters:
*  epNumber: Data Endpoint Number.
*            Valid values are between 1 and 8.
*
* Return:
*  Returns the current byte count from the specified endpoin or 0 for an 
*  invalid endpoint.
*
*******************************************************************************/
uint16 USBFS_1_GetEPCount(uint8 epNumber) 
{
    uint8 ri;
    uint16 count = 0u;
    
    if((epNumber > USBFS_1_EP0) && (epNumber < USBFS_1_MAX_EP))
    {
        ri = ((epNumber - USBFS_1_EP1) << USBFS_1_EPX_CNTX_ADDR_SHIFT);
    
        count = ((uint16)((CY_GET_REG8(&USBFS_1_SIE_EP1_CNT0_PTR[ri]) & USBFS_1_EPX_CNT0_MASK) << 8u) 
                         | CY_GET_REG8(&USBFS_1_SIE_EP1_CNT1_PTR[ri]))
                         - USBFS_1_EPX_CNTX_CRC_COUNT;
    }
    return(count); 
}


#if(USBFS_1_EP_MM != USBFS_1__EP_MANUAL)


    /*******************************************************************************
    * Function Name: USBFS_1_InitEP_DMA
    ********************************************************************************
    *
    * Summary: This function allocate and initializes a EP DMA chanel to be used 
    *     by the USBFS_1_LoadInEP() or USBFS_1_ReadOutEP() APIs.
    *
    * Parameters:
    *  epNumber: Contains the data endpoint number.
    *            Valid values are between 1 and 8.
    *  *pData: A pointer to a data array which will be related to the EP transfers 
    *
    * Return:
    *  None.
    *
    * Reentrant:
    *  No.
    *
    *******************************************************************************/
    void USBFS_1_InitEP_DMA(uint8 epNumber, uint8 *pData) 
    {   
        uint16 src;
        uint16 dst;
        #if (defined(__C51__))          /* PSoC 3 - Source is Flash */
            src = HI16(CYDEV_SRAM_BASE);
            dst = HI16(CYDEV_PERIPH_BASE);
            pData = pData;
        #else                           /* PSoC 5 */
            if((USBFS_1_EP[epNumber].addr & USBFS_1_DIR_IN) != 0u )        
            {   /* for the IN EP source is the flash memory buffer */
                src = HI16(pData);
                dst = HI16(CYDEV_PERIPH_BASE);
            }    
            else
            {   /* for the OUT EP source is the SIE register */
                src = HI16(CYDEV_PERIPH_BASE);
                dst = HI16(pData);
            }
        #endif  /* End C51 */              
        switch(epNumber)
        {
            case USBFS_1_EP1:
                #if(USBFS_1_DMA1_REMOVE == 0u)
                    USBFS_1_DmaChan[epNumber] = USBFS_1_ep1_DmaInitialize(
                        USBFS_1_DMA_BYTES_PER_BURST, USBFS_1_DMA_REQUEST_PER_BURST, src, dst);
                #endif   /* End USBFS_1_DMA1_REMOVE */
                break;
            case USBFS_1_EP2:
                #if(USBFS_1_DMA2_REMOVE == 0u)
                    USBFS_1_DmaChan[epNumber] = USBFS_1_ep2_DmaInitialize(
                        USBFS_1_DMA_BYTES_PER_BURST, USBFS_1_DMA_REQUEST_PER_BURST, src, dst);
                #endif   /* End USBFS_1_DMA2_REMOVE */
                break;
            case USBFS_1_EP3:
                #if(USBFS_1_DMA3_REMOVE == 0u)
                    USBFS_1_DmaChan[epNumber] = USBFS_1_ep3_DmaInitialize(
                        USBFS_1_DMA_BYTES_PER_BURST, USBFS_1_DMA_REQUEST_PER_BURST, src, dst);
                #endif   /* End USBFS_1_DMA3_REMOVE */
                break;
            case USBFS_1_EP4:
                #if(USBFS_1_DMA4_REMOVE == 0u)
                    USBFS_1_DmaChan[epNumber] = USBFS_1_ep4_DmaInitialize(
                        USBFS_1_DMA_BYTES_PER_BURST, USBFS_1_DMA_REQUEST_PER_BURST, src, dst);
                #endif   /* End USBFS_1_DMA4_REMOVE */
                break;
            case USBFS_1_EP5:
                #if(USBFS_1_DMA5_REMOVE == 0u)
                    USBFS_1_DmaChan[epNumber] = USBFS_1_ep5_DmaInitialize(
                        USBFS_1_DMA_BYTES_PER_BURST, USBFS_1_DMA_REQUEST_PER_BURST, src, dst);
                #endif   /* End USBFS_1_DMA5_REMOVE */
                break;
            case USBFS_1_EP6:
                #if(USBFS_1_DMA6_REMOVE == 0u)
                    USBFS_1_DmaChan[epNumber] = USBFS_1_ep6_DmaInitialize(
                        USBFS_1_DMA_BYTES_PER_BURST, USBFS_1_DMA_REQUEST_PER_BURST, src, dst);
                #endif   /* End USBFS_1_DMA6_REMOVE */
                break;
            case USBFS_1_EP7:
                #if(USBFS_1_DMA7_REMOVE == 0u)
                    USBFS_1_DmaChan[epNumber] = USBFS_1_ep7_DmaInitialize(
                        USBFS_1_DMA_BYTES_PER_BURST, USBFS_1_DMA_REQUEST_PER_BURST, src, dst);
                #endif   /* End USBFS_1_DMA7_REMOVE */
                break;
            case USBFS_1_EP8:
                #if(USBFS_1_DMA8_REMOVE == 0u)
                    USBFS_1_DmaChan[epNumber] = USBFS_1_ep8_DmaInitialize(
                        USBFS_1_DMA_BYTES_PER_BURST, USBFS_1_DMA_REQUEST_PER_BURST, src, dst);
                #endif   /* End USBFS_1_DMA8_REMOVE */
                break;
            default:
                /* Do not support EP0 DMA transfers */
                break;        
        }    
        if((epNumber > USBFS_1_EP0) && (epNumber < USBFS_1_MAX_EP))
        {
            USBFS_1_DmaTd[epNumber] = CyDmaTdAllocate();
        }    
    }


    /*******************************************************************************
    * Function Name: USBFS_1_Stop_DMA
    ********************************************************************************
    *
    * Summary: Stops and free DMA
    *
    * Parameters:
    *  epNumber: Contains the data endpoint number or 
    *           USBFS_1_MAX_EP to stop all DMAs
    *
    * Return:
    *  None.
    *
    * Reentrant:
    *  No.
    *
    *******************************************************************************/
    void USBFS_1_Stop_DMA(uint8 epNumber) 
    {
        uint8 i;
        i = (epNumber < USBFS_1_MAX_EP) ? epNumber : USBFS_1_EP1;
        do
        {
            if(USBFS_1_DmaTd[i] != DMA_INVALID_TD)
            {
                CyDmaChDisable(USBFS_1_DmaChan[i]);
                CyDmaTdFree(USBFS_1_DmaTd[i]);
                USBFS_1_DmaTd[i] = DMA_INVALID_TD;
            }
            i++;
        }while((i < USBFS_1_MAX_EP) && (epNumber == USBFS_1_MAX_EP));
    }    

#endif /* End USBFS_1_EP_MM != USBFS_1__EP_MANUAL */

    
/*******************************************************************************
* Function Name: USBFS_1_LoadInEP
********************************************************************************
*
* Summary:
*  Loads and enables the specified USB data endpoint for an IN interrupt or bulk 
*  transfer.
*
* Parameters:
*  epNumber: Contains the data endpoint number.
*            Valid values are between 1 and 8.
*  *pData: A pointer to a data array from which the data for the endpoint space 
*          is loaded.
*  length: The number of bytes to transfer from the array and then send as a 
*          result of an IN request. Valid values are between 0 and 512.
*
* Return:
*  None.
*
* Reentrant:
*  No.
*
*******************************************************************************/
void USBFS_1_LoadInEP(uint8 epNumber, uint8 *pData, uint16 length) 
                                                                        
{
    uint8 ri;
    uint8 *p;
    #if(USBFS_1_EP_MM == USBFS_1__EP_MANUAL)
        uint16 i;
    #endif /* End USBFS_1_EP_MM == USBFS_1__EP_MANUAL */    

    if((epNumber > USBFS_1_EP0) && (epNumber < USBFS_1_MAX_EP))
    {
        ri = ((epNumber - USBFS_1_EP1) << USBFS_1_EPX_CNTX_ADDR_SHIFT);
        p = (uint8 *)&USBFS_1_ARB_RW1_DR_PTR[ri];
        
        #if(USBFS_1_EP_MM != USBFS_1__EP_DMAAUTO)
            /* Limits length to available buffer space, auto MM could send packets up to 1024 bytes */
            if(length > USBFS_1_EPX_DATA_BUF_MAX - USBFS_1_EP[epNumber].buffOffset)
            {
                length = USBFS_1_EPX_DATA_BUF_MAX - USBFS_1_EP[epNumber].buffOffset;
            }
        #endif /* End USBFS_1_EP_MM != USBFS_1__EP_DMAAUTO */
        
        /* Set the count and data toggle */
        CY_SET_REG8(&USBFS_1_SIE_EP1_CNT0_PTR[ri], (length >> 8u) | (USBFS_1_EP[epNumber].epToggle));
        CY_SET_REG8(&USBFS_1_SIE_EP1_CNT1_PTR[ri],  length & 0xFFu);

        #if(USBFS_1_EP_MM == USBFS_1__EP_MANUAL)
            if(pData != NULL)
            {
                /* Copy the data using the arbiter data register */
                for (i = 0u; i < length; i++)
                {
                    CY_SET_REG8(p, pData[i]);
                }
            }    
            USBFS_1_EP[epNumber].apiEpState = USBFS_1_NO_EVENT_PENDING;
            /* Write the Mode register */
            USBFS_1_SIE_EP1_CR0_PTR[ri] = USBFS_1_EP[epNumber].epMode;
        #else
            /*Init DMA if it was not initialized */
            if(USBFS_1_DmaTd[epNumber] == DMA_INVALID_TD)
            {
                USBFS_1_InitEP_DMA(epNumber, pData);
            }
        #endif /* End USBFS_1_EP_MM == USBFS_1__EP_MANUAL */
        
        #if(USBFS_1_EP_MM == USBFS_1__EP_DMAMANUAL)
            if((pData != NULL) && (length > 0))
            {
                 
                /* Enable DMA in mode2 for transfering data */
                CyDmaChDisable(USBFS_1_DmaChan[epNumber]);
                CyDmaTdSetConfiguration(USBFS_1_DmaTd[epNumber], length, DMA_INVALID_TD,\
                                                                                    TD_TERMIN_EN | TD_INC_SRC_ADR);
                CyDmaTdSetAddress(USBFS_1_DmaTd[epNumber],  LO16((uint32)pData), LO16((uint32)p));
                /* Enable the DMA */
                CyDmaChSetInitialTd(USBFS_1_DmaChan[epNumber], USBFS_1_DmaTd[epNumber]);  
                CyDmaChEnable(USBFS_1_DmaChan[epNumber], 1);
                /* Generate DMA request */
                USBFS_1_ARB_EP1_CFG_PTR[ri] |= USBFS_1_ARB_EPX_CFG_DMA_REQ;
                USBFS_1_ARB_EP1_CFG_PTR[ri] &= ~USBFS_1_ARB_EPX_CFG_DMA_REQ;
                /* Mode register will be writen in arb ISR after DMA transfer copmlete */
            }    
            else
            {
                /* When zero-length packet - write the Mode register directly */
                USBFS_1_SIE_EP1_CR0_PTR[ri] = USBFS_1_EP[epNumber].epMode;
            }            
        #endif /* End USBFS_1_EP_MM == USBFS_1__EP_DMAMANUAL */

        #if(USBFS_1_EP_MM == USBFS_1__EP_DMAAUTO)
            if(pData != NULL)
            {
                /* Enable DMA in mode3 for transfering data */
                CyDmaChDisable(USBFS_1_DmaChan[epNumber]);
                CyDmaTdSetConfiguration(USBFS_1_DmaTd[epNumber], length, USBFS_1_DmaTd[epNumber],\
                                                                                    TD_TERMIN_EN | TD_INC_SRC_ADR);
                CyDmaTdSetAddress(USBFS_1_DmaTd[epNumber],  LO16((uint32)pData), LO16((uint32)p));
                /* Clear Any potential pending DMA requests before starting the DMA channel to transfer data */
                CyDmaClearPendingDrq(USBFS_1_DmaChan[epNumber]); 
                //while(DMAC_CH[USBFS_1_DmaChan[epNumber]].basic_status[0] & 2);
                //CyDmaChSetRequest(USBFS_1_DmaChan[epNumber], CPU_TERM_CHAIN);
                //CyDmaChEnable(USBFS_1_DmaChan[epNumber], 1);
                //while(DMAC_CH[USBFS_1_DmaChan[epNumber]].basic_cfg[0] & 1);
                /* Enable the DMA */
                CyDmaChSetInitialTd(USBFS_1_DmaChan[epNumber], USBFS_1_DmaTd[epNumber]);  
                CyDmaChEnable(USBFS_1_DmaChan[epNumber], 1);
            }
            else
            {
                USBFS_1_EP[epNumber].apiEpState = USBFS_1_NO_EVENT_PENDING;
                if(length > 0)
                {
                    /* Set Data ready status, This will generate DMA request */
                    USBFS_1_ARB_EP1_CFG_PTR[ri] |= USBFS_1_ARB_EPX_CFG_IN_DATA_RDY;
                    /* Mode register will be writen in arb ISR(In Buffer Full) after first DMA transfer copmlete */
                }
                else
                {
                    /* When zero-length packet - write the Mode register directly */
                    USBFS_1_SIE_EP1_CR0_PTR[ri] = USBFS_1_EP[epNumber].epMode;
                }
            }
        #endif /* End USBFS_1_EP_MM == USBFS_1__EP_DMAAUTO */
        
    }
}


/*******************************************************************************
* Function Name: USBFS_1_ReadOutEP
********************************************************************************
*
* Summary:
*  Read data from an endpoint.  The application must call 
*  USBFS_1_GetEPState to see if an event is pending.
*
* Parameters:
*  epNumber: Contains the data endpoint number. 
*            Valid values are between 1 and 8.
*  pData: A pointer to a data array from which the data for the endpoint space 
*         is loaded.
*  length: The number of bytes to transfer from the USB Out enpoint and loads 
*          it into data array. Valid values are between 0 and 1023. The function
*          moves fewer than the requested number of bytes if the host sends 
*          fewer bytes than requested.
*
* Returns:
*  Number of bytes received, 0 for an invalid endpoint.
*
* Reentrant:
*  No.
*
*******************************************************************************/
uint16 USBFS_1_ReadOutEP(uint8 epNumber, uint8 *pData, uint16 length)
                                                                        
{
    uint8 ri;
    uint8 *p;
    #if(USBFS_1_EP_MM == USBFS_1__EP_MANUAL)
        uint16 i;
    #endif /* End USBFS_1_EP_MM == USBFS_1__EP_MANUAL */    
    #if(USBFS_1_EP_MM != USBFS_1__EP_DMAAUTO)
        uint16 xferCount;
    #endif /* End USBFS_1_EP_MM != $INSTANCE_NAME`__EP_DMAAUTO */    

    if((epNumber > USBFS_1_EP0) && (epNumber < USBFS_1_MAX_EP) && (pData != NULL))
    {
        ri = ((epNumber - USBFS_1_EP1) << USBFS_1_EPX_CNTX_ADDR_SHIFT);
        p = (uint8 *)&USBFS_1_ARB_RW1_DR_PTR[ri];

        #if(USBFS_1_EP_MM != USBFS_1__EP_DMAAUTO)
            /* Determine which is smaller the requested data or the available data */
            xferCount = USBFS_1_GetEPCount(epNumber);
            if (length > xferCount)
            {
                length = xferCount;
            }
        #endif /* End USBFS_1_EP_MM != USBFS_1__EP_DMAAUTO */
        
        #if(USBFS_1_EP_MM == USBFS_1__EP_MANUAL)
            /* Copy the data using the arbiter data register */
            for (i = 0u; i < length; i++)
            {
                pData[i] = CY_GET_REG8(p);
            }
            
            /* (re)arming of OUT endpoint */
            USBFS_1_EnableOutEP(epNumber);
        #else
            /*Init DMA if it was not initialized */
            if(USBFS_1_DmaTd[epNumber] == DMA_INVALID_TD)
            {
                USBFS_1_InitEP_DMA(epNumber, pData);
            }
        #endif /* End USBFS_1_EP_MM == USBFS_1__EP_MANUAL */
        
        #if(USBFS_1_EP_MM == USBFS_1__EP_DMAMANUAL)
            /* Enable DMA in mode2 for transfering data */
            CyDmaChDisable(USBFS_1_DmaChan[epNumber]);
            CyDmaTdSetConfiguration(USBFS_1_DmaTd[epNumber], length, DMA_INVALID_TD,
                                                                                TD_TERMIN_EN | TD_INC_DST_ADR);
            CyDmaTdSetAddress(USBFS_1_DmaTd[epNumber],  LO16((uint32)p), LO16((uint32)pData));
            /* Enable the DMA */
            CyDmaChSetInitialTd(USBFS_1_DmaChan[epNumber], USBFS_1_DmaTd[epNumber]);  
            CyDmaChEnable(USBFS_1_DmaChan[epNumber], 1);
  
            /* Generate DMA request */
            USBFS_1_ARB_EP1_CFG_PTR[ri] |= USBFS_1_ARB_EPX_CFG_DMA_REQ;
            USBFS_1_ARB_EP1_CFG_PTR[ri] &= ~USBFS_1_ARB_EPX_CFG_DMA_REQ;
            /* Out EP will be (re)armed in arb ISR after transfer complete */
        #endif /* End USBFS_1_EP_MM == USBFS_1__EP_DMAMANUAL */
        
        #if(USBFS_1_EP_MM == USBFS_1__EP_DMAAUTO)
            /* Enable DMA in mode3 for transfering data */
            CyDmaChDisable(USBFS_1_DmaChan[epNumber]);
            CyDmaTdSetConfiguration(USBFS_1_DmaTd[epNumber], length, USBFS_1_DmaTd[epNumber],
                                                                                TD_TERMIN_EN | TD_INC_DST_ADR);
            CyDmaTdSetAddress(USBFS_1_DmaTd[epNumber],  LO16((uint32)p), LO16((uint32)pData));
           
            /* Clear Any potential pending DMA requests before starting the DMA channel to transfer data */
            CyDmaClearPendingDrq(USBFS_1_DmaChan[epNumber]); 
            /*
            while(DMAC_CH[USBFS_1_DmaChan[epNumber]].basic_status[0] & 2);
            CyDmaChSetRequest(USBFS_1_DmaChan[epNumber], CPU_TERM_CHAIN);
            CyDmaChEnable(USBFS_1_DmaChan[epNumber], 1);
            while(DMAC_CH[USBFS_1_DmaChan[epNumber]].basic_cfg[0] & 1);
            */
            /* Enable the DMA */
            CyDmaChSetInitialTd(USBFS_1_DmaChan[epNumber], USBFS_1_DmaTd[epNumber]);  
            CyDmaChEnable(USBFS_1_DmaChan[epNumber], 1);
            /* Out EP will be (re)armed in arb ISR after transfer complete */
        #endif /* End USBFS_1_EP_MM == USBFS_1__EP_DMAAUTO */
        
    }
    else
    {
        length = 0;
    }

    return(length);
}


/*******************************************************************************
* Function Name: USBFS_1_EnableOutEP
********************************************************************************
*
* Summary:
*  This function enables an OUT endpoint.  It should not be
*  called for an IN endpoint.
*
* Parameters:
*  epNumber: Endpoint Number
*            Valid values are between 1 and 8.
*
* Return:
*   None.
*
* Global variables:
*  USBFS_1_EP[epNumber].apiEpState - set to NO_EVENT_PENDING
*
* Reentrant:
*  No.
*
*******************************************************************************/
void USBFS_1_EnableOutEP(uint8 epNumber) 
{
    uint8 ri;

    if((epNumber > USBFS_1_EP0) && (epNumber < USBFS_1_MAX_EP))
    {
        ri = ((epNumber - USBFS_1_EP1) << USBFS_1_EPX_CNTX_ADDR_SHIFT);
        USBFS_1_EP[epNumber].apiEpState = USBFS_1_NO_EVENT_PENDING;
        /* Write the Mode register */
        CY_SET_REG8(&USBFS_1_SIE_EP1_CR0_PTR[ri], USBFS_1_EP[epNumber].epMode);
    }
}


/*******************************************************************************
* Function Name: USBFS_1_DisableOutEP
********************************************************************************
*
* Summary: 
*  This function disables an OUT endpoint.  It should not be
*  called for an IN endpoint.
*
* Parameters:
*  epNumber: Endpoint Number
*            Valid values are between 1 and 8.
*
* Return:
*  None.
*
*******************************************************************************/
void USBFS_1_DisableOutEP(uint8 epNumber) 
{
    uint8 ri ;
    
    if((epNumber > USBFS_1_EP0) && (epNumber < USBFS_1_MAX_EP))
    {
        ri = ((epNumber - USBFS_1_EP1) << USBFS_1_EPX_CNTX_ADDR_SHIFT);
        /* Write the Mode register */
        CY_SET_REG8(&USBFS_1_SIE_EP1_CR0_PTR[ri], USBFS_1_MODE_NAK_OUT);
    }    
}


/*******************************************************************************
* Function Name: USBFS_1_Force
********************************************************************************
*
* Summary:
*  Forces the bus state
*
* Parameters:
*  bState
*    USBFS_1_FORCE_J
*    USBFS_1_FORCE_K
*    USBFS_1_FORCE_SE0
*    USBFS_1_FORCE_NONE
*
* Return:
*  None.
*
*******************************************************************************/
void USBFS_1_Force(uint8 bState) 
{
    CY_SET_REG8(USBFS_1_USBIO_CR0_PTR, bState);
}


/*******************************************************************************
* Function Name: USBFS_1_GetEPAckState
********************************************************************************
*
* Summary:
*  Returns the ACK of the CR0 Register (ACKD)
*
* Parameters:
*  epNumber: Endpoint Number
*            Valid values are between 1 and 8.
*
* Returns
*  0 if nothing has been ACKD, non-=zero something has been ACKD
*
*******************************************************************************/
uint8 USBFS_1_GetEPAckState(uint8 epNumber) 
{
    uint8 ri;
    uint8 cr = 0;
    
    if((epNumber > USBFS_1_EP0) && (epNumber < USBFS_1_MAX_EP))
    {
        ri = ((epNumber - USBFS_1_EP1) << USBFS_1_EPX_CNTX_ADDR_SHIFT);
        cr = CY_GET_REG8(&USBFS_1_SIE_EP1_CR0_PTR[ri]) & USBFS_1_MODE_ACKD; 
    }
    
    return(cr);
}


/*******************************************************************************
* Function Name: USBFS_1_SetPowerStatus
********************************************************************************
*
* Summary:
*  Sets the device power status for reporting in the Get Device Status
*  request
*
* Parameters:
*  powerStatus: USBFS_1_DEVICE_STATUS_BUS_POWERED(0) - Bus Powered, 
*               USBFS_1_DEVICE_STATUS_SELF_POWERED(1) - Self Powered
*
* Return:
*   None.
*
* Global variables:
*  USBFS_1_deviceStatus - set power status
*
* Reentrant:
*  No.
*
*******************************************************************************/
void USBFS_1_SetPowerStatus(uint8 powerStatus) 
{
    if (powerStatus != USBFS_1_DEVICE_STATUS_BUS_POWERED)
    {
        USBFS_1_deviceStatus |=  USBFS_1_DEVICE_STATUS_SELF_POWERED;
    }
    else
    {
        USBFS_1_deviceStatus &=  ~USBFS_1_DEVICE_STATUS_SELF_POWERED;
    }
}


#if (USBFS_1_MON_VBUS == 1u)

    /*******************************************************************************
    * Function Name: USBFS_1_VBusPresent
    ********************************************************************************
    *
    * Summary:
    *  Determines VBUS presense for Self Powered Devices.  
    *
    * Parameters:
    *  None.
    *
    * Return:
    *  1 if VBUS is present, otherwise 0.
    *
    *******************************************************************************/
    uint8 USBFS_1_VBusPresent(void) 
    {
        return((CY_GET_REG8(USBFS_1_VBUS_PS_PTR) & USBFS_1_VBUS_MASK) ? 1u : 0u);
    }

#endif /* USBFS_1_MON_VBUS */


/*******************************************************************************
* Function Name: USBFS_1_RWUEnabled
********************************************************************************
*
* Summary:
*  Returns TRUE if Remote Wake Up is enabled, otherwise FALSE
*
* Parameters:
*   None.
*
* Return:
*  TRUE -  Remote Wake Up Enabled
*  FALSE - Remote Wake Up Disabled
*
* Global variables:
*  USBFS_1_deviceStatus - checked to determine remote status
*
*******************************************************************************/
uint8 USBFS_1_RWUEnabled(void) 
{
    uint8 result = USBFS_1_FALSE;
    if((USBFS_1_deviceStatus & USBFS_1_DEVICE_STATUS_REMOTE_WAKEUP) != 0u)
    {
        result = USBFS_1_TRUE;
    }

    return(result);
}


/* [] END OF FILE */
