Simple USBHost library for STM32F746NG Discovery board. Only either the Fastspeed or the Highspeed port can be used( not both together)

Dependents:   DISCO-F746NG_USB_Host

Fork of KL46Z-USBHost by Norimasa Okamoto

USBHost/TARGET_STM32F7/USBHALHost_F746NG.cpp

Committer:
DieterGraef
Date:
2016-06-17
Revision:
25:7d6d9fc471bf
Parent:
24:5396b6a93262

File content as of revision 25:7d6d9fc471bf:

#if defined(TARGET_DISCO_F746NG)
#include "USBHALHost.h"
#include <algorithm>
#include "mydebug.h"


#ifdef _USB_DBG
#define USB_DBG(...) do{printf("[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);printf(__VA_ARGS__);printf("\n");} while(0);
#define USB_DBG_HEX(A,B) debug_hex<RawSerial>(pc,A,B)

#else
#define USB_DBG(...) while(0)
#define USB_DBG_HEX(A,B) while(0)
#endif

#undef USB_TEST_ASSERT
void usb_test_assert_internal(const char *expr, const char *file, int line);
#define USB_TEST_ASSERT(EXPR) while(!(EXPR)){usb_test_assert_internal(#EXPR,__FILE__,__LINE__);}

#define USB_TRACE1(A) while(0)

#define USB_INFO(...) do{fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\n");}while(0);

__IO bool attach_done = false;

void delay_ms(uint32_t t)
{
    wait_ms(t);
}

// usbh_conf.c

//__attribute__((section(".dmatransfer")));
HCD_HandleTypeDef hhcd_USB_FS;
HCD_HandleTypeDef hhcd_USB_HS;
HCD_URBStateTypeDef URB_FS;
HCD_URBStateTypeDef URB_HS;

void HAL_HCD_MspInit(HCD_HandleTypeDef* hhcd)
{
    GPIO_InitTypeDef  GPIO_InitStruct;
    if(hhcd->Instance==USB_OTG_FS)
    {
        /* Configure USB FS GPIOs */
        __HAL_RCC_GPIOA_CLK_ENABLE();
        __HAL_RCC_GPIOD_CLK_ENABLE();
        GPIO_InitStruct.Pin = (GPIO_PIN_11 | GPIO_PIN_12);
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
        GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS;
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

        GPIO_InitStruct.Pin = GPIO_PIN_10;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
        GPIO_InitStruct.Pull = GPIO_PULLUP;
        GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS;
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

        /* Configure POWER_SWITCH IO pin */
        GPIO_InitStruct.Pin = GPIO_PIN_5;
        GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

        /* Enable USB FS Clocks */
        __HAL_RCC_USB_OTG_FS_CLK_ENABLE();
    }
    if(hhcd->Instance==USB_OTG_HS)
    {
        /* Peripheral clock enable */
        __HAL_RCC_GPIOA_CLK_ENABLE();
        __HAL_RCC_GPIOB_CLK_ENABLE();
        __HAL_RCC_GPIOC_CLK_ENABLE();
        __HAL_RCC_GPIOH_CLK_ENABLE();
        /* CLK */
        GPIO_InitStruct.Pin = GPIO_PIN_5;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
        GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS;
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

        /* D0 */
        GPIO_InitStruct.Pin = GPIO_PIN_3;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
        GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS;
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

        /* D1 D2 D3 D4 D5 D6 D7 */
        GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_5 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS;
        HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

        /* STP */
        GPIO_InitStruct.Pin = GPIO_PIN_0;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS;
        HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

        /* NXT */
        GPIO_InitStruct.Pin = GPIO_PIN_4;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS;
        HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);

        /* DIR */
        GPIO_InitStruct.Pin = GPIO_PIN_2;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS;
        HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

        __HAL_RCC_USB_OTG_HS_ULPI_CLK_ENABLE();

        /* Enable USB HS Clocks */
        __HAL_RCC_USB_OTG_HS_CLK_ENABLE();
    }
}

// stm32f4xx_it.c
extern "C" {
    void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd)
    {
        //USB_TRACE1(hhcd);
        attach_done = true;
    }

} // extern "C"

USBHALHost* USBHALHost::instHost;

USBHALHost::USBHALHost(int InterfaceNumber)
{
    IF_N=InterfaceNumber;
    instHost = this;
}

void USBHALHost::init()
{
    if(IF_N==USB_FastSpeed)
    {
        hhcd_USB_FS.Instance = USB_OTG_FS;
        hhcd_USB_FS.Init.Host_channels = 11;
        hhcd_USB_FS.Init.dma_enable = 0;
        hhcd_USB_FS.Init.low_power_enable = 0;
        hhcd_USB_FS.Init.phy_itface = HCD_PHY_EMBEDDED;
        hhcd_USB_FS.Init.Sof_enable = 1;
        hhcd_USB_FS.Init.speed = HCD_SPEED_FULL;
        hhcd_USB_FS.Init.vbus_sensing_enable = 0;
        hhcd_USB_FS.Init.lpm_enable = 0;

        HAL_HCD_Init(&hhcd_USB_FS);
        /* Peripheral interrupt init*/
        /* Sets the priority grouping field */
        NVIC_SetVector(OTG_FS_IRQn, (uint32_t)&_usbisr_FS);
        HAL_NVIC_SetPriority(OTG_FS_IRQn,  6, 0);
        HAL_NVIC_EnableIRQ(OTG_FS_IRQn);

        HAL_HCD_Start(&hhcd_USB_FS);

        HAL_GPIO_WritePin(GPIOD, GPIO_PIN_5, GPIO_PIN_RESET);

        bool lowSpeed = wait_attach();
        delay_ms(200);
        HAL_HCD_ResetPort(&hhcd_USB_FS);
        delay_ms(100); // Wait for 100 ms after Reset
        addDevice(NULL, 0, lowSpeed);
    }
    if(IF_N==USB_HighSpeed)
    {
        hhcd_USB_HS.Instance = USB_OTG_HS;
        hhcd_USB_HS.Init.Host_channels = 8;
        hhcd_USB_HS.Init.dma_enable = 0;
        hhcd_USB_HS.Init.low_power_enable = 0;
        hhcd_USB_HS.Init.phy_itface = HCD_PHY_ULPI;
        hhcd_USB_HS.Init.Sof_enable = 1;
        hhcd_USB_HS.Init.speed = HCD_SPEED_HIGH;
        hhcd_USB_HS.Init.vbus_sensing_enable = 0;
        hhcd_USB_HS.Init.use_external_vbus = 1;
        hhcd_USB_HS.Init.lpm_enable = 0;

        HAL_HCD_Init(&hhcd_USB_HS);
        NVIC_SetVector(OTG_HS_IRQn, (uint32_t)&_usbisr_HS);
        HAL_NVIC_SetPriority(OTG_HS_IRQn,  6, 0);
        HAL_NVIC_EnableIRQ(OTG_HS_IRQn);

        HAL_HCD_Start(&hhcd_USB_HS);

        bool lowSpeed = wait_attach();
        delay_ms(200);
        HAL_HCD_ResetPort(&hhcd_USB_HS);
        delay_ms(100); // Wait for 100 ms after Reset
        addDevice(NULL, 0, lowSpeed);
    }
}

bool USBHALHost::wait_attach()
{
    Timer t;
    t.reset();
    t.start();
    while(!attach_done)
    {
        if (t.read_ms() > 5*1000)
        {
            t.reset();
            USB_INFO("Please attach USB device.");
        }
    }
    wait_ms(100);
    if(IF_N==USB_FastSpeed)
    {
        return HAL_HCD_GetCurrentSpeed(&hhcd_USB_FS) == USB_OTG_SPEED_LOW;
    }
    else
    {
        return HAL_HCD_GetCurrentSpeed(&hhcd_USB_HS) == USB_OTG_SPEED_LOW;
    }
}



int USBHALHost::token_setup(USBEndpoint* ep, SETUP_PACKET* setup, uint16_t wLength)
{
    const uint8_t ep_addr = 0x00;
    if(IF_N==USB_FastSpeed)
    {
        HC_FS hc;

        USBDeviceConnected* dev = ep->getDevice();
        hc.Init(ep_addr,
                dev->getAddress(),
                dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL,
                EP_TYPE_CTRL, ep->getSize());
        setup->wLength = wLength;

        hc.SubmitRequest((uint8_t*)setup, 8, true); // PID_SETUP
        while(hc.GetURBState() == URB_IDLE);

        switch(hc.GetURBState())
        {
        case URB_DONE:
            LastStatus = ACK;
            break;
        default:
            LastStatus = 0xff;
            break;
        }
        ep->setData01(DATA1);
        return 8;
    }
    else
    {
        HC_HS hc;

        USBDeviceConnected* dev = ep->getDevice();
        hc.Init(ep_addr,
                dev->getAddress(),
                dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_HIGH ,
                EP_TYPE_CTRL, ep->getSize());
        setup->wLength = wLength;

        hc.SubmitRequest((uint8_t*)setup, 8, true); // PID_SETUP
        while(hc.GetURBState() == URB_IDLE);

        switch(hc.GetURBState())
        {
        case URB_DONE:
            LastStatus = ACK;
            break;
        default:
            LastStatus = 0xff;
            break;
        }
        ep->setData01(DATA1);
        return 8;
    }
}

int USBHALHost::token_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit)
{

    switch(ep->getType())
    {
    case CONTROL_ENDPOINT:
        return token_ctl_in(ep, data, size, retryLimit);
    case INTERRUPT_ENDPOINT:
        return token_int_in(ep, data, size);
    case BULK_ENDPOINT:
        return token_blk_in(ep, data, size, retryLimit);
    }
    return -1;
}

int USBHALHost::token_ctl_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit)
{
    const uint8_t ep_addr = 0x80;
    if(IF_N==USB_FastSpeed)
    {
        HC_FS hc;

        USBDeviceConnected* dev = ep->getDevice();
        hc.Init(ep_addr,
                dev->getAddress(),
                dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL,
                EP_TYPE_CTRL, ep->getSize());
        hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1);


        wait_ms(1);
        hc.SubmitRequest(data, size);
        while(hc.GetURBState() == URB_IDLE);


        switch(hc.GetURBState())
        {
        case URB_DONE:
            LastStatus = ACK;
            break;
        default:
            LastStatus = 0xff;
            return -1;
        }
        ep->toggleData01();
        return hc.GetXferCount();
    }
    else
    {
        HC_HS hc;

        USBDeviceConnected* dev = ep->getDevice();
        hc.Init(ep_addr,
                dev->getAddress(),
                dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_HIGH ,
                EP_TYPE_CTRL, ep->getSize());
        hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1);


        wait_ms(1);
        hc.SubmitRequest(data, size);
        while(hc.GetURBState() == URB_IDLE);


        switch(hc.GetURBState())
        {
        case URB_DONE:
            LastStatus = ACK;
            break;
        default:
            LastStatus = 0xff;
            return -1;
        }
        ep->toggleData01();
        return hc.GetXferCount();
    }
}

int USBHALHost::token_int_in(USBEndpoint* ep, uint8_t* data, int size)
{
    if(IF_N==USB_FastSpeed)
    {
        HC_FS hc;

        USBDeviceConnected* dev = ep->getDevice();
        hc.Init(ep->getAddress(),
                dev->getAddress(),
                dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL,
                EP_TYPE_INTR, ep->getSize());
        hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1);


        hc.SubmitRequest(data, size);
        while(hc.GetURBState() == URB_IDLE);

        switch(hc.GetURBState())
        {
        case URB_DONE:
            switch(hc.GetState())
            {
            case HC_XFRC:
                LastStatus = ep->getData01();
                ep->toggleData01();
                return hc.GetXferCount();
            case HC_NAK:
                LastStatus = NAK;
                return -1;
            }
            break;
        }
        LastStatus = STALL;
        return -1;
    }
    else
    {
        HC_HS hc;

        USBDeviceConnected* dev = ep->getDevice();
        hc.Init(ep->getAddress(),
                dev->getAddress(),
                dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_HIGH ,
                EP_TYPE_INTR, ep->getSize());
        hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1);


        hc.SubmitRequest(data, size);
        while(hc.GetURBState() == URB_IDLE);

        switch(hc.GetURBState())
        {
        case URB_DONE:
            switch(hc.GetState())
            {
            case HC_XFRC:
                LastStatus = ep->getData01();
                ep->toggleData01();
                return hc.GetXferCount();
            case HC_NAK:
                LastStatus = NAK;
                return -1;
            }
            break;
        }
        LastStatus = STALL;
        return -1;
    }
}

int USBHALHost::token_blk_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit)
{
    if(IF_N==USB_FastSpeed)
    {
        HC_FS hc;

        USBDeviceConnected* dev = ep->getDevice();
        hc.Init(
            ep->getAddress(),
            dev->getAddress(),
            HCD_SPEED_FULL,
            EP_TYPE_BULK, ep->getSize());
        hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1);

        int retry = 0;
        do
        {


            hc.SubmitRequest(data, size);
            while(hc.GetURBState() == URB_IDLE);


            switch(hc.GetURBState())
            {
            case URB_DONE:
                switch(hc.GetState())
                {
                case HC_XFRC:
                    LastStatus = ep->getData01();
                    ep->toggleData01();
                    return hc.GetXferCount();
                case HC_NAK:
                    LastStatus = NAK;
                    if (retryLimit > 0)
                    {
                        delay_ms(1 + 10 * retry);
                    }
                    break;
                default:
                    break;
                }
                break;
            case URB_STALL:
                LastStatus = STALL;
                return -1;
            default:
                LastStatus = STALL;
                delay_ms(500 + 100 * retry);
                break;
            }
        }
        while(retry++ < retryLimit);
        return -1;
    }
    else
    {
        HC_HS hc;

        USBDeviceConnected* dev = ep->getDevice();
        hc.Init(
            ep->getAddress(),
            dev->getAddress(),
            HCD_SPEED_HIGH,
            EP_TYPE_BULK, ep->getSize());
        hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1);
        int retry = 0;
        do
        {



            hc.SubmitRequest(data, size);
            while(hc.GetURBState() == URB_IDLE);


            switch(hc.GetURBState())
            {
            case URB_DONE:
                switch(hc.GetState())
                {
                case HC_XFRC:
                    LastStatus = ep->getData01();
                    ep->toggleData01();
                    return hc.GetXferCount();
                case HC_NAK:
                    LastStatus = NAK;
                    if (retryLimit > 0)
                    {
                        delay_ms(1 + 10 * retry);
                    }
                    break;
                default:
                    break;
                }
                break;
            case URB_STALL:
                LastStatus = STALL;
                return -1;
            default:
                LastStatus = STALL;
                delay_ms(500 + 100 * retry);
                break;
            }
        }
        while(retry++ < retryLimit);
        return -1;
    }
}

int USBHALHost::token_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit)
{


    switch(ep->getType())
    {
    case CONTROL_ENDPOINT:
        return token_ctl_out(ep, data, size, retryLimit);
    case INTERRUPT_ENDPOINT:
        return token_int_out(ep, data, size);
    case BULK_ENDPOINT:
        return token_blk_out(ep, data, size, retryLimit);
    }
    return -1;
}

int USBHALHost::token_ctl_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit)
{
    const uint8_t ep_addr = 0x00;
    if(IF_N==USB_FastSpeed)
    {
        HC_FS hc;

        USBDeviceConnected* dev = ep->getDevice();
        hc.Init(ep_addr,
                dev->getAddress(),
                dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL,
                EP_TYPE_CTRL, ep->getSize());
        hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1);

        do
        {


            wait_ms(1);
            hc.SubmitRequest((uint8_t*)data, size);
            while(hc.GetURBState() == URB_IDLE);

            switch(hc.GetURBState())
            {
            case URB_DONE:
                LastStatus = ACK;
                ep->toggleData01();
                return size;

            default:
                break;
            }
            delay_ms(1);
        }
        while(retryLimit-- > 0);
        return -1;
    }
    else
    {
        HC_HS hc;

        USBDeviceConnected* dev = ep->getDevice();
        hc.Init(ep_addr,
                dev->getAddress(),
                dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_HIGH ,
                EP_TYPE_CTRL, ep->getSize());
        hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1);

        do
        {


            wait_ms(1);
            hc.SubmitRequest((uint8_t*)data, size);
            while(hc.GetURBState() == URB_IDLE);

            switch(hc.GetURBState())
            {
            case URB_DONE:
                LastStatus = ACK;
                ep->toggleData01();
                return size;

            default:
                break;
            }
            delay_ms(1);
        }
        while(retryLimit-- > 0);
        return -1;
    }
}

int USBHALHost::token_int_out(USBEndpoint* ep, const uint8_t* data, int size)
{
    if(IF_N==USB_FastSpeed)
    {
        HC_FS hc;

        USBDeviceConnected* dev = ep->getDevice();
        hc.Init(
            ep->getAddress(),
            dev->getAddress(),
            dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL,
            EP_TYPE_INTR, ep->getSize());
        hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1);


        hc.SubmitRequest((uint8_t*)data, size);
        while(hc.GetURBState() == URB_IDLE);

        if (hc.GetURBState() != URB_DONE)
        {
            return -1;
        }
        ep->toggleData01();
        return size;
    }
    else
    {
        HC_HS hc;

        USBDeviceConnected* dev = ep->getDevice();
        hc.Init(
            ep->getAddress(),
            dev->getAddress(),
            dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_HIGH ,
            EP_TYPE_INTR, ep->getSize());
        hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1);


        hc.SubmitRequest((uint8_t*)data, size);
        while(hc.GetURBState() == URB_IDLE);

        if (hc.GetURBState() != URB_DONE)
        {
            return -1;
        }
        ep->toggleData01();
        return size;
    }
}

int USBHALHost::token_blk_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit)
{
    if(IF_N==USB_FastSpeed)
    {
        HC_FS hc;

        USBDeviceConnected* dev = ep->getDevice();
        hc.Init(
            ep->getAddress(), dev->getAddress(),
            HCD_SPEED_FULL, EP_TYPE_BULK, ep->getSize());

        hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1);

        int retry = 0;
        do
        {


            hc.SubmitRequest((uint8_t*)data, size);
            while(hc.GetURBState() == URB_IDLE);

            switch(hc.GetURBState())
            {
            case URB_DONE:
                switch(hc.GetState())
                {
                case HC_XFRC: // ACK
                    LastStatus = ep->getData01();
                    ep->toggleData01();
                    return size;
                default:
                    break;
                }
                break;
            case URB_NOTREADY: // HC_NAK
                LastStatus = NAK;
                delay_ms(100 * retry);
                break;
            default:
                LastStatus = STALL;
                return -1;
            }
        }
        while(retry++ < retryLimit);
        return -1;
    }
    else
    {
        HC_HS hc;

        USBDeviceConnected* dev = ep->getDevice();
        hc.Init(
            ep->getAddress(), dev->getAddress(),
            HCD_SPEED_HIGH, EP_TYPE_BULK, ep->getSize());
        hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1);

        int retry = 0;
        do
        {


            hc.SubmitRequest((uint8_t*)data, size);
            while(hc.GetURBState() == URB_IDLE);

            switch(hc.GetURBState())
            {
            case URB_DONE:
                switch(hc.GetState())
                {
                case HC_XFRC: // ACK
                    LastStatus = ep->getData01();
                    ep->toggleData01();
                    return size;
                default:
                    break;
                }
                break;
            case URB_NOTREADY: // HC_NAK
                LastStatus = NAK;
                delay_ms(100 * retry);
                break;
            default:
                LastStatus = STALL;
                return -1;
            }
        }
        while(retry++ < retryLimit);
        return -1;
    }
}

int USBHALHost::token_iso_in(USBEndpoint* ep, uint8_t* data, int size)
{

    if(IF_N==USB_FastSpeed)
    {
        HC_FS* hc = ep->getHALData<HC_FS*>();
        if (hc == NULL)
        {
            hc = new HC_FS();
            ep->setHALData<HC_FS*>(hc);
            USBDeviceConnected* dev = ep->getDevice();
            hc->Init(
                ep->getAddress(), dev->getAddress(),
                HCD_SPEED_FULL, EP_TYPE_ISOC, ep->getSize());
        }


        hc->SubmitRequest(data, size);
        while(hc->GetURBState() == URB_IDLE);

        return hc->GetXferCount();
    }
    else
    {
        HC_HS* hc = ep->getHALData<HC_HS*>();
        if (hc == NULL)
        {
            hc = new HC_HS();
            ep->setHALData<HC_HS*>(hc);
            USBDeviceConnected* dev = ep->getDevice();
            hc->Init(
                ep->getAddress(), dev->getAddress(),
                HCD_SPEED_FULL, EP_TYPE_ISOC, ep->getSize());
        }


        hc->SubmitRequest(data, size);
        while(hc->GetURBState() == URB_IDLE);

        return hc->GetXferCount();
    }
}

int USBHALHost::multi_token_in(USBEndpoint* ep, uint8_t* data, size_t total, bool block)
{
    if (total == 0)
    {
        return token_in(ep);
    }
    int retryLimit = block ? 10 : 0;
    int read_len = 0;
    for(int n = 0; read_len < total; n++)
    {
        int size = std::min((int)total-read_len, ep->getSize());
        int result = token_in(ep, data+read_len, size, retryLimit);
        if (result < 0)
        {
            if (block)
            {
                return -1;
            }
            if (LastStatus == NAK)
            {
                if (n == 0)
                {
                    return -1;
                }
                break;
            }
            return result;
        }
        read_len += result;
        if (result < ep->getSize())
        {
            break;
        }
    }
    return read_len;
}

int USBHALHost::multi_token_out(USBEndpoint* ep, const uint8_t* data, size_t total)
{
    if (total == 0)
    {
        return token_out(ep);
    }
    int write_len = 0;
    for(int n = 0; write_len < total; n++)
    {
        int size = std::min((int)total-write_len, ep->getSize());
        int result = token_out(ep, data+write_len, size);
        if (result < 0)
        {
            if (LastStatus == NAK)
            {
                if (n == 0)
                {
                    return -1;
                }
                break;
            }
            USB_DBG("token_out result=%d %02x", result, LastStatus);
            return result;
        }
        write_len += result;
        if (result < ep->getSize())
        {
            break;
        }
    }
    return write_len;
}
void USBHALHost::multi_token_inNB(USBEndpoint* ep, uint8_t* data, int size)
{
    //USB_TRACE1(size);
    //USB_TEST_ASSERT(ep->getState() != USB_TYPE_PROCESSING);
    ep->setBuffer(data, size);
    ep->setState(USB_TYPE_PROCESSING);
}

USB_TYPE USBHALHost::multi_token_inNB_result(USBEndpoint* ep)
{
    //USB_TEST_ASSERT(ep->getState() == USB_TYPE_PROCESSING);
    uint8_t* buf = ep->getBufStart();
    int size = ep->getBufSize();
    int result = multi_token_in(ep, buf, size, false);
    //USB_TRACE1(result);
    if (result < 0)
    {
        return USB_TYPE_PROCESSING;
    }
    ep->setLengthTransferred(result);
    ep->setState(USB_TYPE_IDLE);
    return USB_TYPE_OK;

}

void USBHALHost::setToggle(USBEndpoint* ep, uint8_t toggle)
{
    //USB_TEST_ASSERT(toggle == 1);
    ep->setData01(toggle == 0 ? DATA0 : DATA1);
}

int USBHALHost::epint_setup(USBEndpoint* ep)
{
    return 1;
}

void USBHALHost::_usbisr_FS(void)
{
    instHost->usbisr_FS();
}

void USBHALHost::_usbisr_HS(void)
{
    instHost->usbisr_HS();
}

void USBHALHost::usbisr_FS(void)
{
    USB_OTG_GlobalTypeDef *USBx = USB_OTG_FS;
    uint32_t i = 0 , interrupt = 0;

    /* ensure that we are in device mode */
    if (USB_GetMode(USB_OTG_FS) == USB_OTG_MODE_HOST)
    {
        /* avoid spurious interrupt */
        if(__HAL_HCD_IS_INVALID_INTERRUPT(&hhcd_USB_FS))
        {
            return;
        }

        if(__HAL_HCD_GET_FLAG(&hhcd_USB_FS, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT))
        {
            /* incorrect mode, acknowledge the interrupt */
            __HAL_HCD_CLEAR_FLAG(&hhcd_USB_FS, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT);
        }

        if(__HAL_HCD_GET_FLAG(&hhcd_USB_FS, USB_OTG_GINTSTS_IISOIXFR))
        {
            /* incorrect mode, acknowledge the interrupt */
            __HAL_HCD_CLEAR_FLAG(&hhcd_USB_FS, USB_OTG_GINTSTS_IISOIXFR);
        }

        if(__HAL_HCD_GET_FLAG(&hhcd_USB_FS, USB_OTG_GINTSTS_PTXFE))
        {
            /* incorrect mode, acknowledge the interrupt */
            __HAL_HCD_CLEAR_FLAG(&hhcd_USB_FS, USB_OTG_GINTSTS_PTXFE);
        }

        if(__HAL_HCD_GET_FLAG(&hhcd_USB_FS, USB_OTG_GINTSTS_MMIS))
        {
            /* incorrect mode, acknowledge the interrupt */
            __HAL_HCD_CLEAR_FLAG(&hhcd_USB_FS, USB_OTG_GINTSTS_MMIS);
        }

        /* Handle Host Disconnect Interrupts */
        if(__HAL_HCD_GET_FLAG(&hhcd_USB_FS, USB_OTG_GINTSTS_DISCINT))
        {

            /* Cleanup HPRT */
            USBx_HPRT0 &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET |\
                            USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG );

            /* Handle Host Port Interrupts */
            HAL_HCD_Disconnect_Callback(&hhcd_USB_FS);
            USB_InitFSLSPClkSel(USB_OTG_FS ,HCFG_48_MHZ );
            __HAL_HCD_CLEAR_FLAG(&hhcd_USB_FS, USB_OTG_GINTSTS_DISCINT);
        }

        /* Handle Host Port Interrupts */
        if(__HAL_HCD_GET_FLAG(&hhcd_USB_FS, USB_OTG_GINTSTS_HPRTINT))
        {
            //
            USB_OTG_GlobalTypeDef *USBx = USB_OTG_FS;
            __IO uint32_t hprt0, hprt0_dup;

            /* Handle Host Port Interrupts */
            hprt0 = USBx_HPRT0;
            hprt0_dup = USBx_HPRT0;

            hprt0_dup &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET |\
                           USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG );

            /* Check wether Port Connect Detected */
            if((hprt0 & USB_OTG_HPRT_PCDET) == USB_OTG_HPRT_PCDET)
            {
                if((hprt0 & USB_OTG_HPRT_PCSTS) == USB_OTG_HPRT_PCSTS)
                {
                    USB_MASK_INTERRUPT(USB_OTG_FS, USB_OTG_GINTSTS_DISCINT);
                    HAL_HCD_Connect_Callback(&hhcd_USB_FS);
                }
                hprt0_dup  |= USB_OTG_HPRT_PCDET;

            }

            /* Check whether Port Enable Changed */
            if((hprt0 & USB_OTG_HPRT_PENCHNG) == USB_OTG_HPRT_PENCHNG)
            {
                hprt0_dup |= USB_OTG_HPRT_PENCHNG;

                if((hprt0 & USB_OTG_HPRT_PENA) == USB_OTG_HPRT_PENA)
                {
                    if(hhcd_USB_FS.Init.phy_itface  == USB_OTG_EMBEDDED_PHY)
                    {
                        if ((hprt0 & USB_OTG_HPRT_PSPD) == (HPRT0_PRTSPD_LOW_SPEED << 17))
                        {
                            USB_InitFSLSPClkSel(USB_OTG_FS ,HCFG_6_MHZ );
                        }
                        else
                        {
                            USB_InitFSLSPClkSel(USB_OTG_FS ,HCFG_48_MHZ );
                        }
                    }
                    else
                    {
                        if(hhcd_USB_FS.Init.speed == HCD_SPEED_FULL)
                        {
                            USBx_HOST->HFIR = (uint32_t)60000;
                        }
                    }
                    HAL_HCD_Connect_Callback(&hhcd_USB_FS);

                    if(hhcd_USB_FS.Init.speed == HCD_SPEED_HIGH)
                    {
                        USB_UNMASK_INTERRUPT(USB_OTG_FS, USB_OTG_GINTSTS_DISCINT);
                    }
                }
                else
                {
                    /* Cleanup HPRT */
                    USBx_HPRT0 &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET |\
                                    USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG );

                    USB_UNMASK_INTERRUPT(USB_OTG_FS, USB_OTG_GINTSTS_DISCINT);
                }
            }

            /* Check For an overcurrent */
            if((hprt0 & USB_OTG_HPRT_POCCHNG) == USB_OTG_HPRT_POCCHNG)
            {
                hprt0_dup |= USB_OTG_HPRT_POCCHNG;
            }

            /* Clear Port Interrupts */
            USBx_HPRT0 = hprt0_dup;
        }


        //


        /* Handle Host SOF Interrupts */
        if(__HAL_HCD_GET_FLAG(&hhcd_USB_FS, USB_OTG_GINTSTS_SOF))
        {
            HAL_HCD_SOF_Callback(&hhcd_USB_FS);
            __HAL_HCD_CLEAR_FLAG(&hhcd_USB_FS, USB_OTG_GINTSTS_SOF);
        }

        /* Handle Host channel Interrupts */
        if(__HAL_HCD_GET_FLAG(&hhcd_USB_FS, USB_OTG_GINTSTS_HCINT))
        {

            interrupt = USB_HC_ReadInterrupt(USB_OTG_FS);
            for (i = 0; i < hhcd_USB_FS.Init.Host_channels ; i++)
            {
                if (interrupt & (1 << i))
                {
                    if ((USBx_HC(i)->HCCHAR) &  USB_OTG_HCCHAR_EPDIR)
                    {
                        //
                        USB_OTG_GlobalTypeDef *USBx = USB_OTG_FS;
                        uint8_t chnum = i;
                        if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_AHBERR)
                        {
                            __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_AHBERR);
                            __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
                        }
                        else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_ACK)
                        {
                            __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_ACK);
                        }

                        else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_STALL)
                        {
                            __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
                            hhcd_USB_FS.hc[chnum].state = HC_STALL;
                            __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
                            __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_STALL);
                            USB_HC_Halt(USB_OTG_FS, chnum);
                        }
                        else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_DTERR)
                        {
                            __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
                            USB_HC_Halt(USB_OTG_FS, chnum);
                            __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
                            hhcd_USB_FS.hc[chnum].state = HC_DATATGLERR;
                            __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_DTERR);
                        }

                        if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_FRMOR)
                        {
                            __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
                            USB_HC_Halt(USB_OTG_FS, chnum);
                            __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_FRMOR);
                        }

                        else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_XFRC)
                        {

                            if (hhcd_USB_FS.Init.dma_enable)
                            {
                                hhcd_USB_FS.hc[chnum].xfer_count = hhcd_USB_FS.hc[chnum].xfer_len - \
                                                                   (USBx_HC(chnum)->HCTSIZ & USB_OTG_HCTSIZ_XFRSIZ);
                            }

                            hhcd_USB_FS.hc[chnum].state = HC_XFRC;
                            __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_XFRC);


                            if ((hhcd_USB_FS.hc[chnum].ep_type == EP_TYPE_CTRL)||
                                    (hhcd_USB_FS.hc[chnum].ep_type == EP_TYPE_BULK))
                            {
                                __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
                                USB_HC_Halt(USB_OTG_FS, chnum);
                                __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);

                            }
                            else if(hhcd_USB_FS.hc[chnum].ep_type == EP_TYPE_INTR)
                            {
                                USBx_HC(chnum)->HCCHAR |= USB_OTG_HCCHAR_ODDFRM;
                                __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
                                USB_HC_Halt(USB_OTG_FS, chnum);
                                __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
                            }
                            else if(hhcd_USB_FS.hc[chnum].ep_type == EP_TYPE_ISOC)
                            {
                                USBx_HC(chnum)->HCCHAR |= USB_OTG_HCCHAR_ODDFRM;
                                hhcd_USB_FS.hc[chnum].urb_state = URB_DONE;
                                HAL_HCD_HC_NotifyURBChange_Callback(&hhcd_USB_FS, chnum, hhcd_USB_FS.hc[chnum].urb_state);
                            }
                            hhcd_USB_FS.hc[chnum].toggle_in ^= 1;

                        }
                        else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_CHH)
                        {
                            __HAL_HCD_MASK_HALT_HC_INT(chnum);

                            if(hhcd_USB_FS.hc[chnum].state == HC_XFRC)
                            {
                                hhcd_USB_FS.hc[chnum].urb_state  = URB_DONE;
                            }

                            else if (hhcd_USB_FS.hc[chnum].state == HC_NAK)
                            {
                                hhcd_USB_FS.hc[chnum].urb_state  = URB_DONE;
                            }

                            else if (hhcd_USB_FS.hc[chnum].state == HC_STALL)
                            {
                                hhcd_USB_FS.hc[chnum].urb_state  = URB_STALL;
                            }

                            else if (hhcd_USB_FS.hc[chnum].state == HC_XACTERR)
                            {
                                hhcd_USB_FS.hc[chnum].urb_state = URB_NOTREADY;
                            }

                            else if (hhcd_USB_FS.hc[chnum].state == HC_DATATGLERR)
                            {
                                hhcd_USB_FS.hc[chnum].urb_state = URB_ERROR;
                            }

                            __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_CHH);
                            HAL_HCD_HC_NotifyURBChange_Callback(&hhcd_USB_FS, chnum, hhcd_USB_FS.hc[chnum].urb_state);
                        }

                        else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_TXERR)
                        {
                            __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
                            hhcd_USB_FS.hc[chnum].state = HC_XACTERR;
                            USB_HC_Halt(USB_OTG_FS, chnum);
                            __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_TXERR);
                        }
                        else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_NAK)
                        {
                            if(hhcd_USB_FS.hc[chnum].ep_type == EP_TYPE_INTR)
                            {
                                __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
                                USB_HC_Halt(USB_OTG_FS, chnum);
                            }
                            else if (hhcd_USB_FS.hc[chnum].ep_type == EP_TYPE_CTRL)
                            {
                                /* re-activate the channel  */
                                USBx_HC(chnum)->HCCHAR &= ~USB_OTG_HCCHAR_CHDIS;
                                USBx_HC(chnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA;

                            }

                            else if (hhcd_USB_FS.hc[chnum].ep_type == EP_TYPE_BULK)
                            {
                                __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
                                USB_HC_Halt(USB_OTG_FS, chnum);
                            }

                            hhcd_USB_FS.hc[chnum].state = HC_NAK;
                            __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
                        }
                        //
                    }
                    else
                    {
                        //
                        uint8_t chnum=i;
                        USB_OTG_GlobalTypeDef *USBx = USB_OTG_FS;

                        if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_AHBERR)
                        {
                            __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_AHBERR);
                            __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
                        }
                        else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_ACK)
                        {
                            __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_ACK);

                            if( hhcd_USB_FS.hc[chnum].do_ping == 1)
                            {
                                hhcd_USB_FS.hc[chnum].state = HC_NYET;
                                __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
                                USB_HC_Halt(USB_OTG_FS, chnum);
                                hhcd_USB_FS.hc[chnum].urb_state  = URB_NOTREADY;
                            }
                        }

                        else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_NYET)
                        {
                            hhcd_USB_FS.hc[chnum].state = HC_NYET;
                            __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
                            USB_HC_Halt(USB_OTG_FS, chnum);
                            __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NYET);

                        }

                        else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_FRMOR)
                        {
                            __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
                            USB_HC_Halt(USB_OTG_FS, chnum);
                            __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_FRMOR);
                        }

                        else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_XFRC)
                        {
                            __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
                            USB_HC_Halt(USB_OTG_FS, chnum);
                            __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_XFRC);
                            hhcd_USB_FS.hc[chnum].state = HC_XFRC;

                        }

                        else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_STALL)
                        {
                            __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_STALL);
                            __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
                            USB_HC_Halt(USB_OTG_FS, chnum);
                            hhcd_USB_FS.hc[chnum].state = HC_STALL;
                        }

                        else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_NAK)
                        {
                            __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
                            USB_HC_Halt(USB_OTG_FS, chnum);
                            hhcd_USB_FS.hc[chnum].state = HC_NAK;
                            __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
                        }

                        else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_TXERR)
                        {
                            __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
                            USB_HC_Halt(USB_OTG_FS, chnum);
                            hhcd_USB_FS.hc[chnum].state = HC_XACTERR;
                            __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_TXERR);
                        }

                        else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_DTERR)
                        {
                            __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
                            USB_HC_Halt(USB_OTG_FS, chnum);
                            __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
                            __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_DTERR);
                            hhcd_USB_FS.hc[chnum].state = HC_DATATGLERR;
                        }


                        else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_CHH)
                        {
                            __HAL_HCD_MASK_HALT_HC_INT(chnum);

                            if(hhcd_USB_FS.hc[chnum].state == HC_XFRC)
                            {
                                hhcd_USB_FS.hc[chnum].urb_state  = URB_DONE;
                                if (hhcd_USB_FS.hc[chnum].ep_type == EP_TYPE_BULK)
                                {
                                    hhcd_USB_FS.hc[chnum].toggle_out ^= 1;
                                }
                            }
                            else if (hhcd_USB_FS.hc[chnum].state == HC_NAK)
                            {
                                hhcd_USB_FS.hc[chnum].urb_state  = URB_NOTREADY;
                            }

                            else if (hhcd_USB_FS.hc[chnum].state == HC_NYET)
                            {
                                hhcd_USB_FS.hc[chnum].urb_state  = URB_NOTREADY;
                                hhcd_USB_FS.hc[chnum].do_ping = 0;
                            }

                            else if (hhcd_USB_FS.hc[chnum].state == HC_STALL)
                            {
                                hhcd_USB_FS.hc[chnum].urb_state  = URB_STALL;
                            }

                            else if(hhcd_USB_FS.hc[chnum].state == HC_XACTERR)
                            {
                                hhcd_USB_FS.hc[chnum].urb_state = URB_NOTREADY;
                            }

                            else if (hhcd_USB_FS.hc[chnum].state == HC_DATATGLERR)
                            {
                                hhcd_USB_FS.hc[chnum].urb_state = URB_ERROR;
                            }

                            __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_CHH);
                            HAL_HCD_HC_NotifyURBChange_Callback(&hhcd_USB_FS, chnum, hhcd_USB_FS.hc[chnum].urb_state);
                        }
                        //
                    }
                }
            }

            __HAL_HCD_CLEAR_FLAG(&hhcd_USB_FS, USB_OTG_GINTSTS_HCINT);
        }

        /* Handle Rx Queue Level Interrupts */
        if(__HAL_HCD_GET_FLAG(&hhcd_USB_FS, USB_OTG_GINTSTS_RXFLVL))
        {
            USB_MASK_INTERRUPT(USB_OTG_FS, USB_OTG_GINTSTS_RXFLVL);

//
            USB_OTG_GlobalTypeDef *USBx = USB_OTG_FS;
            uint8_t                       channelnum =0;
            uint32_t                      pktsts;
            uint32_t                      pktcnt;
            uint32_t                      temp = 0;

            temp = USB_OTG_FS->GRXSTSP ;
            channelnum = temp &  USB_OTG_GRXSTSP_EPNUM;
            pktsts = (temp &  USB_OTG_GRXSTSP_PKTSTS) >> 17;
            pktcnt = (temp &  USB_OTG_GRXSTSP_BCNT) >> 4;

            switch (pktsts)
            {
            case GRXSTS_PKTSTS_IN:
                /* Read the data into the host buffer. */
                if ((pktcnt > 0) && (hhcd_USB_FS.hc[channelnum].xfer_buff != (void  *)0))
                {

                    USB_ReadPacket(USB_OTG_FS, hhcd_USB_FS.hc[channelnum].xfer_buff, pktcnt);

                    /*manage multiple Xfer */
                    hhcd_USB_FS.hc[channelnum].xfer_buff += pktcnt;
                    hhcd_USB_FS.hc[channelnum].xfer_count  += pktcnt;

                    if((USBx_HC(channelnum)->HCTSIZ & USB_OTG_HCTSIZ_PKTCNT) > 0)
                    {
                        /* re-activate the channel when more packets are expected */
                        USBx_HC(channelnum)->HCCHAR &= ~USB_OTG_HCCHAR_CHDIS;
                        USBx_HC(channelnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
                        hhcd_USB_FS.hc[channelnum].toggle_in ^= 1;
                    }
                }
                break;

            case GRXSTS_PKTSTS_DATA_TOGGLE_ERR:
                break;
            case GRXSTS_PKTSTS_IN_XFER_COMP:
            case GRXSTS_PKTSTS_CH_HALTED:
            default:
                break;
            }
//

            USB_UNMASK_INTERRUPT(USB_OTG_FS, USB_OTG_GINTSTS_RXFLVL);
        }
    }
}

void USBHALHost::usbisr_HS(void)
{
    USB_OTG_GlobalTypeDef *USBx = USB_OTG_HS;
    uint32_t i = 0 , interrupt = 0;

    /* ensure that we are in device mode */
    if (USB_GetMode(USB_OTG_HS) == USB_OTG_MODE_HOST)
    {
        /* avoid spurious interrupt */
        if(__HAL_HCD_IS_INVALID_INTERRUPT(&hhcd_USB_HS))
        {
            return;
        }

        if(__HAL_HCD_GET_FLAG(&hhcd_USB_HS, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT))
        {
            /* incorrect mode, acknowledge the interrupt */
            __HAL_HCD_CLEAR_FLAG(&hhcd_USB_HS, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT);
        }

        if(__HAL_HCD_GET_FLAG(&hhcd_USB_HS, USB_OTG_GINTSTS_IISOIXFR))
        {
            /* incorrect mode, acknowledge the interrupt */
            __HAL_HCD_CLEAR_FLAG(&hhcd_USB_HS, USB_OTG_GINTSTS_IISOIXFR);
        }

        if(__HAL_HCD_GET_FLAG(&hhcd_USB_HS, USB_OTG_GINTSTS_PTXFE))
        {
            /* incorrect mode, acknowledge the interrupt */
            __HAL_HCD_CLEAR_FLAG(&hhcd_USB_HS, USB_OTG_GINTSTS_PTXFE);
        }

        if(__HAL_HCD_GET_FLAG(&hhcd_USB_HS, USB_OTG_GINTSTS_MMIS))
        {
            /* incorrect mode, acknowledge the interrupt */
            __HAL_HCD_CLEAR_FLAG(&hhcd_USB_HS, USB_OTG_GINTSTS_MMIS);
        }

        /* Handle Host Disconnect Interrupts */
        if(__HAL_HCD_GET_FLAG(&hhcd_USB_HS, USB_OTG_GINTSTS_DISCINT))
        {

            /* Cleanup HPRT */
            USBx_HPRT0 &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET |\
                            USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG );

            /* Handle Host Port Interrupts */
            HAL_HCD_Disconnect_Callback(&hhcd_USB_HS);
            USB_InitFSLSPClkSel(USB_OTG_HS ,HCFG_48_MHZ );
            __HAL_HCD_CLEAR_FLAG(&hhcd_USB_HS, USB_OTG_GINTSTS_DISCINT);
        }

        /* Handle Host Port Interrupts */
        if(__HAL_HCD_GET_FLAG(&hhcd_USB_HS, USB_OTG_GINTSTS_HPRTINT))
        {
            //
            USB_OTG_GlobalTypeDef *USBx = USB_OTG_HS;
            __IO uint32_t hprt0, hprt0_dup;

            /* Handle Host Port Interrupts */
            hprt0 = USBx_HPRT0;
            hprt0_dup = USBx_HPRT0;

            hprt0_dup &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET |\
                           USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG );

            /* Check wether Port Connect Detected */
            if((hprt0 & USB_OTG_HPRT_PCDET) == USB_OTG_HPRT_PCDET)
            {
                if((hprt0 & USB_OTG_HPRT_PCSTS) == USB_OTG_HPRT_PCSTS)
                {
                    USB_MASK_INTERRUPT(USB_OTG_HS, USB_OTG_GINTSTS_DISCINT);
                    HAL_HCD_Connect_Callback(&hhcd_USB_HS);
                }
                hprt0_dup  |= USB_OTG_HPRT_PCDET;

            }

            /* Check whether Port Enable Changed */
            if((hprt0 & USB_OTG_HPRT_PENCHNG) == USB_OTG_HPRT_PENCHNG)
            {
                hprt0_dup |= USB_OTG_HPRT_PENCHNG;

                if((hprt0 & USB_OTG_HPRT_PENA) == USB_OTG_HPRT_PENA)
                {
                    if(hhcd_USB_HS.Init.phy_itface  == USB_OTG_EMBEDDED_PHY)
                    {
                        if ((hprt0 & USB_OTG_HPRT_PSPD) == (HPRT0_PRTSPD_LOW_SPEED << 17))
                        {
                            USB_InitFSLSPClkSel(USB_OTG_HS ,HCFG_6_MHZ );
                        }
                        else
                        {
                            USB_InitFSLSPClkSel(USB_OTG_HS ,HCFG_48_MHZ );
                        }
                    }
                    else
                    {
                        if(hhcd_USB_HS.Init.speed == HCD_SPEED_FULL)
                        {
                            USBx_HOST->HFIR = (uint32_t)60000;
                        }
                    }
                    HAL_HCD_Connect_Callback(&hhcd_USB_HS);

                    if(hhcd_USB_HS.Init.speed == HCD_SPEED_HIGH)
                    {
                        USB_UNMASK_INTERRUPT(USB_OTG_HS, USB_OTG_GINTSTS_DISCINT);
                    }
                }
                else
                {
                    /* Cleanup HPRT */
                    USBx_HPRT0 &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET |\
                                    USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG );

                    USB_UNMASK_INTERRUPT(USB_OTG_HS, USB_OTG_GINTSTS_DISCINT);
                }
            }

            /* Check For an overcurrent */
            if((hprt0 & USB_OTG_HPRT_POCCHNG) == USB_OTG_HPRT_POCCHNG)
            {
                hprt0_dup |= USB_OTG_HPRT_POCCHNG;
            }

            /* Clear Port Interrupts */
            USBx_HPRT0 = hprt0_dup;
        }


        //


        /* Handle Host SOF Interrupts */
        if(__HAL_HCD_GET_FLAG(&hhcd_USB_HS, USB_OTG_GINTSTS_SOF))
        {
            HAL_HCD_SOF_Callback(&hhcd_USB_HS);
            __HAL_HCD_CLEAR_FLAG(&hhcd_USB_HS, USB_OTG_GINTSTS_SOF);
        }

        /* Handle Host channel Interrupts */
        if(__HAL_HCD_GET_FLAG(&hhcd_USB_HS, USB_OTG_GINTSTS_HCINT))
        {

            interrupt = USB_HC_ReadInterrupt(USB_OTG_HS);
            for (i = 0; i < hhcd_USB_HS.Init.Host_channels ; i++)
            {
                if (interrupt & (1 << i))
                {
                    if ((USBx_HC(i)->HCCHAR) &  USB_OTG_HCCHAR_EPDIR)
                    {
                        //
                        USB_OTG_GlobalTypeDef *USBx = USB_OTG_HS;
                        uint8_t chnum = i;
                        if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_AHBERR)
                        {
                            __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_AHBERR);
                            __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
                        }
                        else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_ACK)
                        {
                            __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_ACK);
                        }

                        else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_STALL)
                        {
                            __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
                            hhcd_USB_HS.hc[chnum].state = HC_STALL;
                            __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
                            __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_STALL);
                            USB_HC_Halt(USB_OTG_HS, chnum);
                        }
                        else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_DTERR)
                        {
                            __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
                            USB_HC_Halt(USB_OTG_HS, chnum);
                            __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
                            hhcd_USB_HS.hc[chnum].state = HC_DATATGLERR;
                            __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_DTERR);
                        }

                        if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_FRMOR)
                        {
                            __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
                            USB_HC_Halt(USB_OTG_HS, chnum);
                            __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_FRMOR);
                        }

                        else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_XFRC)
                        {

                            if (hhcd_USB_HS.Init.dma_enable)
                            {
                                hhcd_USB_HS.hc[chnum].xfer_count = hhcd_USB_HS.hc[chnum].xfer_len - \
                                                                   (USBx_HC(chnum)->HCTSIZ & USB_OTG_HCTSIZ_XFRSIZ);
                            }

                            hhcd_USB_HS.hc[chnum].state = HC_XFRC;
                            __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_XFRC);


                            if ((hhcd_USB_HS.hc[chnum].ep_type == EP_TYPE_CTRL)||
                                    (hhcd_USB_HS.hc[chnum].ep_type == EP_TYPE_BULK))
                            {
                                __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
                                USB_HC_Halt(USB_OTG_HS, chnum);
                                __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);

                            }
                            else if(hhcd_USB_HS.hc[chnum].ep_type == EP_TYPE_INTR)
                            {
                                USBx_HC(chnum)->HCCHAR |= USB_OTG_HCCHAR_ODDFRM;
                                __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
                                USB_HC_Halt(USB_OTG_HS, chnum);
                                __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
                            }
                            else if(hhcd_USB_HS.hc[chnum].ep_type == EP_TYPE_ISOC)
                            {
                                USBx_HC(chnum)->HCCHAR |= USB_OTG_HCCHAR_ODDFRM;
                                hhcd_USB_HS.hc[chnum].urb_state = URB_DONE;
                                HAL_HCD_HC_NotifyURBChange_Callback(&hhcd_USB_HS, chnum, hhcd_USB_HS.hc[chnum].urb_state);
                            }
                            hhcd_USB_HS.hc[chnum].toggle_in ^= 1;

                        }
                        else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_CHH)
                        {
                            __HAL_HCD_MASK_HALT_HC_INT(chnum);

                            if(hhcd_USB_HS.hc[chnum].state == HC_XFRC)
                            {
                                hhcd_USB_HS.hc[chnum].urb_state  = URB_DONE;
                            }

                            else if (hhcd_USB_HS.hc[chnum].state == HC_NAK)
                            {
                                hhcd_USB_HS.hc[chnum].urb_state  = URB_DONE;
                            }

                            else if (hhcd_USB_HS.hc[chnum].state == HC_STALL)
                            {
                                hhcd_USB_HS.hc[chnum].urb_state  = URB_STALL;
                            }

                            else if (hhcd_USB_HS.hc[chnum].state == HC_XACTERR)
                            {
                                hhcd_USB_HS.hc[chnum].urb_state = URB_NOTREADY;
                            }

                            else if (hhcd_USB_HS.hc[chnum].state == HC_DATATGLERR)
                            {
                                hhcd_USB_HS.hc[chnum].urb_state = URB_ERROR;
                            }

                            __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_CHH);
                            HAL_HCD_HC_NotifyURBChange_Callback(&hhcd_USB_HS, chnum, hhcd_USB_HS.hc[chnum].urb_state);
                        }

                        else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_TXERR)
                        {
                            __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
                            hhcd_USB_HS.hc[chnum].state = HC_XACTERR;
                            USB_HC_Halt(USB_OTG_HS, chnum);
                            __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_TXERR);
                        }
                        else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_NAK)
                        {
                            if(hhcd_USB_HS.hc[chnum].ep_type == EP_TYPE_INTR)
                            {
                                __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
                                USB_HC_Halt(USB_OTG_HS, chnum);
                            }
                            else if (hhcd_USB_HS.hc[chnum].ep_type == EP_TYPE_CTRL)
                            {
                                /* re-activate the channel  */
                                USBx_HC(chnum)->HCCHAR &= ~USB_OTG_HCCHAR_CHDIS;
                                USBx_HC(chnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA;

                            }

                            else if (hhcd_USB_HS.hc[chnum].ep_type == EP_TYPE_BULK)
                            {
                                __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
                                USB_HC_Halt(USB_OTG_HS, chnum);
                            }

                            hhcd_USB_HS.hc[chnum].state = HC_NAK;
                            __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
                        }
                        //
                    }
                    else
                    {
                        //
                        uint8_t chnum=i;
                        USB_OTG_GlobalTypeDef *USBx = USB_OTG_HS;

                        if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_AHBERR)
                        {
                            __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_AHBERR);
                            __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
                        }
                        else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_ACK)
                        {
                            __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_ACK);

                            if( hhcd_USB_HS.hc[chnum].do_ping == 1)
                            {
                                hhcd_USB_HS.hc[chnum].state = HC_NYET;
                                __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
                                USB_HC_Halt(USB_OTG_HS, chnum);
                                hhcd_USB_HS.hc[chnum].urb_state  = URB_NOTREADY;
                            }
                        }

                        else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_NYET)
                        {
                            hhcd_USB_HS.hc[chnum].state = HC_NYET;
                            __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
                            USB_HC_Halt(USB_OTG_HS, chnum);
                            __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NYET);

                        }

                        else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_FRMOR)
                        {
                            __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
                            USB_HC_Halt(USB_OTG_HS, chnum);
                            __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_FRMOR);
                        }

                        else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_XFRC)
                        {
                            __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
                            USB_HC_Halt(USB_OTG_HS, chnum);
                            __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_XFRC);
                            hhcd_USB_HS.hc[chnum].state = HC_XFRC;

                        }

                        else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_STALL)
                        {
                            __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_STALL);
                            __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
                            USB_HC_Halt(USB_OTG_HS, chnum);
                            hhcd_USB_HS.hc[chnum].state = HC_STALL;
                        }

                        else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_NAK)
                        {
                            __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
                            USB_HC_Halt(USB_OTG_HS, chnum);
                            hhcd_USB_HS.hc[chnum].state = HC_NAK;
                            __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
                        }

                        else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_TXERR)
                        {
                            __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
                            USB_HC_Halt(USB_OTG_HS, chnum);
                            hhcd_USB_HS.hc[chnum].state = HC_XACTERR;
                            __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_TXERR);
                        }

                        else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_DTERR)
                        {
                            __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
                            USB_HC_Halt(USB_OTG_HS, chnum);
                            __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
                            __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_DTERR);
                            hhcd_USB_HS.hc[chnum].state = HC_DATATGLERR;
                        }


                        else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_CHH)
                        {
                            __HAL_HCD_MASK_HALT_HC_INT(chnum);

                            if(hhcd_USB_HS.hc[chnum].state == HC_XFRC)
                            {
                                hhcd_USB_HS.hc[chnum].urb_state  = URB_DONE;
                                if (hhcd_USB_HS.hc[chnum].ep_type == EP_TYPE_BULK)
                                {
                                    hhcd_USB_HS.hc[chnum].toggle_out ^= 1;
                                }
                            }
                            else if (hhcd_USB_HS.hc[chnum].state == HC_NAK)
                            {
                                hhcd_USB_HS.hc[chnum].urb_state  = URB_NOTREADY;
                            }

                            else if (hhcd_USB_HS.hc[chnum].state == HC_NYET)
                            {
                                hhcd_USB_HS.hc[chnum].urb_state  = URB_NOTREADY;
                                hhcd_USB_HS.hc[chnum].do_ping = 0;
                            }

                            else if (hhcd_USB_HS.hc[chnum].state == HC_STALL)
                            {
                                hhcd_USB_HS.hc[chnum].urb_state  = URB_STALL;
                            }

                            else if(hhcd_USB_HS.hc[chnum].state == HC_XACTERR)
                            {
                                hhcd_USB_HS.hc[chnum].urb_state = URB_NOTREADY;
                            }

                            else if (hhcd_USB_HS.hc[chnum].state == HC_DATATGLERR)
                            {
                                hhcd_USB_HS.hc[chnum].urb_state = URB_ERROR;
                            }

                            __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_CHH);
                            HAL_HCD_HC_NotifyURBChange_Callback(&hhcd_USB_HS, chnum, hhcd_USB_HS.hc[chnum].urb_state);
                        }
                        //
                    }
                }
            }

            __HAL_HCD_CLEAR_FLAG(&hhcd_USB_HS, USB_OTG_GINTSTS_HCINT);
        }

        /* Handle Rx Queue Level Interrupts */
        if(__HAL_HCD_GET_FLAG(&hhcd_USB_HS, USB_OTG_GINTSTS_RXFLVL))
        {
            USB_MASK_INTERRUPT(USB_OTG_HS, USB_OTG_GINTSTS_RXFLVL);

//
            USB_OTG_GlobalTypeDef *USBx = USB_OTG_HS;
            uint8_t                       channelnum =0;
            uint32_t                      pktsts;
            uint32_t                      pktcnt;
            uint32_t                      temp = 0;

            temp = USB_OTG_HS->GRXSTSP ;
            channelnum = temp &  USB_OTG_GRXSTSP_EPNUM;
            pktsts = (temp &  USB_OTG_GRXSTSP_PKTSTS) >> 17;
            pktcnt = (temp &  USB_OTG_GRXSTSP_BCNT) >> 4;

            switch (pktsts)
            {
            case GRXSTS_PKTSTS_IN:
                /* Read the data into the host buffer. */
                if ((pktcnt > 0) && (hhcd_USB_HS.hc[channelnum].xfer_buff != (void  *)0))
                {

                    USB_ReadPacket(USB_OTG_HS, hhcd_USB_HS.hc[channelnum].xfer_buff, pktcnt);

                    /*manage multiple Xfer */
                    hhcd_USB_HS.hc[channelnum].xfer_buff += pktcnt;
                    hhcd_USB_HS.hc[channelnum].xfer_count  += pktcnt;

                    if((USBx_HC(channelnum)->HCTSIZ & USB_OTG_HCTSIZ_PKTCNT) > 0)
                    {
                        /* re-activate the channel when more packets are expected */
                        USBx_HC(channelnum)->HCCHAR &= ~USB_OTG_HCCHAR_CHDIS;
                        USBx_HC(channelnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
                        hhcd_USB_HS.hc[channelnum].toggle_in ^= 1;
                    }
                }
                break;

            case GRXSTS_PKTSTS_DATA_TOGGLE_ERR:
                break;
            case GRXSTS_PKTSTS_IN_XFER_COMP:
            case GRXSTS_PKTSTS_CH_HALTED:
            default:
                break;
            }
//

            USB_UNMASK_INTERRUPT(USB_OTG_HS, USB_OTG_GINTSTS_RXFLVL);
        }
    }
}

uint8_t HC_FS::slot = 0x00;

HC_FS::HC_FS()
{
    static const int start = 1;
    uint8_t mask = (1<<start);
    for(int i = start; i < 8; i++, mask <<= 1)
    {
        if (!(slot & mask))
        {
            slot |= mask;
            _ch = i;
            return;
        }
    }
    _ch = 0; // ERROR!!!
}

HC_FS::HC_FS(int ch)
{
    _ch = ch;
    slot |= (1<<_ch);
}

HC_FS::~HC_FS()
{
    slot &= ~(1<<_ch);
}

HAL_StatusTypeDef HC_FS::Init(uint8_t epnum, uint8_t dev_address, uint8_t speed, uint8_t ep_type, uint16_t mps)
{
    _ep_addr = epnum;
    _ep_type = ep_type;
    return HAL_HCD_HC_Init(&hhcd_USB_FS, _ch,
                           epnum, dev_address, speed, ep_type, mps);
}

HAL_StatusTypeDef HC_FS::SubmitRequest(uint8_t* pbuff, uint16_t length, bool setup)
{
    uint8_t direction = (_ep_addr & 0x80) ? DIR_IN : DIR_OUT;
    if (_ep_type == EP_TYPE_CTRL)
    {
        HCD_HCTypeDef* hc = &hhcd_USB_FS.hc[_ch];
        if (setup)
        {
            hc->data_pid = HC_PID_SETUP;
            hc->toggle_out = 0;
        }
        else
        {
            if (direction == DIR_IN)
            {
                if (hc->toggle_in == 0)
                {
                    hc->data_pid = HC_PID_DATA0;
                }
                else
                {
                    hc->data_pid = HC_PID_DATA1;
                }
            }
            else     // OUT
            {
                if (hc->toggle_out == 0)
                {
                    hc->data_pid = HC_PID_DATA0;
                }
                else
                {
                    hc->data_pid = HC_PID_DATA1;
                }
            }
        }
        hc->xfer_buff = pbuff;
        hc->xfer_len  = length;
        hc->urb_state = URB_IDLE;
        hc->xfer_count = 0;
        hc->ch_num = _ch;
        hc->state = HC_IDLE;

        return USB_HC_StartXfer(hhcd_USB_FS.Instance, hc, 0);
    }
    return HAL_HCD_HC_SubmitRequest(&hhcd_USB_FS, _ch,
                                    direction, _ep_type, 0, pbuff, length, 0);
}

HCD_URBStateTypeDef HC_FS::GetURBState()
{
    return HAL_HCD_HC_GetURBState(&hhcd_USB_FS, _ch);
}

HCD_HCStateTypeDef HC_FS::GetState()
{
    return HAL_HCD_HC_GetState(&hhcd_USB_FS, _ch);
}

uint32_t HC_FS::GetXferCount()
{
    return HAL_HCD_HC_GetXferCount(&hhcd_USB_FS, _ch);
}

void HC_FS::SetToggle(uint8_t toggle)
{
    if (_ep_addr & 0x80)   // IN
    {
        hhcd_USB_FS.hc[_ch].toggle_in = toggle;
    }
    else     // OUT
    {
        hhcd_USB_FS.hc[_ch].toggle_out = toggle;
    }
}


uint8_t HC_HS::slot = 0x00;

HC_HS::HC_HS()
{
    static const int start = 1;
    uint8_t mask = (1<<start);
    for(int i = start; i < 8; i++, mask <<= 1)
    {
        if (!(slot & mask))
        {
            slot |= mask;
            _ch = i;
            return;
        }
    }
    _ch = 0; // ERROR!!!
}

HC_HS::HC_HS(int ch)
{
    _ch = ch;
    slot |= (1<<_ch);
}

HC_HS::~HC_HS()
{
    slot &= ~(1<<_ch);
}

HAL_StatusTypeDef HC_HS::Init(uint8_t epnum, uint8_t dev_address, uint8_t speed, uint8_t ep_type, uint16_t mps)
{
    _ep_addr = epnum;
    _ep_type = ep_type;
    return HAL_HCD_HC_Init(&hhcd_USB_HS, _ch,
                           epnum, dev_address, speed, ep_type, mps);
}

HAL_StatusTypeDef HC_HS::SubmitRequest(uint8_t* pbuff, uint16_t length, bool setup)
{
    uint8_t direction = (_ep_addr & 0x80) ? DIR_IN : DIR_OUT;
    if (_ep_type == EP_TYPE_CTRL)
    {
        HCD_HCTypeDef* hc = &hhcd_USB_HS.hc[_ch];
        if (setup)
        {
            hc->data_pid = HC_PID_SETUP;
            hc->toggle_out = 0;
        }
        else
        {
            if (direction == DIR_IN)
            {
                if (hc->toggle_in == 0)
                {
                    hc->data_pid = HC_PID_DATA0;
                }
                else
                {
                    hc->data_pid = HC_PID_DATA1;
                }
            }
            else     // OUT
            {
                if (hc->toggle_out == 0)
                {
                    hc->data_pid = HC_PID_DATA0;
                }
                else
                {
                    hc->data_pid = HC_PID_DATA1;
                }
            }
        }
        hc->xfer_buff = pbuff;
        hc->xfer_len  = length;
        hc->urb_state = URB_IDLE;
        hc->xfer_count = 0;
        hc->ch_num = _ch;
        hc->state = HC_IDLE;

        return USB_HC_StartXfer(hhcd_USB_HS.Instance, hc, 0);
    }
    return HAL_HCD_HC_SubmitRequest(&hhcd_USB_HS, _ch,
                                    direction, _ep_type, 0, pbuff, length, 0);
}

HCD_URBStateTypeDef HC_HS::GetURBState()
{
    return HAL_HCD_HC_GetURBState(&hhcd_USB_HS, _ch);
}

HCD_HCStateTypeDef HC_HS::GetState()
{
    return HAL_HCD_HC_GetState(&hhcd_USB_HS, _ch);
}

uint32_t HC_HS::GetXferCount()
{
    return HAL_HCD_HC_GetXferCount(&hhcd_USB_HS, _ch);
}

void HC_HS::SetToggle(uint8_t toggle)
{
    if (_ep_addr & 0x80)   // IN
    {
        hhcd_USB_HS.hc[_ch].toggle_in = toggle;
    }
    else     // OUT
    {
        hhcd_USB_HS.hc[_ch].toggle_out = toggle;
    }
}


#endif