1
0
Эх сурвалжийг харах

Merge branch 'master' of https://github.com/RT-Thread/rt-thread

moebius.ever 7 жил өмнө
parent
commit
bb93c74810
29 өөрчлөгдсөн 15153 нэмэгдсэн , 7 устгасан
  1. 13 0
      bsp/imxrt1052-evk/Kconfig
  2. 7 0
      bsp/imxrt1052-evk/drivers/SConscript
  3. 0 2
      bsp/imxrt1052-evk/drivers/drv_hp_rtc.c
  4. 503 0
      bsp/imxrt1052-evk/drivers/drv_usbd.c
  5. 644 0
      bsp/imxrt1052-evk/drivers/usb/device/usb_device.h
  6. 1459 0
      bsp/imxrt1052-evk/drivers/usb/device/usb_device_dci.c
  7. 177 0
      bsp/imxrt1052-evk/drivers/usb/device/usb_device_dci.h
  8. 1807 0
      bsp/imxrt1052-evk/drivers/usb/device/usb_device_ehci.c
  9. 219 0
      bsp/imxrt1052-evk/drivers/usb/device/usb_device_ehci.h
  10. 726 0
      bsp/imxrt1052-evk/drivers/usb/host/usb_host.h
  11. 1414 0
      bsp/imxrt1052-evk/drivers/usb/host/usb_host_devices.c
  12. 178 0
      bsp/imxrt1052-evk/drivers/usb/host/usb_host_devices.h
  13. 4747 0
      bsp/imxrt1052-evk/drivers/usb/host/usb_host_ehci.c
  14. 499 0
      bsp/imxrt1052-evk/drivers/usb/host/usb_host_ehci.h
  15. 1052 0
      bsp/imxrt1052-evk/drivers/usb/host/usb_host_hci.c
  16. 131 0
      bsp/imxrt1052-evk/drivers/usb/host/usb_host_hci.h
  17. 140 0
      bsp/imxrt1052-evk/drivers/usb/include/usb.h
  18. 185 0
      bsp/imxrt1052-evk/drivers/usb/include/usb_device_config.h
  19. 140 0
      bsp/imxrt1052-evk/drivers/usb/include/usb_ehci.h
  20. 452 0
      bsp/imxrt1052-evk/drivers/usb/include/usb_misc.h
  21. 296 0
      bsp/imxrt1052-evk/drivers/usb/include/usb_spec.h
  22. 240 0
      bsp/imxrt1052-evk/drivers/usb/phy/usb_phy.c
  23. 113 0
      bsp/imxrt1052-evk/drivers/usb/phy/usb_phy.h
  24. 2 0
      bsp/stm32f10x-HAL/drivers/drv_usb.c
  25. 0 4
      bsp/v2m-mps2/rtconfig.py
  26. 1 0
      components/drivers/Kconfig
  27. 2 0
      components/drivers/rtc/rtc.c
  28. 1 1
      components/drivers/usb/usbdevice/core/usbdevice.c
  29. 5 0
      components/libc/compilers/armlibc/sys/unistd.h

+ 13 - 0
bsp/imxrt1052-evk/Kconfig

@@ -35,3 +35,16 @@ config RT_USING_HP_RTC
     default n 
 endif
 
+if RT_USING_USB_DEVICE
+    choice
+        prompt "select usb device controller"
+        default RT_USING_EHCI0_AS_DEVICE
+
+        config RT_USING_EHCI0_AS_DEVICE
+            bool "set EHCI0 as device"
+        config RT_USING_EHCI1_AS_DEVICE
+            bool "set EHCI1 as device"
+    endchoice
+endif
+
+

+ 7 - 0
bsp/imxrt1052-evk/drivers/SConscript

@@ -27,6 +27,13 @@ if GetDepend('RT_USING_LWIP'):
     
 if GetDepend('RT_USING_SDIO'):
     src += ['drv_sdio.c']
+if GetDepend('RT_USING_USB_DEVICE'):
+    src += Glob('usb/phy/*.c')
+    CPPDEFINES += ['ENDIANNESS']
+    
+if GetDepend('RT_USING_USB_DEVICE'):
+    src += ['drv_usbd.c']
+    src += Glob('usb/device/*.c')
     
 if GetDepend('RT_USING_RTGUI') or GetDepend('PKG_USING_GUIENGINE'):
     src += ['drv_lcd.c', 'drv_ft5406.c', 'drv_i2c.c']

+ 0 - 2
bsp/imxrt1052-evk/drivers/drv_hp_rtc.c

@@ -61,7 +61,6 @@ static int set_timestamp(time_t timestamp)
     return RT_EOK;
 }
 
-/* Çý¶¯½Ó¿Ú */
 static rt_err_t rt1052_hp_rtc_init(rt_device_t dev)
 {
     snvs_hp_rtc_config_t snvsRtcConfig;
@@ -112,7 +111,6 @@ static rt_err_t rt1052_hp_rtc_control(rt_device_t dev, int cmd, void *args)
         }
         break;
             
-        /* ÎÞЧ²ÎÊý */
         default:
             return RT_EINVAL; 
     }

+ 503 - 0
bsp/imxrt1052-evk/drivers/drv_usbd.c

@@ -0,0 +1,503 @@
+/*
+ * File      : drv_usbc.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2009 RT-Thread Develop Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rt-thread.org/license/LICENSE
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2017-12-04     ZYH          first implementation
+ */
+#include <usb/include/usb_device_config.h>
+#include <usb/include/usb.h>
+#include <rtthread.h>
+#include <usb/phy/usb_phy.h>
+#include <usb/device/usb_device.h>
+#include <usb/device/usb_device_dci.h>
+#include <rtdevice.h>
+#ifdef RT_USING_EHCI0_AS_DEVICE
+#ifdef RT_USING_EHCI1_AS_DEVICE
+#error Can not using 2 controller as usb device
+#endif
+#endif
+
+
+/* USB PHY condfiguration */
+#define BOARD_USB_PHY_D_CAL (0x0CU)
+#define BOARD_USB_PHY_TXCAL45DP (0x06U)
+#define BOARD_USB_PHY_TXCAL45DM (0x06U)
+#define BOARD_XTAL0_CLK_HZ 24000000U
+
+#ifdef RT_USING_EHCI0_AS_DEVICE
+static usb_device_handle ehci0_handle;
+static struct udcd _fsl_udc_0;
+#endif
+#ifdef RT_USING_EHCI1_AS_DEVICE
+static usb_device_handle ehci1_handle;
+static struct udcd _fsl_udc_1;
+#endif
+
+
+
+static usb_status_t usb_device_callback(usb_device_handle handle, uint32_t callbackEvent, void *eventParam);
+static usb_status_t usb_device_endpoint_callback(usb_device_handle handle, usb_device_endpoint_callback_message_struct_t *message, void *callbackParam);
+void USB_DeviceIsrEnable(uint8_t controllerId)
+{
+    uint8_t irqNumber;
+#if defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0U)
+    uint8_t usbDeviceEhciIrq[] = USBHS_IRQS;
+    irqNumber = usbDeviceEhciIrq[controllerId - kUSB_ControllerEhci0];
+#endif
+/* Install isr, set priority, and enable IRQ. */
+#if defined(__GIC_PRIO_BITS)
+    GIC_SetPriority((IRQn_Type)irqNumber, 3);
+#else
+    NVIC_SetPriority((IRQn_Type)irqNumber, 3);
+#endif
+    EnableIRQ((IRQn_Type)irqNumber);
+}
+void USB_DeviceClockInit(uint8_t controllerId)
+{
+#if defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0U)
+    usb_phy_config_struct_t phyConfig = {
+        BOARD_USB_PHY_D_CAL, BOARD_USB_PHY_TXCAL45DP, BOARD_USB_PHY_TXCAL45DM,
+    };
+#endif
+#if defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0U)
+    if (controllerId == kUSB_ControllerEhci0)
+    {
+        CLOCK_EnableUsbhs0PhyPllClock(kCLOCK_Usbphy480M, 480000000U);
+        CLOCK_EnableUsbhs0Clock(kCLOCK_Usb480M, 480000000U);
+    }
+    else
+    {
+        CLOCK_EnableUsbhs1PhyPllClock(kCLOCK_Usbphy480M, 480000000U);
+        CLOCK_EnableUsbhs1Clock(kCLOCK_Usb480M, 480000000U);
+    }
+    USB_EhciPhyInit(controllerId, BOARD_XTAL0_CLK_HZ, &phyConfig);
+#endif
+}
+#ifdef RT_USING_EHCI0_AS_DEVICE
+static struct ep_id _ehci0_ep_pool[] =
+{
+    {0x0,  USB_EP_ATTR_CONTROL,     USB_DIR_INOUT,  64, ID_ASSIGNED  },
+    {0x1,  USB_EP_ATTR_BULK,        USB_DIR_IN,     64, ID_UNASSIGNED},
+    {0x1,  USB_EP_ATTR_BULK,        USB_DIR_OUT,    64, ID_UNASSIGNED},
+    {0x2,  USB_EP_ATTR_INT,         USB_DIR_IN,     64, ID_UNASSIGNED},
+    {0x2,  USB_EP_ATTR_INT,         USB_DIR_OUT,    64, ID_UNASSIGNED},
+    {0x3,  USB_EP_ATTR_BULK,        USB_DIR_IN,     64, ID_UNASSIGNED},
+    {0x3,  USB_EP_ATTR_BULK,        USB_DIR_OUT,    64, ID_UNASSIGNED},
+    {0x4,  USB_EP_ATTR_INT,         USB_DIR_IN,     64, ID_UNASSIGNED},
+    {0x4,  USB_EP_ATTR_INT,         USB_DIR_OUT,    64, ID_UNASSIGNED},
+    {0x5,  USB_EP_ATTR_BULK,        USB_DIR_IN,     64, ID_UNASSIGNED},
+    {0x5,  USB_EP_ATTR_BULK,        USB_DIR_OUT,    64, ID_UNASSIGNED},
+    {0x6,  USB_EP_ATTR_INT,         USB_DIR_IN,     64, ID_UNASSIGNED},
+    {0x6,  USB_EP_ATTR_INT,         USB_DIR_OUT,    64, ID_UNASSIGNED},
+    {0x7,  USB_EP_ATTR_BULK,        USB_DIR_IN,     64, ID_UNASSIGNED},
+    {0x7,  USB_EP_ATTR_BULK,        USB_DIR_OUT,    64, ID_UNASSIGNED},
+    {0xFF, USB_EP_ATTR_TYPE_MASK,   USB_DIR_MASK,   0,  ID_ASSIGNED  },
+};
+void USB_OTG1_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+    
+    USB_DeviceEhciIsrFunction(ehci0_handle);
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+static rt_err_t _ehci0_ep_set_stall(rt_uint8_t address)
+{
+    USB_DeviceStallEndpoint(ehci0_handle, address);
+    return RT_EOK;
+}
+static rt_err_t _ehci0_ep_clear_stall(rt_uint8_t address)
+{
+    USB_DeviceUnstallEndpoint(ehci0_handle, address);
+    return RT_EOK;
+}
+
+static rt_err_t _ehci0_set_address(rt_uint8_t address)
+{
+    USB_DeviceSetStatus(ehci0_handle, kUSB_DeviceStatusAddress, &address);
+    return RT_EOK;
+}
+static rt_err_t _ehci0_set_config(rt_uint8_t address)
+{
+    return RT_EOK;
+}
+static rt_err_t _ehci0_ep_enable(uep_t ep)
+{
+    usb_device_endpoint_init_struct_t ep_init;
+    usb_device_endpoint_callback_struct_t ep_callback;
+    RT_ASSERT(ep != RT_NULL);
+    RT_ASSERT(ep->ep_desc != RT_NULL);
+    ep_init.maxPacketSize = ep->ep_desc->wMaxPacketSize;
+    ep_init.endpointAddress = ep->ep_desc->bEndpointAddress;
+    ep_init.transferType = ep->ep_desc->bmAttributes;
+    ep_init.zlt = 0;
+    ep_callback.callbackFn = usb_device_endpoint_callback;
+    ep_callback.callbackParam = (void *)ep_init.endpointAddress;
+    ep_callback.isBusy = 0;
+    USB_DeviceInitEndpoint(ehci0_handle,&ep_init,&ep_callback);
+    return RT_EOK;
+}
+static rt_err_t _ehci0_ep_disable(uep_t ep)
+{
+    RT_ASSERT(ep != RT_NULL);
+    RT_ASSERT(ep->ep_desc != RT_NULL);
+    USB_DeviceDeinitEndpoint(ehci0_handle, ep->ep_desc->bEndpointAddress);
+    return RT_EOK;
+}
+static rt_size_t _ehci0_ep_read(rt_uint8_t address, void *buffer)
+{
+    rt_size_t size = 0;
+
+    RT_ASSERT(buffer != RT_NULL);
+
+    return size;
+}
+static rt_size_t _ehci0_ep_read_prepare(rt_uint8_t address, void *buffer, rt_size_t size)
+{
+    USB_DeviceRecvRequest(ehci0_handle, address, buffer, size);
+    return size;
+}
+static rt_size_t _ehci0_ep_write(rt_uint8_t address, void *buffer, rt_size_t size)
+{
+    USB_DeviceSendRequest(ehci0_handle, address, buffer, size);
+    return size;
+}
+static rt_err_t _ehci0_ep0_send_status(void)
+{	
+    _ehci0_ep_write(0x00, NULL, 0);
+    return RT_EOK;
+}
+static rt_err_t _ehci0_suspend(void)
+{
+    return RT_EOK;
+}
+
+static rt_err_t _ehci0_wakeup(void)
+{
+    return RT_EOK;
+}
+const static struct udcd_ops _ehci0_udc_ops =
+{
+    _ehci0_set_address,
+    _ehci0_set_config,
+    _ehci0_ep_set_stall,
+    _ehci0_ep_clear_stall,
+    _ehci0_ep_enable,
+    _ehci0_ep_disable,
+    _ehci0_ep_read_prepare,
+    _ehci0_ep_read,
+    _ehci0_ep_write,
+    _ehci0_ep0_send_status,
+    _ehci0_suspend,
+    _ehci0_wakeup,
+};
+static rt_err_t drv_ehci0_usbd_init(rt_device_t device)
+{
+    usb_status_t result;
+    USB_DeviceClockInit(kUSB_ControllerEhci0);
+    
+    result = USB_DeviceInit(kUSB_ControllerEhci0,usb_device_callback,&ehci0_handle);
+    RT_ASSERT(ehci0_handle);
+    if(result == kStatus_USB_Success)
+    {
+        USB_DeviceIsrEnable(kUSB_ControllerEhci0);
+        USB_DeviceRun(ehci0_handle);
+    }
+    else
+    {
+        rt_kprintf("USB_DeviceInit ehci0 error\r\n");
+        return RT_ERROR;
+    }
+    return RT_EOK;
+}
+#endif
+#ifdef RT_USING_EHCI1_AS_DEVICE
+static struct ep_id _ehci1_ep_pool[] =
+{
+    {0x0,  USB_EP_ATTR_CONTROL,     USB_DIR_INOUT,  64, ID_ASSIGNED  },
+    {0x1,  USB_EP_ATTR_BULK,        USB_DIR_IN,     64, ID_UNASSIGNED},
+    {0x1,  USB_EP_ATTR_BULK,        USB_DIR_OUT,    64, ID_UNASSIGNED},
+    {0x2,  USB_EP_ATTR_INT,         USB_DIR_IN,     64, ID_UNASSIGNED},
+    {0x2,  USB_EP_ATTR_INT,         USB_DIR_OUT,    64, ID_UNASSIGNED},
+    {0x3,  USB_EP_ATTR_BULK,        USB_DIR_IN,     64, ID_UNASSIGNED},
+    {0x3,  USB_EP_ATTR_BULK,        USB_DIR_OUT,    64, ID_UNASSIGNED},
+    {0x4,  USB_EP_ATTR_INT,         USB_DIR_IN,     64, ID_UNASSIGNED},
+    {0x4,  USB_EP_ATTR_INT,         USB_DIR_OUT,    64, ID_UNASSIGNED},
+    {0x5,  USB_EP_ATTR_BULK,        USB_DIR_IN,     64, ID_UNASSIGNED},
+    {0x5,  USB_EP_ATTR_BULK,        USB_DIR_OUT,    64, ID_UNASSIGNED},
+    {0x6,  USB_EP_ATTR_INT,         USB_DIR_IN,     64, ID_UNASSIGNED},
+    {0x6,  USB_EP_ATTR_INT,         USB_DIR_OUT,    64, ID_UNASSIGNED},
+    {0x7,  USB_EP_ATTR_BULK,        USB_DIR_IN,     64, ID_UNASSIGNED},
+    {0x7,  USB_EP_ATTR_BULK,        USB_DIR_OUT,    64, ID_UNASSIGNED},
+    {0xFF, USB_EP_ATTR_TYPE_MASK,   USB_DIR_MASK,   0,  ID_ASSIGNED  },
+};
+void USB_OTG2_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+    USB_DeviceEhciIsrFunction(ehci1_handle);
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+static rt_err_t _ehci1_ep_set_stall(rt_uint8_t address)
+{
+    USB_DeviceStallEndpoint(ehci1_handle, address);
+    return RT_EOK;
+}
+static rt_err_t _ehci1_ep_clear_stall(rt_uint8_t address)
+{
+    USB_DeviceUnstallEndpoint(ehci1_handle, address);
+    return RT_EOK;
+}
+
+static rt_err_t _ehci1_set_address(rt_uint8_t address)
+{
+    USB_DeviceSetStatus(ehci1_handle, kUSB_DeviceStatusAddress, &address);
+    return RT_EOK;
+}
+static rt_err_t _ehci1_set_config(rt_uint8_t address)
+{
+    return RT_EOK;
+}
+static rt_err_t _ehci1_ep_enable(uep_t ep)
+{
+    usb_device_endpoint_init_struct_t ep_init;
+    usb_device_endpoint_callback_struct_t ep_callback;
+    RT_ASSERT(ep != RT_NULL);
+    RT_ASSERT(ep->ep_desc != RT_NULL);
+    ep_init.maxPacketSize = ep->ep_desc->wMaxPacketSize;
+    ep_init.endpointAddress = ep->ep_desc->bEndpointAddress;
+    ep_init.transferType = ep->ep_desc->bmAttributes;
+    ep_init.zlt = 0;
+    ep_callback.callbackFn = usb_device_endpoint_callback;
+    ep_callback.callbackParam = (void *)ep_init.endpointAddress;
+    ep_callback.isBusy = 0;
+    USB_DeviceInitEndpoint(ehci1_handle,&ep_init,&ep_callback);
+    return RT_EOK;
+}
+static rt_err_t _ehci1_ep_disable(uep_t ep)
+{
+    RT_ASSERT(ep != RT_NULL);
+    RT_ASSERT(ep->ep_desc != RT_NULL);
+    USB_DeviceDeinitEndpoint(ehci1_handle, ep->ep_desc->bEndpointAddress);
+    return RT_EOK;
+}
+static rt_size_t _ehci1_ep_read(rt_uint8_t address, void *buffer)
+{
+    rt_size_t size = 0;
+
+    RT_ASSERT(buffer != RT_NULL);
+
+    return size;
+}
+static rt_size_t _ehci1_ep_read_prepare(rt_uint8_t address, void *buffer, rt_size_t size)
+{
+    USB_DeviceRecvRequest(ehci1_handle, address, buffer, size);
+    return size;
+}
+static rt_size_t _ehci1_ep_write(rt_uint8_t address, void *buffer, rt_size_t size)
+{
+    USB_DeviceSendRequest(ehci1_handle, address, buffer, size);
+    return size;
+}
+static rt_err_t _ehci1_ep0_send_status(void)
+{	
+    _ehci1_ep_write(0x00, NULL, 0);
+    return RT_EOK;
+}
+static rt_err_t _ehci1_suspend(void)
+{
+    return RT_EOK;
+}
+
+static rt_err_t _ehci1_wakeup(void)
+{
+    return RT_EOK;
+}
+const static struct udcd_ops _ehci1_udc_ops =
+{
+    _ehci1_set_address,
+    _ehci1_set_config,
+    _ehci1_ep_set_stall,
+    _ehci1_ep_clear_stall,
+    _ehci1_ep_enable,
+    _ehci1_ep_disable,
+    _ehci1_ep_read_prepare,
+    _ehci1_ep_read,
+    _ehci1_ep_write,
+    _ehci1_ep0_send_status,
+    _ehci1_suspend,
+    _ehci1_wakeup,
+};
+static rt_err_t drv_ehci1_usbd_init(rt_device_t device)
+{
+    usb_status_t result;
+    USB_DeviceClockInit(kUSB_ControllerEhci1);
+    
+    result = USB_DeviceInit(kUSB_ControllerEhci1,usb_device_callback,&ehci1_handle);
+    RT_ASSERT(ehci1_handle);
+    if(result == kStatus_USB_Success)
+    {
+        USB_DeviceIsrEnable(kUSB_ControllerEhci1);
+        USB_DeviceRun(ehci1_handle);
+    }
+    else
+    {
+        rt_kprintf("USB_DeviceInit ehci1 error\r\n");
+        return RT_ERROR;
+    }
+    return RT_EOK;
+}
+#endif
+
+
+
+#if defined(RT_USING_EHCI0_AS_DEVICE) && defined(RT_USING_EHCI1_AS_DEVICE)
+#error Can not using both now 
+#endif
+static int rt_usbd_init(void)
+{
+    #ifdef RT_USING_EHCI0_AS_DEVICE
+    rt_memset((void *)&_fsl_udc_0, 0, sizeof(struct udcd));
+    _fsl_udc_0.parent.type = RT_Device_Class_USBDevice;
+    _fsl_udc_0.parent.init = drv_ehci0_usbd_init;
+    _fsl_udc_0.ops = &_ehci0_udc_ops;
+    /* Register endpoint infomation */
+    _fsl_udc_0.ep_pool = _ehci0_ep_pool;
+    _fsl_udc_0.ep0.id = &_ehci0_ep_pool[0];
+    rt_device_register((rt_device_t)&_fsl_udc_0, "usbd", 0);
+    rt_usb_device_init();
+    #endif
+    #ifdef RT_USING_EHCI1_AS_DEVICE
+    rt_memset((void *)&_fsl_udc_1, 0, sizeof(struct udcd));
+    _fsl_udc_1.parent.type = RT_Device_Class_USBDevice;
+    _fsl_udc_1.parent.init = drv_ehci1_usbd_init;
+    _fsl_udc_1.ops = &_ehci1_udc_ops;
+    /* Register endpoint infomation */
+    _fsl_udc_1.ep_pool = _ehci1_ep_pool;
+    _fsl_udc_1.ep0.id = &_ehci1_ep_pool[0];
+    rt_device_register((rt_device_t)&_fsl_udc_1, "usbd", 0);
+    rt_usb_device_init();
+    #endif
+    return 0;
+}
+INIT_DEVICE_EXPORT(rt_usbd_init);
+static usb_status_t usb_device_endpoint_callback(usb_device_handle handle, usb_device_endpoint_callback_message_struct_t *message, void *callbackParam)
+{
+    rt_uint32_t ep_addr = (rt_uint32_t)callbackParam;
+    usb_device_struct_t *deviceHandle = (usb_device_struct_t *)handle;
+    udcd_t udcd = RT_NULL;
+    uint8_t state;
+    if(deviceHandle->controllerId == kUSB_ControllerEhci0)
+    {
+        #ifdef RT_USING_EHCI0_AS_DEVICE
+        udcd = &_fsl_udc_0;
+        #endif
+    }
+    else
+    {
+        #ifdef RT_USING_EHCI1_AS_DEVICE
+        udcd = &_fsl_udc_1;
+        #endif
+    }
+    if(message->isSetup)
+    {
+        rt_usbd_ep0_setup_handler(udcd, (struct urequest*)message->buffer);
+    }
+    else if(ep_addr == 0x00)
+    {
+        USB_DeviceGetStatus(handle, kUSB_DeviceStatusDeviceState, &state);
+        if(state == kUSB_DeviceStateAddressing)
+        {
+            if (kStatus_USB_Success == USB_DeviceSetStatus(handle, kUSB_DeviceStatusAddress, NULL))
+            {
+                state = kUSB_DeviceStateAddress;
+                USB_DeviceSetStatus(handle, kUSB_DeviceStatusDeviceState, &state);
+            }
+        }
+        rt_usbd_ep0_out_handler(udcd,message->length);
+    }
+    else if(ep_addr == 0x80)
+    {
+        USB_DeviceGetStatus(handle, kUSB_DeviceStatusDeviceState, &state);
+        if(state == kUSB_DeviceStateAddressing)
+        {
+            if (kStatus_USB_Success == USB_DeviceSetStatus(handle, kUSB_DeviceStatusAddress, NULL))
+            {
+                state = kUSB_DeviceStateAddress;
+                USB_DeviceSetStatus(handle, kUSB_DeviceStatusDeviceState, &state);
+            }
+        }
+        rt_usbd_ep0_in_handler(udcd);
+    }
+    else if(ep_addr&0x80)
+    {
+        rt_usbd_ep_in_handler(udcd, ep_addr, message->length);
+    }
+    else
+    {
+        rt_usbd_ep_out_handler(udcd, ep_addr, message->length);
+    }
+    return kStatus_USB_Success;
+}
+static usb_status_t usb_device_callback(usb_device_handle handle, uint32_t callbackEvent, void *eventParam)
+{
+    usb_status_t error = kStatus_USB_Error;
+    usb_device_struct_t *deviceHandle = (usb_device_struct_t *)handle;
+    usb_device_endpoint_init_struct_t ep0_init = 
+    {
+        0x40,
+        0x00,
+        USB_EP_ATTR_CONTROL,
+        0
+    };
+    usb_device_endpoint_callback_struct_t ep0_callback = 
+    {
+        usb_device_endpoint_callback,
+        0,
+        0
+    };
+    udcd_t udcd = RT_NULL;
+    if(deviceHandle->controllerId == kUSB_ControllerEhci0)
+    {
+        #ifdef RT_USING_EHCI0_AS_DEVICE
+        udcd = &_fsl_udc_0;
+        #endif
+    }
+    else
+    {
+        #ifdef RT_USING_EHCI1_AS_DEVICE
+        udcd = &_fsl_udc_1;
+        #endif
+    }
+    switch (callbackEvent)
+    {
+    case kUSB_DeviceEventBusReset:
+        ep0_init.endpointAddress = 0x00;
+        ep0_callback.callbackParam = (void *)0x00;
+        USB_DeviceInitEndpoint(deviceHandle,&ep0_init,&ep0_callback);
+        ep0_init.endpointAddress = 0x80;
+        ep0_callback.callbackParam = (void *)0x80;
+        USB_DeviceInitEndpoint(deviceHandle,&ep0_init,&ep0_callback);
+        rt_usbd_reset_handler(udcd);
+        break;
+    case kUSB_DeviceEventAttach:
+        rt_usbd_connect_handler(udcd);
+        break;
+    case kUSB_DeviceEventDetach:
+        rt_usbd_disconnect_handler(udcd);
+        break;
+    }
+    return error;
+}
+
+
+

+ 644 - 0
bsp/imxrt1052-evk/drivers/usb/device/usb_device.h

@@ -0,0 +1,644 @@
+/*
+ * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
+ * Copyright 2016 NXP
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright notice, this list
+ *   of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright notice, this
+ *   list of conditions and the following disclaimer in the documentation and/or
+ *   other materials provided with the distribution.
+ *
+ * o Neither the name of the copyright holder nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __FSL_USB_DEVICE_H__
+#define __FSL_USB_DEVICE_H__
+
+/*!
+ * @addtogroup usb_device_driver
+ * @{
+ */
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/*! @brief Defines Get/Set status Types */
+typedef enum _usb_device_status
+{
+    kUSB_DeviceStatusTestMode = 1U,  /*!< Test mode */
+    kUSB_DeviceStatusSpeed,          /*!< Current speed */
+    kUSB_DeviceStatusOtg,            /*!< OTG status */
+    kUSB_DeviceStatusDevice,         /*!< Device status */
+    kUSB_DeviceStatusEndpoint,       /*!< Endpoint state usb_device_endpoint_status_t */
+    kUSB_DeviceStatusDeviceState,    /*!< Device state */
+    kUSB_DeviceStatusAddress,        /*!< Device address */
+    kUSB_DeviceStatusSynchFrame,     /*!< Current frame */
+    kUSB_DeviceStatusBus,            /*!< Bus status */
+    kUSB_DeviceStatusBusSuspend,     /*!< Bus suspend */
+    kUSB_DeviceStatusBusSleep,       /*!< Bus suspend */
+    kUSB_DeviceStatusBusResume,      /*!< Bus resume */
+    kUSB_DeviceStatusRemoteWakeup,   /*!< Remote wakeup state */
+    kUSB_DeviceStatusBusSleepResume, /*!< Bus resume */
+} usb_device_status_t;
+
+/*! @brief Defines USB 2.0 device state */
+typedef enum _usb_device_state
+{
+    kUSB_DeviceStateConfigured = 0U, /*!< Device state, Configured*/
+    kUSB_DeviceStateAddress,         /*!< Device state, Address*/
+    kUSB_DeviceStateDefault,         /*!< Device state, Default*/
+    kUSB_DeviceStateAddressing,      /*!< Device state, Address setting*/
+    kUSB_DeviceStateTestMode,        /*!< Device state, Test mode*/
+} usb_device_state_t;
+
+#if (defined(USB_DEVICE_CHARGER_DETECT_ENABLE) && (USB_DEVICE_CHARGER_DETECT_ENABLE > 0U))
+typedef enum _usb_dcd_detection_sequence_status
+{
+    kUSB_DcdDetectionNotEnabled = 0x0U,
+    kUSB_DcdDataPinDetectionCompleted = 0x01U,
+    kUSB_DcdChargingPortDetectionCompleted = 0x02U,
+    kUSB_DcdChargerTypeDetectionCompleted = 0x03U,
+} usb_dcd_detection_sequence_status_t;
+
+typedef enum _usb_dcd_detection_sequence_results
+{
+    kUSB_DcdDetectionNoResults = 0x0U,
+    kUSB_DcdDetectionStandardHost = 0x01U,
+    kUSB_DcdDetectionChargingPort = 0x02U,
+    kUSB_DcdDetectionDedicatedCharger = 0x03U,
+} usb_dcd_detection_sequence_results_t;
+#endif
+
+/*! @brief Defines endpoint state */
+typedef enum _usb_endpoint_status
+{
+    kUSB_DeviceEndpointStateIdle = 0U, /*!< Endpoint state, idle*/
+    kUSB_DeviceEndpointStateStalled,   /*!< Endpoint state, stalled*/
+} usb_device_endpoint_status_t;
+
+/*! @brief Control endpoint index */
+#define USB_CONTROL_ENDPOINT (0U)
+/*! @brief Control endpoint maxPacketSize */
+#define USB_CONTROL_MAX_PACKET_SIZE (64U)
+
+#if (USB_DEVICE_CONFIG_EHCI && (USB_CONTROL_MAX_PACKET_SIZE != (64U)))
+#error For high speed, USB_CONTROL_MAX_PACKET_SIZE must be 64!!!
+#endif
+
+/*! @brief The setup packet size of USB control transfer. */
+#define USB_SETUP_PACKET_SIZE (8U)
+/*! @brief  USB endpoint mask */
+#define USB_ENDPOINT_NUMBER_MASK (0x0FU)
+
+/*! @brief Default invalid value or the endpoint callback length of cancelled transfer */
+#define USB_UNINITIALIZED_VAL_32 (0xFFFFFFFFU)
+
+/*! @brief Available common EVENT types in device callback */
+typedef enum _usb_device_event
+{
+    kUSB_DeviceEventBusReset = 1U, /*!< USB bus reset signal detected */
+    kUSB_DeviceEventSuspend,       /*!< USB bus suspend signal detected */
+    kUSB_DeviceEventResume,    /*!< USB bus resume signal detected. The resume signal is driven by itself or a host */
+    kUSB_DeviceEventSleeped,   /*!< USB bus LPM suspend signal detected */
+    kUSB_DeviceEventLPMResume, /*!< USB bus LPM resume signal detected. The resume signal is driven by itself or a host
+                                  */
+    kUSB_DeviceEventError,     /*!< An error is happened in the bus. */
+    kUSB_DeviceEventDetach,    /*!< USB device is disconnected from a host. */
+    kUSB_DeviceEventAttach,    /*!< USB device is connected to a host. */
+    kUSB_DeviceEventSetConfiguration, /*!< Set configuration. */
+    kUSB_DeviceEventSetInterface,     /*!< Set interface. */
+
+    kUSB_DeviceEventGetDeviceDescriptor,          /*!< Get device descriptor. */
+    kUSB_DeviceEventGetConfigurationDescriptor,   /*!< Get configuration descriptor. */
+    kUSB_DeviceEventGetStringDescriptor,          /*!< Get string descriptor. */
+    kUSB_DeviceEventGetHidDescriptor,             /*!< Get HID descriptor. */
+    kUSB_DeviceEventGetHidReportDescriptor,       /*!< Get HID report descriptor. */
+    kUSB_DeviceEventGetHidPhysicalDescriptor,     /*!< Get HID physical descriptor. */
+    kUSB_DeviceEventGetBOSDescriptor,             /*!< Get configuration descriptor. */
+    kUSB_DeviceEventGetDeviceQualifierDescriptor, /*!< Get device qualifier descriptor. */
+    kUSB_DeviceEventVendorRequest,                /*!< Vendor request. */
+    kUSB_DeviceEventSetRemoteWakeup,              /*!< Enable or disable remote wakeup function. */
+    kUSB_DeviceEventGetConfiguration,             /*!< Get current configuration index */
+    kUSB_DeviceEventGetInterface,                 /*!< Get current interface alternate setting value */
+    kUSB_DeviceEventSetBHNPEnable,
+#if (defined(USB_DEVICE_CHARGER_DETECT_ENABLE) && (USB_DEVICE_CHARGER_DETECT_ENABLE > 0U))
+    kUSB_DeviceEventDcdTimeOut,               /*!< Dcd detect result is timeout */
+    kUSB_DeviceEventDcdUnknownType,           /*!< Dcd detect result is unknown type */
+    kUSB_DeviceEventSDPDetected,              /*!< The SDP facility is detected */
+    kUSB_DeviceEventChargingPortDetected,     /*!< The charging port is detected */
+    kUSB_DeviceEventChargingHostDetected,     /*!< The CDP facility is detected */
+    kUSB_DeviceEventDedicatedChargerDetected, /*!< The DCP facility is detected */
+#endif
+} usb_device_event_t;
+
+/*! @brief Endpoint callback message structure */
+typedef struct _usb_device_endpoint_callback_message_struct
+{
+    uint8_t *buffer; /*!< Transferred buffer */
+    uint32_t length; /*!< Transferred data length */
+    uint8_t isSetup; /*!< Is in a setup phase */
+} usb_device_endpoint_callback_message_struct_t;
+
+/*!
+ * @brief Endpoint callback function typedef.
+ *
+ * This callback function is used to notify the upper layer what the transfer result is.
+ * This callback pointer is passed when a specified endpoint is initialized by calling API #USB_DeviceInitEndpoint.
+ *
+ * @param handle          The device handle. It equals to the value returned from #USB_DeviceInit.
+ * @param message         The result of a transfer, which includes transfer buffer, transfer length, and whether is in a
+ * setup phase.
+ * phase for control pipe.
+ * @param callbackParam  The parameter for this callback. It is same with
+ * usb_device_endpoint_callback_struct_t::callbackParam.
+ *
+ * @return A USB error code or kStatus_USB_Success.
+ */
+typedef usb_status_t (*usb_device_endpoint_callback_t)(usb_device_handle handle,
+                                                       usb_device_endpoint_callback_message_struct_t *message,
+                                                       void *callbackParam);
+
+/*!
+ * @brief Device callback function typedef.
+ *
+ * This callback function is used to notify the upper layer that the device status has changed.
+ * This callback pointer is passed by calling API #USB_DeviceInit.
+ *
+ * @param handle          The device handle. It equals the value returned from #USB_DeviceInit.
+ * @param callbackEvent  The callback event type. See enumeration #usb_device_event_t.
+ * @param eventParam     The event parameter for this callback. The parameter type is determined by the callback event.
+ *
+ * @return A USB error code or kStatus_USB_Success.
+ */
+typedef usb_status_t (*usb_device_callback_t)(usb_device_handle handle, uint32_t callbackEvent, void *eventParam);
+
+/*! @brief Endpoint callback structure */
+typedef struct _usb_device_endpoint_callback_struct
+{
+    usb_device_endpoint_callback_t callbackFn; /*!< Endpoint callback function*/
+    void *callbackParam;                       /*!< Parameter for callback function*/
+    uint8_t isBusy;
+} usb_device_endpoint_callback_struct_t;
+
+/*! @brief Endpoint initialization structure */
+typedef struct _usb_device_endpoint_init_struct
+{
+    uint16_t maxPacketSize;  /*!< Endpoint maximum packet size */
+    uint8_t endpointAddress; /*!< Endpoint address*/
+    uint8_t transferType;    /*!< Endpoint transfer type*/
+    uint8_t zlt;             /*!< ZLT flag*/
+} usb_device_endpoint_init_struct_t;
+
+/*! @brief Endpoint status structure */
+typedef struct _usb_device_endpoint_status_struct
+{
+    uint8_t endpointAddress; /*!< Endpoint address */
+    uint16_t endpointStatus; /*!< Endpoint status : idle or stalled */
+} usb_device_endpoint_status_struct_t;
+
+#if (defined(USB_DEVICE_CHARGER_DETECT_ENABLE) && (USB_DEVICE_CHARGER_DETECT_ENABLE > 0U))
+/*! @brief USB DCD charge timing specification structure */
+typedef struct _usb_device_dcd_charging_time
+{
+    uint16_t dcdSeqInitTime;      /*!< The dcd sequence init time */
+    uint16_t dcdDbncTime;         /*!< The debounce time period on DP signal */
+    uint16_t dcdDpSrcOnTime;      /*!< The time period comparator enabled */
+    uint16_t dcdTimeWaitAfterPrD; /*!< The time period between primary and secondary detection */
+    uint8_t dcdTimeDMSrcOn;       /*!< The amount of time that the modules enable the Vdm_src */
+} usb_device_dcd_charging_time_t;
+#endif
+
+#if defined(__cplusplus)
+extern "C" {
+#endif /* __cplusplus*/
+
+/*!
+ * @name USB device APIs
+ * @{
+ */
+
+/*******************************************************************************
+ * API
+ ******************************************************************************/
+
+/*!
+ * @brief Initializes the USB device stack.
+ *
+ * This function initializes the USB device module specified by the controllerId.
+ *
+ * @param[in] controllerId   The controller ID of the USB IP. See the enumeration #usb_controller_index_t.
+ * @param[in] deviceCallback Function pointer of the device callback.
+ * @param[out] handle          It is an out parameter used to return the pointer of the device handle to the caller.
+ *
+ * @retval kStatus_USB_Success              The device is initialized successfully.
+ * @retval kStatus_USB_InvalidHandle        The handle is a NULL pointer.
+ * @retval kStatus_USB_Busy                 Cannot allocate a device handle.
+ * @retval kStatus_USB_ControllerNotFound   Cannot find the controller according to the controller id.
+ * @retval kStatus_USB_InvalidControllerInterface  The controller driver interfaces is invalid. There is an empty
+ * 													interface entity.
+ * @retval kStatus_USB_Error                The macro USB_DEVICE_CONFIG_ENDPOINTS is more than the IP's endpoint number.
+ *                                          Or, the device has been initialized.
+ *                                          Or, the mutex or message queue is created failed.
+ */
+extern usb_status_t USB_DeviceInit(uint8_t controllerId,
+                                   usb_device_callback_t deviceCallback,
+                                   usb_device_handle *handle);
+
+/*!
+ * @brief Enables the device functionality.
+ *
+ * The function enables the device functionality, so that the device can be recognized by the host when the device
+ * detects that it has been connected to a host.
+ *
+ * @param[in] handle The device handle got from #USB_DeviceInit.
+ *
+ * @retval kStatus_USB_Success              The device is run successfully.
+ * @retval kStatus_USB_ControllerNotFound   Cannot find the controller.
+ * @retval kStatus_USB_InvalidHandle        The device handle is a NULL pointer. Or the controller handle is invalid.
+ *
+ */
+extern usb_status_t USB_DeviceRun(usb_device_handle handle);
+
+/*!
+ * @brief Disables the device functionality.
+ *
+ * The function disables the device functionality. After this function called, even if the device is detached to the
+ * host,
+ * it can't work.
+ *
+ * @param[in] handle The device handle received from #USB_DeviceInit.
+ *
+ * @retval kStatus_USB_Success              The device is stopped successfully.
+ * @retval kStatus_USB_ControllerNotFound   Cannot find the controller.
+ * @retval kStatus_USB_InvalidHandle        The device handle is a NULL pointer or the controller handle is invalid.
+ */
+extern usb_status_t USB_DeviceStop(usb_device_handle handle);
+
+/*!
+ * @brief De-initializes the device controller.
+ *
+ * The function de-initializes the device controller specified by the handle.
+ *
+ * @param[in] handle The device handle got from #USB_DeviceInit.
+ *
+ * @retval kStatus_USB_Success              The device is stopped successfully.
+ * @retval kStatus_USB_InvalidHandle        The device handle is a NULL pointer or the controller handle is invalid.
+ */
+extern usb_status_t USB_DeviceDeinit(usb_device_handle handle);
+
+/*!
+ * @brief Sends data through a specified endpoint.
+ *
+ * The function is used to send data through a specified endpoint.
+ *
+ * @param[in] handle The device handle got from #USB_DeviceInit.
+ * @param[in] endpointAddress Endpoint index.
+ * @param[in] buffer The memory address to hold the data need to be sent. The function is not reentrant.
+ * @param[in] length The data length need to be sent.
+ *
+ * @retval kStatus_USB_Success              The send request is sent successfully.
+ * @retval kStatus_USB_InvalidHandle        The handle is a NULL pointer. Or the controller handle is invalid.
+ * @retval kStatus_USB_Busy                 Cannot allocate DTDS for current transfer in EHCI driver.
+ * @retval kStatus_USB_ControllerNotFound   Cannot find the controller.
+ * @retval kStatus_USB_Error                The device is doing reset.
+ *
+ * @note The return value indicates whether the sending request is successful or not. The transfer done is notified by
+ * the
+ * corresponding callback function.
+ * Currently, only one transfer request can be supported for one specific endpoint.
+ * If there is a specific requirement to support multiple transfer requests for one specific endpoint, the application
+ * should implement a queue on the application level.
+ * The subsequent transfer can begin only when the previous transfer is done (get notification through the endpoint
+ * callback).
+ */
+extern usb_status_t USB_DeviceSendRequest(usb_device_handle handle,
+                                          uint8_t endpointAddress,
+                                          uint8_t *buffer,
+                                          uint32_t length);
+
+/*!
+ * @brief Receives data through a specified endpoint.
+ *
+ * The function is used to receive data through a specified endpoint. The function is not reentrant.
+ *
+ * @param[in] handle The device handle got from #USB_DeviceInit.
+ * @param[in] endpointAddress Endpoint index.
+ * @param[in] buffer The memory address to save the received data.
+ * @param[in] length The data length want to be received.
+ *
+ * @retval kStatus_USB_Success              The receive request is sent successfully.
+ * @retval kStatus_USB_InvalidHandle        The handle is a NULL pointer. Or the controller handle is invalid.
+ * @retval kStatus_USB_Busy                 Cannot allocate DTDS for current transfer in EHCI driver.
+ * @retval kStatus_USB_ControllerNotFound   Cannot find the controller.
+ * @retval kStatus_USB_Error                The device is doing reset.
+ *
+ * @note The return value indicates whether the receiving request is successful or not. The transfer done is notified by
+ * the
+ * corresponding callback function.
+ * Currently, only one transfer request can be supported for one specific endpoint.
+ * If there is a specific requirement to support multiple transfer requests for one specific endpoint, the application
+ * should implement a queue on the application level.
+ * The subsequent transfer can begin only when the previous transfer is done (get notification through the endpoint
+ * callback).
+ */
+extern usb_status_t USB_DeviceRecvRequest(usb_device_handle handle,
+                                          uint8_t endpointAddress,
+                                          uint8_t *buffer,
+                                          uint32_t length);
+
+/*!
+ * @brief Cancels the pending transfer in a specified endpoint.
+ *
+ * The function is used to cancel the pending transfer in a specified endpoint.
+ *
+ * @param[in] handle The device handle got from #USB_DeviceInit.
+ * @param[in] endpointAddress Endpoint address, bit7 is the direction of endpoint, 1U - IN, and 0U - OUT.
+ *
+ * @retval kStatus_USB_Success              The transfer is cancelled.
+ * @retval kStatus_USB_InvalidHandle        The handle is a NULL pointer or the controller handle is invalid.
+ * @retval kStatus_USB_ControllerNotFound   Cannot find the controller.
+ */
+extern usb_status_t USB_DeviceCancel(usb_device_handle handle, uint8_t endpointAddress);
+
+/*!
+ * @brief Initializes a specified endpoint.
+ *
+ * The function is used to initialize a specified endpoint. The corresponding endpoint callback is also initialized.
+ *
+ * @param[in] handle The device handle received from #USB_DeviceInit.
+ * @param[in] epInit Endpoint initialization structure. See the structure usb_device_endpoint_init_struct_t.
+ * @param[in] epCallback Endpoint callback structure. See the structure
+ * usb_device_endpoint_callback_struct_t.
+ *
+ * @retval kStatus_USB_Success              The endpoint is initialized successfully.
+ * @retval kStatus_USB_InvalidHandle        The handle is a NULL pointer. Or the controller handle is invalid.
+ * @retval kStatus_USB_InvalidParameter     The epInit or epCallback is NULL pointer. Or the endpoint number is
+ * more than USB_DEVICE_CONFIG_ENDPOINTS.
+ * @retval kStatus_USB_Busy                 The endpoint is busy in EHCI driver.
+ * @retval kStatus_USB_ControllerNotFound   Cannot find the controller.
+ */
+extern usb_status_t USB_DeviceInitEndpoint(usb_device_handle handle,
+                                           usb_device_endpoint_init_struct_t *epInit,
+                                           usb_device_endpoint_callback_struct_t *epCallback);
+
+/*!
+ * @brief Deinitializes a specified endpoint.
+ *
+ * The function is used to deinitializes a specified endpoint.
+ *
+ * @param[in] handle The device handle got from #USB_DeviceInit.
+ * @param[in] endpointAddress Endpoint address, bit7 is the direction of endpoint, 1U - IN, and 0U - OUT.
+ *
+ * @retval kStatus_USB_Success              The endpoint is de-initialized successfully.
+ * @retval kStatus_USB_InvalidHandle        The handle is a NULL pointer. Or the controller handle is invalid.
+ * @retval kStatus_USB_InvalidParameter     The endpoint number is more than USB_DEVICE_CONFIG_ENDPOINTS.
+ * @retval kStatus_USB_Busy                 The endpoint is busy in EHCI driver.
+ * @retval kStatus_USB_ControllerNotFound   Cannot find the controller.
+ */
+extern usb_status_t USB_DeviceDeinitEndpoint(usb_device_handle handle, uint8_t endpointAddress);
+
+/*!
+ * @brief Stalls a specified endpoint.
+ *
+ * The function is used to stall a specified endpoint.
+ *
+ * @param[in] handle The device handle received from #USB_DeviceInit.
+ * @param[in] endpointAddress Endpoint address, bit7 is the direction of endpoint, 1U - IN, and 0U - OUT.
+ *
+ * @retval kStatus_USB_Success              The endpoint is stalled successfully.
+ * @retval kStatus_USB_InvalidHandle        The handle is a NULL pointer. Or the controller handle is invalid.
+ * @retval kStatus_USB_InvalidParameter     The endpoint number is more than USB_DEVICE_CONFIG_ENDPOINTS.
+ * @retval kStatus_USB_ControllerNotFound   Cannot find the controller.
+ */
+extern usb_status_t USB_DeviceStallEndpoint(usb_device_handle handle, uint8_t endpointAddress);
+
+/*!
+ * @brief Unstalls a specified endpoint.
+ *
+ * The function is used to unstall a specified endpoint.
+ *
+ * @param[in] handle The device handle received from #USB_DeviceInit.
+ * @param[in] endpointAddress Endpoint address, bit7 is the direction of endpoint, 1U - IN, and 0U - OUT.
+ *
+ * @retval kStatus_USB_Success              The endpoint is unstalled successfully.
+ * @retval kStatus_USB_InvalidHandle        The handle is a NULL pointer. Or the controller handle is invalid.
+ * @retval kStatus_USB_InvalidParameter     The endpoint number is more than USB_DEVICE_CONFIG_ENDPOINTS.
+ * @retval kStatus_USB_ControllerNotFound   Cannot find the controller.
+ */
+extern usb_status_t USB_DeviceUnstallEndpoint(usb_device_handle handle, uint8_t endpointAddress);
+
+/*!
+ * @brief Gets the status of the selected item.
+ *
+ * The function is used to get the status of the selected item.
+ *
+ * @param[in] handle The device handle got from #USB_DeviceInit.
+ * @param[in] type   The selected item. See the structure #usb_device_status_t.
+ * @param[out] param  The parameter type is determined by the selected item.
+ *
+ * @retval kStatus_USB_Success              Get status successfully.
+ * @retval kStatus_USB_InvalidHandle        The handle is a NULL pointer. Or the controller handle is invalid.
+ * @retval kStatus_USB_InvalidParameter     The parameter is NULL pointer.
+ * @retval kStatus_USB_ControllerNotFound   Cannot find the controller.
+ * @retval kStatus_USB_Error                Unsupported type.
+ */
+extern usb_status_t USB_DeviceGetStatus(usb_device_handle handle, usb_device_status_t type, void *param);
+
+/*!
+ * @brief Sets the status of the selected item.
+ *
+ * The function is used to set the status of the selected item.
+ *
+ * @param[in] handle The device handle got from #USB_DeviceInit.
+ * @param[in] type The selected item. See the structure #usb_device_status_t.
+ * @param[in] param The parameter type is determined by the selected item.
+ *
+ * @retval kStatus_USB_Success              Set status successfully.
+ * @retval kStatus_USB_InvalidHandle        The handle is a NULL pointer. Or the controller handle is invalid.
+ * @retval kStatus_USB_ControllerNotFound   Cannot find the controller.
+ * @retval kStatus_USB_Error                Unsupported type or the parameter is NULL pointer.
+ */
+extern usb_status_t USB_DeviceSetStatus(usb_device_handle handle, usb_device_status_t type, void *param);
+
+#if (defined(USB_DEVICE_CHARGER_DETECT_ENABLE) && (USB_DEVICE_CHARGER_DETECT_ENABLE > 0U))
+/*!
+ * @brief Initializes the device dcd module.
+ *
+ * The function initializes the device dcd module.
+ *
+ * @param[in] handle The device handle got from #USB_DeviceInit.
+ * @param[in] time_param The time parameter used to config the dcd timing registers.
+ *
+ * @retval kStatus_USB_Success              The device is run successfully.
+ * @retval kStatus_USB_ControllerNotFound   Cannot find the controller.
+ * @retval kStatus_USB_InvalidHandle        The device handle is a NULL pointer. Or the controller handle is invalid.
+ *
+ */
+extern usb_status_t USB_DeviceDcdInitModule(usb_device_handle handle, void *time_param);
+
+/*!
+ * @brief De-initializes the device dcd module.
+ *
+ * The function de-initializes the device dcd module specified by the handle.
+ *
+ * @param[in] handle The device handle got from #USB_DeviceInit.
+ *
+ * @retval kStatus_USB_Success 			 The device is stopped successfully.
+ * @retval kStatus_USB_InvalidHandle		 The device handle is a NULL pointer or the controller handle is invalid.
+ */
+extern usb_status_t USB_DeviceDcdDeinitModule(usb_device_handle handle);
+#endif
+/*!
+ * @brief Device task function.
+ *
+ * The function is used to handle the controller message.
+ * This function should not be called in the application directly.
+ *
+ * @param[in] deviceHandle The device handle got from #USB_DeviceInit.
+ */
+extern void USB_DeviceTaskFunction(void *deviceHandle);
+
+#if ((defined(USB_DEVICE_CONFIG_KHCI)) && (USB_DEVICE_CONFIG_KHCI > 0U))
+/*!
+ * @brief Device KHCI task function.
+ *
+ * The function is used to handle the KHCI controller message.
+ * In the bare metal environment, this function should be called periodically in the main function.
+ * In the RTOS environment, this function should be used as a function entry to create a task.
+ *
+ * @param[in] deviceHandle The device handle got from #USB_DeviceInit.
+ */
+#define USB_DeviceKhciTaskFunction(deviceHandle) USB_DeviceTaskFunction(deviceHandle)
+#endif
+
+#if ((defined(USB_DEVICE_CONFIG_EHCI)) && (USB_DEVICE_CONFIG_EHCI > 0U))
+/*!
+ * @brief Device EHCI task function.
+ *
+ * The function is used to handle the EHCI controller message.
+ * In the bare metal environment, this function should be called periodically in the main function.
+ * In the RTOS environment, this function should be used as a function entry to create a task.
+ *
+ * @param[in] deviceHandle The device handle got from #USB_DeviceInit.
+ */
+#define USB_DeviceEhciTaskFunction(deviceHandle) USB_DeviceTaskFunction(deviceHandle)
+#if (defined(USB_DEVICE_CHARGER_DETECT_ENABLE) && (USB_DEVICE_CHARGER_DETECT_ENABLE > 0U))
+/*!
+ * @brief Device EHCI DCD ISR function.
+ *
+ * The function is the EHCI DCD interrupt service routine.
+ *
+ * @param[in] deviceHandle The device handle got from #USB_DeviceInit.
+ */
+extern void USB_DeviceDcdHSIsrFunction(void *deviceHandle);
+#endif
+#endif
+
+#if (((defined(USB_DEVICE_CONFIG_LPCIP3511FS)) && (USB_DEVICE_CONFIG_LPCIP3511FS > 0U)) || \
+     ((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U)))
+/*!
+ * @brief Device LPC ip3511 controller task function.
+ *
+ * The function is used to handle the LPC ip3511 controller message.
+ * In the bare metal environment, this function should be called periodically in the main function.
+ * In the RTOS environment, this function should be used as a function entry to create a task.
+ *
+ * @param[in] deviceHandle The device handle got from #USB_DeviceInit.
+ */
+#define USB_DeviceLpcIp3511TaskFunction(deviceHandle) USB_DeviceTaskFunction(deviceHandle)
+#endif
+
+#if ((defined(USB_DEVICE_CONFIG_KHCI)) && (USB_DEVICE_CONFIG_KHCI > 0U))
+/*!
+ * @brief Device KHCI ISR function.
+ *
+ * The function is the KHCI interrupt service routine.
+ *
+ * @param[in] deviceHandle The device handle got from #USB_DeviceInit.
+ */
+extern void USB_DeviceKhciIsrFunction(void *deviceHandle);
+#if (defined(USB_DEVICE_CHARGER_DETECT_ENABLE) && (USB_DEVICE_CHARGER_DETECT_ENABLE > 0U))
+/*!
+ * @brief Device KHCI DCD ISR function.
+ *
+ * The function is the KHCI DCD interrupt service routine.
+ *
+ * @param[in] deviceHandle The device handle got from #USB_DeviceInit.
+ */
+extern void USB_DeviceDcdIsrFunction(void *deviceHandle);
+#endif
+#endif
+
+#if ((defined(USB_DEVICE_CONFIG_EHCI)) && (USB_DEVICE_CONFIG_EHCI > 0U))
+/*!
+ * @brief Device EHCI ISR function.
+ *
+ * The function is the EHCI interrupt service routine.
+ *
+ * @param[in] deviceHandle The device handle got from #USB_DeviceInit.
+ */
+extern void USB_DeviceEhciIsrFunction(void *deviceHandle);
+#endif
+
+#if (((defined(USB_DEVICE_CONFIG_LPCIP3511FS)) && (USB_DEVICE_CONFIG_LPCIP3511FS > 0U)) || \
+     ((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U)))
+/*!
+ * @brief Device LPC USB ISR function.
+ *
+ * The function is the LPC USB interrupt service routine.
+ *
+ * @param[in] deviceHandle The device handle got from #USB_DeviceInit.
+ */
+extern void USB_DeviceLpcIp3511IsrFunction(void *deviceHandle);
+#endif
+
+/*!
+ * @brief Gets the device stack version function.
+ *
+ * The function is used to get the device stack version.
+ *
+ * @param[out] version The version structure pointer to keep the device stack version.
+ *
+ */
+extern void USB_DeviceGetVersion(uint32_t *version);
+
+#if ((defined(USB_DEVICE_CONFIG_REMOTE_WAKEUP)) && (USB_DEVICE_CONFIG_REMOTE_WAKEUP > 0U))
+/*!
+ * @brief Update the hardware tick.
+ *
+ * The function is used to update the hardware tick.
+ *
+ * @param[in] handle The device handle got from #USB_DeviceInit.
+ * @param[in] tick Current hardware tick(uint is ms).
+ *
+ */
+extern usb_status_t USB_DeviceUpdateHwTick(usb_device_handle handle, uint64_t tick);
+#endif
+
+/*! @}*/
+
+#if defined(__cplusplus)
+}
+#endif /* __cplusplus*/
+
+/*! @}*/
+
+#endif /* __USB_DEVICE_H__ */

+ 1459 - 0
bsp/imxrt1052-evk/drivers/usb/device/usb_device_dci.c

@@ -0,0 +1,1459 @@
+/*
+ * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
+ * Copyright 2016 - 2017 NXP
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright notice, this list
+ *   of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright notice, this
+ *   list of conditions and the following disclaimer in the documentation and/or
+ *   other materials provided with the distribution.
+ *
+ * o Neither the name of the copyright holder nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <usb/include/usb_device_config.h>
+#include <usb/include/usb.h>
+
+#include "usb_device.h"
+#include "usb_device_dci.h"
+
+#include "fsl_device_registers.h"
+
+#if ((defined(USB_DEVICE_CONFIG_NUM)) && (USB_DEVICE_CONFIG_NUM > 0U))
+
+#if ((defined(USB_DEVICE_CONFIG_KHCI)) && (USB_DEVICE_CONFIG_KHCI > 0U))
+#include "usb_device_khci.h"
+#endif
+
+#if ((defined(USB_DEVICE_CONFIG_EHCI)) && (USB_DEVICE_CONFIG_EHCI > 0U))
+#include "usb_device_ehci.h"
+#endif
+
+#if (((defined(USB_DEVICE_CONFIG_LPCIP3511FS)) && (USB_DEVICE_CONFIG_LPCIP3511FS > 0U)) || \
+     ((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U)))
+#include "usb_device_lpcip3511.h"
+#endif
+
+#if (defined(USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE) && (USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE > 0U))
+#include "fsl_cache.h"
+#endif
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/*******************************************************************************
+ * Prototypes
+ ******************************************************************************/
+static usb_status_t USB_DeviceAllocateHandle(uint8_t controllerId, usb_device_struct_t **handle);
+static usb_status_t USB_DeviceFreeHandle(usb_device_struct_t *handle);
+static usb_status_t USB_DeviceGetControllerInterface(
+    uint8_t controllerId, const usb_device_controller_interface_struct_t **controllerInterface);
+static usb_status_t USB_DeviceTransfer(usb_device_handle handle,
+                                       uint8_t endpointAddress,
+                                       uint8_t *buffer,
+                                       uint32_t length);
+static usb_status_t USB_DeviceControl(usb_device_handle handle, usb_device_control_type_t type, void *param);
+static usb_status_t USB_DeviceResetNotification(usb_device_struct_t *handle,
+                                                usb_device_callback_message_struct_t *message);
+#if (defined(USB_DEVICE_CONFIG_LOW_POWER_MODE) && (USB_DEVICE_CONFIG_LOW_POWER_MODE > 0U))
+static usb_status_t USB_DeviceSuspendNotification(usb_device_struct_t *handle,
+                                                  usb_device_callback_message_struct_t *message);
+static usb_status_t USB_DeviceResumeNotification(usb_device_struct_t *handle,
+                                                 usb_device_callback_message_struct_t *message);
+#if (defined(USB_DEVICE_CONFIG_LPM_L1) && (USB_DEVICE_CONFIG_LPM_L1 > 0U))
+static usb_status_t USB_DeviceSleepNotification(usb_device_struct_t *handle,
+                                                usb_device_callback_message_struct_t *message);
+
+#endif
+#endif /* USB_DEVICE_CONFIG_LOW_POWER_MODE */
+#if (defined(USB_DEVICE_CONFIG_DETACH_ENABLE) && (USB_DEVICE_CONFIG_DETACH_ENABLE > 0U))
+static usb_status_t USB_DeviceDetachNotification(usb_device_struct_t *handle,
+                                                 usb_device_callback_message_struct_t *message);
+static usb_status_t USB_DeviceAttachNotification(usb_device_struct_t *handle,
+                                                 usb_device_callback_message_struct_t *message);
+#endif
+static usb_status_t USB_DeviceNotification(usb_device_struct_t *handle, usb_device_callback_message_struct_t *message);
+
+/*******************************************************************************
+ * Variables
+ ******************************************************************************/
+
+USB_GLOBAL static usb_device_struct_t s_UsbDevice[USB_DEVICE_CONFIG_NUM];
+
+/*******************************************************************************
+ * Code
+ ******************************************************************************/
+
+/*!
+ * @brief Allocate a device handle.
+ *
+ * This function allocates a device handle.
+ *
+ * @param controllerId   The controller id of the USB IP. Please refer to the enumeration usb_controller_index_t.
+ * @param handle          It is out parameter, is used to return pointer of the device handle to the caller.
+ *
+ * @retval kStatus_USB_Success              Get a device handle successfully.
+ * @retval kStatus_USB_Busy                 Cannot allocate a device handle.
+ * @retval kStatus_USB_Error                The device has been initialized.
+ */
+static usb_status_t USB_DeviceAllocateHandle(uint8_t controllerId, usb_device_struct_t **handle)
+{
+    uint32_t count;
+    USB_OSA_SR_ALLOC();
+
+    USB_OSA_ENTER_CRITICAL();
+    /* Check the controller is initialized or not. */
+    for (count = 0U; count < USB_DEVICE_CONFIG_NUM; count++)
+    {
+        if ((NULL != s_UsbDevice[count].controllerHandle) && (controllerId == s_UsbDevice[count].controllerId))
+        {
+            USB_OSA_EXIT_CRITICAL();
+            return kStatus_USB_Error;
+        }
+    }
+    /* Get a free device handle. */
+    for (count = 0U; count < USB_DEVICE_CONFIG_NUM; count++)
+    {
+        if (NULL == s_UsbDevice[count].controllerHandle)
+        {
+            s_UsbDevice[count].controllerId = controllerId;
+            *handle = &s_UsbDevice[count];
+            USB_OSA_EXIT_CRITICAL();
+            return kStatus_USB_Success;
+        }
+    }
+    USB_OSA_EXIT_CRITICAL();
+    return kStatus_USB_Busy;
+}
+
+/*!
+ * @brief Free a device handle.
+ *
+ * This function frees a device handle.
+ *
+ * @param handle          The device handle.
+ *
+ * @retval kStatus_USB_Success              Free device handle successfully.
+ */
+static usb_status_t USB_DeviceFreeHandle(usb_device_struct_t *handle)
+{
+    USB_OSA_SR_ALLOC();
+
+    USB_OSA_ENTER_CRITICAL();
+    handle->controllerHandle = NULL;
+    handle->controllerId = 0U;
+    USB_OSA_EXIT_CRITICAL();
+    return kStatus_USB_Success;
+}
+
+#if ((defined(USB_DEVICE_CONFIG_KHCI)) && (USB_DEVICE_CONFIG_KHCI > 0U))
+/* KHCI device driver interface */
+static const usb_device_controller_interface_struct_t s_UsbDeviceKhciInterface = {
+    USB_DeviceKhciInit, USB_DeviceKhciDeinit, USB_DeviceKhciSend,
+    USB_DeviceKhciRecv, USB_DeviceKhciCancel, USB_DeviceKhciControl};
+#endif
+
+#if ((defined(USB_DEVICE_CONFIG_EHCI)) && (USB_DEVICE_CONFIG_EHCI > 0U))
+/* EHCI device driver interface */
+static const usb_device_controller_interface_struct_t s_UsbDeviceEhciInterface = {
+    USB_DeviceEhciInit, USB_DeviceEhciDeinit, USB_DeviceEhciSend,
+    USB_DeviceEhciRecv, USB_DeviceEhciCancel, USB_DeviceEhciControl};
+#endif
+
+#if (((defined(USB_DEVICE_CONFIG_LPCIP3511FS)) && (USB_DEVICE_CONFIG_LPCIP3511FS > 0U)) || \
+     ((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U)))
+/* EHCI device driver interface */
+static const usb_device_controller_interface_struct_t s_UsbDeviceLpc3511IpInterface = {
+    USB_DeviceLpc3511IpInit, USB_DeviceLpc3511IpDeinit, USB_DeviceLpc3511IpSend,
+    USB_DeviceLpc3511IpRecv, USB_DeviceLpc3511IpCancel, USB_DeviceLpc3511IpControl};
+#endif
+
+/*!
+ * @brief Get the controller interface handle.
+ *
+ * This function is used to get the controller interface handle.
+ *
+ * @param controllerId          The controller id of the USB IP. Please refer to the enumeration usb_controller_index_t.
+ * @param controllerInterface   It is out parameter, is used to return pointer of the device controller handle to the
+ * caller.
+ *
+ * @retval kStatus_USB_Success              Get a device handle successfully.
+ * @retval kStatus_USB_ControllerNotFound   The controller id is invalided.
+ */
+static usb_status_t USB_DeviceGetControllerInterface(
+    uint8_t controllerId, const usb_device_controller_interface_struct_t **controllerInterface)
+{
+    usb_status_t error = kStatus_USB_ControllerNotFound;
+    switch (controllerId)
+    {
+#if ((defined(USB_DEVICE_CONFIG_KHCI)) && (USB_DEVICE_CONFIG_KHCI > 0U))
+        /* Get the KHCI controller driver interface */
+        case kUSB_ControllerKhci0:
+        case kUSB_ControllerKhci1:
+            *controllerInterface = (const usb_device_controller_interface_struct_t *)&s_UsbDeviceKhciInterface;
+            error = kStatus_USB_Success;
+            break;
+#endif
+#if ((defined(USB_DEVICE_CONFIG_EHCI)) && (USB_DEVICE_CONFIG_EHCI > 0U))
+        /* Get the EHCI controller driver interface */
+        case kUSB_ControllerEhci0:
+        case kUSB_ControllerEhci1:
+            error = kStatus_USB_Success;
+            *controllerInterface = (const usb_device_controller_interface_struct_t *)&s_UsbDeviceEhciInterface;
+            break;
+#endif
+#if (((defined(USB_DEVICE_CONFIG_LPCIP3511FS)) && (USB_DEVICE_CONFIG_LPCIP3511FS > 0U)) || \
+     ((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U)))
+        /* Get the EHCI controller driver interface */
+        case kUSB_ControllerLpcIp3511Fs0:
+        case kUSB_ControllerLpcIp3511Fs1:
+        case kUSB_ControllerLpcIp3511Hs0:
+        case kUSB_ControllerLpcIp3511Hs1:
+            error = kStatus_USB_Success;
+            *controllerInterface = (const usb_device_controller_interface_struct_t *)&s_UsbDeviceLpc3511IpInterface;
+            break;
+#endif
+        default:
+            break;
+    }
+    return error;
+}
+
+/*!
+ * @brief Start a new transfer.
+ *
+ * This function is used to start a new transfer.
+ *
+ * @param handle                 The device handle. It equals the value returned from USB_DeviceInit.
+ * @param endpointAddress       Endpoint address. Bit7 is direction, 0U - USB_OUT, 1U - USB_IN.
+ * @param buffer                 The memory address to be transferred, or the memory address to hold the data need to be
+ * sent.
+ * @param length                 The length of the data.
+ *
+ * @retval kStatus_USB_Success              Get a device handle successfully.
+ * @retval kStatus_USB_InvalidHandle        The device handle is invalided.
+ * @retval kStatus_USB_ControllerNotFound   The controller interface is not found.
+ * @retval kStatus_USB_Error                The device is doing reset.
+ */
+static usb_status_t USB_DeviceTransfer(usb_device_handle handle,
+                                       uint8_t endpointAddress,
+                                       uint8_t *buffer,
+                                       uint32_t length)
+{
+    usb_device_struct_t *deviceHandle = (usb_device_struct_t *)handle;
+    usb_status_t error = kStatus_USB_Error;
+    uint8_t endpoint = endpointAddress & USB_ENDPOINT_NUMBER_MASK;
+    uint8_t direction = (endpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >>
+                        USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT;
+    USB_OSA_SR_ALLOC();
+
+    if (NULL == deviceHandle)
+    {
+        return kStatus_USB_InvalidHandle;
+    }
+
+    if (NULL != deviceHandle->controllerInterface)
+    {
+        if (deviceHandle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].isBusy)
+        {
+            return kStatus_USB_Busy;
+        }
+        USB_OSA_ENTER_CRITICAL();
+        deviceHandle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].isBusy = 1U;
+        USB_OSA_EXIT_CRITICAL();
+        if (endpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK)
+        {
+#if (defined(USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE) && (USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE > 0U))
+            if (length)
+            {
+                DCACHE_CleanByRange((uint32_t)buffer, length);
+            }
+#endif
+            /* Call the controller send interface. */
+            error = deviceHandle->controllerInterface->deviceSend(deviceHandle->controllerHandle, endpointAddress,
+                                                                  buffer, length);
+        }
+        else
+        {
+#if (defined(USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE) && (USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE > 0U))
+            if (length)
+            {
+                DCACHE_CleanInvalidateByRange((uint32_t)buffer, length);
+            }
+#endif
+            /* Call the controller receive interface. */
+            error = deviceHandle->controllerInterface->deviceRecv(deviceHandle->controllerHandle, endpointAddress,
+                                                                  buffer, length);
+        }
+        if (kStatus_USB_Success != error)
+        {
+            USB_OSA_ENTER_CRITICAL();
+            deviceHandle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].isBusy = 0U;
+            USB_OSA_EXIT_CRITICAL();
+        }
+    }
+    else
+    {
+        error = kStatus_USB_ControllerNotFound;
+    }
+    return error;
+}
+
+/*!
+ * @brief Control the status of the selected item.
+ *
+ * This function is used to control the status of the selected item..
+ *
+ * @param handle                 The device handle. It equals the value returned from USB_DeviceInit.
+ * @param type                   The control type, please refer to the enumeration usb_device_control_type_t.
+ * @param param                  The param type is determined by the selected item.
+ *
+ * @retval kStatus_USB_Success              Get a device handle successfully.
+ * @retval kStatus_USB_InvalidHandle        The device handle is invalided.
+ * @retval kStatus_USB_ControllerNotFound   The controller interface is not found.
+ * @retval kStatus_USB_Error                Unsupport type.
+ *                                          Or, the param is NULL pointer.
+ */
+static usb_status_t USB_DeviceControl(usb_device_handle handle, usb_device_control_type_t type, void *param)
+{
+    usb_device_struct_t *deviceHandle = (usb_device_struct_t *)handle;
+    usb_status_t error = kStatus_USB_Error;
+
+    if (NULL == deviceHandle)
+    {
+        return kStatus_USB_InvalidHandle;
+    }
+
+    if (NULL != deviceHandle->controllerInterface)
+    {
+        /* Call the controller control interface. */
+        error = deviceHandle->controllerInterface->deviceControl(deviceHandle->controllerHandle, type, param);
+    }
+    else
+    {
+        error = kStatus_USB_ControllerNotFound;
+    }
+    return error;
+}
+
+/*!
+ * @brief Handle the reset notification.
+ *
+ * This function is used to handle the reset notification.
+ *
+ * @param handle                 The device handle. It equals the value returned from USB_DeviceInit.
+ * @param message                The device callback message handle.
+ *
+ * @retval kStatus_USB_Success              Get a device handle successfully.
+ */
+static usb_status_t USB_DeviceResetNotification(usb_device_struct_t *handle,
+                                                usb_device_callback_message_struct_t *message)
+{
+#if (defined(USB_DEVICE_CONFIG_USE_TASK) && (USB_DEVICE_CONFIG_USE_TASK > 0U))
+    USB_OSA_SR_ALLOC();
+#endif
+
+    handle->isResetting = 1U;
+
+#if ((defined(USB_DEVICE_CONFIG_REMOTE_WAKEUP)) && (USB_DEVICE_CONFIG_REMOTE_WAKEUP > 0U))
+    /* Clear remote wakeup feature */
+    handle->remotewakeup = 0U;
+#endif
+
+#if (defined(USB_DEVICE_CONFIG_USE_TASK) && (USB_DEVICE_CONFIG_USE_TASK > 0U))
+    USB_OSA_ENTER_CRITICAL();
+    handle->epCallbackDirectly = 1;
+    USB_OSA_EXIT_CRITICAL();
+#endif
+    /* Set the controller to default status. */
+    USB_DeviceControl(handle, kUSB_DeviceControlSetDefaultStatus, NULL);
+#if (defined(USB_DEVICE_CONFIG_USE_TASK) && (USB_DEVICE_CONFIG_USE_TASK > 0U))
+    USB_OSA_ENTER_CRITICAL();
+    handle->epCallbackDirectly = 0;
+    USB_OSA_EXIT_CRITICAL();
+#endif
+
+    handle->state = kUSB_DeviceStateDefault;
+    handle->deviceAddress = 0U;
+
+    for (uint32_t count = 0U; count < (USB_DEVICE_CONFIG_ENDPOINTS * 2U); count++)
+    {
+        handle->epCallback[count].callbackFn = (usb_device_endpoint_callback_t)NULL;
+        handle->epCallback[count].callbackParam = NULL;
+        handle->epCallback[count].isBusy = 0U;
+    }
+
+    /* Call device callback to notify the application that the USB bus reset signal detected. */
+    handle->deviceCallback(handle, kUSB_DeviceEventBusReset, NULL);
+
+    handle->isResetting = 0U;
+    return kStatus_USB_Success;
+}
+
+#if (defined(USB_DEVICE_CONFIG_LOW_POWER_MODE) && (USB_DEVICE_CONFIG_LOW_POWER_MODE > 0U))
+/*!
+ * @brief Handle the suspend notification.
+ *
+ * This function is used to handle the suspend notification.
+ *
+ * @param handle                 The device handle. It equals the value returned from USB_DeviceInit.
+ * @param message                The device callback message handle.
+ *
+ * @return A USB error code or kStatus_USB_Success.
+ */
+static usb_status_t USB_DeviceSuspendNotification(usb_device_struct_t *handle,
+                                                  usb_device_callback_message_struct_t *message)
+{
+    /* Call device callback to notify the application that the USB bus suspend signal detected. */
+    return handle->deviceCallback(handle, kUSB_DeviceEventSuspend, NULL);
+}
+
+/*!
+ * @brief Handle the resume notification.
+ *
+ * This function is used to handle the resume notification.
+ *
+ * @param handle                 The device handle. It equals the value returned from USB_DeviceInit.
+ * @param message                The device callback message handle.
+ *
+ * @return A USB error code or kStatus_USB_Success.
+ */
+static usb_status_t USB_DeviceResumeNotification(usb_device_struct_t *handle,
+                                                 usb_device_callback_message_struct_t *message)
+{
+    /* Call device callback to notify the application that the USB bus resume signal detected. */
+    return handle->deviceCallback(handle, kUSB_DeviceEventResume, NULL);
+}
+#if (defined(USB_DEVICE_CONFIG_LPM_L1) && (USB_DEVICE_CONFIG_LPM_L1 > 0U))
+/*!
+ * @brief Handle the suspend notification.
+ *
+ * This function is used to handle the suspend notification.
+ *
+ * @param handle                 The device handle. It equals the value returned from USB_DeviceInit.
+ * @param message                The device callback message handle.
+ *
+ * @return A USB error code or kStatus_USB_Success.
+ */
+static usb_status_t USB_DeviceSleepNotification(usb_device_struct_t *handle,
+                                                usb_device_callback_message_struct_t *message)
+{
+    /* Call device callback to notify the application that the USB bus suspend signal detected. */
+    return handle->deviceCallback(handle, kUSB_DeviceEventSleeped, NULL);
+}
+#endif
+/*!
+ * @brief Handle the remotewakeup notification.
+ *
+ * This function is used to handle the remotewakeup notification.
+ *
+ * @param handle                 The device handle. It equals the value returned from USB_DeviceInit.
+ * @param flag                   The buffer pointer to store remotewakeup flag.
+ *
+ * @return A USB error code or kStatus_USB_Success.
+ */
+usb_status_t USB_DeviceGetRemoteWakeUp(usb_device_struct_t *handle, uint8_t **flag)
+{
+    /* Call device callback to notify the application that the USB bus suspend signal detected. */
+    return USB_DeviceControl(handle, kUSB_DeviceControlGetRemoteWakeUp, flag);
+}
+
+#endif /* USB_DEVICE_CONFIG_LOW_POWER_MODE */
+
+#if (defined(USB_DEVICE_CONFIG_ERROR_HANDLING) && (USB_DEVICE_CONFIG_ERROR_HANDLING > 0U))
+usb_status_t USB_DeviceErrorNotification(usb_device_struct_t *handle, usb_device_callback_message_struct_t *message)
+{
+    /* Call device callback to notify the application that the USB bus error signal detected. */
+    return handle->deviceCallback(handle, kUSB_DeviceEventError, NULL);
+}
+#endif /* USB_DEVICE_CONFIG_ERROR_HANDLING */
+
+#if (defined(USB_DEVICE_CONFIG_DETACH_ENABLE) && (USB_DEVICE_CONFIG_DETACH_ENABLE > 0U))
+/*!
+ * @brief Handle the detach notification.
+ *
+ * This function is used to handle the detach notification.
+ *
+ * @param handle                 The device handle. It equals the value returned from USB_DeviceInit.
+ * @param message                The device callback message handle.
+ *
+ * @return A USB error code or kStatus_USB_Success.
+ */
+static usb_status_t USB_DeviceDetachNotification(usb_device_struct_t *handle,
+                                                 usb_device_callback_message_struct_t *message)
+{
+    /* Call device callback to notify the application that the device is disconnected from a host. */
+    return handle->deviceCallback(handle, kUSB_DeviceEventDetach, NULL);
+}
+
+/*!
+ * @brief Handle the attach notification.
+ *
+ * This function is used to handle the attach notification.
+ *
+ * @param handle                 The device handle. It equals the value returned from USB_DeviceInit.
+ * @param message                The device callback message handle.
+ *
+ * @return A USB error code or kStatus_USB_Success.
+ */
+static usb_status_t USB_DeviceAttachNotification(usb_device_struct_t *handle,
+                                                 usb_device_callback_message_struct_t *message)
+{
+    /* Call device callback to notify the application that the device is connected to a host. */
+    return handle->deviceCallback(handle, kUSB_DeviceEventAttach, NULL);
+}
+#endif
+
+#if (defined(USB_DEVICE_CHARGER_DETECT_ENABLE) && (USB_DEVICE_CHARGER_DETECT_ENABLE > 0U)) && \
+    ((defined(FSL_FEATURE_SOC_USBDCD_COUNT) && (FSL_FEATURE_SOC_USBDCD_COUNT > 0U)) ||        \
+     (defined(FSL_FEATURE_SOC_USBHSDCD_COUNT) && (FSL_FEATURE_SOC_USBHSDCD_COUNT > 0U)))
+/*!
+ * @brief Handle the dcd module timeout notification.
+ *
+ * This function is used to handle the dcd module timeout notification.
+ *
+ * @param handle                 The device handle. It equals the value returned from USB_DeviceInit.
+ * @param message                The device callback message handle.
+ *
+ * @return A USB error code or kStatus_USB_Success.
+ */
+static usb_status_t USB_DeviceDcdTimeOutNotification(usb_device_struct_t *handle,
+                                                     usb_device_callback_message_struct_t *message)
+{
+    /* Call device callback to notify the application that the device charger detect timeout happened. */
+    return handle->deviceCallback(handle, kUSB_DeviceEventDcdTimeOut, NULL);
+}
+
+/*!
+ * @brief Handle the dcd module unknown port type notification.
+ *
+ * This function is used to handle the dcd module unknown port type notification.
+ *
+ * @param handle                 The device handle. It equals the value returned from USB_DeviceInit.
+ * @param message                The device callback message handle.
+ *
+ * @return A USB error code or kStatus_USB_Success.
+ */
+static usb_status_t USB_DeviceDcdUnknownPortTypeNotification(usb_device_struct_t *handle,
+                                                             usb_device_callback_message_struct_t *message)
+{
+    /* Call device callback to notify the application that the device charger detect unknown port type happened. */
+    return handle->deviceCallback(handle, kUSB_DeviceEventDcdUnknownType, NULL);
+}
+
+/*!
+ * @brief Handle the SDP facility is detected notification.
+ *
+ * This function is used to handle the SDP facility is detectednotification.
+ *
+ * @param handle                 The device handle. It equals the value returned from USB_DeviceInit.
+ * @param message                The device callback message handle.
+ *
+ * @return A USB error code or kStatus_USB_Success.
+ */
+static usb_status_t USB_DeviceDcdSDPDetectNotification(usb_device_struct_t *handle,
+                                                       usb_device_callback_message_struct_t *message)
+{
+    /* Call device callback to notify the application that the SDP facility is detected. */
+    return handle->deviceCallback(handle, kUSB_DeviceEventSDPDetected, NULL);
+}
+
+/*!
+ * @brief Handle the charging port is detected notification.
+ *
+ * This function is used to handle the charging port is detectednotification.
+ *
+ * @param handle                 The device handle. It equals the value returned from USB_DeviceInit.
+ * @param message                The device callback message handle.
+ *
+ * @return A USB error code or kStatus_USB_Success.
+ */
+static usb_status_t USB_DeviceDcdChargingPortDetectNotification(usb_device_struct_t *handle,
+                                                                usb_device_callback_message_struct_t *message)
+{
+    /* Call device callback to notify the application that the charing port is detected. */
+    return handle->deviceCallback(handle, kUSB_DeviceEventChargingPortDetected, NULL);
+}
+
+/*!
+ * @brief Handle the CDP facility is detected notification.
+ *
+ * This function is used to handle the CDP facility is detectednotification.
+ *
+ * @param handle                 The device handle. It equals the value returned from USB_DeviceInit.
+ * @param message                The device callback message handle.
+ *
+ * @return A USB error code or kStatus_USB_Success.
+ */
+static usb_status_t USB_DeviceDcdChargingHostDetectNotification(usb_device_struct_t *handle,
+                                                                usb_device_callback_message_struct_t *message)
+{
+    /* Call device callback to notify the application that the CDP facility is detected. */
+    return handle->deviceCallback(handle, kUSB_DeviceEventChargingHostDetected, NULL);
+}
+
+/*!
+ * @brief Handle the DCP facility is detected notification.
+ *
+ * This function is used to handle the DCP facility is detectednotification.
+ *
+ * @param handle                 The device handle. It equals the value returned from USB_DeviceInit.
+ * @param message                The device callback message handle.
+ *
+ * @return A USB error code or kStatus_USB_Success.
+ */
+
+static usb_status_t USB_DeviceDcdDedicatedChargerDetectNotification(usb_device_struct_t *handle,
+                                                                    usb_device_callback_message_struct_t *message)
+{
+    /* Call device callback to notify the application that the DCP facility is detected. */
+    return handle->deviceCallback(handle, kUSB_DeviceEventDedicatedChargerDetected, NULL);
+}
+#endif
+
+/*!
+ * @brief Handle the attach notification.
+ *
+ * This function is used to handle the attach notification.
+ *
+ * @param handle                 The device handle. It equals the value returned from USB_DeviceInit.
+ * @param message                The device callback message handle.
+ *
+ * @return A USB error code or kStatus_USB_Success.
+ */
+static usb_status_t USB_DeviceNotification(usb_device_struct_t *handle, usb_device_callback_message_struct_t *message)
+{
+    uint8_t endpoint = message->code & USB_ENDPOINT_NUMBER_MASK;
+    uint8_t direction = (message->code & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >>
+                        USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT;
+    usb_status_t error = kStatus_USB_Error;
+
+    switch (message->code)
+    {
+        case kUSB_DeviceNotifyBusReset:
+            error = USB_DeviceResetNotification(handle, message);
+            break;
+#if (defined(USB_DEVICE_CONFIG_LOW_POWER_MODE) && (USB_DEVICE_CONFIG_LOW_POWER_MODE > 0U))
+        case kUSB_DeviceNotifySuspend:
+            error = USB_DeviceSuspendNotification(handle, message);
+            break;
+        case kUSB_DeviceNotifyResume:
+            error = USB_DeviceResumeNotification(handle, message);
+            break;
+#if (defined(USB_DEVICE_CONFIG_LPM_L1) && (USB_DEVICE_CONFIG_LPM_L1 > 0U))
+        case kUSB_DeviceNotifyLPMSleep:
+            error = USB_DeviceSleepNotification(handle, message);
+            break;
+#endif
+#endif
+
+#if (defined(USB_DEVICE_CONFIG_ERROR_HANDLING) && (USB_DEVICE_CONFIG_ERROR_HANDLING > 0U))
+        case kUSB_DeviceNotifyError:
+            error = USB_DeviceErrorNotification(handle, message);
+            break;
+#endif
+
+#if USB_DEVICE_CONFIG_DETACH_ENABLE
+        case kUSB_DeviceNotifyDetach:
+            error = USB_DeviceDetachNotification(handle, message);
+            break;
+        case kUSB_DeviceNotifyAttach:
+            error = USB_DeviceAttachNotification(handle, message);
+            break;
+#endif
+#if (defined(USB_DEVICE_CHARGER_DETECT_ENABLE) && (USB_DEVICE_CHARGER_DETECT_ENABLE > 0U)) && \
+    ((defined(FSL_FEATURE_SOC_USBDCD_COUNT) && (FSL_FEATURE_SOC_USBDCD_COUNT > 0U)) ||        \
+     (defined(FSL_FEATURE_SOC_USBHSDCD_COUNT) && (FSL_FEATURE_SOC_USBHSDCD_COUNT > 0U)))
+        case kUSB_DeviceNotifyDcdTimeOut:
+            error = USB_DeviceDcdTimeOutNotification(handle, message);
+            break;
+        case kUSB_DeviceNotifyDcdUnknownPortType:
+            error = USB_DeviceDcdUnknownPortTypeNotification(handle, message);
+            break;
+        case kUSB_DeviceNotifySDPDetected:
+            error = USB_DeviceDcdSDPDetectNotification(handle, message);
+            break;
+        case kUSB_DeviceNotifyChargingPortDetected:
+            error = USB_DeviceDcdChargingPortDetectNotification(handle, message);
+            break;
+        case kUSB_DeviceNotifyChargingHostDetected:
+            error = USB_DeviceDcdChargingHostDetectNotification(handle, message);
+            break;
+        case kUSB_DeviceNotifyDedicatedChargerDetected:
+            error = USB_DeviceDcdDedicatedChargerDetectNotification(handle, message);
+            break;
+#endif
+
+        default:
+            if (endpoint < USB_DEVICE_CONFIG_ENDPOINTS)
+            {
+                if (handle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].callbackFn)
+                {
+                    usb_device_endpoint_callback_message_struct_t endpointCallbackMessage;
+                    endpointCallbackMessage.buffer = message->buffer;
+                    endpointCallbackMessage.length = message->length;
+                    endpointCallbackMessage.isSetup = message->isSetup;
+                    if (message->isSetup)
+                    {
+                        handle->epCallback[0].isBusy = 0U;
+                        handle->epCallback[1].isBusy = 0U;
+                    }
+                    else
+                    {
+                        handle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].isBusy = 0U;
+                    }
+                    /* Call endpoint callback */
+                    error = handle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].callbackFn(
+                        handle, &endpointCallbackMessage,
+                        handle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].callbackParam);
+                }
+            }
+            break;
+    }
+    return error;
+}
+
+/*!
+ * @brief Notify the device that the controller status changed.
+ *
+ * This function is used to notify the device that the controller status changed.
+ *
+ * @param handle                 The device handle. It equals the value returned from USB_DeviceInit.
+ * @param message                The device callback message handle.
+ *
+ * @return A USB error code or kStatus_USB_Success.
+ */
+usb_status_t USB_DeviceNotificationTrigger(void *handle, void *msg)
+{
+    usb_device_struct_t *deviceHandle = (usb_device_struct_t *)handle;
+    usb_device_callback_message_struct_t *message = (usb_device_callback_message_struct_t *)msg;
+
+    if ((NULL == msg) || (NULL == handle))
+    {
+        return kStatus_USB_InvalidHandle;
+    }
+
+    /* The device callback is invalid or not. */
+    if (!deviceHandle->deviceCallback)
+    {
+        return kStatus_USB_Error;
+    }
+
+#if (defined(USB_DEVICE_CONFIG_USE_TASK) && (USB_DEVICE_CONFIG_USE_TASK > 0U))
+    if (deviceHandle->epCallbackDirectly)
+    {
+        if ((message->code & USB_ENDPOINT_NUMBER_MASK) && (!(message->code & 0x70U)))
+        {
+            return USB_DeviceNotification(deviceHandle, message);
+        }
+    }
+
+    /* Add the message to message queue when the device task is enabled. */
+    if (kStatus_USB_OSA_Success != USB_OsaMsgqSend(deviceHandle->notificationQueue, (void *)message))
+    {
+        return kStatus_USB_Busy;
+    }
+    return kStatus_USB_Success;
+#else
+    /* Handle the notification by calling USB_DeviceNotification. */
+    return USB_DeviceNotification(deviceHandle, message);
+#endif
+}
+
+/*!
+ * @brief Initialize the USB device stack.
+ *
+ * This function initializes the USB device module specified by the controllerId.
+ *
+ * @param controllerId   The controller id of the USB IP. Please refer to the enumeration usb_controller_index_t.
+ * @param deviceCallback Function pointer of the device callback.
+ * @param handle          It is out parameter, is used to return pointer of the device handle to the caller.
+ *
+ * @retval kStatus_USB_Success              The device is initialized successfully.
+ * @retval kStatus_USB_InvalidHandle        The handle is a NULL pointer.
+ * @retval kStatus_USB_Busy                 Cannot allocate a device handle.
+ * @retval kStatus_USB_ControllerNotFound   Cannot find the controller according to the controller id.
+ * @retval kStatus_USB_InvalidControllerInterface  The controller driver interfaces is invaild, There is an empty
+ * interface entity.
+ * @retval kStatus_USB_Error                The macro USB_DEVICE_CONFIG_ENDPOINTS is more than IP's endpoint number.
+ *                                          Or, the device has been initialized.
+ *                                          Or, the message queue is created failed.
+ */
+usb_status_t USB_DeviceInit(uint8_t controllerId, usb_device_callback_t deviceCallback, usb_device_handle *handle)
+{
+    usb_device_struct_t *deviceHandle = NULL;
+    usb_status_t error;
+    uint32_t count;
+
+    if (NULL == handle)
+    {
+        return kStatus_USB_InvalidHandle;
+    }
+
+    /* Allocate a device handle by using the controller id. */
+    error = USB_DeviceAllocateHandle(controllerId, &deviceHandle);
+
+    if (kStatus_USB_Success != error)
+    {
+        return error;
+    }
+
+    /* Save the device callback */
+    deviceHandle->deviceCallback = deviceCallback;
+    /* Save the controller id */
+    deviceHandle->controllerId = controllerId;
+    /* Clear the device address */
+    deviceHandle->deviceAddress = 0U;
+    /* Clear the device reset state */
+    deviceHandle->isResetting = 0U;
+
+    /* Initialize the enpoints */
+    for (count = 0U; count < (USB_DEVICE_CONFIG_ENDPOINTS * 2U); count++)
+    {
+        deviceHandle->epCallback[count].callbackFn = (usb_device_endpoint_callback_t)NULL;
+        deviceHandle->epCallback[count].callbackParam = NULL;
+        deviceHandle->epCallback[count].isBusy = 0U;
+    }
+
+    /* Get the controller interface according to the controller id */
+    error = USB_DeviceGetControllerInterface(controllerId, &deviceHandle->controllerInterface);
+    if (kStatus_USB_Success != error)
+    {
+        USB_DeviceFreeHandle(deviceHandle);
+        return error;
+    }
+    if (NULL == deviceHandle->controllerInterface)
+    {
+        USB_DeviceFreeHandle(deviceHandle);
+        return kStatus_USB_ControllerNotFound;
+    }
+    if (((usb_device_controller_init_t)NULL == deviceHandle->controllerInterface->deviceInit) ||
+        ((usb_device_controller_deinit_t)NULL == deviceHandle->controllerInterface->deviceDeinit) ||
+        ((usb_device_controller_send_t)NULL == deviceHandle->controllerInterface->deviceSend) ||
+        ((usb_device_controller_recv_t)NULL == deviceHandle->controllerInterface->deviceRecv) ||
+        ((usb_device_controller_cancel_t)NULL == deviceHandle->controllerInterface->deviceCancel) ||
+        ((usb_device_controller_control_t)NULL == deviceHandle->controllerInterface->deviceControl))
+    {
+        USB_DeviceFreeHandle(deviceHandle);
+        return kStatus_USB_InvalidControllerInterface;
+    }
+
+#if USB_DEVICE_CONFIG_USE_TASK
+    /* Create a message queue when the device handle is enabled. */
+    if (kStatus_USB_OSA_Success !=
+        USB_OsaMsgqCreate(&deviceHandle->notificationQueue, USB_DEVICE_CONFIG_MAX_MESSAGES,
+                          (1U + (sizeof(usb_device_callback_message_struct_t) - 1U) / sizeof(uint32_t))))
+    {
+        USB_DeviceDeinit(deviceHandle);
+        return kStatus_USB_Error;
+    }
+#endif
+
+    *handle = deviceHandle;
+
+    /* Initialize the controller */
+    error = deviceHandle->controllerInterface->deviceInit(controllerId, deviceHandle, &deviceHandle->controllerHandle);
+    if (kStatus_USB_Success != error)
+    {
+        USB_DeviceDeinit(deviceHandle);
+        *handle = NULL;
+        return error;
+    }
+    /* Set the device to deafult state */
+    deviceHandle->state = kUSB_DeviceStateDefault;
+
+    return error;
+}
+
+/*!
+ * @brief Enable the device functionality.
+ *
+ * The function enables the device functionality, so that the device can be recognized by the host when the device
+ * detects that it has been connected to a host.
+ *
+ * @param handle The device handle got from USB_DeviceInit.
+ *
+ * @retval kStatus_USB_Success              The device is run successfully.
+ * @retval kStatus_USB_ControllerNotFound   Cannot find the controller.
+ * @retval kStatus_USB_InvalidHandle        The device handle is a NULL pointer. Or the controller handle is invalid.
+ *
+ */
+usb_status_t USB_DeviceRun(usb_device_handle handle)
+{
+    return USB_DeviceControl(handle, kUSB_DeviceControlRun, NULL);
+}
+/*!
+ * @brief Disable the device functionality.
+ *
+ * The function disables the device functionality, after this function called, even the device is detached to the host,
+ * and the device can't work.
+ *
+ * @param handle The device handle got from USB_DeviceInit.
+ *
+ * @retval kStatus_USB_Success              The device is stopped successfully.
+ * @retval kStatus_USB_ControllerNotFound   Cannot find the controller.
+ * @retval kStatus_USB_InvalidHandle        The device handle is a NULL pointer. Or the controller handle is invalid.
+ */
+usb_status_t USB_DeviceStop(usb_device_handle handle)
+{
+    return USB_DeviceControl(handle, kUSB_DeviceControlStop, NULL);
+}
+/*!
+ * @brief De-initialize the device controller.
+ *
+ * The function de-initializes the device controller specified by the handle.
+ *
+ * @param handle The device handle got from USB_DeviceInit.
+ *
+ * @retval kStatus_USB_Success              The device is stopped successfully.
+ * @retval kStatus_USB_InvalidHandle        The device handle is a NULL pointer. Or the controller handle is invalid.
+ */
+usb_status_t USB_DeviceDeinit(usb_device_handle handle)
+{
+    usb_device_struct_t *deviceHandle = (usb_device_struct_t *)handle;
+
+    if (NULL == deviceHandle)
+    {
+        return kStatus_USB_InvalidHandle;
+    }
+    /* De-initialize the controller */
+    if (NULL != deviceHandle->controllerInterface)
+    {
+        deviceHandle->controllerInterface->deviceDeinit(deviceHandle->controllerHandle);
+        deviceHandle->controllerInterface = (usb_device_controller_interface_struct_t *)NULL;
+    }
+
+#if USB_DEVICE_CONFIG_USE_TASK
+    /* Destroy the message queue. */
+    if (NULL != deviceHandle->notificationQueue)
+    {
+        USB_OsaMsgqDestroy(deviceHandle->notificationQueue);
+        deviceHandle->notificationQueue = NULL;
+    }
+#endif
+
+    /* Free the device handle. */
+    USB_DeviceFreeHandle(deviceHandle);
+    return kStatus_USB_Success;
+}
+
+/*!
+ * @brief Send data through a specified endpoint.
+ *
+ * The function is used to send data through a specified endpoint.
+ *
+ * @param handle The device handle got from USB_DeviceInit.
+ * @param endpointAddress Endpoint index.
+ * @param buffer The memory address to hold the data need to be sent.
+ * @param length The data length need to be sent.
+ *
+ * @retval kStatus_USB_Success              The send request is sent successfully.
+ * @retval kStatus_USB_InvalidHandle        The handle is a NULL pointer. Or the controller handle is invalid.
+ * @retval kStatus_USB_Busy                 Cannot allocate dtds for current tansfer in EHCI driver.
+ * @retval kStatus_USB_ControllerNotFound   Cannot find the controller.
+ * @retval kStatus_USB_Error                The device is doing reset.
+ *
+ * @note The return value just means if the sending request is successful or not; the transfer done is notified by the
+ * corresponding callback function.
+ * Currently, only one transfer request can be supported for one specific endpoint.
+ * If there is a specific requirement to support multiple transfer requests for one specific endpoint, the application
+ * should implement a queue in the application level.
+ * The subsequent transfer could begin only when the previous transfer is done (get notification through the endpoint
+ * callback).
+ */
+usb_status_t USB_DeviceSendRequest(usb_device_handle handle, uint8_t endpointAddress, uint8_t *buffer, uint32_t length)
+{
+    return USB_DeviceTransfer(handle, (endpointAddress & USB_ENDPOINT_NUMBER_MASK) |
+                                          (USB_IN << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT),
+                              buffer, length);
+}
+
+/*!
+ * @brief Receive data through a specified endpoint.
+ *
+ * The function is used to receive data through a specified endpoint.
+ *
+ * @param handle The device handle got from USB_DeviceInit.
+ * @param endpointAddress Endpoint index.
+ * @param buffer The memory address to save the received data.
+ * @param length The data length want to be received.
+ *
+ * @retval kStatus_USB_Success              The receive request is sent successfully.
+ * @retval kStatus_USB_InvalidHandle        The handle is a NULL pointer. Or the controller handle is invalid.
+ * @retval kStatus_USB_Busy                 Cannot allocate dtds for current tansfer in EHCI driver.
+ * @retval kStatus_USB_ControllerNotFound   Cannot find the controller.
+ * @retval kStatus_USB_Error                The device is doing reset.
+ *
+ * @note The return value just means if the receiving request is successful or not; the transfer done is notified by the
+ * corresponding callback function.
+ * Currently, only one transfer request can be supported for one specific endpoint.
+ * If there is a specific requirement to support multiple transfer requests for one specific endpoint, the application
+ * should implement a queue in the application level.
+ * The subsequent transfer could begin only when the previous transfer is done (get notification through the endpoint
+ * callback).
+ */
+usb_status_t USB_DeviceRecvRequest(usb_device_handle handle, uint8_t endpointAddress, uint8_t *buffer, uint32_t length)
+{
+    return USB_DeviceTransfer(handle, (endpointAddress & USB_ENDPOINT_NUMBER_MASK) |
+                                          (USB_OUT << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT),
+                              buffer, length);
+}
+
+/*!
+ * @brief Cancel the pending transfer in a specified endpoint.
+ *
+ * The function is used to cancel the pending transfer in a specified endpoint.
+ *
+ * @param handle The device handle got from USB_DeviceInit.
+ * @param endpointAddress Endpoint address, bit7 is the direction of endpoint, 1U - IN, abd 0U - OUT.
+ *
+ * @retval kStatus_USB_Success              The transfer is cancelled.
+ * @retval kStatus_USB_InvalidHandle        The handle is a NULL pointer. Or the controller handle is invalid.
+ * @retval kStatus_USB_ControllerNotFound   Cannot find the controller.
+ */
+usb_status_t USB_DeviceCancel(usb_device_handle handle, uint8_t endpointAddress)
+{
+    usb_device_struct_t *deviceHandle = (usb_device_struct_t *)handle;
+    usb_status_t error = kStatus_USB_Error;
+
+    if (NULL == deviceHandle)
+    {
+        return kStatus_USB_InvalidHandle;
+    }
+
+    if (NULL != deviceHandle->controllerInterface)
+    {
+        error = deviceHandle->controllerInterface->deviceCancel(deviceHandle->controllerHandle, endpointAddress);
+    }
+    else
+    {
+        error = kStatus_USB_ControllerNotFound;
+    }
+    return error;
+}
+
+/*!
+ * @brief Initialize a specified endpoint.
+ *
+ * The function is used to initialize a specified endpoint and the corresponding endpoint callback is also initialized.
+ *
+ * @param handle The device handle got from USB_DeviceInit.
+ * @param epInit Endpoint initizlization structure. Please refer to the structure usb_device_endpoint_init_struct_t.
+ * @param epCallback Endpoint callback structure. Please refer to the structure
+ * usb_device_endpoint_callback_struct_t.
+ *
+ * @retval kStatus_USB_Success              The endpoint is initialized successfully.
+ * @retval kStatus_USB_InvalidHandle        The handle is a NULL pointer. Or the controller handle is invalid.
+ * @retval kStatus_USB_InvalidParameter     The epInit or epCallback is NULL pointer. Or the endpoint number is
+ * more than USB_DEVICE_CONFIG_ENDPOINTS.
+ * @retval kStatus_USB_Busy                 The endpoint is busy in EHCI driver.
+ * @retval kStatus_USB_ControllerNotFound   Cannot find the controller.
+ */
+usb_status_t USB_DeviceInitEndpoint(usb_device_handle handle,
+                                    usb_device_endpoint_init_struct_t *epInit,
+                                    usb_device_endpoint_callback_struct_t *epCallback)
+{
+    usb_device_struct_t *deviceHandle = (usb_device_struct_t *)handle;
+    uint8_t endpoint;
+    uint8_t direction;
+
+    if (!deviceHandle)
+    {
+        return kStatus_USB_InvalidHandle;
+    }
+
+    if ((!epInit) || (!epCallback))
+    {
+        return kStatus_USB_InvalidParameter;
+    }
+
+    endpoint = epInit->endpointAddress & USB_ENDPOINT_NUMBER_MASK;
+    direction = (epInit->endpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >>
+                USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT;
+
+    if (endpoint < USB_DEVICE_CONFIG_ENDPOINTS)
+    {
+        deviceHandle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].callbackFn = epCallback->callbackFn;
+        deviceHandle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].callbackParam =
+            epCallback->callbackParam;
+        deviceHandle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].isBusy = 0U;
+    }
+    else
+    {
+        return kStatus_USB_InvalidParameter;
+    }
+    return USB_DeviceControl(handle, kUSB_DeviceControlEndpointInit, epInit);
+}
+
+/*!
+ * @brief De-initizlize a specified endpoint.
+ *
+ * The function is used to de-initizlize a specified endpoint.
+ *
+ * @param handle The device handle got from USB_DeviceInit.
+ * @param endpointAddress Endpoint address, bit7 is the direction of endpoint, 1U - IN, abd 0U - OUT.
+ *
+ * @retval kStatus_USB_Success              The endpoint is de-initialized successfully.
+ * @retval kStatus_USB_InvalidHandle        The handle is a NULL pointer. Or the controller handle is invalid.
+ * @retval kStatus_USB_InvalidParameter     The endpoint number is more than USB_DEVICE_CONFIG_ENDPOINTS.
+ * @retval kStatus_USB_Busy                 The endpoint is busy in EHCI driver.
+ * @retval kStatus_USB_ControllerNotFound   Cannot find the controller.
+ */
+usb_status_t USB_DeviceDeinitEndpoint(usb_device_handle handle, uint8_t endpointAddress)
+{
+    usb_device_struct_t *deviceHandle = (usb_device_struct_t *)handle;
+    uint8_t endpoint = endpointAddress & USB_ENDPOINT_NUMBER_MASK;
+    uint8_t direction = (endpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >>
+                        USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT;
+    usb_status_t error = kStatus_USB_Error;
+#if (defined(USB_DEVICE_CONFIG_USE_TASK) && (USB_DEVICE_CONFIG_USE_TASK > 0U))
+    USB_OSA_SR_ALLOC();
+#endif
+
+    if (!deviceHandle)
+    {
+        return kStatus_USB_InvalidHandle;
+    }
+#if (defined(USB_DEVICE_CONFIG_USE_TASK) && (USB_DEVICE_CONFIG_USE_TASK > 0U))
+    USB_OSA_ENTER_CRITICAL();
+    deviceHandle->epCallbackDirectly = 1;
+    USB_OSA_EXIT_CRITICAL();
+#endif
+    error = USB_DeviceControl(handle, kUSB_DeviceControlEndpointDeinit, &endpointAddress);
+#if (defined(USB_DEVICE_CONFIG_USE_TASK) && (USB_DEVICE_CONFIG_USE_TASK > 0U))
+    USB_OSA_ENTER_CRITICAL();
+    deviceHandle->epCallbackDirectly = 0;
+    USB_OSA_EXIT_CRITICAL();
+#endif
+
+    if (endpoint < USB_DEVICE_CONFIG_ENDPOINTS)
+    {
+        deviceHandle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].callbackFn =
+            (usb_device_endpoint_callback_t)NULL;
+        deviceHandle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].callbackParam = NULL;
+        deviceHandle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].isBusy = 0U;
+    }
+    else
+    {
+        return kStatus_USB_InvalidParameter;
+    }
+    return error;
+}
+
+/*!
+ * @brief Stall a specified endpoint.
+ *
+ * The function is used to stall a specified endpoint.
+ *
+ * @param handle The device handle got from USB_DeviceInit.
+ * @param endpointAddress Endpoint address, bit7 is the direction of endpoint, 1U - IN, abd 0U - OUT.
+ *
+ * @retval kStatus_USB_Success              The endpoint is stalled successfully.
+ * @retval kStatus_USB_InvalidHandle        The handle is a NULL pointer. Or the controller handle is invalid.
+ * @retval kStatus_USB_InvalidParameter     The endpoint number is more than USB_DEVICE_CONFIG_ENDPOINTS.
+ * @retval kStatus_USB_ControllerNotFound   Cannot find the controller.
+ */
+usb_status_t USB_DeviceStallEndpoint(usb_device_handle handle, uint8_t endpointAddress)
+{
+    if ((endpointAddress & USB_ENDPOINT_NUMBER_MASK) < USB_DEVICE_CONFIG_ENDPOINTS)
+    {
+        return USB_DeviceControl(handle, kUSB_DeviceControlEndpointStall, &endpointAddress);
+    }
+    else
+    {
+        return kStatus_USB_InvalidParameter;
+    }
+}
+
+/*!
+ * @brief Un-stall a specified endpoint.
+ *
+ * The function is used to un-stall a specified endpoint.
+ *
+ * @param handle The device handle got from USB_DeviceInit.
+ * @param endpointAddress Endpoint address, bit7 is the direction of endpoint, 1U - IN, abd 0U - OUT.
+ *
+ * @retval kStatus_USB_Success              The endpoint is un-stalled successfully.
+ * @retval kStatus_USB_InvalidHandle        The handle is a NULL pointer. Or the controller handle is invalid.
+ * @retval kStatus_USB_InvalidParameter     The endpoint number is more than USB_DEVICE_CONFIG_ENDPOINTS.
+ * @retval kStatus_USB_ControllerNotFound   Cannot find the controller.
+ */
+usb_status_t USB_DeviceUnstallEndpoint(usb_device_handle handle, uint8_t endpointAddress)
+{
+    if ((endpointAddress & USB_ENDPOINT_NUMBER_MASK) < USB_DEVICE_CONFIG_ENDPOINTS)
+    {
+        return USB_DeviceControl(handle, kUSB_DeviceControlEndpointUnstall, &endpointAddress);
+    }
+    else
+    {
+        return kStatus_USB_InvalidParameter;
+    }
+}
+
+/*!
+ * @brief Get the status of the selected item.
+ *
+ * The function is used to get the status of the selected item.
+ *
+ * @param handle The device handle got from USB_DeviceInit.
+ * @param type   The selected item. Please refer to the structure usb_device_status_t.
+ * @param param  The param type is determined by the selected item.
+ *
+ * @retval kStatus_USB_Success              Get status successfully.
+ * @retval kStatus_USB_InvalidHandle        The handle is a NULL pointer. Or the controller handle is invalid.
+ * @retval kStatus_USB_InvalidParameter     The param is NULL pointer.
+ * @retval kStatus_USB_ControllerNotFound   Cannot find the controller.
+ * @retval kStatus_USB_Error                Unsupported type.
+ */
+usb_status_t USB_DeviceGetStatus(usb_device_handle handle, usb_device_status_t type, void *param)
+{
+    uint8_t *temp8;
+    usb_status_t error = kStatus_USB_Error;
+
+    if (NULL == param)
+    {
+        return kStatus_USB_InvalidParameter;
+    }
+    switch (type)
+    {
+        case kUSB_DeviceStatusSpeed:
+            error = USB_DeviceControl(handle, kUSB_DeviceControlGetSpeed, param);
+            break;
+        case kUSB_DeviceStatusOtg:
+            error = USB_DeviceControl(handle, kUSB_DeviceControlGetOtgStatus, param);
+            break;
+        case kUSB_DeviceStatusDeviceState:
+            temp8 = (uint8_t *)param;
+            error = kStatus_USB_Success;
+            *temp8 = ((usb_device_struct_t *)handle)->state;
+            break;
+        case kUSB_DeviceStatusAddress:
+            temp8 = (uint8_t *)param;
+            error = kStatus_USB_Success;
+            *temp8 = ((usb_device_struct_t *)handle)->deviceAddress;
+            break;
+        case kUSB_DeviceStatusDevice:
+            error = USB_DeviceControl(handle, kUSB_DeviceControlGetDeviceStatus, param);
+            break;
+        case kUSB_DeviceStatusEndpoint:
+            error = USB_DeviceControl(handle, kUSB_DeviceControlGetEndpointStatus, param);
+            break;
+        case kUSB_DeviceStatusSynchFrame:
+            error = USB_DeviceControl(handle, kUSB_DeviceControlGetSynchFrame, param);
+            break;
+#if ((defined(USB_DEVICE_CONFIG_REMOTE_WAKEUP)) && (USB_DEVICE_CONFIG_REMOTE_WAKEUP > 0U))
+        case kUSB_DeviceStatusRemoteWakeup:
+            temp8 = (uint8_t *)param;
+            error = kStatus_USB_Success;
+            *temp8 = ((usb_device_struct_t *)handle)->remotewakeup;
+            break;
+#endif
+        default:
+            break;
+    }
+    return error;
+}
+
+/*!
+ * @brief Set the status of the selected item.
+ *
+ * The function is used to set the status of the selected item.
+ *
+ * @param handle The device handle got from USB_DeviceInit.
+ * @param type The selected item. Please refer to the structure usb_device_status_t.
+ * @param param The param type is determined by the selected item.
+ *
+ * @retval kStatus_USB_Success              Set status successfully.
+ * @retval kStatus_USB_InvalidHandle        The handle is a NULL pointer. Or the controller handle is invalid.
+ * @retval kStatus_USB_ControllerNotFound   Cannot find the controller.
+ * @retval kStatus_USB_Error                Unsupported type, or the param is NULL pointer.
+ */
+usb_status_t USB_DeviceSetStatus(usb_device_handle handle, usb_device_status_t type, void *param)
+{
+    usb_status_t error = kStatus_USB_Error;
+    switch (type)
+    {
+#if (defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0U) ||                  \
+     (defined(USB_DEVICE_CONFIG_LPCIP3511HS) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U))) && \
+    (defined(USB_DEVICE_CONFIG_USB20_TEST_MODE) && (USB_DEVICE_CONFIG_USB20_TEST_MODE > 0U))
+        case kUSB_DeviceStatusTestMode:
+            error = USB_DeviceControl(handle, kUSB_DeviceControlSetTestMode, param);
+            break;
+#endif
+        case kUSB_DeviceStatusOtg:
+            error = USB_DeviceControl(handle, kUSB_DeviceControlSetOtgStatus, param);
+            break;
+        case kUSB_DeviceStatusDeviceState:
+            if (NULL != param)
+            {
+                error = kStatus_USB_Success;
+                ((usb_device_struct_t *)handle)->state = (uint8_t)(*(uint8_t *)param);
+            }
+            break;
+        case kUSB_DeviceStatusAddress:
+            if (kUSB_DeviceStateAddressing != ((usb_device_struct_t *)handle)->state)
+            {
+                if (NULL != param)
+                {
+                    error = kStatus_USB_Success;
+                    ((usb_device_struct_t *)handle)->deviceAddress = (uint8_t)(*(uint8_t *)param);
+                    ((usb_device_struct_t *)handle)->state = kUSB_DeviceStateAddressing;
+                }
+            }
+            else
+            {
+                error = USB_DeviceControl(handle, kUSB_DeviceControlSetDeviceAddress,
+                                          &((usb_device_struct_t *)handle)->deviceAddress);
+            }
+            break;
+        case kUSB_DeviceStatusBusResume:
+            error = USB_DeviceControl(handle, kUSB_DeviceControlResume, param);
+            break;
+        case kUSB_DeviceStatusBusSleepResume:
+            error = USB_DeviceControl(handle, kUSB_DeviceControlSleepResume, param);
+            break;
+#if ((defined(USB_DEVICE_CONFIG_REMOTE_WAKEUP)) && (USB_DEVICE_CONFIG_REMOTE_WAKEUP > 0U))
+        case kUSB_DeviceStatusRemoteWakeup:
+            if (NULL != param)
+            {
+                error = kStatus_USB_Success;
+                ((usb_device_struct_t *)handle)->remotewakeup = (uint8_t)(*(uint8_t *)param);
+            }
+            break;
+#endif
+        case kUSB_DeviceStatusBusSuspend:
+            error = USB_DeviceControl(handle, kUSB_DeviceControlSuspend, param);
+            break;
+        case kUSB_DeviceStatusBusSleep:
+            error = USB_DeviceControl(handle, kUSB_DeviceControlSleep, param);
+            break;
+        default:
+            break;
+    }
+    return error;
+}
+
+#if (defined(USB_DEVICE_CHARGER_DETECT_ENABLE) && (USB_DEVICE_CHARGER_DETECT_ENABLE > 0U)) && \
+    ((defined(FSL_FEATURE_SOC_USBDCD_COUNT) && (FSL_FEATURE_SOC_USBDCD_COUNT > 0U)) ||        \
+     (defined(FSL_FEATURE_SOC_USBHSDCD_COUNT) && (FSL_FEATURE_SOC_USBHSDCD_COUNT > 0U)))
+/*!
+ * @brief Initializes the device dcd module.
+ *
+ * The function initializes the device dcd module.
+ *
+ * @param handle The device handle got from USB_DeviceInit.
+ *
+ * @retval kStatus_USB_Success              The device is run successfully.
+ * @retval kStatus_USB_ControllerNotFound   Cannot find the controller.
+ * @retval kStatus_USB_InvalidHandle        The device handle is a NULL pointer. Or the controller handle is invalid.
+ *
+ */
+usb_status_t USB_DeviceDcdInitModule(usb_device_handle handle, void *time_param)
+{
+    return USB_DeviceControl(handle, kUSB_DeviceControlDcdInitModule, time_param);
+}
+
+/*!
+ * @brief De-initializes the device dcd module.
+ *
+ * The function de-intializes the device dcd module.
+ *
+ * @param handle The device handle got from USB_DeviceInit.
+ *
+ * @retval kStatus_USB_Success              The device is run successfully.
+ * @retval kStatus_USB_InvalidHandle        The device handle is a NULL pointer. Or the controller handle is invalid.
+ *
+ */
+usb_status_t USB_DeviceDcdDeinitModule(usb_device_handle handle)
+{
+    return USB_DeviceControl(handle, kUSB_DeviceControlDcdDeinitModule, NULL);
+}
+#endif
+
+#if USB_DEVICE_CONFIG_USE_TASK
+/*!
+ * @brief Device task function.
+ *
+ * The function is used to handle controller message.
+ * This function should not be called in applicartion directly.
+ *
+ * @param handle The device handle got from USB_DeviceInit.
+ */
+void USB_DeviceTaskFunction(void *deviceHandle)
+{
+    usb_device_struct_t *handle = (usb_device_struct_t *)deviceHandle;
+    static usb_device_callback_message_struct_t message;
+
+    if (deviceHandle)
+    {
+        /* Get the message from the queue */
+        if (kStatus_USB_OSA_Success == USB_OsaMsgqRecv(handle->notificationQueue, (uint32_t *)&message, 0U))
+        {
+            /* Handle the message */
+            USB_DeviceNotification(handle, &message);
+        }
+    }
+}
+#endif
+
+/*!
+ * @brief Get dvice stack version function.
+ *
+ * The function is used to get dvice stack version.
+ *
+ * @param[out] version The version structure pointer to keep the device stack version.
+ *
+ */
+void USB_DeviceGetVersion(uint32_t *version)
+{
+    if (version)
+    {
+        *version =
+            (uint32_t)USB_MAKE_VERSION(USB_STACK_VERSION_MAJOR, USB_STACK_VERSION_MINOR, USB_STACK_VERSION_BUGFIX);
+    }
+}
+
+#if ((defined(USB_DEVICE_CONFIG_REMOTE_WAKEUP)) && (USB_DEVICE_CONFIG_REMOTE_WAKEUP > 0U))
+/*!
+ * @brief Update the hardware tick.
+ *
+ * The function is used to update the hardware tick.
+ *
+ * @param[in] handle The device handle got from #USB_DeviceInit.
+ * @param[in] tick Current hardware tick.
+ *
+ */
+usb_status_t USB_DeviceUpdateHwTick(usb_device_handle handle, uint64_t tick)
+{
+    usb_device_struct_t *deviceHandle;
+    usb_status_t status = kStatus_USB_Success;
+
+    if (handle == NULL)
+    {
+        return kStatus_USB_InvalidHandle;
+    }
+    deviceHandle = (usb_device_struct_t *)handle;
+
+    deviceHandle->hwTick = tick;
+
+    return status;
+}
+#endif
+#endif /* USB_DEVICE_CONFIG_NUM */

+ 177 - 0
bsp/imxrt1052-evk/drivers/usb/device/usb_device_dci.h

@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
+ * Copyright 2016 NXP
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright notice, this list
+ *   of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright notice, this
+ *   list of conditions and the following disclaimer in the documentation and/or
+ *   other materials provided with the distribution.
+ *
+ * o Neither the name of the copyright holder nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __USB_DEVICE_DCI_H__
+#define __USB_DEVICE_DCI_H__
+
+/*!
+ * @addtogroup usb_device_controller_driver
+ * @{
+ */
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/*! @brief Macro to define controller handle */
+#define usb_device_controller_handle usb_device_handle
+
+/*! @brief Available notify types for device notification */
+typedef enum _usb_device_notification
+{
+    kUSB_DeviceNotifyBusReset = 0x10U, /*!< Reset signal detected */
+    kUSB_DeviceNotifySuspend,          /*!< Suspend signal detected */
+    kUSB_DeviceNotifyResume,           /*!< Resume signal detected */
+    kUSB_DeviceNotifyLPMSleep,         /*!< LPM signal detected */
+    kUSB_DeviceNotifyLPMResume,        /*!< Resume signal detected */
+    kUSB_DeviceNotifyError,            /*!< Errors happened in bus */
+    kUSB_DeviceNotifyDetach,           /*!< Device disconnected from a host */
+    kUSB_DeviceNotifyAttach,           /*!< Device connected to a host */
+#if (defined(USB_DEVICE_CHARGER_DETECT_ENABLE) && (USB_DEVICE_CHARGER_DETECT_ENABLE > 0U))
+    kUSB_DeviceNotifyDcdTimeOut,               /*!< Device charger detection timeout */
+    kUSB_DeviceNotifyDcdUnknownPortType,       /*!< Device charger detection unknown port type */
+    kUSB_DeviceNotifySDPDetected,              /*!< The SDP facility is detected */
+    kUSB_DeviceNotifyChargingPortDetected,     /*!< The charging port is detected */
+    kUSB_DeviceNotifyChargingHostDetected,     /*!< The CDP facility is detected */
+    kUSB_DeviceNotifyDedicatedChargerDetected, /*!< The DCP facility is detected */
+#endif
+} usb_device_notification_t;
+
+/*! @brief Device notification message structure */
+typedef struct _usb_device_callback_message_struct
+{
+    uint8_t *buffer; /*!< Transferred buffer */
+    uint32_t length; /*!< Transferred data length */
+    uint8_t code;    /*!< Notification code */
+    uint8_t isSetup; /*!< Is in a setup phase */
+} usb_device_callback_message_struct_t;
+
+/*! @brief Control type for controller */
+typedef enum _usb_device_control_type
+{
+    kUSB_DeviceControlRun = 0U,          /*!< Enable the device functionality */
+    kUSB_DeviceControlStop,              /*!< Disable the device functionality */
+    kUSB_DeviceControlEndpointInit,      /*!< Initialize a specified endpoint */
+    kUSB_DeviceControlEndpointDeinit,    /*!< De-initialize a specified endpoint */
+    kUSB_DeviceControlEndpointStall,     /*!< Stall a specified endpoint */
+    kUSB_DeviceControlEndpointUnstall,   /*!< Unstall a specified endpoint */
+    kUSB_DeviceControlGetDeviceStatus,   /*!< Get device status */
+    kUSB_DeviceControlGetEndpointStatus, /*!< Get endpoint status */
+    kUSB_DeviceControlSetDeviceAddress,  /*!< Set device address */
+    kUSB_DeviceControlGetSynchFrame,     /*!< Get current frame */
+    kUSB_DeviceControlResume,            /*!< Drive controller to generate a resume signal in USB bus */
+    kUSB_DeviceControlSleepResume,       /*!< Drive controller to generate a LPM resume signal in USB bus */
+    kUSB_DeviceControlSuspend,           /*!< Drive controller to enetr into suspend mode */
+    kUSB_DeviceControlSleep,             /*!< Drive controller to enetr into sleep mode */
+    kUSB_DeviceControlSetDefaultStatus,  /*!< Set controller to default status */
+    kUSB_DeviceControlGetSpeed,          /*!< Get current speed */
+    kUSB_DeviceControlGetOtgStatus,      /*!< Get OTG status */
+    kUSB_DeviceControlSetOtgStatus,      /*!< Set OTG status */
+    kUSB_DeviceControlSetTestMode,       /*!< Drive xCHI into test mode */
+    kUSB_DeviceControlGetRemoteWakeUp,   /*!< Get flag of LPM Remote Wake-up Enabled by USB host. */
+#if (defined(USB_DEVICE_CHARGER_DETECT_ENABLE) && (USB_DEVICE_CHARGER_DETECT_ENABLE > 0U))
+    kUSB_DeviceControlDcdInitModule,
+    kUSB_DeviceControlDcdDeinitModule,
+#endif
+} usb_device_control_type_t;
+
+/*! @brief USB device controller initialization function typedef */
+typedef usb_status_t (*usb_device_controller_init_t)(uint8_t controllerId,
+                                                     usb_device_handle handle,
+                                                     usb_device_controller_handle *controllerHandle);
+
+/*! @brief USB device controller de-initialization function typedef */
+typedef usb_status_t (*usb_device_controller_deinit_t)(usb_device_controller_handle controllerHandle);
+
+/*! @brief USB device controller send data function typedef */
+typedef usb_status_t (*usb_device_controller_send_t)(usb_device_controller_handle controllerHandle,
+                                                     uint8_t endpointAddress,
+                                                     uint8_t *buffer,
+                                                     uint32_t length);
+
+/*! @brief USB device controller receive data function typedef */
+typedef usb_status_t (*usb_device_controller_recv_t)(usb_device_controller_handle controllerHandle,
+                                                     uint8_t endpointAddress,
+                                                     uint8_t *buffer,
+                                                     uint32_t length);
+
+/*! @brief USB device controller cancel transfer function in a specified endpoint typedef */
+typedef usb_status_t (*usb_device_controller_cancel_t)(usb_device_controller_handle controllerHandle,
+                                                       uint8_t endpointAddress);
+
+/*! @brief USB device controller control function typedef */
+typedef usb_status_t (*usb_device_controller_control_t)(usb_device_controller_handle controllerHandle,
+                                                        usb_device_control_type_t command,
+                                                        void *param);
+
+/*! @brief USB device controller interface structure */
+typedef struct _usb_device_controller_interface_struct
+{
+    usb_device_controller_init_t deviceInit;       /*!< Controller initialization */
+    usb_device_controller_deinit_t deviceDeinit;   /*!< Controller de-initialization */
+    usb_device_controller_send_t deviceSend;       /*!< Controller send data */
+    usb_device_controller_recv_t deviceRecv;       /*!< Controller receive data */
+    usb_device_controller_cancel_t deviceCancel;   /*!< Controller cancel transfer */
+    usb_device_controller_control_t deviceControl; /*!< Controller control */
+} usb_device_controller_interface_struct_t;
+
+/*! @brief USB device status structure */
+typedef struct _usb_device_struct
+{
+#if ((defined(USB_DEVICE_CONFIG_REMOTE_WAKEUP)) && (USB_DEVICE_CONFIG_REMOTE_WAKEUP > 0U))
+    volatile uint64_t hwTick; /*!< Current hw tick(ms)*/
+#endif
+    usb_device_controller_handle controllerHandle;                       /*!< Controller handle */
+    const usb_device_controller_interface_struct_t *controllerInterface; /*!< Controller interface handle */
+#if USB_DEVICE_CONFIG_USE_TASK
+    usb_osa_msgq_handle notificationQueue; /*!< Message queue */
+#endif
+    usb_device_callback_t deviceCallback; /*!< Device callback function pointer */
+    usb_device_endpoint_callback_struct_t
+        epCallback[USB_DEVICE_CONFIG_ENDPOINTS << 1U]; /*!< Endpoint callback function structure */
+    uint8_t deviceAddress;                             /*!< Current device address */
+    uint8_t controllerId;                              /*!< Controller ID */
+    uint8_t state;                                     /*!< Current device state */
+#if ((defined(USB_DEVICE_CONFIG_REMOTE_WAKEUP)) && (USB_DEVICE_CONFIG_REMOTE_WAKEUP > 0U))
+    uint8_t remotewakeup; /*!< Remote wakeup is enabled or not */
+#endif
+    uint8_t isResetting; /*!< Is doing device reset or not */
+#if (defined(USB_DEVICE_CONFIG_USE_TASK) && (USB_DEVICE_CONFIG_USE_TASK > 0U))
+    uint8_t epCallbackDirectly; /*!< Whether call ep callback directly when the task is enabled */
+#endif
+} usb_device_struct_t;
+
+/*******************************************************************************
+ * API
+ ******************************************************************************/
+
+/*! @}*/
+
+#endif /* __USB_DEVICE_DCI_H__ */

+ 1807 - 0
bsp/imxrt1052-evk/drivers/usb/device/usb_device_ehci.c

@@ -0,0 +1,1807 @@
+/*
+ * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
+ * Copyright 2016 - 2017 NXP
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright notice, this list
+ *   of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright notice, this
+ *   list of conditions and the following disclaimer in the documentation and/or
+ *   other materials provided with the distribution.
+ *
+ * o Neither the name of the copyright holder nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <usb/include/usb_device_config.h>
+#include "fsl_device_registers.h"
+#include <usb/include/usb.h>
+#include "usb_device.h"
+#if ((defined(USB_DEVICE_CONFIG_EHCI)) && (USB_DEVICE_CONFIG_EHCI > 0U))
+
+#include "usb_device_dci.h"
+
+#include "usb_device_ehci.h"
+#if (defined(USB_DEVICE_CONFIG_LOW_POWER_MODE) && (USB_DEVICE_CONFIG_LOW_POWER_MODE > 0U))
+#include "usb_phy.h"
+#endif
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+#if defined(USB_STACK_USE_DEDICATED_RAM) && (USB_STACK_USE_DEDICATED_RAM > 0U)
+
+#error The SOC does not suppoort dedicated RAM case.
+
+#endif
+
+/*******************************************************************************
+ * Prototypes
+ ******************************************************************************/
+
+static void USB_DeviceEhciSetDefaultState(usb_device_ehci_state_struct_t *ehciState);
+static usb_status_t USB_DeviceEhciEndpointInit(usb_device_ehci_state_struct_t *ehciState,
+                                               usb_device_endpoint_init_struct_t *epInit);
+static usb_status_t USB_DeviceEhciEndpointDeinit(usb_device_ehci_state_struct_t *ehciState, uint8_t ep);
+static usb_status_t USB_DeviceEhciEndpointStall(usb_device_ehci_state_struct_t *ehciState, uint8_t ep);
+static usb_status_t USB_DeviceEhciEndpointUnstall(usb_device_ehci_state_struct_t *ehciState, uint8_t ep);
+static void USB_DeviceEhciFillSetupBuffer(usb_device_ehci_state_struct_t *ehciState, uint8_t ep);
+static void USB_DeviceEhciCancelControlPipe(usb_device_ehci_state_struct_t *ehciState,
+                                            uint8_t endpoint,
+                                            uint8_t direction);
+static void USB_DeviceEhciInterruptTokenDone(usb_device_ehci_state_struct_t *ehciState);
+static void USB_DeviceEhciInterruptPortChange(usb_device_ehci_state_struct_t *ehciState);
+static void USB_DeviceEhciInterruptReset(usb_device_ehci_state_struct_t *ehciState);
+static void USB_DeviceEhciInterruptSof(usb_device_ehci_state_struct_t *ehciState);
+#if (defined(USB_DEVICE_CONFIG_LOW_POWER_MODE) && (USB_DEVICE_CONFIG_LOW_POWER_MODE > 0U))
+static void USB_DeviceEhciInterruptSuspend(usb_device_ehci_state_struct_t *ehciState);
+#endif /* USB_DEVICE_CONFIG_LOW_POWER_MODE */
+static usb_status_t USB_DeviceEhciTransfer(usb_device_ehci_state_struct_t *ehciState,
+                                           uint8_t endpointAddress,
+                                           uint8_t *buffer,
+                                           uint32_t length);
+
+extern usb_status_t USB_DeviceNotificationTrigger(void *handle, void *msg);
+
+/*******************************************************************************
+ * Variables
+ ******************************************************************************/
+
+/* Apply for QH buffer, 2048-byte alignment */
+USB_RAM_ADDRESS_ALIGNMENT(2048)
+USB_CONTROLLER_DATA static uint8_t qh_buffer[(USB_DEVICE_CONFIG_EHCI - 1) * 2048 +
+                                             USB_DEVICE_CONFIG_ENDPOINTS * 2 * sizeof(usb_device_ehci_qh_struct_t)];
+
+/* Apply for DTD buffer, 32-byte alignment */
+USB_RAM_ADDRESS_ALIGNMENT(32)
+USB_CONTROLLER_DATA static usb_device_ehci_dtd_struct_t
+    s_UsbDeviceEhciDtd[USB_DEVICE_CONFIG_EHCI][USB_DEVICE_CONFIG_EHCI_MAX_DTD];
+
+/* Apply for ehci device state structure */
+static usb_device_ehci_state_struct_t g_UsbDeviceEhciSate[USB_DEVICE_CONFIG_EHCI];
+
+#if (defined(USB_DEVICE_CHARGER_DETECT_ENABLE) && (USB_DEVICE_CHARGER_DETECT_ENABLE > 0U)) && \
+    (defined(FSL_FEATURE_SOC_USBHSDCD_COUNT) && (FSL_FEATURE_SOC_USBHSDCD_COUNT > 0U))
+/* Apply for device dcd state structure */
+static usb_device_dcd_state_struct_t s_UsbDeviceDcdHSState[USB_DEVICE_CONFIG_EHCI];
+#endif
+
+/*******************************************************************************
+ * Code
+ ******************************************************************************/
+/*!
+ * @brief EHCI NC get USB NC bass address.
+ *
+ * This function is used to get USB NC bass address.
+ *
+ * @param[in] controllerId    EHCI controller ID; See the #usb_controller_index_t.
+ *
+ * @retval USB NC bass address.
+ */
+#if (defined(USB_DEVICE_CONFIG_LOW_POWER_MODE) && (USB_DEVICE_CONFIG_LOW_POWER_MODE > 0U))
+#if (defined(FSL_FEATURE_SOC_USBNC_COUNT) && (FSL_FEATURE_SOC_USBNC_COUNT > 0U))
+void *USB_EhciNCGetBase(uint8_t controllerId)
+{
+    void *usbNCBase = NULL;
+#if ((defined FSL_FEATURE_SOC_USBNC_COUNT) && (FSL_FEATURE_SOC_USBNC_COUNT > 0U))
+    uint32_t instance;
+    uint32_t newinstance = 0;
+    uint32_t usbnc_base_temp[] = USBNC_BASE_ADDRS;
+    uint32_t usbnc_base[] = USBNC_BASE_ADDRS;
+
+    if (controllerId < kUSB_ControllerEhci0)
+    {
+        return NULL;
+    }
+
+    controllerId = controllerId - kUSB_ControllerEhci0;
+
+    for (instance = 0; instance < (sizeof(usbnc_base_temp) / sizeof(usbnc_base_temp[0])); instance++)
+    {
+        if (usbnc_base_temp[instance])
+        {
+            usbnc_base[newinstance++] = usbnc_base_temp[instance];
+        }
+    }
+    if (controllerId > newinstance)
+    {
+        return NULL;
+    }
+
+    usbNCBase = (void *)usbnc_base[controllerId];
+#endif
+    return usbNCBase;
+}
+#endif
+#endif
+
+/*!
+ * @brief Set device controller state to default state.
+ *
+ * The function is used to set device controller state to default state.
+ * The function will be called when USB_DeviceEhciInit called or the control type kUSB_DeviceControlGetEndpointStatus
+ * received in USB_DeviceEhciControl.
+ *
+ * @param ehciState       Pointer of the device EHCI state structure.
+ *
+ */
+static void USB_DeviceEhciSetDefaultState(usb_device_ehci_state_struct_t *ehciState)
+{
+    usb_device_ehci_dtd_struct_t *p;
+
+    /* Initialize the dtd free queue */
+    ehciState->dtdFree = ehciState->dtd;
+    p = ehciState->dtdFree;
+    for (uint32_t i = 1U; i < USB_DEVICE_CONFIG_EHCI_MAX_DTD; i++)
+    {
+        p->nextDtdPointer = (uint32_t)&ehciState->dtd[i];
+        p = (usb_device_ehci_dtd_struct_t *)p->nextDtdPointer;
+    }
+    p->nextDtdPointer = 0U;
+    ehciState->dtdCount = USB_DEVICE_CONFIG_EHCI_MAX_DTD;
+
+    /* Not use interrupt threshold. */
+    ehciState->registerBase->USBCMD &= ~USBHS_USBCMD_ITC_MASK;
+    ehciState->registerBase->USBCMD |= USBHS_USBCMD_ITC(0U);
+
+    /* Disable setup lockout, please refer to "Control Endpoint Operation" section in RM. */
+    ehciState->registerBase->USBMODE |= USBHS_USBMODE_SLOM_MASK;
+
+/* Set the endian by using CPU's endian */
+#if (ENDIANNESS == USB_BIG_ENDIAN)
+    ehciState->registerBase->USBMODE |= USBHS_USBMODE_ES_MASK;
+#else
+    ehciState->registerBase->USBMODE &= ~USBHS_USBMODE_ES_MASK;
+#endif
+    /* Initialize the QHs of endpoint. */
+    for (uint32_t i = 0U; i < (USB_DEVICE_CONFIG_ENDPOINTS * 2U); i++)
+    {
+        ehciState->qh[i].nextDtdPointer = USB_DEVICE_ECHI_DTD_TERMINATE_MASK;
+        ehciState->qh[i].capabilttiesCharacteristicsUnion.capabilttiesCharacteristicsBitmap.maxPacketSize =
+            USB_CONTROL_MAX_PACKET_SIZE;
+        ehciState->dtdHard[i] = NULL;
+        ehciState->dtdTail[i] = NULL;
+        ehciState->qh[i].endpointStatusUnion.endpointStatusBitmap.isOpened = 0U;
+    }
+
+    /* Add QH buffer address to USBHS_EPLISTADDR_REG */
+    ehciState->registerBase->EPLISTADDR = (uint32_t)ehciState->qh;
+
+    /* Clear device address */
+    ehciState->registerBase->DEVICEADDR = 0U;
+
+#if defined(USB_DEVICE_CONFIG_DETACH_ENABLE) && (USB_DEVICE_CONFIG_DETACH_ENABLE > 0U)
+    ehciState->registerBase->OTGSC = ehciState->registerBase->OTGSC & 0x0000FFFF;
+    ehciState->registerBase->OTGSC |= USBHS_OTGSC_BSVIE_MASK;
+#endif /* USB_DEVICE_CONFIG_DETACH_ENABLE */
+
+    /* Enable reset, sof, token, stall interrupt */
+    ehciState->registerBase->USBINTR =
+        (USBHS_USBINTR_UE_MASK | USBHS_USBINTR_UEE_MASK | USBHS_USBINTR_PCE_MASK | USBHS_USBINTR_URE_MASK
+#if (defined(USB_DEVICE_CONFIG_LOW_POWER_MODE) && (USB_DEVICE_CONFIG_LOW_POWER_MODE > 0U))
+         | USBHS_USBINTR_SLE_MASK
+#endif /* USB_DEVICE_CONFIG_LOW_POWER_MODE */
+         );
+
+    /* Clear reset flag */
+    ehciState->isResetting = 0U;
+}
+
+/*!
+ * @brief Initialize a specified endpoint.
+ *
+ * The function is used to initialize a specified endpoint.
+ *
+ * @param ehciState       Pointer of the device EHCI state structure.
+ * @param epInit          The endpoint initialization structure pointer.
+ *
+ * @return A USB error code or kStatus_USB_Success.
+ */
+static usb_status_t USB_DeviceEhciEndpointInit(usb_device_ehci_state_struct_t *ehciState,
+                                               usb_device_endpoint_init_struct_t *epInit)
+{
+    uint32_t primeBit = 1U << ((epInit->endpointAddress & USB_ENDPOINT_NUMBER_MASK) +
+                               ((epInit->endpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >> 0x03U));
+    uint16_t maxPacketSize = epInit->maxPacketSize & USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_SIZE_MASK;
+    uint8_t endpoint = (epInit->endpointAddress & USB_ENDPOINT_NUMBER_MASK);
+    uint8_t direction = (epInit->endpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >>
+                        USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT;
+    uint8_t index = ((uint8_t)((uint32_t)endpoint << 1U)) | direction;
+    uint8_t transferType = epInit->transferType & USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_TYPE_MASK;
+
+    /* Cancel pending transfer of the endpoint */
+    USB_DeviceEhciCancel(ehciState, epInit->endpointAddress);
+
+    if ((ehciState->registerBase->EPPRIME & primeBit) || (ehciState->registerBase->EPSR & primeBit))
+    {
+        return kStatus_USB_Busy;
+    }
+
+    /* Make the endpoint max packet size align with USB Specification 2.0. */
+    if (USB_ENDPOINT_ISOCHRONOUS == transferType)
+    {
+        if (maxPacketSize > USB_DEVICE_MAX_HS_ISO_MAX_PACKET_SIZE)
+        {
+            maxPacketSize = USB_DEVICE_MAX_HS_ISO_MAX_PACKET_SIZE;
+        }
+        ehciState->qh[index].capabilttiesCharacteristicsUnion.capabilttiesCharacteristicsBitmap.mult =
+            1U + ((maxPacketSize & USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_MASK) >>
+                  USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_SHFIT);
+    }
+    else
+    {
+        ehciState->qh[index].capabilttiesCharacteristicsUnion.capabilttiesCharacteristicsBitmap.mult = 0U;
+    }
+
+    /* Save the max packet size of the endpoint */
+    ehciState->qh[index].capabilttiesCharacteristicsUnion.capabilttiesCharacteristicsBitmap.maxPacketSize =
+        maxPacketSize;
+    /* Set ZLT bit. */
+    ehciState->qh[index].capabilttiesCharacteristicsUnion.capabilttiesCharacteristicsBitmap.zlt = !epInit->zlt;
+
+    /* Enable the endpoint. */
+    if (USB_ENDPOINT_CONTROL == transferType)
+    {
+        ehciState->qh[index].capabilttiesCharacteristicsUnion.capabilttiesCharacteristicsBitmap.ios = 1U;
+        ehciState->registerBase->EPCR0 |=
+            (direction ?
+                 (USBHS_EPCR_TXE_MASK | USBHS_EPCR_TXR_MASK | ((uint32_t)transferType << USBHS_EPCR_TXT_SHIFT)) :
+                 (USBHS_EPCR_RXE_MASK | USBHS_EPCR_RXR_MASK | ((uint32_t)transferType << USBHS_EPCR_RXT_SHIFT)));
+    }
+    else
+    {
+        ehciState->qh[index].capabilttiesCharacteristicsUnion.capabilttiesCharacteristicsBitmap.ios = 0U;
+        ehciState->registerBase->EPCR[endpoint - 1U] |=
+            (direction ?
+                 (USBHS_EPCR_TXE_MASK | USBHS_EPCR_TXR_MASK | ((uint32_t)transferType << USBHS_EPCR_TXT_SHIFT)) :
+                 (USBHS_EPCR_RXE_MASK | USBHS_EPCR_RXR_MASK | ((uint32_t)transferType << USBHS_EPCR_RXT_SHIFT)));
+    }
+
+    ehciState->qh[index].endpointStatusUnion.endpointStatusBitmap.isOpened = 1U;
+    return kStatus_USB_Success;
+}
+
+/*!
+ * @brief De-initialize a specified endpoint.
+ *
+ * The function is used to de-initialize a specified endpoint.
+ * Current transfer of the endpoint will be cancelled and the specified endpoint will be disabled.
+ *
+ * @param ehciState       Pointer of the device EHCI state structure.
+ * @param ep               The endpoint address, Bit7, 0U - USB_OUT, 1U - USB_IN.
+ *
+ * @return A USB error code or kStatus_USB_Success.
+ */
+static usb_status_t USB_DeviceEhciEndpointDeinit(usb_device_ehci_state_struct_t *ehciState, uint8_t ep)
+{
+    uint32_t primeBit =
+        1U << ((ep & USB_ENDPOINT_NUMBER_MASK) + ((ep & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >> 0x03U));
+    uint8_t endpoint = (ep & USB_ENDPOINT_NUMBER_MASK);
+    uint8_t direction =
+        (ep & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >> USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT;
+    uint8_t index = ((uint8_t)((uint32_t)endpoint << 1U)) | direction;
+
+    ehciState->qh[index].endpointStatusUnion.endpointStatusBitmap.isOpened = 0U;
+
+    /* Cancel the transfer of the endpoint */
+    USB_DeviceEhciCancel(ehciState, ep);
+
+    if ((ehciState->registerBase->EPPRIME & primeBit) || (ehciState->registerBase->EPSR & primeBit))
+    {
+        return kStatus_USB_Busy;
+    }
+
+    /* Clear endpoint state */
+    ehciState->qh[index].capabilttiesCharacteristicsUnion.capabilttiesCharacteristics = 0U;
+    /* Disable the endpoint */
+    if (!endpoint)
+    {
+        ehciState->registerBase->EPCR0 &=
+            ~(direction ? (USBHS_EPCR_TXE_MASK | USBHS_EPCR_TXT_MASK) : (USBHS_EPCR_RXE_MASK | USBHS_EPCR_RXT_MASK));
+    }
+    else
+    {
+        ehciState->registerBase->EPCR[endpoint - 1U] &=
+            ~(direction ? (USBHS_EPCR_TXE_MASK | USBHS_EPCR_TXT_MASK) : (USBHS_EPCR_RXE_MASK | USBHS_EPCR_RXT_MASK));
+    }
+
+    return kStatus_USB_Success;
+}
+
+/*!
+ * @brief Stall a specified endpoint.
+ *
+ * The function is used to stall a specified endpoint.
+ * Current transfer of the endpoint will be cancelled and the specified endpoint will be stalled.
+ *
+ * @param ehciState       Pointer of the device EHCI state structure.
+ * @param ep               The endpoint address, Bit7, 0U - USB_OUT, 1U - USB_IN.
+ *
+ * @return A USB error code or kStatus_USB_Success.
+ */
+static usb_status_t USB_DeviceEhciEndpointStall(usb_device_ehci_state_struct_t *ehciState, uint8_t ep)
+{
+    uint8_t endpoint = ep & USB_ENDPOINT_NUMBER_MASK;
+    uint8_t direction =
+        (ep & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >> USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT;
+    uint8_t index = ((uint8_t)((uint32_t)endpoint << 1U)) | direction;
+
+    /* Cancel the transfer of the endpoint */
+    USB_DeviceEhciCancel(ehciState, ep);
+
+    /* Set endpoint stall flag. */
+    if (ehciState->qh[index].capabilttiesCharacteristicsUnion.capabilttiesCharacteristicsBitmap.ios)
+    {
+        if (!endpoint)
+        {
+            ehciState->registerBase->EPCR0 |= (USBHS_EPCR_TXS_MASK | USBHS_EPCR_RXS_MASK);
+        }
+        else
+        {
+            ehciState->registerBase->EPCR[endpoint - 1U] |= (USBHS_EPCR_TXS_MASK | USBHS_EPCR_RXS_MASK);
+        }
+    }
+    else
+    {
+        if (!endpoint)
+        {
+            ehciState->registerBase->EPCR0 |= (direction ? USBHS_EPCR_TXS_MASK : USBHS_EPCR_RXS_MASK);
+        }
+        else
+        {
+            ehciState->registerBase->EPCR[endpoint - 1U] |= (direction ? USBHS_EPCR_TXS_MASK : USBHS_EPCR_RXS_MASK);
+        }
+    }
+
+    return kStatus_USB_Success;
+}
+
+/*!
+ * @brief Un-stall a specified endpoint.
+ *
+ * The function is used to un-stall a specified endpoint.
+ * Current transfer of the endpoint will be cancelled and the specified endpoint will be un-stalled.
+ *
+ * @param ehciState       Pointer of the device EHCI state structure.
+ * @param ep               The endpoint address, Bit7, 0U - USB_OUT, 1U - USB_IN.
+ *
+ * @return A USB error code or kStatus_USB_Success.
+ */
+static usb_status_t USB_DeviceEhciEndpointUnstall(usb_device_ehci_state_struct_t *ehciState, uint8_t ep)
+{
+    uint8_t endpoint = ep & USB_ENDPOINT_NUMBER_MASK;
+    uint8_t direction =
+        (ep & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >> USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT;
+
+    /* Clear the endpoint stall state */
+    if (!endpoint)
+    {
+        ehciState->registerBase->EPCR0 &= ~(direction ? USBHS_EPCR_TXS_MASK : USBHS_EPCR_RXS_MASK);
+    }
+    else
+    {
+        ehciState->registerBase->EPCR[endpoint - 1U] &= ~(direction ? USBHS_EPCR_TXS_MASK : USBHS_EPCR_RXS_MASK);
+        ehciState->registerBase->EPCR[endpoint - 1U] |= (direction ? USBHS_EPCR_TXR_MASK : USBHS_EPCR_RXR_MASK);
+    }
+
+    return kStatus_USB_Success;
+}
+
+/*!
+ * @brief Get setup packet data.
+ *
+ * The function is used to get setup packet data and copy to a backup buffer.
+ *
+ * @param ehciState       Pointer of the device EHCI state structure.
+ * @param ep               The endpoint number.
+ *
+ */
+static void USB_DeviceEhciFillSetupBuffer(usb_device_ehci_state_struct_t *ehciState, uint8_t ep)
+{
+    uint8_t waitingSafelyAccess = 1U;
+    uint8_t index = (ep * 2U) | USB_OUT;
+
+    /* Write 1U to clear corresponding bit in EPSETUPSR. */
+    ehciState->registerBase->EPSETUPSR = 1U << ep;
+
+    while (waitingSafelyAccess)
+    {
+        /* Set the setup tripwire bit. */
+        ehciState->registerBase->USBCMD |= USBHS_USBCMD_SUTW_MASK;
+
+        /* Copy setup packet data to backup buffer */
+        ehciState->qh[index].setupBufferBack[0] = ehciState->qh[index].setupBuffer[0];
+        ehciState->qh[index].setupBufferBack[1] = ehciState->qh[index].setupBuffer[1];
+
+        /* Read the USBCMD[SUTW] bit. If set, jump out from the while loop; if cleared continue */
+        if (ehciState->registerBase->USBCMD & USBHS_USBCMD_SUTW_MASK)
+        {
+            waitingSafelyAccess = 0U;
+        }
+    }
+    /* Clear the setup tripwire bit */
+    ehciState->registerBase->USBCMD &= ~USBHS_USBCMD_SUTW_MASK;
+
+    /* Poll until the EPSETUPSR bit clearred */
+    while (ehciState->registerBase->EPSETUPSR & (1U << ep))
+    {
+    }
+}
+
+/*!
+ * @brief Cancel the transfer of the control pipe.
+ *
+ * The function is used to cancel the transfer of the control pipe.
+ *
+ * @param ehciState       Pointer of the device EHCI state structure.
+ * @param endpoint         The endpoint number.
+ * @param direction        The direction of the endpoint.
+ *
+ */
+static void USB_DeviceEhciCancelControlPipe(usb_device_ehci_state_struct_t *ehciState,
+                                            uint8_t endpoint,
+                                            uint8_t direction)
+{
+    usb_device_ehci_dtd_struct_t *currentDtd;
+    uint32_t index = ((uint32_t)endpoint << 1U) + (uint32_t)direction;
+    usb_device_callback_message_struct_t message;
+
+    message.buffer = NULL;
+    message.length = 0U;
+    /* Get the dtd of the control pipe */
+    currentDtd =
+        (usb_device_ehci_dtd_struct_t *)((uint32_t)ehciState->dtdHard[index] & USB_DEVICE_ECHI_DTD_POINTER_MASK);
+    while (currentDtd)
+    {
+        /* Pass the transfer buffer address */
+        if (NULL == message.buffer)
+        {
+            uint32_t bufferAddress = currentDtd->bufferPointerPage[0];
+            message.buffer = (uint8_t *)((bufferAddress & USB_DEVICE_ECHI_DTD_PAGE_MASK) |
+                                         (currentDtd->reservedUnion.originalBufferInfo.originalBufferOffest));
+        }
+        /* If the dtd is active, set the message length to USB_UNINITIALIZED_VAL_32. Or set the length by using finished
+         * length. */
+        if (currentDtd->dtdTokenUnion.dtdTokenBitmap.status & USB_DEVICE_ECHI_DTD_STATUS_ACTIVE)
+        {
+            message.length = USB_UNINITIALIZED_VAL_32;
+        }
+        else
+        {
+            message.length += (currentDtd->reservedUnion.originalBufferInfo.originalBufferLength -
+                               currentDtd->dtdTokenUnion.dtdTokenBitmap.totalBytes);
+        }
+
+        /* Move the dtd head pointer to next. */
+        /* If the pointer of the head equals to the tail, set the dtd queue to null. */
+        if (ehciState->dtdHard[index] == ehciState->dtdTail[index])
+        {
+            ehciState->dtdHard[index] = NULL;
+            ehciState->dtdTail[index] = NULL;
+            ehciState->qh[index].nextDtdPointer = USB_DEVICE_ECHI_DTD_TERMINATE_MASK;
+            ehciState->qh[index].dtdTokenUnion.dtdToken = 0U;
+        }
+        else
+        {
+            ehciState->dtdHard[index] = (usb_device_ehci_dtd_struct_t *)ehciState->dtdHard[index]->nextDtdPointer;
+        }
+
+        /* When the ioc is set or the dtd queue is empty, the up layer will be notified. */
+        if ((currentDtd->dtdTokenUnion.dtdTokenBitmap.ioc) ||
+            (0 == ((uint32_t)ehciState->dtdHard[index] & USB_DEVICE_ECHI_DTD_POINTER_MASK)))
+        {
+            message.code = endpoint | (uint8_t)((uint32_t)direction << 0x07U);
+            message.isSetup = 0U;
+            USB_DeviceNotificationTrigger(ehciState->deviceHandle, &message);
+            message.buffer = NULL;
+            message.length = 0U;
+        }
+
+        /* Clear the token field of the dtd. */
+        currentDtd->dtdTokenUnion.dtdToken = 0U;
+        /* Add the dtd to the free dtd queue. */
+        currentDtd->nextDtdPointer = (uint32_t)ehciState->dtdFree;
+        ehciState->dtdFree = currentDtd;
+        ehciState->dtdCount++;
+
+        /* Get the next in-used dtd. */
+        currentDtd =
+            (usb_device_ehci_dtd_struct_t *)((uint32_t)ehciState->dtdHard[index] & USB_DEVICE_ECHI_DTD_POINTER_MASK);
+    }
+}
+
+/*!
+ * @brief Handle the endpoint token done interrupt.
+ *
+ * The function is used to handle the endpoint token done interrupt.
+ *
+ * @param ehciState       Pointer of the device EHCI state structure.
+ *
+ */
+static void USB_DeviceEhciInterruptTokenDone(usb_device_ehci_state_struct_t *ehciState)
+{
+    uint32_t status;
+    uint32_t primeBit;
+    usb_device_ehci_dtd_struct_t *currentDtd;
+    usb_device_callback_message_struct_t message;
+    uint8_t endpoint;
+    uint8_t direction;
+    uint8_t count;
+    uint8_t index;
+
+    /* Get the EPSETUPSR to check the setup packect received in which one endpoint. */
+    status = ehciState->registerBase->EPSETUPSR;
+
+    if (status)
+    {
+        for (endpoint = 0U; endpoint < USB_DEVICE_CONFIG_ENDPOINTS; endpoint++)
+        {
+            /* Check the endpoint receive the setup packet. */
+            if (status & (1U << endpoint))
+            {
+                /* Get last setup packet */
+                usb_setup_struct_t *deviceSetup =
+                    (usb_setup_struct_t *)&ehciState->qh[(uint8_t)((uint32_t)endpoint << 1U) + USB_OUT].setupBufferBack;
+
+                /* Check the direction of the data phase. */
+                direction = (deviceSetup->bmRequestType & USB_REQUEST_TYPE_DIR_IN) >> USB_REQUEST_TYPE_DIR_SHIFT;
+                /* Cancel the data phase transfer */
+                USB_DeviceEhciCancelControlPipe(ehciState, endpoint, direction);
+                /* Cancel the status phase transfer */
+                USB_DeviceEhciCancelControlPipe(ehciState, endpoint, 1U ^ direction);
+                message.code = (endpoint) | (USB_OUT << 0x07U);
+                message.buffer = (uint8_t *)deviceSetup;
+                message.length = USB_SETUP_PACKET_SIZE;
+                message.isSetup = 1U;
+                /* Fill the setup packet to the backup buffer */
+                USB_DeviceEhciFillSetupBuffer(ehciState, endpoint);
+                /* Notify the up layer the EHCI status changed. */
+                USB_DeviceNotificationTrigger(ehciState->deviceHandle, &message);
+            }
+        }
+    }
+    /* Read the USBHS_EPCOMPLETE_REG to get the endpoint transfer done status */
+    status = ehciState->registerBase->EPCOMPLETE;
+    /* Clear the endpoint transfer done status */
+    ehciState->registerBase->EPCOMPLETE = status;
+
+    if (status)
+    {
+        for (count = 0U; count < 32U; count++)
+        {
+            /* Check the transfer is done or not in the specified endpoint. */
+            if (status & ((uint32_t)(1U << count)))
+            {
+                if (count > 15U)
+                {
+                    endpoint = count - 16U;
+                    direction = USB_IN;
+                }
+                else
+                {
+                    endpoint = count;
+                    direction = USB_OUT;
+                }
+                if (endpoint >= USB_DEVICE_CONFIG_ENDPOINTS)
+                {
+                    continue;
+                }
+                index = (endpoint << 1U) + direction;
+                message.buffer = NULL;
+                message.length = 0U;
+
+                /* Get the in-used dtd of the specified endpoint. */
+                currentDtd = (usb_device_ehci_dtd_struct_t *)((uint32_t)ehciState->dtdHard[index] &
+                                                              USB_DEVICE_ECHI_DTD_POINTER_MASK);
+                while (currentDtd)
+                {
+                    uint8_t isTokenDone = 0;
+                    /* Get the in-used dtd of the specified endpoint. */
+                    currentDtd = (usb_device_ehci_dtd_struct_t *)((uint32_t)ehciState->dtdHard[index] &
+                                                                  USB_DEVICE_ECHI_DTD_POINTER_MASK);
+
+                    while (currentDtd)
+                    {
+                        /* Don't handle the active dtd. */
+                        if ((currentDtd->dtdTokenUnion.dtdTokenBitmap.status & USB_DEVICE_ECHI_DTD_STATUS_ACTIVE) ||
+                            (currentDtd->dtdTokenUnion.dtdTokenBitmap.ioc))
+                        {
+                            if ((!(currentDtd->dtdTokenUnion.dtdTokenBitmap.status &
+                                   USB_DEVICE_ECHI_DTD_STATUS_ACTIVE)) &&
+                                (currentDtd->dtdTokenUnion.dtdTokenBitmap.ioc))
+                            {
+                                isTokenDone = 1U;
+                            }
+                            break;
+                        }
+                        currentDtd = (usb_device_ehci_dtd_struct_t *)(currentDtd->nextDtdPointer &
+                                                                      USB_DEVICE_ECHI_DTD_POINTER_MASK);
+                    }
+
+                    if ((0 == isTokenDone) && (currentDtd))
+                    {
+                        break;
+                    }
+
+                    /* Get the in-used dtd of the specified endpoint. */
+                    currentDtd = (usb_device_ehci_dtd_struct_t *)((uint32_t)ehciState->dtdHard[index] &
+                                                                  USB_DEVICE_ECHI_DTD_POINTER_MASK);
+                    while (currentDtd)
+                    {
+                        /* Don't handle the active dtd. */
+                        if (currentDtd->dtdTokenUnion.dtdTokenBitmap.status & USB_DEVICE_ECHI_DTD_STATUS_ACTIVE)
+                        {
+                            break;
+                        }
+
+                        /* Save the transfer buffer address */
+                        if (NULL == message.buffer)
+                        {
+                            message.buffer =
+                                (uint8_t *)((currentDtd->bufferPointerPage[0] & USB_DEVICE_ECHI_DTD_PAGE_MASK) |
+                                            (currentDtd->reservedUnion.originalBufferInfo.originalBufferOffest));
+                        }
+                        /* Save the transferred data length */
+                        message.length += (currentDtd->reservedUnion.originalBufferInfo.originalBufferLength -
+                                           currentDtd->dtdTokenUnion.dtdTokenBitmap.totalBytes);
+
+                        /* Move the dtd queue head pointer to next */
+                        if (ehciState->dtdHard[index] == ehciState->dtdTail[index])
+                        {
+                            ehciState->dtdHard[index] = NULL;
+                            ehciState->dtdTail[index] = NULL;
+                            ehciState->qh[index].nextDtdPointer = USB_DEVICE_ECHI_DTD_TERMINATE_MASK;
+                            ehciState->qh[index].dtdTokenUnion.dtdToken = 0U;
+                        }
+                        else
+                        {
+                            ehciState->dtdHard[index] =
+                                (usb_device_ehci_dtd_struct_t *)ehciState->dtdHard[index]->nextDtdPointer;
+                        }
+
+                        /* When the ioc is set or the dtd queue is empty, the up layer will be notified. */
+                        if ((currentDtd->dtdTokenUnion.dtdTokenBitmap.ioc) ||
+                            (0 == ((uint32_t)ehciState->dtdHard[index] & USB_DEVICE_ECHI_DTD_POINTER_MASK)))
+                        {
+                            message.code = endpoint | (uint8_t)((uint32_t)direction << 0x07U);
+                            message.isSetup = 0U;
+                            USB_DeviceNotificationTrigger(ehciState->deviceHandle, &message);
+                            message.buffer = NULL;
+                            message.length = 0U;
+                        }
+                        /* Clear the token field of the dtd */
+                        currentDtd->dtdTokenUnion.dtdToken = 0U;
+                        currentDtd->nextDtdPointer = (uint32_t)ehciState->dtdFree;
+                        ehciState->dtdFree = currentDtd;
+                        ehciState->dtdCount++;
+                        /* Get the next in-used dtd */
+                        currentDtd = (usb_device_ehci_dtd_struct_t *)((uint32_t)ehciState->dtdHard[index] &
+                                                                      USB_DEVICE_ECHI_DTD_POINTER_MASK);
+
+                        if ((NULL != currentDtd) &&
+                            (currentDtd->dtdTokenUnion.dtdTokenBitmap.status & USB_DEVICE_ECHI_DTD_STATUS_ACTIVE))
+                        {
+                            primeBit = 1U << (endpoint + 16U * direction);
+
+                            /* Try to prime the next dtd. */
+                            ehciState->registerBase->EPPRIME = primeBit;
+
+                            /* Whether the endpoint transmit/receive buffer is ready or not. If not, wait for prime bit
+                             * cleared and prime the next dtd. */
+                            if (!(ehciState->registerBase->EPSR & primeBit))
+                            {
+                                /* Wait for the endpoint prime bit cleared by HW */
+                                while (ehciState->registerBase->EPPRIME & primeBit)
+                                {
+                                }
+
+                                /* If the endpoint transmit/receive buffer is not ready */
+                                if (!(ehciState->registerBase->EPSR & primeBit))
+                                {
+                                    /* Prime next dtd and prime the transfer */
+                                    ehciState->qh[index].nextDtdPointer = (uint32_t)currentDtd;
+                                    ehciState->qh[index].dtdTokenUnion.dtdToken = 0U;
+                                    ehciState->registerBase->EPPRIME = primeBit;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+/*!
+ * @brief Handle the port status change interrupt.
+ *
+ * The function is used to handle the port status change interrupt.
+ *
+ * @param ehciState       Pointer of the device EHCI state structure.
+ *
+ */
+static void USB_DeviceEhciInterruptPortChange(usb_device_ehci_state_struct_t *ehciState)
+{
+    usb_device_callback_message_struct_t message;
+
+    message.buffer = (uint8_t *)NULL;
+    message.length = 0U;
+    message.isSetup = 0U;
+
+    /* Whether the port is doing reset. */
+    if (!(ehciState->registerBase->PORTSC1 & USBHS_PORTSC1_PR_MASK))
+    {
+        /* If not, update the USB speed. */
+        if (ehciState->registerBase->PORTSC1 & USBHS_PORTSC1_HSP_MASK)
+        {
+            ehciState->speed = USB_SPEED_HIGH;
+        }
+        else
+        {
+            ehciState->speed = USB_SPEED_FULL;
+        }
+
+        /* If the device reset flag is non-zero, notify the up layer the device reset finished. */
+        if (ehciState->isResetting)
+        {
+            message.code = kUSB_DeviceNotifyBusReset;
+            USB_DeviceNotificationTrigger(ehciState->deviceHandle, &message);
+            ehciState->isResetting = 0U;
+        }
+    }
+
+#if (defined(USB_DEVICE_CONFIG_LOW_POWER_MODE) && (USB_DEVICE_CONFIG_LOW_POWER_MODE > 0U))
+    if ((ehciState->isSuspending) && (!(ehciState->registerBase->PORTSC1 & USBHS_PORTSC1_SUSP_MASK)))
+    {
+        /* Set the resume flag */
+        ehciState->isSuspending = 0U;
+
+        message.code = kUSB_DeviceNotifyResume;
+        USB_DeviceNotificationTrigger(ehciState->deviceHandle, &message);
+    }
+#endif /* USB_DEVICE_CONFIG_LOW_POWER_MODE */
+}
+
+/*!
+ * @brief Handle the reset interrupt.
+ *
+ * The function is used to handle the reset interrupt.
+ *
+ * @param ehciState       Pointer of the device EHCI state structure.
+ *
+ */
+static void USB_DeviceEhciInterruptReset(usb_device_ehci_state_struct_t *ehciState)
+{
+    uint32_t status = 0U;
+
+    /* Clear the setup flag */
+    status = ehciState->registerBase->EPSETUPSR;
+    ehciState->registerBase->EPSETUPSR = status;
+    /* Clear the endpoint complete flag */
+    status = ehciState->registerBase->EPCOMPLETE;
+    ehciState->registerBase->EPCOMPLETE = status;
+
+    do
+    {
+        /* Flush the pending transfers */
+        ehciState->registerBase->EPFLUSH = USBHS_EPFLUSH_FERB_MASK | USBHS_EPFLUSH_FETB_MASK;
+    } while (ehciState->registerBase->EPPRIME & (USBHS_EPPRIME_PERB_MASK | USBHS_EPPRIME_PETB_MASK));
+
+    /* Whether is the port reset. If yes, set the isResetting flag. Or, notify the up layer. */
+    if (ehciState->registerBase->PORTSC1 & USBHS_PORTSC1_PR_MASK)
+    {
+        ehciState->isResetting = 1U;
+    }
+    else
+    {
+        usb_device_callback_message_struct_t message;
+        message.buffer = (uint8_t *)NULL;
+        message.code = kUSB_DeviceNotifyBusReset;
+        message.length = 0U;
+        message.isSetup = 0U;
+
+        USB_DeviceNotificationTrigger(ehciState->deviceHandle, &message);
+    }
+}
+
+/*!
+ * @brief Handle the sof interrupt.
+ *
+ * The function is used to handle the sof interrupt.
+ *
+ * @param ehciState       Pointer of the device EHCI state structure.
+ *
+ */
+static void USB_DeviceEhciInterruptSof(usb_device_ehci_state_struct_t *ehciState)
+{
+}
+
+#if (defined(USB_DEVICE_CONFIG_LOW_POWER_MODE) && (USB_DEVICE_CONFIG_LOW_POWER_MODE > 0U))
+/*!
+ * @brief Handle the suspend interrupt.
+ *
+ * The function is used to handle the suspend interrupt.
+ *
+ * @param ehciState       Pointer of the device EHCI state structure.
+ *
+ */
+static void USB_DeviceEhciInterruptSuspend(usb_device_ehci_state_struct_t *ehciState)
+{
+    /* If the port is in suspend state, notify the up layer */
+    if (ehciState->registerBase->PORTSC1 & USBHS_PORTSC1_SUSP_MASK)
+    {
+#if (defined(FSL_FEATURE_SOC_USBNC_COUNT) && (FSL_FEATURE_SOC_USBNC_COUNT > 0U))
+#else
+        if (ehciState->registerPhyBase->USB1_VBUS_DET_STAT & USBPHY_USB1_VBUS_DET_STAT_VBUS_VALID_3V_MASK)
+#endif
+        {
+            usb_device_callback_message_struct_t message;
+            message.buffer = (uint8_t *)NULL;
+            message.length = 0U;
+            message.isSetup = 0U;
+            message.code = kUSB_DeviceNotifySuspend;
+            USB_DeviceNotificationTrigger(ehciState->deviceHandle, &message);
+        }
+    }
+}
+#endif /* USB_DEVICE_CONFIG_LOW_POWER_MODE */
+
+/*!
+ * @brief Get dtds and link to QH.
+ *
+ * The function is used to get dtds and link to QH.
+ *
+ * @param ehciState       Pointer of the device EHCI state structure.
+ * @param endpointAddress The endpoint address, Bit7, 0U - USB_OUT, 1U - USB_IN.
+ * @param buffer           The memory address needed to be transferred.
+ * @param length           Data length.
+ *
+ * @return A USB error code or kStatus_USB_Success.
+ */
+static usb_status_t USB_DeviceEhciTransfer(usb_device_ehci_state_struct_t *ehciState,
+                                           uint8_t endpointAddress,
+                                           uint8_t *buffer,
+                                           uint32_t length)
+{
+    usb_device_ehci_dtd_struct_t *dtd;
+    usb_device_ehci_dtd_struct_t *dtdHard;
+    uint32_t index = ((endpointAddress & USB_ENDPOINT_NUMBER_MASK) << 1U) |
+                     ((endpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >>
+                      USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT);
+    uint32_t primeBit = 1U << ((endpointAddress & USB_ENDPOINT_NUMBER_MASK) +
+                               ((endpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >> 0x03U));
+    uint8_t epStatus = primeBit;
+    uint32_t sendLength;
+    uint32_t currentIndex = 0U;
+    uint32_t dtdRequestCount = (length + USB_DEVICE_ECHI_DTD_TOTAL_BYTES - 1U) / USB_DEVICE_ECHI_DTD_TOTAL_BYTES;
+    uint8_t qhIdle = 0U;
+    uint8_t waitingSafelyAccess = 1U;
+    USB_OSA_SR_ALLOC();
+
+    if (!ehciState)
+    {
+        return kStatus_USB_InvalidHandle;
+    }
+
+    if (0U == ehciState->qh[index].endpointStatusUnion.endpointStatusBitmap.isOpened)
+    {
+        return kStatus_USB_Error;
+    }
+    /* Return error when ehci is doing reset */
+    if (ehciState->isResetting)
+    {
+        return kStatus_USB_Error;
+    }
+
+    if (!dtdRequestCount)
+    {
+        dtdRequestCount = 1U;
+    }
+
+    USB_OSA_ENTER_CRITICAL();
+    /* The free dtd count need to not less than the transfer requests. */
+    if (dtdRequestCount > (uint32_t)ehciState->dtdCount)
+    {
+        USB_OSA_EXIT_CRITICAL();
+        return kStatus_USB_Busy;
+    }
+
+    do
+    {
+        /* The transfer length need to not more than USB_DEVICE_ECHI_DTD_TOTAL_BYTES for each dtd. */
+        if (length > USB_DEVICE_ECHI_DTD_TOTAL_BYTES)
+        {
+            sendLength = USB_DEVICE_ECHI_DTD_TOTAL_BYTES;
+        }
+        else
+        {
+            sendLength = length;
+        }
+        length -= sendLength;
+
+        /* Get a free dtd */
+        dtd = ehciState->dtdFree;
+
+        ehciState->dtdFree = (usb_device_ehci_dtd_struct_t *)dtd->nextDtdPointer;
+        ehciState->dtdCount--;
+
+        /* Save the dtd head when current active buffer offset is zero. */
+        if (!currentIndex)
+        {
+            dtdHard = dtd;
+        }
+
+        /* Set the dtd field */
+        dtd->nextDtdPointer = USB_DEVICE_ECHI_DTD_TERMINATE_MASK;
+        dtd->dtdTokenUnion.dtdToken = 0U;
+        dtd->bufferPointerPage[0] = (uint32_t)(buffer + currentIndex);
+        dtd->bufferPointerPage[1] =
+            (dtd->bufferPointerPage[0] + USB_DEVICE_ECHI_DTD_PAGE_BLOCK) & USB_DEVICE_ECHI_DTD_PAGE_MASK;
+        dtd->bufferPointerPage[2] = dtd->bufferPointerPage[1] + USB_DEVICE_ECHI_DTD_PAGE_BLOCK;
+        dtd->bufferPointerPage[3] = dtd->bufferPointerPage[2] + USB_DEVICE_ECHI_DTD_PAGE_BLOCK;
+        dtd->bufferPointerPage[4] = dtd->bufferPointerPage[3] + USB_DEVICE_ECHI_DTD_PAGE_BLOCK;
+
+        dtd->dtdTokenUnion.dtdTokenBitmap.totalBytes = sendLength;
+
+        /* Save the data length needed to be transferred. */
+        dtd->reservedUnion.originalBufferInfo.originalBufferLength = sendLength;
+        /* Save the original buffer address */
+        dtd->reservedUnion.originalBufferInfo.originalBufferOffest =
+            dtd->bufferPointerPage[0] & USB_DEVICE_ECHI_DTD_PAGE_OFFSET_MASK;
+        dtd->reservedUnion.originalBufferInfo.dtdInvalid = 0U;
+
+        /* Set the IOC field in last dtd. */
+        if (!length)
+        {
+            dtd->dtdTokenUnion.dtdTokenBitmap.ioc = 1U;
+        }
+
+        /* Set dtd active */
+        dtd->dtdTokenUnion.dtdTokenBitmap.status = USB_DEVICE_ECHI_DTD_STATUS_ACTIVE;
+
+        /* Move the buffer offset index */
+        currentIndex += sendLength;
+
+        /* Add dtd to the in-used dtd queue */
+        if (ehciState->dtdTail[index])
+        {
+            ehciState->dtdTail[index]->nextDtdPointer = (uint32_t)dtd;
+            ehciState->dtdTail[index] = dtd;
+        }
+        else
+        {
+            ehciState->dtdHard[index] = dtd;
+            ehciState->dtdTail[index] = dtd;
+            qhIdle = 1U;
+        }
+    } while (length);
+
+    /* If the QH is not empty */
+    if (!qhIdle)
+    {
+        /* If the prime bit is set, nothing need to do. */
+        if (ehciState->registerBase->EPPRIME & primeBit)
+        {
+            USB_OSA_EXIT_CRITICAL();
+            return kStatus_USB_Success;
+        }
+
+        /* To safely a dtd */
+        while (waitingSafelyAccess)
+        {
+            /* set the ATDTW flag to USBHS_USBCMD_REG. */
+            ehciState->registerBase->USBCMD |= USBHS_USBCMD_ATDTW_MASK;
+            /* Read EPSR */
+            epStatus = ehciState->registerBase->EPSR;
+            /* Wait the ATDTW bit set */
+            if (ehciState->registerBase->USBCMD & USBHS_USBCMD_ATDTW_MASK)
+            {
+                waitingSafelyAccess = 0U;
+            }
+        }
+        /* Clear the ATDTW bit */
+        ehciState->registerBase->USBCMD &= ~USBHS_USBCMD_ATDTW_MASK;
+    }
+
+    /* If QH is empty or the endpoint is not primed, need to link current dtd head to the QH. */
+    /* When the endpoint is not primed if qhIdle is zero, it means the QH is empty. */
+    if ((qhIdle) || (!(epStatus & primeBit)))
+    {
+        ehciState->qh[index].nextDtdPointer = (uint32_t)dtdHard;
+        ehciState->qh[index].dtdTokenUnion.dtdToken = 0U;
+        ehciState->registerBase->EPPRIME = primeBit;
+        while (!(ehciState->registerBase->EPSR & primeBit))
+        {
+            if (ehciState->registerBase->EPCOMPLETE & primeBit)
+            {
+                break;
+            }
+            else
+            {
+                ehciState->registerBase->EPPRIME = primeBit;
+            }
+        }
+    }
+
+    USB_OSA_EXIT_CRITICAL();
+    return kStatus_USB_Success;
+}
+
+/*!
+ * @brief Initialize the USB device EHCI instance.
+ *
+ * This function initializes the USB device EHCI module specified by the controllerId.
+ *
+ * @param controllerId The controller id of the USB IP. Please refer to enumeration type usb_controller_index_t.
+ * @param handle        Pointer of the device handle, used to identify the device object is belonged to.
+ * @param ehciHandle   It is out parameter, is used to return pointer of the device EHCI handle to the caller.
+ *
+ * @return A USB error code or kStatus_USB_Success.
+ */
+usb_status_t USB_DeviceEhciInit(uint8_t controllerId,
+                                usb_device_handle handle,
+                                usb_device_controller_handle *ehciHandle)
+{
+    usb_device_ehci_state_struct_t *ehciState;
+    uint32_t ehci_base[] = USBHS_BASE_ADDRS;
+
+#if (defined(USB_DEVICE_CHARGER_DETECT_ENABLE) && (USB_DEVICE_CHARGER_DETECT_ENABLE > 0U)) && \
+    (defined(FSL_FEATURE_SOC_USBHSDCD_COUNT) && (FSL_FEATURE_SOC_USBHSDCD_COUNT > 0U))
+    usb_device_dcd_state_struct_t *dcdHSState;
+    uint32_t dcd_base[] = USBHSDCD_BASE_ADDRS;
+    usb_device_callback_message_struct_t message;
+#endif
+
+    if ((controllerId < kUSB_ControllerEhci0) ||
+        ((uint32_t)(controllerId - kUSB_ControllerEhci0) >= USB_DEVICE_CONFIG_EHCI) ||
+        ((uint32_t)(controllerId - kUSB_ControllerEhci0) >= (sizeof(ehci_base) / sizeof(uint32_t))))
+    {
+        return kStatus_USB_ControllerNotFound;
+    }
+
+    ehciState = &g_UsbDeviceEhciSate[controllerId - kUSB_ControllerEhci0];
+
+    ehciState->dtd = s_UsbDeviceEhciDtd[controllerId - kUSB_ControllerEhci0];
+    ehciState->qh = (usb_device_ehci_qh_struct_t *)&qh_buffer[(controllerId - kUSB_ControllerEhci0) * 2048];
+
+    ehciState->controllerId = controllerId;
+
+    ehciState->registerBase = (USBHS_Type *)ehci_base[controllerId - kUSB_ControllerEhci0];
+#if (defined(USB_DEVICE_CONFIG_LOW_POWER_MODE) && (USB_DEVICE_CONFIG_LOW_POWER_MODE > 0U))
+    ehciState->registerPhyBase = (USBPHY_Type *)USB_EhciPhyGetBase(controllerId);
+
+#if (defined(FSL_FEATURE_SOC_USBNC_COUNT) && (FSL_FEATURE_SOC_USBNC_COUNT > 0U))
+    ehciState->registerNcBase = (USBNC_Type *)USB_EhciNCGetBase(controllerId);
+#endif
+
+#endif
+
+    /* Get the HW's endpoint count */
+    ehciState->endpointCount =
+        (uint8_t)((ehciState->registerBase->DCCPARAMS & USBHS_DCCPARAMS_DEN_MASK) >> USBHS_DCCPARAMS_DEN_SHIFT);
+
+    if (ehciState->endpointCount < USB_DEVICE_CONFIG_ENDPOINTS)
+    {
+        return kStatus_USB_Error;
+    }
+    ehciState->deviceHandle = (usb_device_struct_t *)handle;
+
+    /* Clear the controller mode field and set to device mode. */
+    ehciState->registerBase->USBMODE &= ~USBHS_USBMODE_CM_MASK;
+    ehciState->registerBase->USBMODE |= USBHS_USBMODE_CM(0x02U);
+
+    /* Set the EHCI to default status. */
+    USB_DeviceEhciSetDefaultState(ehciState);
+    *ehciHandle = (usb_device_controller_handle)ehciState;
+#if (defined(USB_DEVICE_CHARGER_DETECT_ENABLE) && (USB_DEVICE_CHARGER_DETECT_ENABLE > 0U)) && \
+    (defined(FSL_FEATURE_SOC_USBHSDCD_COUNT) && (FSL_FEATURE_SOC_USBHSDCD_COUNT > 0U))
+    dcdHSState = &s_UsbDeviceDcdHSState[controllerId - kUSB_ControllerEhci0];
+
+    dcdHSState->controllerId = controllerId;
+
+    dcdHSState->dcdRegisterBase = (USBHSDCD_Type *)dcd_base[controllerId - kUSB_ControllerEhci0];
+
+    dcdHSState->deviceHandle = (usb_device_struct_t *)handle;
+
+    message.buffer = (uint8_t *)NULL;
+    message.length = 0U;
+    message.isSetup = 0U;
+    if (ehciState->registerBase->OTGSC & USBHS_OTGSC_BSV_MASK)
+    {
+        /* Device is connected to a host. */
+        message.code = kUSB_DeviceNotifyAttach;
+        USB_DeviceNotificationTrigger(ehciState->deviceHandle, &message);
+    }
+#endif
+
+    return kStatus_USB_Success;
+}
+
+/*!
+ * @brief De-initialize the USB device EHCI instance.
+ *
+ * This function de-initializes the USB device EHCI module.
+ *
+ * @param ehciHandle   Pointer of the device EHCI handle.
+ *
+ * @return A USB error code or kStatus_USB_Success.
+ */
+usb_status_t USB_DeviceEhciDeinit(usb_device_controller_handle ehciHandle)
+{
+    usb_device_ehci_state_struct_t *ehciState = (usb_device_ehci_state_struct_t *)ehciHandle;
+
+    if (!ehciHandle)
+    {
+        return kStatus_USB_InvalidHandle;
+    }
+
+    /* Disable all interrupt. */
+    ehciState->registerBase->USBINTR = 0U;
+    /* Stop the device functionality. */
+    ehciState->registerBase->USBCMD &= ~USBHS_USBCMD_RS_MASK;
+    /* Reset the controller. */
+    ehciState->registerBase->USBCMD |= USBHS_USBCMD_RST_MASK;
+
+    return kStatus_USB_Success;
+}
+
+/*!
+ * @brief Send data through a specified endpoint.
+ *
+ * This function sends data through a specified endpoint.
+ *
+ * @param ehciHandle      Pointer of the device EHCI handle.
+ * @param endpointAddress Endpoint index.
+ * @param buffer           The memory address to hold the data need to be sent.
+ * @param length           The data length need to be sent.
+ *
+ * @return A USB error code or kStatus_USB_Success.
+ *
+ * @note The return value just means if the sending request is successful or not; the transfer done is notified by the
+ * corresponding callback function.
+ * Currently, only one transfer request can be supported for one specific endpoint.
+ * If there is a specific requirement to support multiple transfer requests for one specific endpoint, the application
+ * should implement a queue in the application level.
+ * The subsequent transfer could begin only when the previous transfer is done (get notification through the endpoint
+ * callback).
+ */
+usb_status_t USB_DeviceEhciSend(usb_device_controller_handle ehciHandle,
+                                uint8_t endpointAddress,
+                                uint8_t *buffer,
+                                uint32_t length)
+{
+    /* Add dtd to the QH */
+    return USB_DeviceEhciTransfer(
+        (usb_device_ehci_state_struct_t *)ehciHandle,
+        (endpointAddress & USB_ENDPOINT_NUMBER_MASK) | (USB_IN << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT),
+        buffer, length);
+}
+
+/*!
+ * @brief Receive data through a specified endpoint.
+ *
+ * This function Receives data through a specified endpoint.
+ *
+ * @param ehciHandle      Pointer of the device EHCI handle.
+ * @param endpointAddress Endpoint index.
+ * @param buffer           The memory address to save the received data.
+ * @param length           The data length want to be received.
+ *
+ * @return A USB error code or kStatus_USB_Success.
+ *
+ * @note The return value just means if the receiving request is successful or not; the transfer done is notified by the
+ * corresponding callback function.
+ * Currently, only one transfer request can be supported for one specific endpoint.
+ * If there is a specific requirement to support multiple transfer requests for one specific endpoint, the application
+ * should implement a queue in the application level.
+ * The subsequent transfer could begin only when the previous transfer is done (get notification through the endpoint
+ * callback).
+ */
+usb_status_t USB_DeviceEhciRecv(usb_device_controller_handle ehciHandle,
+                                uint8_t endpointAddress,
+                                uint8_t *buffer,
+                                uint32_t length)
+{
+    /* Add dtd to the QH */
+    return USB_DeviceEhciTransfer(
+        (usb_device_ehci_state_struct_t *)ehciHandle,
+        (endpointAddress & USB_ENDPOINT_NUMBER_MASK) | (USB_OUT << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT),
+        buffer, length);
+}
+
+/*!
+ * @brief Cancel the pending transfer in a specified endpoint.
+ *
+ * The function is used to cancel the pending transfer in a specified endpoint.
+ *
+ * @param ehciHandle      Pointer of the device EHCI handle.
+ * @param ep               Endpoint address, bit7 is the direction of endpoint, 1U - IN, 0U - OUT.
+ *
+ * @return A USB error code or kStatus_USB_Success.
+ */
+usb_status_t USB_DeviceEhciCancel(usb_device_controller_handle ehciHandle, uint8_t ep)
+{
+    usb_device_ehci_state_struct_t *ehciState = (usb_device_ehci_state_struct_t *)ehciHandle;
+    usb_device_callback_message_struct_t message;
+    usb_device_ehci_dtd_struct_t *currentDtd;
+    uint32_t primeBit =
+        1U << ((ep & USB_ENDPOINT_NUMBER_MASK) + ((ep & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >> 0x03U));
+    uint8_t index =
+        ((ep & USB_ENDPOINT_NUMBER_MASK) << 1U) | ((ep & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >> 0x07U);
+
+    USB_OSA_SR_ALLOC();
+
+    if (!ehciHandle)
+    {
+        return kStatus_USB_InvalidHandle;
+    }
+
+    USB_OSA_ENTER_CRITICAL();
+
+    message.buffer = NULL;
+    message.length = USB_UNINITIALIZED_VAL_32;
+
+    /* Get the first dtd */
+    currentDtd =
+        (usb_device_ehci_dtd_struct_t *)((uint32_t)ehciState->dtdHard[index] & USB_DEVICE_ECHI_DTD_POINTER_MASK);
+
+    while (currentDtd)
+    {
+        currentDtd->reservedUnion.originalBufferInfo.dtdInvalid = 1U;
+        currentDtd = (usb_device_ehci_dtd_struct_t *)(currentDtd->nextDtdPointer & USB_DEVICE_ECHI_DTD_POINTER_MASK);
+    }
+
+    /* Get the first dtd */
+    currentDtd =
+        (usb_device_ehci_dtd_struct_t *)((uint32_t)ehciState->dtdHard[index] & USB_DEVICE_ECHI_DTD_POINTER_MASK);
+    while (currentDtd)
+    {
+        if (!currentDtd->reservedUnion.originalBufferInfo.dtdInvalid)
+        {
+            break;
+        }
+        else
+        {
+            if (currentDtd->dtdTokenUnion.dtdTokenBitmap.status & USB_DEVICE_ECHI_DTD_STATUS_ACTIVE)
+            {
+                /* Flush the endpoint to stop a transfer. */
+                do
+                {
+                    /* Set the corresponding bit(s) in the EPFLUSH register */
+                    ehciState->registerBase->EPFLUSH |= primeBit;
+
+                    /* Wait until all bits in the EPFLUSH register are cleared. */
+                    while (ehciState->registerBase->EPFLUSH & primeBit)
+                    {
+                    }
+                    /*
+                     * Read the EPSR register to ensure that for all endpoints
+                     * commanded to be flushed, that the corresponding bits
+                     * are now cleared.
+                     */
+                } while (ehciState->registerBase->EPSR & primeBit);
+            }
+
+            /* Save the original buffer address. */
+            if (NULL == message.buffer)
+            {
+                message.buffer = (uint8_t *)((currentDtd->bufferPointerPage[0] & USB_DEVICE_ECHI_DTD_PAGE_MASK) |
+                                             (currentDtd->reservedUnion.originalBufferInfo.originalBufferOffest));
+            }
+
+            /* Remove the dtd from the dtd in-used queue. */
+            if (ehciState->dtdHard[index] == ehciState->dtdTail[index])
+            {
+                ehciState->dtdHard[index] = NULL;
+                ehciState->dtdTail[index] = NULL;
+            }
+            else
+            {
+                ehciState->dtdHard[index] = (usb_device_ehci_dtd_struct_t *)ehciState->dtdHard[index]->nextDtdPointer;
+            }
+
+            /* When the ioc is set or the dtd queue is empty, the up layer will be notified. */
+            if ((currentDtd->dtdTokenUnion.dtdTokenBitmap.ioc) ||
+                (0 == ((uint32_t)ehciState->dtdHard[index] & USB_DEVICE_ECHI_DTD_POINTER_MASK)))
+            {
+                message.code = ep;
+                message.isSetup = 0U;
+                USB_DeviceNotificationTrigger(ehciState->deviceHandle, &message);
+                message.buffer = NULL;
+            }
+            /* Clear the token field. */
+            currentDtd->dtdTokenUnion.dtdToken = 0U;
+            /* Save the dtd to the free queue. */
+            currentDtd->nextDtdPointer = (uint32_t)ehciState->dtdFree;
+            ehciState->dtdFree = currentDtd;
+            ehciState->dtdCount++;
+        }
+        /* Get the next dtd. */
+        currentDtd =
+            (usb_device_ehci_dtd_struct_t *)((uint32_t)ehciState->dtdHard[index] & USB_DEVICE_ECHI_DTD_POINTER_MASK);
+    }
+    if (!currentDtd)
+    {
+        /* Set the QH to empty. */
+        ehciState->qh[index].nextDtdPointer = USB_DEVICE_ECHI_DTD_TERMINATE_MASK;
+        ehciState->qh[index].dtdTokenUnion.dtdToken = 0U;
+    }
+    USB_OSA_EXIT_CRITICAL();
+    return kStatus_USB_Success;
+}
+
+/*!
+ * @brief Control the status of the selected item.
+ *
+ * The function is used to control the status of the selected item.
+ *
+ * @param ehciHandle      Pointer of the device EHCI handle.
+ * @param type             The selected item. Please refer to enumeration type usb_device_control_type_t.
+ * @param param            The param type is determined by the selected item.
+ *
+ * @return A USB error code or kStatus_USB_Success.
+ */
+usb_status_t USB_DeviceEhciControl(usb_device_controller_handle ehciHandle, usb_device_control_type_t type, void *param)
+{
+    usb_device_ehci_state_struct_t *ehciState = (usb_device_ehci_state_struct_t *)ehciHandle;
+    usb_status_t error = kStatus_USB_Error;
+    uint16_t *temp16;
+    uint8_t *temp8;
+#if (defined(USB_DEVICE_CHARGER_DETECT_ENABLE) && (USB_DEVICE_CHARGER_DETECT_ENABLE > 0U)) && \
+    (defined(FSL_FEATURE_SOC_USBHSDCD_COUNT) && (FSL_FEATURE_SOC_USBHSDCD_COUNT > 0U))
+    usb_device_dcd_state_struct_t *dcdHSState;
+    dcdHSState =
+        &s_UsbDeviceDcdHSState[ehciState->controllerId - kUSB_ControllerEhci0]; /*The hard code should be replaced*/
+    usb_device_dcd_charging_time_t *deviceDcdTimingConfig = (usb_device_dcd_charging_time_t *)param;
+#endif
+#if ((defined(USB_DEVICE_CONFIG_REMOTE_WAKEUP)) && (USB_DEVICE_CONFIG_REMOTE_WAKEUP > 0U))
+    usb_device_struct_t *deviceHandle;
+    uint64_t startTick;
+#endif
+
+    if (!ehciHandle)
+    {
+        return kStatus_USB_InvalidHandle;
+    }
+
+#if ((defined(USB_DEVICE_CONFIG_REMOTE_WAKEUP)) && (USB_DEVICE_CONFIG_REMOTE_WAKEUP > 0U))
+    deviceHandle = (usb_device_struct_t *)ehciState->deviceHandle;
+#endif
+
+    switch (type)
+    {
+        case kUSB_DeviceControlRun:
+            ehciState->registerBase->USBCMD |= USBHS_USBCMD_RS_MASK;
+            error = kStatus_USB_Success;
+            break;
+        case kUSB_DeviceControlStop:
+            ehciState->registerBase->USBCMD &= ~USBHS_USBCMD_RS_MASK;
+            error = kStatus_USB_Success;
+            break;
+        case kUSB_DeviceControlEndpointInit:
+            if (param)
+            {
+                error = USB_DeviceEhciEndpointInit(ehciState, (usb_device_endpoint_init_struct_t *)param);
+            }
+            break;
+        case kUSB_DeviceControlEndpointDeinit:
+            if (param)
+            {
+                temp8 = (uint8_t *)param;
+                error = USB_DeviceEhciEndpointDeinit(ehciState, *temp8);
+            }
+            break;
+        case kUSB_DeviceControlEndpointStall:
+            if (param)
+            {
+                temp8 = (uint8_t *)param;
+                error = USB_DeviceEhciEndpointStall(ehciState, *temp8);
+            }
+            break;
+        case kUSB_DeviceControlEndpointUnstall:
+            if (param)
+            {
+                temp8 = (uint8_t *)param;
+                error = USB_DeviceEhciEndpointUnstall(ehciState, *temp8);
+            }
+            break;
+        case kUSB_DeviceControlGetDeviceStatus:
+            if (param)
+            {
+                temp16 = (uint16_t *)param;
+                *temp16 = (USB_DEVICE_CONFIG_SELF_POWER << (USB_REQUEST_STANDARD_GET_STATUS_DEVICE_SELF_POWERED_SHIFT))
+#if ((defined(USB_DEVICE_CONFIG_REMOTE_WAKEUP)) && (USB_DEVICE_CONFIG_REMOTE_WAKEUP > 0U))
+                          | (deviceHandle->remotewakeup << (USB_REQUEST_STANDARD_GET_STATUS_DEVICE_REMOTE_WARKUP_SHIFT))
+#endif
+                    ;
+                error = kStatus_USB_Success;
+            }
+            break;
+        case kUSB_DeviceControlGetEndpointStatus:
+            if (param)
+            {
+                usb_device_endpoint_status_struct_t *endpointStatus = (usb_device_endpoint_status_struct_t *)param;
+                uint8_t ep = (endpointStatus->endpointAddress) & USB_ENDPOINT_NUMBER_MASK;
+                uint8_t direction =
+                    ((endpointStatus->endpointAddress) & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >>
+                    USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT;
+
+                if (ep < USB_DEVICE_CONFIG_ENDPOINTS)
+                {
+                    if (ep)
+                    {
+                        endpointStatus->endpointStatus = (ehciState->registerBase->EPCR[ep - 1U] &
+                                                          (direction ? USBHS_EPCR_TXS_MASK : USBHS_EPCR_RXS_MASK)) ?
+                                                             kUSB_DeviceEndpointStateStalled :
+                                                             kUSB_DeviceEndpointStateIdle;
+                    }
+                    else
+                    {
+                        endpointStatus->endpointStatus =
+                            (ehciState->registerBase->EPCR0 & (direction ? USBHS_EPCR_TXS_MASK : USBHS_EPCR_RXS_MASK)) ?
+                                kUSB_DeviceEndpointStateStalled :
+                                kUSB_DeviceEndpointStateIdle;
+                    }
+                    error = kStatus_USB_Success;
+                }
+            }
+            break;
+        case kUSB_DeviceControlSetDeviceAddress:
+            if (param)
+            {
+                temp8 = (uint8_t *)param;
+                ehciState->registerBase->DEVICEADDR = (((uint32_t)(*temp8)) << USBHS_DEVICEADDR_USBADR_SHIFT);
+                error = kStatus_USB_Success;
+            }
+            break;
+        case kUSB_DeviceControlGetSynchFrame:
+            break;
+#if (defined(USB_DEVICE_CONFIG_LOW_POWER_MODE) && (USB_DEVICE_CONFIG_LOW_POWER_MODE > 0U))
+#if defined(USB_DEVICE_CONFIG_REMOTE_WAKEUP) && (USB_DEVICE_CONFIG_REMOTE_WAKEUP > 0U)
+        case kUSB_DeviceControlResume:
+#if (defined(FSL_FEATURE_SOC_USBNC_COUNT) && (FSL_FEATURE_SOC_USBNC_COUNT > 0U))
+            ehciState->registerNcBase->USB_OTGn_CTRL &= ~USBNC_USB_OTGn_CTRL_WIE_MASK;
+#else
+            ehciState->registerBase->USBGENCTRL &= ~USBHS_USBGENCTRL_WU_IE_MASK;
+#endif
+            ehciState->registerBase->PORTSC1 &= ~USBHS_PORTSC1_PHCD_MASK;
+            ehciState->registerBase->PORTSC1 |= USBHS_PORTSC1_FPR_MASK;
+            startTick = deviceHandle->hwTick;
+            while ((deviceHandle->hwTick - startTick) < 10)
+            {
+                __ASM("nop");
+            }
+            ehciState->registerBase->PORTSC1 &= ~USBHS_PORTSC1_FPR_MASK;
+            error = kStatus_USB_Success;
+            break;
+#endif /* USB_DEVICE_CONFIG_REMOTE_WAKEUP */
+        case kUSB_DeviceControlSuspend:
+            ehciState->registerBase->OTGSC |= 0x007F0000U;
+            ehciState->registerPhyBase->PWD = 0xFFFFFFFF;
+            /* ehciState->registerBase->OTGCTL |= ((1U<<10) | (1U<<17) | (1U<<16)); */
+            while (ehciState->registerPhyBase->CTRL & (USBPHY_CTRL_UTMI_SUSPENDM_MASK))
+            {
+                __ASM("nop");
+            }
+            /* ehciState->registerPhyBase->CTRL |= ((1U << 21) | (1U << 22) | (1U << 23)); */
+            ehciState->registerBase->USBSTS |= USBHS_USBSTS_SRI_MASK;
+            ehciState->registerBase->PORTSC1 |= USBHS_PORTSC1_PHCD_MASK;
+#if (defined(FSL_FEATURE_SOC_USBNC_COUNT) && (FSL_FEATURE_SOC_USBNC_COUNT > 0U))
+            ehciState->registerPhyBase->CTRL |= USBPHY_CTRL_ENVBUSCHG_WKUP_MASK | USBPHY_CTRL_ENIDCHG_WKUP_MASK |
+                                                USBPHY_CTRL_ENDPDMCHG_WKUP_MASK | USBPHY_CTRL_ENIRQRESUMEDETECT_MASK;
+            ehciState->registerNcBase->USB_OTGn_CTRL |= USBNC_USB_OTGn_CTRL_WKUP_ID_EN_MASK |
+                                                        USBNC_USB_OTGn_CTRL_WKUP_VBUS_EN_MASK |
+                                                        USBNC_USB_OTGn_CTRL_WKUP_DPDM_EN_MASK;
+            ehciState->registerNcBase->USB_OTGn_CTRL |= USBNC_USB_OTGn_CTRL_WIE_MASK;
+#else
+            ehciState->registerBase->USBGENCTRL = USBHS_USBGENCTRL_WU_IE_MASK;
+#endif
+            ehciState->registerPhyBase->CTRL |= USBPHY_CTRL_CLKGATE_MASK;
+            ehciState->isSuspending = 1U;
+            error = kStatus_USB_Success;
+            break;
+#endif /* USB_DEVICE_CONFIG_LOW_POWER_MODE */
+        case kUSB_DeviceControlSetDefaultStatus:
+            for (uint8_t count = 0U; count < USB_DEVICE_CONFIG_ENDPOINTS; count++)
+            {
+                USB_DeviceEhciEndpointDeinit(ehciState, (count | (USB_IN << 0x07U)));
+                USB_DeviceEhciEndpointDeinit(ehciState, (count | (USB_OUT << 0x07U)));
+            }
+            USB_DeviceEhciSetDefaultState(ehciState);
+            error = kStatus_USB_Success;
+            break;
+        case kUSB_DeviceControlGetSpeed:
+            if (param)
+            {
+                temp8 = (uint8_t *)param;
+                *temp8 = ehciState->speed;
+                error = kStatus_USB_Success;
+            }
+            break;
+        case kUSB_DeviceControlGetOtgStatus:
+            break;
+        case kUSB_DeviceControlSetOtgStatus:
+            break;
+#if (defined(USB_DEVICE_CONFIG_USB20_TEST_MODE) && (USB_DEVICE_CONFIG_USB20_TEST_MODE > 0U))
+        case kUSB_DeviceControlSetTestMode:
+            if (param)
+            {
+                temp8 = (uint8_t *)param;
+                ehciState->registerBase->PORTSC1 |= ((uint32_t)(*temp8) << 16U);
+                error = kStatus_USB_Success;
+            }
+            break;
+#endif
+#if (defined(USB_DEVICE_CHARGER_DETECT_ENABLE) && (USB_DEVICE_CHARGER_DETECT_ENABLE > 0U)) && \
+    (defined(FSL_FEATURE_SOC_USBHSDCD_COUNT) && (FSL_FEATURE_SOC_USBHSDCD_COUNT > 0U))
+        case kUSB_DeviceControlDcdInitModule:
+            dcdHSState->dcdRegisterBase->CONTROL |= USBDCD_CONTROL_SR_MASK;
+            dcdHSState->dcdRegisterBase->TIMER0 = USBDCD_TIMER0_TSEQ_INIT(deviceDcdTimingConfig->dcdSeqInitTime);
+            dcdHSState->dcdRegisterBase->TIMER1 = USBDCD_TIMER1_TDCD_DBNC(deviceDcdTimingConfig->dcdDbncTime);
+            dcdHSState->dcdRegisterBase->TIMER1 |= USBDCD_TIMER1_TVDPSRC_ON(deviceDcdTimingConfig->dcdDpSrcOnTime);
+            dcdHSState->dcdRegisterBase->TIMER2_BC12 =
+                USBDCD_TIMER2_BC12_TWAIT_AFTER_PRD(deviceDcdTimingConfig->dcdTimeWaitAfterPrD);
+            dcdHSState->dcdRegisterBase->TIMER2_BC12 |=
+                USBDCD_TIMER2_BC12_TVDMSRC_ON(deviceDcdTimingConfig->dcdTimeDMSrcOn);
+            dcdHSState->dcdRegisterBase->CONTROL |= USBDCD_CONTROL_IE_MASK;
+            dcdHSState->dcdRegisterBase->CONTROL |= USBDCD_CONTROL_BC12_MASK;
+            dcdHSState->dcdRegisterBase->CONTROL |= USBDCD_CONTROL_START_MASK;
+            break;
+        case kUSB_DeviceControlDcdDeinitModule:
+            dcdHSState->dcdRegisterBase->CONTROL |= USBDCD_CONTROL_SR_MASK;
+            break;
+#endif
+
+        default:
+            break;
+    }
+
+    return error;
+}
+
+/*!
+ * @brief Handle the EHCI device interrupt.
+ *
+ * The function is used to handle the EHCI device interrupt.
+ *
+ * @param deviceHandle    The device handle got from USB_DeviceInit.
+ *
+ */
+void USB_DeviceEhciIsrFunction(void *deviceHandle)
+{
+    usb_device_struct_t *handle = (usb_device_struct_t *)deviceHandle;
+    usb_device_ehci_state_struct_t *ehciState;
+    uint32_t status;
+
+    if (NULL == deviceHandle)
+    {
+        return;
+    }
+
+    ehciState = (usb_device_ehci_state_struct_t *)(handle->controllerHandle);
+
+#if ((defined(USB_DEVICE_CONFIG_LOW_POWER_MODE)) && (USB_DEVICE_CONFIG_LOW_POWER_MODE > 0U))
+
+#if (defined(FSL_FEATURE_SOC_USBNC_COUNT) && (FSL_FEATURE_SOC_USBNC_COUNT > 0U))
+
+    if (ehciState->registerNcBase->USB_OTGn_CTRL & USBNC_USB_OTGn_CTRL_WIE_MASK)
+    {
+        if (ehciState->registerNcBase->USB_OTGn_CTRL & USBNC_USB_OTGn_CTRL_WIR_MASK)
+        {
+            ehciState->registerBase->PORTSC1 &= ~USBHS_PORTSC1_PHCD_MASK;
+            ehciState->registerNcBase->USB_OTGn_CTRL &= ~USBNC_USB_OTGn_CTRL_WIE_MASK;
+        }
+    }
+    else
+    {
+    }
+
+#else
+    if (ehciState->registerBase->USBGENCTRL & USBHS_USBGENCTRL_WU_IE_MASK)
+    {
+        if (ehciState->registerBase->USBGENCTRL & (1U << 8))
+        {
+            ehciState->registerBase->USBGENCTRL &= ~(1U << 8);
+            ehciState->registerBase->USBGENCTRL |= USBHS_USBGENCTRL_WU_INT_CLR_MASK;
+            ehciState->registerBase->PORTSC1 &= ~USBHS_PORTSC1_PHCD_MASK;
+            ehciState->registerBase->USBGENCTRL &= ~USBHS_USBGENCTRL_WU_IE_MASK;
+        }
+    }
+    else
+    {
+    }
+#endif
+
+#endif
+
+#if defined(USB_DEVICE_CONFIG_DETACH_ENABLE) && (USB_DEVICE_CONFIG_DETACH_ENABLE > 0U)
+    if (ehciState->registerBase->OTGSC & USBHS_OTGSC_BSVIS_MASK)
+    {
+        usb_device_callback_message_struct_t message;
+
+        ehciState->registerBase->OTGSC |= USBHS_OTGSC_BSVIS_MASK;
+
+        message.buffer = (uint8_t *)NULL;
+        message.length = 0U;
+        message.isSetup = 0U;
+        if (ehciState->registerBase->OTGSC & USBHS_OTGSC_BSV_MASK)
+        {
+            /* Device is connected to a host. */
+            message.code = kUSB_DeviceNotifyAttach;
+            USB_DeviceNotificationTrigger(ehciState->deviceHandle, &message);
+        }
+        else
+        {
+            /* Device is disconnected from a host. */
+            message.code = kUSB_DeviceNotifyDetach;
+            USB_DeviceNotificationTrigger(ehciState->deviceHandle, &message);
+        }
+    }
+#endif /* USB_DEVICE_CONFIG_DETACH_ENABLE */
+
+    status = ehciState->registerBase->USBSTS;
+    status &= ehciState->registerBase->USBINTR;
+
+    ehciState->registerBase->USBSTS = status;
+
+#if defined(USB_DEVICE_CONFIG_ERROR_HANDLING) && (USB_DEVICE_CONFIG_ERROR_HANDLING > 0U)
+    if (status & USBHS_USBSTS_UEI_MASK)
+    {
+        /* Error interrupt */
+        USB_DeviceEhciInterruptError(ehciState);
+    }
+#endif /* USB_DEVICE_CONFIG_ERROR_HANDLING */
+
+    if (status & USBHS_USBSTS_URI_MASK)
+    {
+        /* Reset interrupt */
+        USB_DeviceEhciInterruptReset(ehciState);
+    }
+
+    if (status & USBHS_USBSTS_UI_MASK)
+    {
+        /* Token done interrupt */
+        USB_DeviceEhciInterruptTokenDone(ehciState);
+    }
+
+    if (status & USBHS_USBSTS_PCI_MASK)
+    {
+        /* Port status change interrupt */
+        USB_DeviceEhciInterruptPortChange(ehciState);
+    }
+
+#if (defined(USB_DEVICE_CONFIG_LOW_POWER_MODE) && (USB_DEVICE_CONFIG_LOW_POWER_MODE > 0U))
+    if (status & USBHS_USBSTS_SLI_MASK)
+    {
+        /* Suspend interrupt */
+        USB_DeviceEhciInterruptSuspend(ehciState);
+    }
+#endif /* USB_DEVICE_CONFIG_LOW_POWER_MODE */
+
+    if (status & USBHS_USBSTS_SRI_MASK)
+    {
+        /* Sof interrupt */
+        USB_DeviceEhciInterruptSof(ehciState);
+    }
+}
+
+#if (defined(USB_DEVICE_CHARGER_DETECT_ENABLE) && (USB_DEVICE_CHARGER_DETECT_ENABLE > 0U)) && \
+    (defined(FSL_FEATURE_SOC_USBHSDCD_COUNT) && (FSL_FEATURE_SOC_USBHSDCD_COUNT > 0U))
+void USB_DeviceDcdHSIsrFunction(void *deviceHandle)
+{
+    usb_device_struct_t *handle = (usb_device_struct_t *)deviceHandle;
+    usb_device_ehci_state_struct_t *ehciState;
+    usb_device_dcd_state_struct_t *dcdHSState;
+    uint32_t status;
+    uint32_t chargerType;
+    usb_device_callback_message_struct_t message;
+
+    if (NULL == deviceHandle)
+    {
+        return;
+    }
+
+    ehciState = (usb_device_ehci_state_struct_t *)(handle->controllerHandle);
+
+    dcdHSState = &s_UsbDeviceDcdHSState[ehciState->controllerId - kUSB_ControllerEhci0];
+
+    status = dcdHSState->dcdRegisterBase->STATUS;
+
+    dcdHSState->dcdRegisterBase->CONTROL |= USBDCD_CONTROL_IACK_MASK;
+
+    message.buffer = (uint8_t *)NULL;
+    message.length = 0U;
+    message.isSetup = 0U;
+
+    if (status & USBDCD_STATUS_ERR_MASK)
+    {
+        if (status & USBDCD_STATUS_TO_MASK)
+        {
+            dcdHSState->dcdRegisterBase->CONTROL |= USBDCD_CONTROL_SR_MASK;
+            message.code = kUSB_DeviceNotifyDcdTimeOut;
+            USB_DeviceNotificationTrigger(dcdHSState->deviceHandle, &message);
+        }
+        else
+        {
+            dcdHSState->dcdRegisterBase->CONTROL |= USBDCD_CONTROL_SR_MASK;
+            message.code = kUSB_DeviceNotifyDcdUnknownPortType;
+            USB_DeviceNotificationTrigger(dcdHSState->deviceHandle, &message);
+        }
+    }
+    else
+    {
+        switch (status & USBDCD_STATUS_SEQ_STAT_MASK)
+        {
+            case USBDCD_STATUS_SEQ_STAT(kUSB_DcdChargingPortDetectionCompleted):
+                chargerType = status & USBDCD_STATUS_SEQ_RES_MASK;
+                if (chargerType == USBDCD_STATUS_SEQ_RES(kUSB_DcdDetectionStandardHost))
+                {
+                    dcdHSState->dcdRegisterBase->CONTROL |= USBDCD_CONTROL_SR_MASK;
+                    message.code = kUSB_DeviceNotifySDPDetected;
+                    USB_DeviceNotificationTrigger(dcdHSState->deviceHandle, &message);
+                }
+                else if (chargerType == USBDCD_STATUS_SEQ_RES(kUSB_DcdDetectionChargingPort))
+                {
+                    message.code = kUSB_DeviceNotifyChargingPortDetected;
+                    USB_DeviceNotificationTrigger(dcdHSState->deviceHandle, &message);
+                }
+                break;
+            case USBDCD_STATUS_SEQ_STAT(kUSB_DcdChargerTypeDetectionCompleted):
+                chargerType = status & USBDCD_STATUS_SEQ_RES_MASK;
+                if (chargerType == USBDCD_STATUS_SEQ_RES(kUSB_DcdDetectionChargingPort))
+                {
+                    dcdHSState->dcdRegisterBase->CONTROL |= USBDCD_CONTROL_SR_MASK;
+                    message.code = kUSB_DeviceNotifyChargingHostDetected;
+                    USB_DeviceNotificationTrigger(dcdHSState->deviceHandle, &message);
+                }
+                else if (chargerType == USBDCD_STATUS_SEQ_RES(kUSB_DcdDetectionDedicatedCharger))
+                {
+                    dcdHSState->dcdRegisterBase->CONTROL |= USBDCD_CONTROL_SR_MASK;
+                    message.code = kUSB_DeviceNotifyDedicatedChargerDetected;
+                    USB_DeviceNotificationTrigger(dcdHSState->deviceHandle, &message);
+                }
+                break;
+
+            default:
+                break;
+        }
+    }
+}
+#endif
+
+#endif /* USB_DEVICE_CONFIG_EHCI */

+ 219 - 0
bsp/imxrt1052-evk/drivers/usb/device/usb_device_ehci.h

@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2015, Freescale Semiconductor, Inc.
+ * Copyright 2016 NXP
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright notice, this list
+ *   of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright notice, this
+ *   list of conditions and the following disclaimer in the documentation and/or
+ *   other materials provided with the distribution.
+ *
+ * o Neither the name of the copyright holder nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __USB_DEVICE_EHCI_H__
+#define __USB_DEVICE_EHCI_H__
+
+#include <usb/include/usb_ehci.h>
+
+/*!
+ * @addtogroup usb_device_controller_ehci_driver
+ * @{
+ */
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/*! @brief The maximum value of ISO type maximum packet size for HS in USB specification 2.0 */
+#define USB_DEVICE_MAX_HS_ISO_MAX_PACKET_SIZE (1024U)
+
+/*! @brief The maximum value of interrupt type maximum packet size for HS in USB specification 2.0 */
+#define USB_DEVICE_MAX_HS_INTERUPT_MAX_PACKET_SIZE (1024U)
+
+/*! @brief The maximum value of bulk type maximum packet size for HS in USB specification 2.0 */
+#define USB_DEVICE_MAX_HS_BULK_MAX_PACKET_SIZE (512U)
+
+/*! @brief The maximum value of control type maximum packet size for HS in USB specification 2.0 */
+#define USB_DEVICE_MAX_HS_CONTROL_MAX_PACKET_SIZE (64U)
+
+/*! @brief EHCI state structure */
+typedef struct _usb_device_ehci_state_struct
+{
+    usb_device_struct_t *deviceHandle; /*!< Device handle used to identify the device object is belonged to */
+    USBHS_Type *registerBase;          /*!< The base address of the register */
+#if (defined(USB_DEVICE_CONFIG_LOW_POWER_MODE) && (USB_DEVICE_CONFIG_LOW_POWER_MODE > 0U))
+    USBPHY_Type *registerPhyBase; /*!< The base address of the PHY register */
+#if (defined(FSL_FEATURE_SOC_USBNC_COUNT) && (FSL_FEATURE_SOC_USBNC_COUNT > 0U))
+    USBNC_Type *registerNcBase; /*!< The base address of the USBNC register */
+#endif
+#endif
+    usb_device_ehci_qh_struct_t *qh;       /*!< The QH structure base address */
+    usb_device_ehci_dtd_struct_t *dtd;     /*!< The DTD structure base address */
+    usb_device_ehci_dtd_struct_t *dtdFree; /*!< The idle DTD list head */
+    usb_device_ehci_dtd_struct_t
+        *dtdHard[USB_DEVICE_CONFIG_ENDPOINTS * 2]; /*!< The transferring DTD list head for each endpoint */
+    usb_device_ehci_dtd_struct_t
+        *dtdTail[USB_DEVICE_CONFIG_ENDPOINTS * 2]; /*!< The transferring DTD list tail for each endpoint */
+    int8_t dtdCount;                               /*!< The idle DTD node count */
+    uint8_t endpointCount;                         /*!< The endpoint number of EHCI */
+    uint8_t isResetting;                           /*!< Whether a PORT reset is occurring or not  */
+    uint8_t controllerId;                          /*!< Controller ID */
+    uint8_t speed;                                 /*!< Current speed of EHCI */
+    uint8_t isSuspending;                          /*!< Is suspending of the PORT */
+} usb_device_ehci_state_struct_t;
+
+#if (defined(USB_DEVICE_CHARGER_DETECT_ENABLE) && (USB_DEVICE_CHARGER_DETECT_ENABLE > 0U)) && \
+    (defined(FSL_FEATURE_SOC_USBHSDCD_COUNT) && (FSL_FEATURE_SOC_USBHSDCD_COUNT > 0U))
+typedef struct _usb_device_dcd_state_struct
+{
+    usb_device_struct_t *deviceHandle; /*!< Device handle used to identify the device object belongs to */
+    USBHSDCD_Type *dcdRegisterBase;    /*!< The base address of the dcd module */
+    uint8_t controllerId;              /*!< Controller ID */
+} usb_device_dcd_state_struct_t;
+#endif
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/*!
+ * @name USB device EHCI functions
+ * @{
+ */
+
+/*******************************************************************************
+ * API
+ ******************************************************************************/
+
+/*!
+ * @brief Initializes the USB device EHCI instance.
+ *
+ * This function initializes the USB device EHCI module specified by the controllerId.
+ *
+ * @param[in] controllerId The controller ID of the USB IP. See the enumeration type usb_controller_index_t.
+ * @param[in] handle        Pointer of the device handle used to identify the device object is belonged to.
+ * @param[out] ehciHandle   An out parameter used to return the pointer of the device EHCI handle to the caller.
+ *
+ * @return A USB error code or kStatus_USB_Success.
+ */
+usb_status_t USB_DeviceEhciInit(uint8_t controllerId,
+                                usb_device_handle handle,
+                                usb_device_controller_handle *ehciHandle);
+
+/*!
+ * @brief Deinitializes the USB device EHCI instance.
+ *
+ * This function deinitializes the USB device EHCI module.
+ *
+ * @param[in] ehciHandle   Pointer of the device EHCI handle.
+ *
+ * @return A USB error code or kStatus_USB_Success.
+ */
+usb_status_t USB_DeviceEhciDeinit(usb_device_controller_handle ehciHandle);
+
+/*!
+ * @brief Sends data through a specified endpoint.
+ *
+ * This function sends data through a specified endpoint.
+ *
+ * @param[in] ehciHandle      Pointer of the device EHCI handle.
+ * @param[in] endpointAddress Endpoint index.
+ * @param[in] buffer           The memory address to hold the data need to be sent.
+ * @param[in] length           The data length to be sent.
+ *
+ * @return A USB error code or kStatus_USB_Success.
+ *
+ * @note The return value means whether the sending request is successful or not. The transfer completion is indicated
+ * by the
+ * corresponding callback function.
+ * Currently, only one transfer request can be supported for a specific endpoint.
+ * If there is a specific requirement to support multiple transfer requests for a specific endpoint, the application
+ * should implement a queue in the application level.
+ * The subsequent transfer can begin only when the previous transfer is done (a notification is received through the
+ * endpoint
+ * callback).
+ */
+usb_status_t USB_DeviceEhciSend(usb_device_controller_handle ehciHandle,
+                                uint8_t endpointAddress,
+                                uint8_t *buffer,
+                                uint32_t length);
+
+/*!
+ * @brief Receive data through a specified endpoint.
+ *
+ * This function Receives data through a specified endpoint.
+ *
+ * @param[in] ehciHandle      Pointer of the device EHCI handle.
+ * @param[in] endpointAddress Endpoint index.
+ * @param[in] buffer           The memory address to save the received data.
+ * @param[in] length           The data length want to be received.
+ *
+ * @return A USB error code or kStatus_USB_Success.
+ *
+ * @note The return value just means if the receiving request is successful or not; the transfer done is notified by the
+ * corresponding callback function.
+ * Currently, only one transfer request can be supported for one specific endpoint.
+ * If there is a specific requirement to support multiple transfer requests for one specific endpoint, the application
+ * should implement a queue in the application level.
+ * The subsequent transfer could begin only when the previous transfer is done (get notification through the endpoint
+ * callback).
+ */
+usb_status_t USB_DeviceEhciRecv(usb_device_controller_handle ehciHandle,
+                                uint8_t endpointAddress,
+                                uint8_t *buffer,
+                                uint32_t length);
+
+/*!
+ * @brief Cancels the pending transfer in a specified endpoint.
+ *
+ * The function is used to cancel the pending transfer in a specified endpoint.
+ *
+ * @param[in] ehciHandle      Pointer of the device EHCI handle.
+ * @param[in] ep               Endpoint address, bit7 is the direction of endpoint, 1U - IN, 0U - OUT.
+ *
+ * @return A USB error code or kStatus_USB_Success.
+ */
+usb_status_t USB_DeviceEhciCancel(usb_device_controller_handle ehciHandle, uint8_t ep);
+
+/*!
+ * @brief Controls the status of the selected item.
+ *
+ * The function is used to control the status of the selected item.
+ *
+ * @param[in] ehciHandle      Pointer of the device EHCI handle.
+ * @param[in] type             The selected item. See enumeration type usb_device_control_type_t.
+ * @param[in,out] param            The parameter type is determined by the selected item.
+ *
+ * @return A USB error code or kStatus_USB_Success.
+ */
+usb_status_t USB_DeviceEhciControl(usb_device_controller_handle ehciHandle,
+                                   usb_device_control_type_t type,
+                                   void *param);
+
+/*! @} */
+
+#if defined(__cplusplus)
+}
+#endif
+
+/*! @} */
+
+#endif /* __USB_DEVICE_EHCI_H__ */

+ 726 - 0
bsp/imxrt1052-evk/drivers/usb/host/usb_host.h

@@ -0,0 +1,726 @@
+/*
+ * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
+ * Copyright 2016 NXP
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright notice, this list
+ *   of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright notice, this
+ *   list of conditions and the following disclaimer in the documentation and/or
+ *   other materials provided with the distribution.
+ *
+ * o Neither the name of the copyright holder nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _USB_HOST_H_
+#define _USB_HOST_H_
+
+#include <usb/include/usb.h>
+#include <usb/include/usb_misc.h>
+#include <usb/include/usb_spec.h>
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+struct _usb_host_transfer; /* for cross reference */
+
+/*!
+ * @addtogroup usb_host_drv
+ * @{
+ */
+
+/*! @brief USB host class handle type define */
+typedef void *usb_host_class_handle;
+
+/*! @brief USB host controller handle type define */
+typedef void *usb_host_controller_handle;
+
+/*! @brief USB host configuration handle type define */
+typedef void *usb_host_configuration_handle;
+
+/*! @brief USB host interface handle type define */
+typedef void *usb_host_interface_handle;
+
+/*! @brief USB host pipe handle type define */
+typedef void *usb_host_pipe_handle;
+
+/*! @brief Event codes for device attach/detach */
+typedef enum _usb_host_event
+{
+    kUSB_HostEventAttach = 1U,     /*!< Device is attached */
+    kUSB_HostEventDetach,          /*!< Device is detached */
+    kUSB_HostEventEnumerationDone, /*!< Device's enumeration is done and the device is supported */
+    kUSB_HostEventNotSupported,    /*!< Device's enumeration is done and the device is not supported */
+#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
+    kUSB_HostEventNotSuspended,      /*!< Suspend failed */
+    kUSB_HostEventSuspended,         /*!< Suspend successful */
+    kUSB_HostEventNotResumed,        /*!< Resume failed */
+    kUSB_HostEventDetectResume,      /*!< Detect resume signal */
+    kUSB_HostEventResumed,           /*!< Resume successful */
+    kUSB_HostEventL1Sleeped,         /*!< L1 Sleep successful,state transition was successful (ACK) */
+    kUSB_HostEventL1SleepNYET,       /*!< Device was unable to enter the L1 state at this time (NYET)  */
+    kUSB_HostEventL1SleepNotSupport, /*!< Device does not support the L1 state (STALL)  */
+    kUSB_HostEventL1SleepError,      /*!< Device failed to respond or an error occurred  */
+    kUSB_HostEventL1NotResumed,      /*!< Resume failed */
+    kUSB_HostEventL1DetectResume,    /*!< Detect resume signal */
+    kUSB_HostEventL1Resumed,         /*!< Resume successful */
+#endif
+} usb_host_event_t;
+
+/*! @brief USB host device information code */
+typedef enum _usb_host_dev_info
+{
+    kUSB_HostGetDeviceAddress = 1U,  /*!< Device's address */
+    kUSB_HostGetDeviceHubNumber,     /*!< Device's first hub address */
+    kUSB_HostGetDevicePortNumber,    /*!< Device's first hub port number */
+    kUSB_HostGetDeviceSpeed,         /*!< Device's speed */
+    kUSB_HostGetDeviceHSHubNumber,   /*!< Device's first high-speed hub address */
+    kUSB_HostGetDeviceHSHubPort,     /*!< Device's first high-speed hub number */
+    kUSB_HostGetDeviceLevel,         /*!< Device's hub level */
+    kUSB_HostGetHostHandle,          /*!< Device's host handle */
+    kUSB_HostGetDeviceControlPipe,   /*!< Device's control pipe handle */
+    kUSB_HostGetDevicePID,           /*!< Device's PID */
+    kUSB_HostGetDeviceVID,           /*!< Device's VID */
+    kUSB_HostGetHubThinkTime,        /*!< Device's hub total think time */
+    kUSB_HostGetDeviceConfigIndex,   /*!< Device's running zero-based config index */
+    kUSB_HostGetConfigurationDes,    /*!< Device's configuration descriptor pointer */
+    kUSB_HostGetConfigurationLength, /*!< Device's configuration descriptor pointer */
+} usb_host_dev_info_t;
+
+/*!
+ * @brief Host callback function typedef.
+ *
+ * This callback function is used to notify application device attach/detach event.
+ * This callback pointer is passed when initializing the host.
+ *
+ * @param deviceHandle           The device handle, which indicates the attached device.
+ * @param configurationHandle The configuration handle contains the attached device's configuration information.
+ * @param event_code           The callback event code; See the enumeration host_event_t.
+ *
+ * @return A USB error code or kStatus_USB_Success.
+ * @retval kStatus_USB_Success       Application handles the attached device successfully.
+ * @retval kStatus_USB_NotSupported  Application don't support the attached device.
+ * @retval kStatus_USB_Error         Application handles the attached device falsely.
+ */
+typedef usb_status_t (*host_callback_t)(usb_device_handle deviceHandle,
+                                        usb_host_configuration_handle configurationHandle,
+                                        uint32_t eventCode);
+
+/*!
+ * @brief Transfer callback function typedef.
+ *
+ * This callback function is used to notify the upper layer the result of the transfer.
+ * This callback pointer is passed when calling the send/receive APIs.
+ *
+ * @param param     The parameter pointer, which is passed when calling the send/receive APIs.
+ * @param data      The data buffer pointer.
+ * @param data_len  The result data length.
+ * @param status    A USB error code or kStatus_USB_Success.
+ */
+typedef void (*transfer_callback_t)(void *param, uint8_t *data, uint32_t dataLen, usb_status_t status);
+
+/*!
+ * @brief Host stack inner transfer callback function typedef.
+ *
+ * This callback function is used to notify the upper layer the result of a transfer.
+ * This callback pointer is passed when initializing the structure usb_host_transfer_t.
+ *
+ * @param param     The parameter pointer, which is passed when calling the send/receive APIs.
+ * @param transfer  The transfer information; See the structure usb_host_transfer_t.
+ * @param status    A USB error code or kStatus_USB_Success.
+ */
+typedef void (*host_inner_transfer_callback_t)(void *param, struct _usb_host_transfer *transfer, usb_status_t status);
+
+/*! @brief USB host endpoint information structure */
+typedef struct _usb_host_ep
+{
+    usb_descriptor_endpoint_t *epDesc; /*!< Endpoint descriptor pointer*/
+    uint8_t *epExtension;              /*!< Endpoint extended descriptor pointer*/
+    uint16_t epExtensionLength;        /*!< Extended descriptor length*/
+} usb_host_ep_t;
+
+/*! @brief USB host interface information structure */
+typedef struct _usb_host_interface
+{
+    usb_host_ep_t epList[USB_HOST_CONFIG_INTERFACE_MAX_EP]; /*!< Endpoint array*/
+    usb_descriptor_interface_t *interfaceDesc;              /*!< Interface descriptor pointer*/
+    uint8_t *interfaceExtension;                            /*!< Interface extended descriptor pointer*/
+    uint16_t interfaceExtensionLength;                      /*!< Extended descriptor length*/
+    uint8_t interfaceIndex;                                 /*!< The interface index*/
+    uint8_t alternateSettingNumber;                         /*!< The interface alternate setting value*/
+    uint8_t epCount;                                        /*!< Interface's endpoint number*/
+} usb_host_interface_t;
+
+/*! @brief USB host configuration information structure */
+typedef struct _usb_host_configuration
+{
+    usb_host_interface_t interfaceList[USB_HOST_CONFIG_CONFIGURATION_MAX_INTERFACE]; /*!< Interface array*/
+    usb_descriptor_configuration_t *configurationDesc; /*!< Configuration descriptor pointer*/
+    uint8_t *configurationExtension;                   /*!< Configuration extended descriptor pointer*/
+    uint16_t configurationExtensionLength;             /*!< Extended descriptor length*/
+    uint8_t interfaceCount;                            /*!< The configuration's interface number*/
+} usb_host_configuration_t;
+
+/*! @brief USB host pipe common structure */
+typedef struct _usb_host_pipe
+{
+    struct _usb_host_pipe *next;    /*!< Link the idle pipes*/
+    usb_device_handle deviceHandle; /*!< This pipe's device's handle*/
+    uint16_t currentCount;          /*!< For KHCI transfer*/
+    uint16_t nakCount;              /*!< Maximum NAK count*/
+    uint16_t maxPacketSize;         /*!< Maximum packet size*/
+    uint16_t interval;              /*!< FS/LS: frame unit; HS: micro-frame unit*/
+    uint8_t open;                   /*!< 0 - closed, 1 - open*/
+    uint8_t nextdata01;             /*!< Data toggle*/
+    uint8_t endpointAddress;        /*!< Endpoint address*/
+    uint8_t direction;              /*!< Pipe direction*/
+    uint8_t pipeType;               /*!< Pipe type, for example USB_ENDPOINT_BULK*/
+    uint8_t numberPerUframe;        /*!< Transaction number per micro-frame*/
+} usb_host_pipe_t;
+
+/*! @brief USB host transfer structure */
+typedef struct _usb_host_transfer
+{
+    struct _usb_host_transfer *next;           /*!< The next transfer structure*/
+    uint8_t *transferBuffer;                   /*!< Transfer data buffer*/
+    uint32_t transferLength;                   /*!< Transfer data length*/
+    uint32_t transferSofar;                    /*!< Length transferred so far*/
+    host_inner_transfer_callback_t callbackFn; /*!< Transfer callback function*/
+    void *callbackParam;                       /*!< Transfer callback parameter*/
+    usb_host_pipe_t *transferPipe;             /*!< Transfer pipe pointer*/
+    usb_setup_struct_t *setupPacket;           /*!< Set up packet buffer*/
+    uint8_t direction;                         /*!< Transfer direction; it's values are USB_OUT or USB_IN*/
+    uint8_t setupStatus;                       /*!< Set up the transfer status*/
+    union
+    {
+        uint32_t unitHead;      /*!< xTD head for this transfer*/
+        int32_t transferResult; /*!< KHCI transfer result */
+    } union1;
+
+    union
+    {
+        uint32_t unitTail; /*!<xTD tail for this transfer*/
+        uint32_t frame;    /*!< KHCI transfer frame number */
+    } union2;
+
+#if USB_HOST_CONFIG_KHCI
+    uint16_t nakTimeout; /*!< KHCI transfer NAK timeout */
+    uint16_t retry;      /*!< KHCI transfer retry */
+#endif
+} usb_host_transfer_t;
+
+/*! @brief USB host pipe information structure for opening pipe */
+typedef struct _usb_host_pipe_init
+{
+    void *devInstance;       /*!< Device instance handle*/
+    uint16_t nakCount;       /*!< Maximum NAK retry count. MUST be zero for interrupt*/
+    uint16_t maxPacketSize;  /*!< Pipe's maximum packet size*/
+    uint8_t interval;        /*!< Pipe's interval*/
+    uint8_t endpointAddress; /*!< Endpoint address*/
+    uint8_t direction;       /*!< Endpoint direction*/
+    uint8_t pipeType;        /*!< Endpoint type, the value is USB_ENDPOINT_INTERRUPT, USB_ENDPOINT_CONTROL,
+                                USB_ENDPOINT_ISOCHRONOUS, USB_ENDPOINT_BULK*/
+    uint8_t numberPerUframe; /*!< Transaction number for each micro-frame*/
+} usb_host_pipe_init_t;
+
+/*! @brief Cancel transfer parameter structure */
+typedef struct _usb_host_cancel_param
+{
+    usb_host_pipe_handle pipeHandle; /*!< Cancelling pipe handle*/
+    usb_host_transfer_t *transfer;   /*!< Cancelling transfer*/
+} usb_host_cancel_param_t;
+
+/*******************************************************************************
+ * API
+ ******************************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*!
+ * @name USB host APIs Part 1
+ * The following APIs are recommended for application use.
+ * @{
+ */
+
+/*!
+ * @brief Initializes the USB host stack.
+ *
+ * This function initializes the USB host module specified by the controllerId.
+ *
+ * @param[in] controllerId    The controller ID of the USB IP. See the enumeration usb_controller_index_t.
+ * @param[out] hostHandle     Returns the host handle.
+ * @param[in] callbackFn      Host callback function notifies device attach/detach.
+ *
+ * @retval kStatus_USB_Success              The host is initialized successfully.
+ * @retval kStatus_USB_InvalidHandle        The hostHandle is a NULL pointer.
+ * @retval kStatus_USB_ControllerNotFound   Cannot find the controller according to the controller ID.
+ * @retval kStatus_USB_AllocFail            Allocation memory fail.
+ * @retval kStatus_USB_Error                Host mutex create fail; KHCI/EHCI mutex or KHCI/EHCI event create fail,
+ *                                          or, KHCI/EHCI IP initialize fail.
+ */
+extern usb_status_t USB_HostInit(uint8_t controllerId, usb_host_handle *hostHandle, host_callback_t callbackFn);
+
+/*!
+ * @brief Deinitializes the USB host stack.
+ *
+ * This function deinitializes the USB host module specified by the hostHandle.
+ *
+ * @param[in] hostHandle  The host handle.
+ *
+ * @retval kStatus_USB_Success              The host is initialized successfully.
+ * @retval kStatus_USB_InvalidHandle        The hostHandle is a NULL pointer.
+ * @retval kStatus_USB_Error                Controller deinitialization fail.
+ */
+extern usb_status_t USB_HostDeinit(usb_host_handle hostHandle);
+
+/*!
+ * @brief Gets the device information.
+ *
+ * This function gets the device information.
+ *
+ * @param[in] deviceHandle   Removing device handle.
+ * @param[in] infoCode       See the enumeration host_dev_info_t.
+ * @param[out] infoValue     Return the information value.
+ *
+ * @retval kStatus_USB_Success              Close successfully.
+ * @retval kStatus_USB_InvalidParameter     The deviceHandle or info_value is a NULL pointer.
+ * @retval kStatus_USB_Error                The info_code is not the host_dev_info_t value.
+ */
+extern usb_status_t USB_HostHelperGetPeripheralInformation(usb_device_handle deviceHandle,
+                                                           uint32_t infoCode,
+                                                           uint32_t *infoValue);
+
+/*!
+ * @brief Parses the alternate interface descriptor.
+ *
+ * This function parses the alternate interface descriptor and returns an interface information through the structure
+ * usb_host_interface_t.
+ *
+ * @param[in] interfaceHandle     The whole interface handle.
+ * @param[in] alternateSetting    Alternate setting value.
+ * @param[out] interface          Return interface information.
+ *
+ * @retval kStatus_USB_Success              Close successfully.
+ * @retval kStatus_USB_InvalidHandle        The interfaceHandle is a NULL pointer.
+ * @retval kStatus_USB_InvalidParameter     The alternateSetting is 0.
+ * @retval kStatus_USB_Error                The interface descriptor is wrong.
+ */
+extern usb_status_t USB_HostHelperParseAlternateSetting(usb_host_interface_handle interfaceHandle,
+                                                        uint8_t alternateSetting,
+                                                        usb_host_interface_t *interface);
+
+/*!
+ * @brief Removes the attached device.
+ *
+ * This function removes the attached device.
+ * This function should not be used all the time.
+ *
+ * @param[in] hostHandle     The host handle.
+ * @param[in] deviceHandle   Removing device handle.
+ *
+ * @retval kStatus_USB_Success              Remove successfully.
+ * @retval kStatus_USB_InvalidHandle        The hostHandle or deviceHandle is a NULL pointer.
+ * @retval kStatus_USB_InvalidParameter     The deviceHandle instance don't belong to hostHandle instance.
+ */
+extern usb_status_t USB_HostRemoveDevice(usb_host_handle hostHandle, usb_device_handle deviceHandle);
+
+/*!
+ * @brief KHCI task function.
+ *
+ * The function is used to handle the KHCI controller message.
+ * In the bare metal environment, this function should be called periodically in the main function.
+ * In the RTOS environment, this function should be used as a function entry to create a task.
+ *
+ * @param[in] hostHandle The host handle.
+ */
+extern void USB_HostKhciTaskFunction(void *hostHandle);
+
+/*!
+ * @brief EHCI task function.
+ *
+ * The function is used to handle the EHCI controller message.
+ * In the bare metal environment, this function should be called periodically in the main function.
+ * In the RTOS environment, this function should be used as a function entry to create a task.
+ *
+ * @param[in] hostHandle The host handle.
+ */
+extern void USB_HostEhciTaskFunction(void *hostHandle);
+
+/*!
+ * @brief OHCI task function.
+ *
+ * The function is used to handle the OHCI controller message.
+ * In the bare metal environment, this function should be called periodically in the main function.
+ * In the RTOS environment, this function should be used as a function entry to create a task.
+ *
+ * @param[in] hostHandle The host handle.
+ */
+extern void USB_HostOhciTaskFunction(void *hostHandle);
+
+/*!
+ * @brief IP3516HS task function.
+ *
+ * The function is used to handle the IP3516HS controller message.
+ * In the bare metal environment, this function should be called periodically in the main function.
+ * In the RTOS environment, this function should be used as a function entry to create a task.
+ *
+ * @param[in] hostHandle The host handle.
+ */
+extern void USB_HostIp3516HsTaskFunction(void *hostHandle);
+
+/*!
+ * @brief Device KHCI ISR function.
+ *
+ * The function is the KHCI interrupt service routine.
+ *
+ * @param[in] hostHandle The host handle.
+ */
+extern void USB_HostKhciIsrFunction(void *hostHandle);
+
+/*!
+ * @brief Device EHCI ISR function.
+ *
+ * The function is the EHCI interrupt service routine.
+ *
+ * @param[in] hostHandle The host handle.
+ */
+extern void USB_HostEhciIsrFunction(void *hostHandle);
+
+/*!
+ * @brief Device OHCI ISR function.
+ *
+ * The function is the OHCI interrupt service routine.
+ *
+ * @param[in] hostHandle The host handle.
+ */
+extern void USB_HostOhciIsrFunction(void *hostHandle);
+
+/*!
+ * @brief Device IP3516HS ISR function.
+ *
+ * The function is the IP3516HS interrupt service routine.
+ *
+ * @param[in] hostHandle The host handle.
+ */
+extern void USB_HostIp3516HsIsrFunction(void *hostHandle);
+
+/*! @}*/
+
+/*!
+ * @name USB host APIs Part 2.
+ * The following APIs are not recommended for application use. They are mainly used in the class driver.
+ * @{
+ */
+
+/*!
+ * @brief Opens the USB host pipe.
+ *
+ * This function opens a pipe according to the pipe_init_ptr parameter.
+ *
+ * @param[in] hostHandle  The host handle.
+ * @param[out] pipeHandle The pipe handle pointer used to return the pipe handle.
+ * @param[in] pipeInit    Used to initialize the pipe.
+ *
+ * @retval kStatus_USB_Success              The host is initialized successfully.
+ * @retval kStatus_USB_InvalidHandle        The hostHandle or pipe_handle_ptr is a NULL pointer.
+ * @retval kStatus_USB_Error                There is no idle pipe.
+ *                                          Or, there is no idle QH for EHCI.
+ *                                          Or, bandwidth allocate fail for EHCI.
+ */
+extern usb_status_t USB_HostOpenPipe(usb_host_handle hostHandle,
+                                     usb_host_pipe_handle *pipeHandle,
+                                     usb_host_pipe_init_t *pipeInit);
+
+/*!
+ * @brief Closes the USB host pipe.
+ *
+ * This function closes a pipe and frees the related resources.
+ *
+ * @param[in] hostHandle     The host handle.
+ * @param[in] pipeHandle     The closing pipe handle.
+ *
+ * @retval kStatus_USB_Success              The host is initialized successfully.
+ * @retval kStatus_USB_InvalidHandle        The hostHandle or pipeHandle is a NULL pointer.
+ */
+extern usb_status_t USB_HostClosePipe(usb_host_handle hostHandle, usb_host_pipe_handle pipeHandle);
+
+/*!
+ * @brief Sends data to a pipe.
+ *
+ * This function requests to send the transfer to the specified pipe.
+ *
+ * @param[in] hostHandle     The host handle.
+ * @param[in] pipeHandle     The sending pipe handle.
+ * @param[in] transfer        The transfer information.
+ *
+ * @retval kStatus_USB_Success              Send successfully.
+ * @retval kStatus_USB_InvalidHandle        The hostHandle, pipeHandle or transfer is a NULL pointer.
+ * @retval kStatus_USB_LackSwapBuffer       There is no swap buffer for KHCI.
+ * @retval kStatus_USB_Error                There is no idle QTD/ITD/SITD for EHCI.
+ */
+extern usb_status_t USB_HostSend(usb_host_handle hostHandle,
+                                 usb_host_pipe_handle pipeHandle,
+                                 usb_host_transfer_t *transfer);
+
+/*!
+ * @brief Sends a setup transfer to the pipe.
+ *
+ * This function request to send the setup transfer to the specified pipe.
+ *
+ * @param[in] hostHandle     The host handle.
+ * @param[in] pipeHandle     The sending pipe handle.
+ * @param[in] transfer        The transfer information.
+ *
+ * @retval kStatus_USB_Success              Send successfully.
+ * @retval kStatus_USB_InvalidHandle        The hostHandle, pipeHandle or transfer is a NULL pointer.
+ * @retval kStatus_USB_LackSwapBuffer       There is no swap buffer for KHCI.
+ * @retval kStatus_USB_Error                There is no idle QTD/ITD/SITD for EHCI.
+ */
+extern usb_status_t USB_HostSendSetup(usb_host_handle hostHandle,
+                                      usb_host_pipe_handle pipeHandle,
+                                      usb_host_transfer_t *transfer);
+
+/*!
+ * @brief Receives the data from the pipe.
+ *
+ * This function requests to receive the transfer from the specified pipe.
+ *
+ * @param[in] hostHandle     The host handle.
+ * @param[in] pipeHandle     The receiving pipe handle.
+ * @param[in] transfer        The transfer information.
+ *
+ * @retval kStatus_USB_Success              Receive successfully.
+ * @retval kStatus_USB_InvalidHandle        The hostHandle, pipeHandle or transfer is a NULL pointer.
+ * @retval kStatus_USB_LackSwapBuffer       There is no swap buffer for KHCI.
+ * @retval kStatus_USB_Error                There is no idle QTD/ITD/SITD for EHCI.
+ */
+extern usb_status_t USB_HostRecv(usb_host_handle hostHandle,
+                                 usb_host_pipe_handle pipeHandle,
+                                 usb_host_transfer_t *transfer);
+
+/*!
+ * @brief Cancel the pipe's transfers.
+ *
+ * This function cancels all pipe's transfers when the parameter transfer is NULL or cancels the transfers altogether.
+ *
+ * @param[in] hostHandle     The host handle.
+ * @param[in] pipeHandle     The receiving pipe handle.
+ * @param[in] transfer        The transfer information.
+ *
+ * @retval kStatus_USB_Success              Cancel successfully.
+ * @retval kStatus_USB_InvalidHandle        The hostHandle or pipeHandle is a NULL pointer.
+ */
+extern usb_status_t USB_HostCancelTransfer(usb_host_handle hostHandle,
+                                           usb_host_pipe_handle pipeHandle,
+                                           usb_host_transfer_t *transfer);
+
+/*!
+ * @brief Allocates a transfer resource.
+ *
+ * This function allocates a transfer. This transfer is used to pass data information to a low level stack.
+ *
+ * @param[in] hostHandle     The host handle.
+ * @param[out] transfer       Return the transfer.
+ *
+ * @retval kStatus_USB_Success              Allocate successfully.
+ * @retval kStatus_USB_InvalidHandle        The hostHandle or transfer is a NULL pointer.
+ * @retval kStatus_USB_Error                There is no idle transfer.
+ */
+extern usb_status_t USB_HostMallocTransfer(usb_host_handle hostHandle, usb_host_transfer_t **transfer);
+
+/*!
+ * @brief Frees a transfer resource.
+ *
+ * This function frees a transfer. This transfer is used to pass data information to a low level stack.
+ *
+ * @param[in] hostHandle     The host handle.
+ * @param[in] transfer        Release the transfer.
+ *
+ * @retval kStatus_USB_Success              Free successfully.
+ * @retval kStatus_USB_InvalidHandle        The hostHandle or transfer is a NULL pointer.
+ */
+extern usb_status_t USB_HostFreeTransfer(usb_host_handle hostHandle, usb_host_transfer_t *transfer);
+
+/*!
+ * @brief Requests the USB standard request.
+ *
+ * This function sends the USB standard request packet.
+ *
+ * @param[in] deviceHandle    The device handle for control transfer.
+ * @param[in] usbRequest      A USB standard request code. Se the usb_spec.h.
+ * @param[in] transfer        The used transfer.
+ * @param[in] param           The parameter structure is different for different request, see
+ * usb_host_framework.h.
+ *
+ * @retval kStatus_USB_Success              Send successfully.
+ * @retval kStatus_USB_InvalidHandle        The deviceHandle is a NULL pointer.
+ * @retval kStatus_USB_LackSwapBuffer       There is no swap buffer for KHCI.
+ * @retval kStatus_USB_Error                There is no idle QTD/ITD/SITD for EHCI,
+ *                                          Or, the request is not standard request.
+ */
+extern usb_status_t USB_HostRequestControl(usb_device_handle deviceHandle,
+                                           uint8_t usbRequest,
+                                           usb_host_transfer_t *transfer,
+                                           void *param);
+
+/*!
+ * @brief Opens the interface.
+ *
+ * This function opens the interface. It is used to notify the host driver the interface is used by APP or class driver.
+ *
+ * @param[in] deviceHandle      Removing device handle.
+ * @param[in] interfaceHandle   Opening interface handle.
+ *
+ * @retval kStatus_USB_Success              Open successfully.
+ * @retval kStatus_USB_InvalidHandle        The deviceHandle or interfaceHandle is a NULL pointer.
+ */
+extern usb_status_t USB_HostOpenDeviceInterface(usb_device_handle deviceHandle,
+                                                usb_host_interface_handle interfaceHandle);
+
+/*!
+ * @brief Closes an interface.
+ *
+ * This function opens an interface. It is used to notify the host driver the interface is not used by APP or class
+ * driver.
+ *
+ * @param[in] deviceHandle      Removing device handle.
+ * @param[in] interfaceHandle   Opening interface handle.
+ *
+ * @retval kStatus_USB_Success              Close successfully.
+ * @retval kStatus_USB_InvalidHandle        The deviceHandle is a NULL pointer.
+ */
+extern usb_status_t USB_HostCloseDeviceInterface(usb_device_handle deviceHandle,
+                                                 usb_host_interface_handle interfaceHandle);
+
+/*!
+ * @brief Gets a host stack version function.
+ *
+ * The function is used to get the host stack version.
+ *
+ * @param[out] version The version structure pointer to keep the host stack version.
+ *
+ */
+extern void USB_HostGetVersion(uint32_t *version);
+
+#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
+/*!
+ * @brief Send a bus or device suspend request.
+ *
+ * This function is used to send a bus or device suspend request.
+ *
+ * @param[in] hostHandle     The host handle.
+ * @param[in] deviceHandle      The device handle.
+ *
+ * @retval kStatus_USB_Success              Request successfully.
+ * @retval kStatus_USB_InvalidHandle        The hostHandle is a NULL pointer. Or the controller handle is invalid.
+ * @retval kStatus_USB_Error                There is no idle transfer.
+ *                                          Or, the deviceHandle is invalid.
+ *                                          Or, the request is invalid.
+ */
+extern usb_status_t USB_HostSuspendDeviceResquest(usb_host_handle hostHandle, usb_device_handle deviceHandle);
+
+/*!
+ * @brief Send a bus or device resume request.
+ *
+ * This function is used to send a bus or device resume request.
+ *
+ * @param[in] hostHandle     The host handle.
+ * @param[in] deviceHandle      The device handle.
+ *
+ * @retval kStatus_USB_Success              Request successfully.
+ * @retval kStatus_USB_InvalidHandle        The hostHandle is a NULL pointer. Or the controller handle is invalid.
+ * @retval kStatus_USB_Error                There is no idle transfer.
+ *                                          Or, the deviceHandle is invalid.
+ *                                          Or, the request is invalid.
+ */
+extern usb_status_t USB_HostResumeDeviceResquest(usb_host_handle hostHandle, usb_device_handle deviceHandle);
+#if ((defined(USB_HOST_CONFIG_LPM_L1)) && (USB_HOST_CONFIG_LPM_L1 > 0U))
+/*!
+ * @brief Send a bus or device suspend request.
+ *
+ * This function is used to send a bus or device suspend request.
+ *
+ * @param[in] hostHandle     The host handle.
+ * @param[in] deviceHandle      The device handle.
+ *@param[in] sleeptype      Bus suspend or single device suspend.
+ *
+ * @retval kStatus_USB_Success              Request successfully.
+ * @retval kStatus_USB_InvalidHandle        The hostHandle is a NULL pointer. Or the controller handle is invalid.
+ * @retval kStatus_USB_Error                There is no idle transfer.
+ *                                          Or, the deviceHandle is invalid.
+ *                                          Or, the request is invalid.
+ */
+extern usb_status_t USB_HostL1SleepDeviceResquest(usb_host_handle hostHandle,
+                                                  usb_device_handle deviceHandle,
+                                                  uint8_t sleeptype);
+
+/*!
+ * @brief Send a bus or device resume request.
+ *
+ * This function is used to send a bus or device resume request.
+ *
+ * @param[in] hostHandle     The host handle.
+ * @param[in] deviceHandle      The device handle.
+ * *@param[in] sleeptype      Bus suspend or single device suspend.
+ *
+ * @retval kStatus_USB_Success              Request successfully.
+ * @retval kStatus_USB_InvalidHandle        The hostHandle is a NULL pointer. Or the controller handle is invalid.
+ * @retval kStatus_USB_Error                There is no idle transfer.
+ *                                          Or, the deviceHandle is invalid.
+ *                                          Or, the request is invalid.
+ */
+extern usb_status_t USB_HostL1ResumeDeviceResquest(usb_host_handle hostHandle,
+                                                   usb_device_handle deviceHandle,
+                                                   uint8_t sleepType);
+/*!
+ * @brief Update the lpm param.
+ *
+ * The function is used to configuure the lpm token.
+ *
+ * @param[in] hostHandle The host handle.
+ * @param[in] lpmParam HIRD vaule and whether enable remotewakeup.
+ *
+ */
+extern usb_status_t USB_HostL1SleepDeviceResquestConfig(usb_host_handle hostHandle, uint8_t *lpmParam);
+#endif
+/*!
+ * @brief Update the hardware tick.
+ *
+ * The function is used to update the hardware tick.
+ *
+ * @param[in] hostHandle The host handle.
+ * @param[in] tick Current hardware tick(uint is ms).
+ *
+ */
+extern usb_status_t USB_HostUpdateHwTick(usb_host_handle hostHandle, uint64_t tick);
+
+#endif
+
+/*! @}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+/*! @}*/
+
+#endif /* _USB_HOST_H_ */

+ 1414 - 0
bsp/imxrt1052-evk/drivers/usb/host/usb_host_devices.c

@@ -0,0 +1,1414 @@
+/*
+ * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
+ * Copyright 2016 NXP
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright notice, this list
+ *   of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright notice, this
+ *   list of conditions and the following disclaimer in the documentation and/or
+ *   other materials provided with the distribution.
+ *
+ * o Neither the name of the copyright holder nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <usb/include/usb_device_config.h>
+#include "usb_host.h"
+#include "usb_host_hci.h"
+#include "usb_host_devices.h"
+
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+#include "usb_host_hub.h"
+#endif /* USB_HOST_CONFIG_HUB */
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/*******************************************************************************
+ * Prototypes
+ ******************************************************************************/
+
+/*!
+ * @brief enumeration transfer callback function.
+ *
+ * @param param      callback parameter.
+ * @param transfer   the transfer.
+ * @param status     transfer result status.
+ */
+static void USB_HostEnumerationTransferCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
+
+/*!
+ * @brief process the new step state.
+ *
+ * @param deviceInstance    device instance pointer.
+ *
+ * @return kStatus_USB_Success or error codes
+ */
+static usb_status_t USB_HostProcessState(usb_host_device_instance_t *deviceInstance);
+
+/*!
+ * @brief process the previous step transfer result.
+ *
+ * @param deviceInstance    device instance pointer.
+ *
+ * @return kStatus_USB_Success or error codes
+ */
+static usb_status_t USB_HostProcessCallback(usb_host_device_instance_t *deviceInstance);
+
+/*!
+ * @brief notify the application event, the callback is registered when initializing host.
+ *
+ * @param deviceInstance   device instance pointer.
+ * @param eventCode        event code.
+ *
+ * @return kStatus_USB_Success or error codes
+ */
+static usb_status_t USB_HostNotifyDevice(usb_host_device_instance_t *deviceInstance, uint32_t eventCode);
+
+/*!
+ * @brief allocate one address.
+ *
+ * @param hostInstance    host instance pointer.
+ *
+ * @return address, 0 is invalid.
+ */
+static uint8_t USB_HostAllocateDeviceAddress(usb_host_instance_t *hostInstance);
+
+/*!
+ * @brief release one address.
+ *
+ * @param hostInstance    host instance pointer.
+ * @param address     releasing address.
+ */
+static void USB_HostReleaseDeviceAddress(usb_host_instance_t *hostInstance, uint8_t address);
+
+/*!
+ * @brief release device resource.
+ *
+ * @param hostInstance   host instance pointer.
+ * @param deviceInstance    device instance pointer.
+ */
+static void USB_HostReleaseDeviceResource(usb_host_instance_t *hostInstance,
+                                          usb_host_device_instance_t *deviceInstance);
+
+/*!
+ * @brief parse device configuration descriptor.
+ *
+ * @param deviceHandle    device handle.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+static usb_status_t USB_HostParseDeviceConfigurationDescriptor(usb_device_handle deviceHandle);
+
+/*!
+ * @brief remove device instance from host device list.
+ *
+ * @param hostHandle   host instance handle.
+ * @param deviceHandle    device handle.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+static usb_status_t USB_HostRemoveDeviceInstance(usb_host_handle hostHandle, usb_device_handle deviceHandle);
+
+/*!
+ * @brief control the bus.
+ *
+ * This function control the host bus.
+ *
+ * @param[in] hostHandle     the host handle.
+ * @param[in] controlType    the control code, please reference to bus_event_t.
+ *
+ * @retval kStatus_USB_Success              control successfully.
+ * @retval kStatus_USB_InvalidHandle        The hostHandle is a NULL pointer.
+ */
+static usb_status_t USB_HostControlBus(usb_host_handle hostHandle, uint8_t controlType);
+
+extern usb_status_t USB_HostStandardSetGetDescriptor(usb_host_device_instance_t *deviceInstance,
+                                                     usb_host_transfer_t *transfer,
+                                                     void *param);
+extern usb_status_t USB_HostStandardSetAddress(usb_host_device_instance_t *deviceInstance,
+                                               usb_host_transfer_t *transfer,
+                                               void *param);
+extern usb_status_t USB_HostCh9RequestCommon(usb_host_device_instance_t *deviceInstance,
+                                             usb_host_transfer_t *transfer,
+                                             uint8_t *buffer,
+                                             uint32_t bufferLen);
+
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+
+extern usb_status_t USB_HostHubDeviceEvent(usb_host_handle hostHandle,
+                                           usb_device_handle deviceHandle,
+                                           usb_host_configuration_handle configurationHandle,
+                                           uint32_t eventCode);
+
+extern uint32_t USB_HostHubGetHsHubNumber(usb_host_handle hostHandle, uint8_t parentHubNo);
+
+extern uint32_t USB_HostHubGetHsHubPort(usb_host_handle hostHandle, uint8_t parentHubNo, uint8_t parentPortNo);
+
+extern usb_status_t USB_HostHubRemovePort(usb_host_handle hostHandle, uint8_t hubNumber, uint8_t portNumber);
+
+#endif
+
+/*******************************************************************************
+ * Variables
+ ******************************************************************************/
+
+extern usb_host_instance_t g_UsbHostInstance[USB_HOST_CONFIG_MAX_HOST];
+
+/*! @brief enumeration step process array */
+static const usb_host_enum_process_entry_t s_EnumEntries[] = \
+{
+    /* kStatus_dev_initial */
+    {
+        0, 0, NULL,
+    },
+    /* kStatus_DEV_GetDes8 */
+    {
+        kStatus_DEV_SetAddress, kStatus_DEV_GetDes8, USB_HostProcessCallback,
+    },
+    /* kStatus_DEV_SetAddress */
+    {
+        kStatus_DEV_GetDes, kStatus_DEV_SetAddress, USB_HostProcessCallback,
+    },
+    /* kStatus_DEV_GetDes */
+    {
+        kStatus_DEV_GetCfg9, kStatus_DEV_GetDes, NULL,
+    },
+    /* kStatus_DEV_GetCfg9 */
+    {
+        kStatus_DEV_GetCfg, kStatus_DEV_GetCfg9, USB_HostProcessCallback,
+    },
+    /* kStatus_DEV_GetCfg */
+    {
+        kStatus_DEV_SetCfg, kStatus_DEV_GetCfg9, USB_HostProcessCallback,
+    },
+    /* kStatus_DEV_SetCfg */
+    {
+        kStatus_DEV_EnumDone, kStatus_DEV_SetCfg, NULL,
+    },
+};
+
+/*******************************************************************************
+ * Code
+ ******************************************************************************/
+
+static void USB_HostEnumerationTransferCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
+{
+    uint8_t nextStep = 0;
+    usb_host_device_instance_t *deviceInstance = (usb_host_device_instance_t *)param;
+
+    USB_HostFreeTransfer(deviceInstance->hostHandle, transfer); /* free transfer */
+
+    if (status == kStatus_USB_Success)
+    {
+        nextStep = 1;
+    }
+    else if (status == kStatus_USB_TransferStall)
+    {
+#if ((defined USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST))
+        usb_echo("no response from device\r\n");
+#endif                                        /* USB_HOST_CONFIG_COMPLIANCE_TEST */
+        if (deviceInstance->stallRetries > 0) /* retry same transfer when stall */
+        {
+            deviceInstance->stallRetries--;
+        }
+        else /* process next state when all retries stall */
+        {
+            nextStep = 1;
+        }
+    }
+    else if (status == kStatus_USB_TransferCancel)
+    {
+        return;
+    }
+    else
+    {
+        if (deviceInstance->enumRetries > 0) /* next whole retry */
+        {
+            deviceInstance->enumRetries--;
+            deviceInstance->stallRetries = USB_HOST_CONFIG_ENUMERATION_MAX_STALL_RETRIES;
+            deviceInstance->configurationValue = 0;
+            deviceInstance->state = kStatus_DEV_GetDes8;
+        }
+        else
+        {
+#if ((defined USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST))
+            usb_echo("Device No Response\r\n");
+#endif
+            return;
+        }
+    }
+
+    if (nextStep == 1)
+    {
+        deviceInstance->stallRetries = USB_HOST_CONFIG_ENUMERATION_MAX_STALL_RETRIES;
+        if (s_EnumEntries[deviceInstance->state - 1].process == NULL)
+        {
+            deviceInstance->state = s_EnumEntries[deviceInstance->state - 1].successState; /* next state */
+        }
+        else
+        {
+            status = s_EnumEntries[deviceInstance->state - 1].process(
+                deviceInstance);               /* process the previous state result */
+            if (status == kStatus_USB_Success) /* process success */
+            {
+                deviceInstance->state = s_EnumEntries[deviceInstance->state - 1].successState;
+            }
+            else if (status == kStatus_USB_Retry) /* need retry */
+            {
+                deviceInstance->state = s_EnumEntries[deviceInstance->state - 1].retryState;
+            }
+            else if (status == kStatus_USB_NotSupported) /* device don't suport by the application */
+            {
+                return; /* unrecoverable fail */
+            }
+            else /* process error, next retry */
+            {
+                if (deviceInstance->enumRetries > 0) /* next whole retry */
+                {
+                    deviceInstance->enumRetries--;
+                    deviceInstance->stallRetries = USB_HOST_CONFIG_ENUMERATION_MAX_STALL_RETRIES;
+                    deviceInstance->configurationValue = 0;
+                    deviceInstance->state = kStatus_DEV_GetDes8;
+                }
+                else
+                {
+#if ((defined USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST))
+                    usb_echo("Device No Response\r\n");
+#endif
+                    return; /* unrecoverable fail */
+                }
+            }
+        }
+    }
+
+    if (USB_HostProcessState(deviceInstance) != kStatus_USB_Success) /* process the new state */
+    {
+#ifdef HOST_ECHO
+        usb_echo("enumation setup error\r\n");
+#endif
+        return;
+    }
+}
+
+static usb_status_t USB_HostProcessState(usb_host_device_instance_t *deviceInstance)
+{
+    usb_status_t status = kStatus_USB_Success;
+    usb_host_process_descriptor_param_t getDescriptorParam;
+    usb_host_transfer_t *transfer;
+
+    /* malloc transfer */
+    if (deviceInstance->state != kStatus_DEV_EnumDone)
+    {
+        if (USB_HostMallocTransfer(deviceInstance->hostHandle, &transfer) != kStatus_USB_Success)
+        {
+#ifdef HOST_ECHO
+            usb_echo("error to get transfer\r\n");
+#endif
+            return kStatus_USB_Error;
+        }
+        transfer->callbackFn = USB_HostEnumerationTransferCallback;
+        transfer->callbackParam = deviceInstance;
+
+        /* reset transfer fields */
+        transfer->setupPacket->bmRequestType = 0x00;
+        transfer->setupPacket->wIndex = 0;
+        transfer->setupPacket->wLength = 0;
+        transfer->setupPacket->wValue = 0;
+    }
+
+    switch (deviceInstance->state)
+    {
+        case kStatus_DEV_GetDes8:
+        case kStatus_DEV_GetDes: /* get descriptor state */
+            getDescriptorParam.descriptorLength = sizeof(usb_descriptor_device_t);
+            if (deviceInstance->state == kStatus_DEV_GetDes8)
+            {
+                getDescriptorParam.descriptorLength = 8;
+            }
+            getDescriptorParam.descriptorBuffer = (uint8_t *)deviceInstance->deviceDescriptor;
+            getDescriptorParam.descriptorType = USB_DESCRIPTOR_TYPE_DEVICE;
+            getDescriptorParam.descriptorIndex = 0;
+            getDescriptorParam.languageId = 0;
+
+            transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_DIR_IN;
+            transfer->setupPacket->bRequest = USB_REQUEST_STANDARD_GET_DESCRIPTOR;
+            status = USB_HostStandardSetGetDescriptor(deviceInstance, transfer, &getDescriptorParam);
+            break;
+        case kStatus_DEV_SetAddress: /* set address state */
+            transfer->setupPacket->bRequest = USB_REQUEST_STANDARD_SET_ADDRESS;
+            status = USB_HostStandardSetAddress(deviceInstance, transfer, &deviceInstance->allocatedAddress);
+            break;
+
+        case kStatus_DEV_GetCfg9: /* get 9 bytes configuration state */
+            getDescriptorParam.descriptorBuffer = deviceInstance->enumBuffer;
+            getDescriptorParam.descriptorType = USB_DESCRIPTOR_TYPE_CONFIGURE;
+            getDescriptorParam.descriptorIndex = deviceInstance->configurationValue;
+            getDescriptorParam.descriptorLength = 9;
+            getDescriptorParam.languageId = 0;
+
+            transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_DIR_IN;
+            transfer->setupPacket->bRequest = USB_REQUEST_STANDARD_GET_DESCRIPTOR;
+            status = USB_HostStandardSetGetDescriptor(deviceInstance, transfer, &getDescriptorParam);
+            break;
+
+        case kStatus_DEV_GetCfg: /* get configuration state */
+            getDescriptorParam.descriptorBuffer = deviceInstance->configurationDesc;
+            getDescriptorParam.descriptorType = USB_DESCRIPTOR_TYPE_CONFIGURE;
+            getDescriptorParam.descriptorIndex = deviceInstance->configurationValue;
+            getDescriptorParam.descriptorLength = deviceInstance->configurationLen;
+            getDescriptorParam.languageId = 0;
+
+            transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_DIR_IN;
+            transfer->setupPacket->bRequest = USB_REQUEST_STANDARD_GET_DESCRIPTOR;
+            status = USB_HostStandardSetGetDescriptor(deviceInstance, transfer, &getDescriptorParam);
+            break;
+
+        case kStatus_DEV_SetCfg: /* set configuration state */
+            transfer->setupPacket->wValue =
+                USB_SHORT_TO_LITTLE_ENDIAN(deviceInstance->configuration.configurationDesc->bConfigurationValue);
+            transfer->setupPacket->bRequest = USB_REQUEST_STANDARD_SET_CONFIGURATION;
+            status = USB_HostCh9RequestCommon(deviceInstance, transfer, NULL, 0);
+            break;
+
+        case kStatus_DEV_EnumDone: /* enumeration done state */
+            status = USB_HostNotifyDevice(deviceInstance,
+                                          kUSB_HostEventEnumerationDone); /* notify device enumeration done */
+            if (status == kStatus_USB_Success)
+            {
+                deviceInstance->state = kStatus_DEV_AppUsed;
+            }
+            break;
+
+        default:
+            break;
+    }
+
+    return status;
+}
+
+static usb_status_t USB_HostProcessCallback(usb_host_device_instance_t *deviceInstance)
+{
+    usb_host_pipe_t *pipe = (usb_host_pipe_t *)deviceInstance->controlPipe;
+    usb_status_t status = kStatus_USB_Success;
+    usb_descriptor_configuration_t *configureDesc;
+    usb_host_instance_t *hostInstance = (usb_host_instance_t *)deviceInstance->hostHandle;
+
+    switch (deviceInstance->state)
+    {
+        case kStatus_DEV_GetDes8: /* process get 8 bytes descriptor result */
+            pipe->maxPacketSize = deviceInstance->deviceDescriptor->bMaxPacketSize0;
+            hostInstance->controllerTable->controllerIoctl(
+                hostInstance->controllerHandle, kUSB_HostUpdateControlPacketSize, deviceInstance->controlPipe);
+            break;
+
+        case kStatus_DEV_SetAddress: /* process set address result */
+            deviceInstance->setAddress = deviceInstance->allocatedAddress;
+            hostInstance->controllerTable->controllerIoctl(
+                hostInstance->controllerHandle, kUSB_HostUpdateControlEndpointAddress, deviceInstance->controlPipe);
+            break;
+
+        case kStatus_DEV_GetDes: /* process set address result */
+            /* NULL */
+            break;
+
+        case kStatus_DEV_GetCfg9: /* process get 9 bytes configuration result */
+            configureDesc = (usb_descriptor_configuration_t *)&deviceInstance->enumBuffer[0];
+
+            deviceInstance->configurationLen = USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(configureDesc->wTotalLength);
+            if (deviceInstance->configurationDesc != NULL)
+            {
+#if ((defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE)) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE > 0U))
+                SDK_Free(deviceInstance->configurationDesc);
+#else
+                USB_OsaMemoryFree(deviceInstance->configurationDesc);
+#endif
+                deviceInstance->configurationDesc = NULL;
+            }
+            /* for KHCI, the start address and the length should be 4 byte align */
+            if ((deviceInstance->configurationLen & 0x03) != 0)
+            {
+#if ((defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE)) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE > 0U))
+                deviceInstance->configurationDesc =
+                    (uint8_t *)SDK_Malloc((deviceInstance->configurationLen & 0xFFFFFFFCu) + 4, USB_CACHE_LINESIZE);
+#else
+                deviceInstance->configurationDesc =
+                    (uint8_t *)USB_OsaMemoryAllocate((deviceInstance->configurationLen & 0xFFFFFFFCu) + 4);
+#endif
+            }
+            else
+            {
+#if ((defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE)) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE > 0U))
+                deviceInstance->configurationDesc =
+                    (uint8_t *)SDK_Malloc(deviceInstance->configurationLen, USB_CACHE_LINESIZE);
+#else
+                deviceInstance->configurationDesc = (uint8_t *)USB_OsaMemoryAllocate(deviceInstance->configurationLen);
+#endif
+            }
+            if (deviceInstance->configurationDesc == NULL)
+            {
+                return kStatus_USB_Error;
+            }
+            break;
+
+        case kStatus_DEV_GetCfg: /* process get cofiguration result */
+            if (((usb_descriptor_configuration_t *)deviceInstance->configurationDesc)->bMaxPower >
+                USB_HOST_CONFIG_MAX_POWER)
+            {
+                return kStatus_USB_Error;
+            }
+            deviceInstance->configurationValue++;
+            if (USB_HostParseDeviceConfigurationDescriptor(deviceInstance) !=
+                kStatus_USB_Success) /* parse configuration descriptor */
+            {
+                return kStatus_USB_Error;
+            }
+
+            status = USB_HostNotifyDevice(deviceInstance, kUSB_HostEventAttach);
+
+            if (status != kStatus_USB_Success)
+            {
+                /* next configuration */
+                if (deviceInstance->configurationValue < deviceInstance->deviceDescriptor->bNumConfigurations)
+                {
+                    return kStatus_USB_Retry;
+                }
+                else
+                {
+                    USB_HostNotifyDevice(deviceInstance,
+                                         kUSB_HostEventNotSupported); /* notify application device is not supported */
+                    return kStatus_USB_NotSupported;
+                }
+            }
+            break;
+
+        case kStatus_DEV_SetCfg:
+            /* NULL */
+            break;
+
+        default:
+            break;
+    }
+
+    return status;
+}
+
+static usb_status_t USB_HostNotifyDevice(usb_host_device_instance_t *deviceInstance, uint32_t eventCode)
+{
+    usb_host_instance_t *hostInstance;
+    usb_status_t status1 = kStatus_USB_Error;
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+    usb_status_t status2 = kStatus_USB_Error;
+    uint8_t haveHub;
+    uint8_t haveNoHub;
+    uint8_t interfaceIndex;
+#endif /* USB_HOST_CONFIG_HUB */
+
+    if (deviceInstance == NULL)
+    {
+        return kStatus_USB_InvalidHandle;
+    }
+    hostInstance = (usb_host_instance_t *)deviceInstance->hostHandle;
+
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+    haveHub = 0;
+    haveNoHub = 0;
+    for (interfaceIndex = 0; interfaceIndex < deviceInstance->configuration.interfaceCount; ++interfaceIndex)
+    {
+        if (((usb_descriptor_interface_t *)deviceInstance->configuration.interfaceList[interfaceIndex].interfaceDesc)
+                ->bInterfaceClass == USB_HOST_HUB_CLASS_CODE)
+        {
+            haveHub = 1;
+        }
+        else
+        {
+            haveNoHub = 1;
+        }
+    }
+
+    if ((haveNoHub == 1) && (hostInstance->deviceCallback != NULL))
+    {
+        status1 = hostInstance->deviceCallback(deviceInstance, &deviceInstance->configuration,
+                                               eventCode); /* notify application event */
+    }
+    if (haveHub)
+    {
+        status2 = USB_HostHubDeviceEvent(hostInstance, deviceInstance, &deviceInstance->configuration,
+                                         eventCode); /* notify hub event */
+    }
+
+    if ((status1 == kStatus_USB_Success) || (status2 == kStatus_USB_Success)) /* the device is supported */
+    {
+        return kStatus_USB_Success;
+    }
+    else if (eventCode == kUSB_HostEventAttach) /* attach event */
+    {
+        status1 = kStatus_USB_NotSupported;
+    }
+    else
+    {
+        status1 = kStatus_USB_Error;
+    }
+#else
+    if (hostInstance->deviceCallback != NULL)
+    {
+        status1 = hostInstance->deviceCallback(deviceInstance, &deviceInstance->configuration,
+                                               eventCode); /* call host callback function */
+    }
+#endif
+    return status1;
+}
+
+static uint8_t USB_HostAllocateDeviceAddress(usb_host_instance_t *hostInstance)
+{
+    uint8_t address = 0;
+    uint8_t addressIndex;
+    uint8_t addressBitIndex;
+    for (addressIndex = 0; addressIndex < 8; ++addressIndex) /* find the idle address postion byte */
+    {
+        if (hostInstance->addressBitMap[addressIndex] != 0xFF)
+        {
+            break;
+        }
+    }
+    if (addressIndex < 8)
+    {
+        for (addressBitIndex = 0; addressBitIndex < 8; ++addressBitIndex) /* find the idle address position bit */
+        {
+            if (!(hostInstance->addressBitMap[addressIndex] & (0x01u << addressBitIndex)))
+            {
+                hostInstance->addressBitMap[addressIndex] |= (0x01u << addressBitIndex); /* set the allocated bit */
+                address = addressIndex * 8 + addressBitIndex + 1;                        /* the address minimum is 1 */
+                break;
+            }
+        }
+    }
+    return address;
+}
+
+static void USB_HostReleaseDeviceAddress(usb_host_instance_t *hostInstance, uint8_t address)
+{
+    USB_HostLock();
+    hostInstance->addressBitMap[(uint32_t)(address - 1) >> 3] &=
+        (~(0x01u << (((uint32_t)address - 1) & 0x07U))); /* reset the allocated bit */
+    USB_HostUnlock();
+}
+
+static usb_status_t USB_HostRemoveDeviceInstance(usb_host_handle hostHandle, usb_device_handle deviceHandle)
+{
+    usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle;
+    usb_host_device_instance_t *currentInstance;
+    usb_host_device_instance_t *prevInstance;
+    if ((hostHandle == NULL) || (deviceHandle == NULL))
+    {
+        return kStatus_USB_InvalidHandle;
+    }
+
+    /* search and remove device instance */
+    prevInstance = (usb_host_device_instance_t *)hostInstance->deviceList;
+    if (prevInstance == deviceHandle)
+    {
+        hostInstance->deviceList = prevInstance->next;
+        return kStatus_USB_Success;
+    }
+    else
+    {
+        currentInstance = prevInstance->next;
+    }
+
+    while (currentInstance != NULL)
+    {
+        if (currentInstance == deviceHandle)
+        {
+            prevInstance->next = currentInstance->next;
+            return kStatus_USB_Success;
+        }
+        prevInstance = currentInstance;
+        currentInstance = currentInstance->next;
+    }
+
+    return kStatus_USB_Success;
+}
+
+static void USB_HostReleaseDeviceResource(usb_host_instance_t *hostInstance, usb_host_device_instance_t *deviceInstance)
+{
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+    uint8_t level = 0;
+#endif
+
+#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
+    if (deviceInstance == hostInstance->suspendedDevice)
+    {
+        hostInstance->suspendedDevice = NULL;
+    }
+#endif
+    /* release device's address */
+    if (deviceInstance->setAddress != 0)
+    {
+        USB_HostReleaseDeviceAddress(hostInstance, deviceInstance->setAddress);
+    }
+    else
+    {
+        if (deviceInstance->allocatedAddress != 0)
+        {
+            USB_HostReleaseDeviceAddress(hostInstance, deviceInstance->allocatedAddress);
+        }
+    }
+
+    /* close control pipe */
+    if (deviceInstance->controlPipe != NULL)
+    {
+        USB_HostCancelTransfer(hostInstance, deviceInstance->controlPipe, NULL);
+        if (USB_HostClosePipe(hostInstance, deviceInstance->controlPipe) != kStatus_USB_Success)
+        {
+#ifdef HOST_ECHO
+            usb_echo("error when close pipe\r\n");
+#endif
+        }
+        deviceInstance->controlPipe = NULL;
+    }
+
+    /* free configuration buffer */
+    if (deviceInstance->configurationDesc != NULL)
+    {
+#if ((defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE)) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE > 0U))
+        SDK_Free(deviceInstance->configurationDesc);
+#else
+        USB_OsaMemoryFree(deviceInstance->configurationDesc);
+#endif
+    }
+
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+    level = deviceInstance->level;
+#endif
+#if ((defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE)) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE > 0U))
+    SDK_Free(deviceInstance->deviceDescriptor);
+#else
+    USB_OsaMemoryFree(deviceInstance->deviceDescriptor);
+#endif
+    /* free device instance buffer */
+    USB_OsaMemoryFree(deviceInstance);
+
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+    /* enable controller attach if root hub */
+    if (level == 1)
+    {
+        USB_HostControlBus(hostInstance, kUSB_HostBusEnableAttach);
+    }
+#else
+    /* enable controller attach */
+    USB_HostControlBus(hostInstance, kUSB_HostBusEnableAttach);
+#endif
+}
+
+static usb_status_t USB_HostParseDeviceConfigurationDescriptor(usb_device_handle deviceHandle)
+{
+    usb_host_device_instance_t *deviceInstance = (usb_host_device_instance_t *)deviceHandle;
+    uint32_t endPos;
+    usb_descriptor_union_t *unionDes;
+    usb_host_interface_t *interfaceParse = NULL;
+    usb_host_ep_t *epParse;
+    uint8_t *buffer;
+
+    if (deviceHandle == NULL)
+    {
+        return kStatus_USB_InvalidParameter;
+    }
+
+    buffer = (uint8_t *)&deviceInstance->configuration;
+    /* clear the previous parse result, note: end_pos means buffer index here*/
+    for (endPos = 0; endPos < sizeof(usb_host_configuration_t); endPos++)
+    {
+        buffer[endPos] = 0;
+    }
+    for (endPos = 0; endPos < USB_HOST_CONFIG_CONFIGURATION_MAX_INTERFACE; ++endPos)
+    {
+        deviceInstance->interfaceStatus[endPos] = 0;
+    }
+
+    /* parse configuration descriptor */
+    unionDes = (usb_descriptor_union_t *)deviceInstance->configurationDesc;
+    endPos = (uint32_t)(deviceInstance->configurationDesc + deviceInstance->configurationLen);
+
+    if ((unionDes->common.bLength == USB_DESCRIPTOR_LENGTH_CONFIGURE) &&
+        (unionDes->common.bDescriptorType == USB_DESCRIPTOR_TYPE_CONFIGURE))
+    {
+        /* configuration descriptor */
+        deviceInstance->configuration.configurationDesc = (usb_descriptor_configuration_t *)unionDes;
+        deviceInstance->configuration.configurationExtensionLength = 0;
+        deviceInstance->configuration.configurationExtension = NULL;
+        deviceInstance->configuration.interfaceCount = 0;
+        unionDes = (usb_descriptor_union_t *)((uint32_t)unionDes + unionDes->common.bLength);
+        while ((uint32_t)unionDes < endPos)
+        {
+            if (unionDes->common.bDescriptorType != USB_DESCRIPTOR_TYPE_INTERFACE)
+            {
+                if (deviceInstance->configuration.configurationExtension == NULL)
+                {
+                    deviceInstance->configuration.configurationExtension = (uint8_t *)unionDes;
+                }
+                if ((unionDes->common.bDescriptorType == 0x00) ||
+                    (unionDes->common.bLength == 0x00)) /* the descriptor data is wrong */
+                {
+                    return kStatus_USB_Error;
+                }
+                deviceInstance->configuration.configurationExtensionLength += unionDes->common.bLength;
+                unionDes = (usb_descriptor_union_t *)((uint32_t)unionDes + unionDes->common.bLength);
+            }
+            else
+            {
+                break;
+            }
+        }
+
+        /* interface descriptor */
+        deviceInstance->configuration.interfaceCount = 0;
+        while ((uint32_t)unionDes < endPos)
+        {
+            if (unionDes->common.bDescriptorType == USB_DESCRIPTOR_TYPE_INTERFACE)
+            {
+                if (unionDes->interface.bAlternateSetting == 0x00)
+                {
+                    if (deviceInstance->configuration.interfaceCount >= USB_HOST_CONFIG_CONFIGURATION_MAX_INTERFACE)
+                    {
+#ifdef HOST_ECHO
+                        usb_echo(
+                            "Unsupported Device attached\r\n too many interfaces in one configuration, please increase "
+                            "the USB_HOST_CONFIG_CONFIGURATION_MAX_INTERFACE value\n");
+#endif
+                        return kStatus_USB_Error;
+                    }
+                    interfaceParse =
+                        &deviceInstance->configuration.interfaceList[deviceInstance->configuration.interfaceCount];
+                    deviceInstance->configuration.interfaceCount++;
+                    interfaceParse->alternateSettingNumber = 0;
+                    interfaceParse->epCount = 0;
+                    interfaceParse->interfaceDesc = &unionDes->interface;
+                    interfaceParse->interfaceExtensionLength = 0;
+                    interfaceParse->interfaceExtension = NULL;
+                    interfaceParse->interfaceIndex = unionDes->interface.bInterfaceNumber;
+                    if (unionDes->common.bLength == 0x00) /* the descriptor data is wrong */
+                    {
+                        return kStatus_USB_Error;
+                    }
+                    unionDes = (usb_descriptor_union_t *)((uint32_t)unionDes + unionDes->common.bLength);
+                    while ((uint32_t)unionDes < endPos)
+                    {
+                        if ((unionDes->common.bDescriptorType != USB_DESCRIPTOR_TYPE_INTERFACE) &&
+                            (unionDes->common.bDescriptorType != USB_DESCRIPTOR_TYPE_ENDPOINT))
+                        {
+                            if (interfaceParse->interfaceExtension == NULL)
+                            {
+                                interfaceParse->interfaceExtension = (uint8_t *)unionDes;
+                            }
+                            if ((unionDes->common.bDescriptorType == 0x00) ||
+                                (unionDes->common.bLength == 0x00)) /* the descriptor data is wrong */
+                            {
+                                return kStatus_USB_Error;
+                            }
+                            interfaceParse->interfaceExtensionLength += unionDes->common.bLength;
+                            unionDes = (usb_descriptor_union_t *)((uint32_t)unionDes + unionDes->common.bLength);
+                        }
+                        else
+                        {
+                            break;
+                        }
+                    }
+
+                    /* endpoint descriptor */
+                    if (interfaceParse->interfaceDesc->bNumEndpoints != 0)
+                    {
+                        if ((unionDes->common.bDescriptorType != USB_DESCRIPTOR_TYPE_ENDPOINT) ||
+                            (interfaceParse->interfaceDesc->bNumEndpoints > USB_HOST_CONFIG_INTERFACE_MAX_EP))
+                        {
+#ifdef HOST_ECHO
+                            usb_echo("interface descriptor error\n");
+#endif
+                            return kStatus_USB_Error;
+                        }
+                        for (; interfaceParse->epCount < interfaceParse->interfaceDesc->bNumEndpoints;
+                             (interfaceParse->epCount)++)
+                        {
+                            if (((uint32_t)unionDes >= endPos) ||
+                                (unionDes->common.bDescriptorType != USB_DESCRIPTOR_TYPE_ENDPOINT))
+                            {
+#ifdef HOST_ECHO
+                                usb_echo("endpoint descriptor error\n");
+#endif
+                                return kStatus_USB_Error;
+                            }
+                            epParse = (usb_host_ep_t *)&interfaceParse->epList[interfaceParse->epCount];
+                            epParse->epDesc = (usb_descriptor_endpoint_t *)unionDes;
+                            epParse->epExtensionLength = 0;
+                            epParse->epExtension = NULL;
+                            if (unionDes->common.bLength == 0x00) /* the descriptor data is wrong */
+                            {
+                                return kStatus_USB_Error;
+                            }
+                            unionDes = (usb_descriptor_union_t *)((uint32_t)unionDes + unionDes->common.bLength);
+                            while ((uint32_t)unionDes < endPos)
+                            {
+                                if ((unionDes->common.bDescriptorType != USB_DESCRIPTOR_TYPE_ENDPOINT) &&
+                                    (unionDes->common.bDescriptorType != USB_DESCRIPTOR_TYPE_INTERFACE))
+                                {
+                                    if (epParse->epExtension == NULL)
+                                    {
+                                        epParse->epExtension = (uint8_t *)unionDes;
+                                    }
+                                    if ((unionDes->common.bDescriptorType == 0x00) ||
+                                        (unionDes->common.bLength == 0x00)) /* the descriptor data is wrong */
+                                    {
+                                        return kStatus_USB_Error;
+                                    }
+                                    epParse->epExtensionLength += unionDes->common.bLength;
+                                    unionDes =
+                                        (usb_descriptor_union_t *)((uint32_t)unionDes + unionDes->common.bLength);
+                                }
+                                else
+                                {
+                                    break;
+                                }
+                            }
+                        }
+                    }
+                }
+                else
+                {
+                    if (interfaceParse == NULL)
+                    {
+                        return kStatus_USB_Error; /* in normal situation this cannot reach */
+                    }
+                    interfaceParse->alternateSettingNumber++;
+                    if (interfaceParse->interfaceExtension == NULL)
+                    {
+                        interfaceParse->interfaceExtension = (uint8_t *)unionDes;
+                    }
+                    if (unionDes->common.bLength == 0x00) /* the descriptor data is wrong */
+                    {
+                        return kStatus_USB_Error;
+                    }
+                    interfaceParse->interfaceExtensionLength += unionDes->common.bLength;
+                    unionDes = (usb_descriptor_union_t *)((uint32_t)unionDes + unionDes->common.bLength);
+                    while ((uint32_t)unionDes < endPos)
+                    {
+                        if (unionDes->common.bDescriptorType != USB_DESCRIPTOR_TYPE_INTERFACE)
+                        {
+                            if ((unionDes->common.bDescriptorType == 0x00) ||
+                                (unionDes->common.bLength == 0x00)) /* the descriptor data is wrong */
+                            {
+                                return kStatus_USB_Error;
+                            }
+                            interfaceParse->interfaceExtensionLength += unionDes->common.bLength;
+                            unionDes = (usb_descriptor_union_t *)((uint32_t)unionDes + unionDes->common.bLength);
+                        }
+                        else
+                        {
+                            break;
+                        }
+                    }
+                }
+            }
+            else
+            {
+                return kStatus_USB_Error;
+            }
+        }
+    }
+
+    for (endPos = 0; endPos < deviceInstance->configuration.interfaceCount; ++endPos)
+    {
+        deviceInstance->interfaceStatus[endPos] = kStatus_interface_Attached;
+    }
+
+    return kStatus_USB_Success;
+}
+
+usb_status_t USB_HostAttachDevice(usb_host_handle hostHandle,
+                                  uint8_t speed,
+                                  uint8_t hubNumber,
+                                  uint8_t portNumber,
+                                  uint8_t level,
+                                  usb_device_handle *deviceHandle)
+{
+    usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle;
+    usb_host_device_instance_t *newInstance;
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+    usb_host_device_instance_t *currentInstance;
+#endif
+    uint8_t address;
+    usb_host_pipe_init_t pipeInit;
+
+    if (hostHandle == NULL)
+    {
+        return kStatus_USB_InvalidHandle;
+    }
+
+/* check whether is the device attached? */
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+    currentInstance = (usb_host_device_instance_t *)hostInstance->deviceList;
+    while (currentInstance != NULL)
+    {
+        if ((currentInstance->hubNumber == hubNumber) && (currentInstance->portNumber == portNumber))
+        {
+            *deviceHandle = NULL;
+#ifdef HOST_ECHO
+            usb_echo("device has attached\r\n");
+#endif
+            return kStatus_USB_Busy;
+        }
+        else
+        {
+            currentInstance = currentInstance->next;
+        }
+    }
+#else
+    if (hostInstance->deviceList != NULL)
+    {
+        *deviceHandle = NULL;
+        usb_echo("device has attached\r\n");
+        return kStatus_USB_Busy;
+    }
+#endif
+
+    /* Allocate new device instance */
+    newInstance = (usb_host_device_instance_t *)USB_OsaMemoryAllocate(sizeof(usb_host_device_instance_t));
+    if (newInstance == NULL)
+    {
+#ifdef HOST_ECHO
+        usb_echo("allocate dev instance fail\r\n");
+#endif
+        return kStatus_USB_AllocFail;
+    }
+
+    /* new instance fields init */
+    newInstance->hostHandle = hostHandle;
+    newInstance->speed = speed;
+    newInstance->stallRetries = USB_HOST_CONFIG_ENUMERATION_MAX_STALL_RETRIES;
+    newInstance->enumRetries = USB_HOST_CONFIG_ENUMERATION_MAX_RETRIES;
+    newInstance->setAddress = 0;
+    newInstance->deviceAttachState = kStatus_device_Attached;
+#if ((defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE)) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE > 0U))
+    newInstance->deviceDescriptor =
+        (usb_descriptor_device_t *)SDK_Malloc(sizeof(usb_descriptor_device_t) + 9, USB_CACHE_LINESIZE);
+#else
+    newInstance->deviceDescriptor =
+        (usb_descriptor_device_t *)USB_OsaMemoryAllocate(sizeof(usb_descriptor_device_t) + 9);
+#endif
+    if (newInstance->deviceDescriptor == NULL)
+    {
+#ifdef HOST_ECHO
+        usb_echo("allocate newInstance->deviceDescriptor fail\r\n");
+#endif
+#if ((defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE)) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE > 0U))
+        SDK_Free(newInstance->deviceDescriptor);
+#else
+        USB_OsaMemoryFree(newInstance->deviceDescriptor);
+#endif
+        USB_OsaMemoryFree(newInstance);
+        return kStatus_USB_AllocFail;
+    }
+    newInstance->enumBuffer = (uint8_t *)((uint8_t *)newInstance->deviceDescriptor + sizeof(usb_descriptor_device_t));
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+    newInstance->hubNumber = hubNumber;
+    newInstance->portNumber = portNumber;
+    newInstance->level = level;
+
+    if ((speed != USB_SPEED_HIGH) && (level > 1))
+    {
+        newInstance->hsHubNumber = USB_HostHubGetHsHubNumber(hostHandle, hubNumber);
+        newInstance->hsHubPort = USB_HostHubGetHsHubPort(hostHandle, hubNumber, portNumber);
+    }
+    else
+    {
+        newInstance->hsHubNumber = hubNumber;
+        newInstance->hsHubPort = portNumber;
+    }
+#endif /* USB_HOST_CONFIG_HUB */
+
+    USB_HostLock();
+    /* allocate address && insert to the dev list */
+    address = USB_HostAllocateDeviceAddress(hostInstance);
+    if (address == 0)
+    {
+#ifdef HOST_ECHO
+        usb_echo("allocate address fail\r\n");
+#endif
+        USB_HostUnlock();
+#if ((defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE)) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE > 0U))
+        SDK_Free(newInstance->deviceDescriptor);
+#else
+        USB_OsaMemoryFree(newInstance->deviceDescriptor);
+#endif
+        USB_OsaMemoryFree(newInstance);
+        return kStatus_USB_Error;
+    }
+    newInstance->allocatedAddress = address;
+
+    newInstance->next = (usb_host_device_instance_t *)hostInstance->deviceList;
+    hostInstance->deviceList = newInstance;
+    newInstance->state = kStatus_DEV_Initial;
+    USB_HostUnlock();
+
+    /* open control pipe */
+    pipeInit.devInstance = newInstance;
+    pipeInit.pipeType = USB_ENDPOINT_CONTROL;
+    pipeInit.direction = 0;
+    pipeInit.endpointAddress = 0;
+    pipeInit.interval = 0;
+    pipeInit.maxPacketSize = 8;
+    pipeInit.numberPerUframe = 0;
+    pipeInit.nakCount = USB_HOST_CONFIG_MAX_NAK;
+    if (USB_HostOpenPipe(hostHandle, &newInstance->controlPipe, &pipeInit) != kStatus_USB_Success)
+    {
+        /* don't need release resource, resource is released when detach */
+        *deviceHandle = newInstance;
+#if ((defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE)) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE > 0U))
+        SDK_Free(newInstance->deviceDescriptor);
+#else
+        USB_OsaMemoryFree(newInstance->deviceDescriptor);
+#endif
+        USB_OsaMemoryFree(newInstance);
+        return kStatus_USB_Error;
+    }
+
+    /* start enumeration */
+    newInstance->state = kStatus_DEV_GetDes8;
+    USB_HostProcessState(newInstance); /* process enumeration state machine */
+
+    *deviceHandle = newInstance;
+    return kStatus_USB_Success;
+}
+
+usb_status_t USB_HostDetachDevice(usb_host_handle hostHandle, uint8_t hubNumber, uint8_t portNumber)
+{
+    usb_host_device_instance_t *deviceInstance;
+    usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle;
+
+    if (hostHandle == NULL)
+    {
+        return kStatus_USB_InvalidHandle;
+    }
+
+    USB_HostLock();
+/* search for device instance handle */
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+    deviceInstance = (usb_host_device_instance_t *)hostInstance->deviceList;
+    while (deviceInstance != NULL)
+    {
+        if ((deviceInstance->hubNumber == hubNumber) && (deviceInstance->portNumber == portNumber))
+        {
+            break;
+        }
+        deviceInstance = deviceInstance->next;
+    }
+#else
+    deviceInstance = (usb_host_device_instance_t *)hostInstance->deviceList;
+#endif
+    USB_HostUnlock();
+    if (deviceInstance != NULL)
+    {
+        return USB_HostDetachDeviceInternal(hostHandle, deviceInstance); /* device instance detach */
+    }
+    return kStatus_USB_Success;
+}
+
+usb_status_t USB_HostDetachDeviceInternal(usb_host_handle hostHandle, usb_device_handle deviceHandle)
+{
+    usb_host_device_instance_t *deviceInstance = (usb_host_device_instance_t *)deviceHandle;
+    usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle;
+    if ((hostHandle == NULL) || (deviceHandle == NULL))
+    {
+        return kStatus_USB_InvalidHandle;
+    }
+
+    deviceInstance->deviceAttachState = kStatus_device_Detached; /* mark the device is detached from host */
+
+    if (deviceInstance->state >= kStatus_DEV_Initial) /* device instance is valid */
+    {
+        /* detach internally */
+        if (deviceInstance->state < kStatus_DEV_AppUsed) /* enumeration is not done */
+        {
+            if (deviceInstance->controlPipe != NULL)
+            {
+                USB_HostCancelTransfer(hostInstance, deviceInstance->controlPipe, NULL);
+            }
+
+            /* remove device instance from host */
+            USB_HostRemoveDeviceInstance(hostInstance, deviceInstance);
+            USB_HostReleaseDeviceResource(hostInstance, deviceInstance);
+        }
+        else /* enumeration has be done and notifed application */
+        {
+            USB_HostNotifyDevice(deviceInstance, kUSB_HostEventDetach); /* notify application device detach */
+        }
+    }
+
+    return kStatus_USB_Success;
+}
+
+uint8_t USB_HostGetDeviceAttachState(usb_device_handle deviceHandle)
+{
+    return deviceHandle ? ((usb_host_device_instance_t *)deviceHandle)->deviceAttachState : 0x0;
+}
+
+usb_status_t USB_HostValidateDevice(usb_host_handle hostHandle, usb_device_handle deviceHandle)
+{
+    usb_host_device_instance_t *searchDev;
+
+    if (deviceHandle == NULL)
+    {
+        return kStatus_USB_InvalidParameter;
+    }
+    /* search for the device */
+    searchDev = (usb_host_device_instance_t *)((usb_host_instance_t *)hostHandle)->deviceList;
+    while ((searchDev != NULL) && ((usb_device_handle)searchDev != deviceHandle))
+    {
+        searchDev = searchDev->next;
+    }
+
+    if (searchDev)
+    {
+        return kStatus_USB_Success;
+    }
+    return kStatus_USB_Error;
+}
+
+static usb_status_t USB_HostControlBus(usb_host_handle hostHandle, uint8_t controlType)
+{
+    usb_status_t status = kStatus_USB_Success;
+    usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle;
+
+    if (hostHandle == NULL)
+    {
+        return kStatus_USB_InvalidHandle;
+    }
+
+    status = hostInstance->controllerTable->controllerIoctl(hostInstance->controllerHandle, kUSB_HostBusControl,
+                                                            &controlType);
+
+    return status;
+}
+
+usb_status_t USB_HostOpenDeviceInterface(usb_device_handle deviceHandle, usb_host_interface_handle interfaceHandle)
+{
+    usb_host_device_instance_t *deviceInstance = (usb_host_device_instance_t *)deviceHandle;
+    usb_host_instance_t *hostInstance = NULL;
+    uint8_t interfaceIndex;
+    uint8_t index = 0;
+
+    if ((deviceHandle == NULL) || (interfaceHandle == NULL))
+    {
+        return kStatus_USB_InvalidHandle;
+    }
+
+    hostInstance = (usb_host_instance_t *)deviceInstance->hostHandle;
+    USB_HostLock();
+    /* check host_instance valid? */
+    for (; index < USB_HOST_CONFIG_MAX_HOST; ++index)
+    {
+        if ((g_UsbHostInstance[index].occupied == 1) &&
+            ((usb_host_instance_t *)(&g_UsbHostInstance[index]) == (hostInstance)))
+        {
+            break;
+        }
+    }
+    if (index >= USB_HOST_CONFIG_MAX_HOST)
+    {
+        USB_HostUnlock();
+        return kStatus_USB_Error;
+    }
+
+    /* check deviceHandle valid? */
+    if (USB_HostValidateDevice(hostInstance, deviceHandle) != kStatus_USB_Success)
+    {
+        USB_HostUnlock();
+        return kStatus_USB_Error;
+    }
+
+    /* search interface and set the interface as opened */
+    for (interfaceIndex = 0; interfaceIndex < deviceInstance->configuration.interfaceCount; ++interfaceIndex)
+    {
+        if (&deviceInstance->configuration.interfaceList[interfaceIndex] == interfaceHandle)
+        {
+            deviceInstance->interfaceStatus[interfaceIndex] = kStatus_interface_Opened;
+            break;
+        }
+    }
+    USB_HostUnlock();
+
+    return kStatus_USB_Success;
+}
+
+usb_status_t USB_HostCloseDeviceInterface(usb_device_handle deviceHandle, usb_host_interface_handle interfaceHandle)
+{
+    usb_host_device_instance_t *deviceInstance = (usb_host_device_instance_t *)deviceHandle;
+    usb_host_instance_t *hostInstance = NULL;
+    uint8_t interfaceIndex;
+    uint8_t removeLabel = 1;
+    uint8_t index = 0;
+
+    if (deviceHandle == NULL)
+    {
+        return kStatus_USB_InvalidHandle;
+    }
+
+    hostInstance = (usb_host_instance_t *)deviceInstance->hostHandle;
+    USB_HostLock();
+    /* check host_instance valid? */
+    for (; index < USB_HOST_CONFIG_MAX_HOST; ++index)
+    {
+        if ((g_UsbHostInstance[index].occupied == 1) &&
+            ((usb_host_instance_t *)(&g_UsbHostInstance[index]) == (hostInstance)))
+        {
+            break;
+        }
+    }
+    if (index >= USB_HOST_CONFIG_MAX_HOST)
+    {
+        USB_HostUnlock();
+        return kStatus_USB_Error;
+    }
+
+    /* check deviceHandle valid? */
+    if (USB_HostValidateDevice(hostInstance, deviceHandle) != kStatus_USB_Success)
+    {
+        USB_HostUnlock();
+        return kStatus_USB_Error;
+    }
+
+    if (interfaceHandle != NULL)
+    {
+        /* search interface and set the interface as detached */
+        for (interfaceIndex = 0; interfaceIndex < deviceInstance->configuration.interfaceCount; ++interfaceIndex)
+        {
+            if (&deviceInstance->configuration.interfaceList[interfaceIndex] == interfaceHandle)
+            {
+                deviceInstance->interfaceStatus[interfaceIndex] = kStatus_interface_Detached;
+                break;
+            }
+        }
+    }
+
+    if (deviceInstance->deviceAttachState == kStatus_device_Detached) /* device is removed from host */
+    {
+        removeLabel = 1;
+        /* check all the interfaces of the device are not opened */
+        for (interfaceIndex = 0; interfaceIndex < deviceInstance->configuration.interfaceCount; ++interfaceIndex)
+        {
+            if (deviceInstance->interfaceStatus[interfaceIndex] == kStatus_interface_Opened)
+            {
+                removeLabel = 0;
+                break;
+            }
+        }
+        if (removeLabel == 1)
+        {
+            /* remove device instance from host */
+            USB_HostRemoveDeviceInstance(hostInstance, deviceInstance);
+        }
+        USB_HostUnlock();
+
+        if (removeLabel == 1)
+        {
+            USB_HostReleaseDeviceResource((usb_host_instance_t *)deviceInstance->hostHandle,
+                                          deviceInstance); /* release device resource */
+        }
+    }
+    else
+    {
+        USB_HostUnlock();
+    }
+
+    return kStatus_USB_Success;
+}
+
+usb_status_t USB_HostRemoveDevice(usb_host_handle hostHandle, usb_device_handle deviceHandle)
+{
+    usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle;
+    usb_host_device_instance_t *deviceInstance = (usb_host_device_instance_t *)deviceHandle;
+    uint8_t interfaceIndex = 0;
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+    uint8_t level = 0;
+    uint8_t devHubNo;
+    uint8_t devPortNo;
+#endif
+
+    if ((hostHandle == NULL) || (deviceHandle == NULL))
+    {
+        return kStatus_USB_InvalidHandle;
+    }
+    if (deviceInstance->hostHandle != hostHandle)
+    {
+        return kStatus_USB_InvalidParameter;
+    }
+
+    if (USB_HostValidateDevice(hostInstance, deviceInstance) == kStatus_USB_Success) /* device is valid */
+    {
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+        devHubNo = deviceInstance->hubNumber;
+        devPortNo = deviceInstance->portNumber;
+        level = deviceInstance->level;
+#endif
+
+        deviceInstance->deviceAttachState = kStatus_device_Detached;
+        if (deviceInstance->state >= kStatus_DEV_Initial) /* device is valid */
+        {
+            if (deviceInstance->state < kStatus_DEV_AppUsed) /* enumeraion is not done or application don't use */
+            {
+                /* detach internally */
+                USB_HostDetachDeviceInternal(hostHandle, deviceHandle);
+            }
+            else /* application use the device */
+            {
+                for (interfaceIndex = 0; interfaceIndex < deviceInstance->configuration.interfaceCount;
+                     ++interfaceIndex)
+                {
+                    if (deviceInstance->interfaceStatus[interfaceIndex] == kStatus_interface_Opened)
+                    {
+#ifdef HOST_ECHO
+                        usb_echo("error: there is class instance that is not deinited\r\n");
+#endif
+                        break;
+                    }
+                }
+                /* remove device instance from host */
+                USB_HostRemoveDeviceInstance(hostInstance, deviceInstance);
+                USB_HostReleaseDeviceResource(hostInstance, deviceInstance); /* release resource */
+            }
+        }
+
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+        if (level == 1)
+        {
+            USB_HostControlBus(hostHandle, kUSB_HostBusReset);   /* reset controller port */
+            USB_HostControlBus(hostHandle, kUSB_HostBusRestart); /* restart controller port */
+        }
+        else
+        {
+            USB_HostHubRemovePort(hostHandle, devHubNo, devPortNo); /* reset hub port */
+        }
+#else
+        USB_HostControlBus(hostHandle, kUSB_HostBusReset);   /* reset controller port */
+        USB_HostControlBus(hostHandle, kUSB_HostBusRestart); /* restart controller port */
+#endif /* USB_HOST_CONFIG_HUB */
+    }
+
+    return kStatus_USB_Success;
+}

+ 178 - 0
bsp/imxrt1052-evk/drivers/usb/host/usb_host_devices.h

@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2015, Freescale Semiconductor, Inc.
+ * Copyright 2016 NXP
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright notice, this list
+ *   of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright notice, this
+ *   list of conditions and the following disclaimer in the documentation and/or
+ *   other materials provided with the distribution.
+ *
+ * o Neither the name of the copyright holder nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _USB_HOST_DEV_MNG_H_
+#define _USB_HOST_DEV_MNG_H_
+
+#include "usb_host.h"
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+/*!
+ * @addtogroup usb_host_drv
+ * @{
+ */
+/*! @brief States of device instances enumeration */
+typedef enum _usb_host_device_enumeration_status
+{
+    kStatus_DEV_Notinit = 0, /*!< Device is invalid */
+    kStatus_DEV_Initial,     /*!< Device has been processed by host driver */
+    kStatus_DEV_GetDes8,     /*!< Enumeration process: get 8 bytes' device descriptor */
+    kStatus_DEV_SetAddress,  /*!< Enumeration process: set device address */
+    kStatus_DEV_GetDes,      /*!< Enumeration process: get device descriptor */
+    kStatus_DEV_GetCfg9,     /*!< Enumeration process: get 9 bytes' configuration descriptor */
+    kStatus_DEV_GetCfg,      /*!< Enumeration process: get configuration descriptor */
+    kStatus_DEV_SetCfg,      /*!< Enumeration process: set configuration */
+    kStatus_DEV_EnumDone,    /*!< Enumeration is done */
+    kStatus_DEV_AppUsed,     /*!< This device has been used by application */
+} usb_host_device_enumeration_status_t;
+
+/*! @brief States of device's interface */
+typedef enum _usb_host_interface_state
+{
+    kStatus_interface_Attached = 1, /*!< Interface's default status */
+    kStatus_interface_Opened,       /*!< Interface is used by application */
+    kStatus_interface_Detached,     /*!< Interface is not used by application */
+} usb_host_interface_state_t;
+
+/*! @brief States of device */
+typedef enum _usb_host_device_state
+{
+    kStatus_device_Detached = 0, /*!< Device is used by application */
+    kStatus_device_Attached,     /*!< Device's default status */
+} usb_host_device_state_t;
+
+/*! @brief Device instance */
+typedef struct _usb_host_device_instance
+{
+    struct _usb_host_device_instance *next;    /*!< Next device, or NULL */
+    usb_host_handle hostHandle;                /*!< Host handle */
+    usb_host_configuration_t configuration;    /*!< Parsed configuration information for the device */
+    usb_descriptor_device_t *deviceDescriptor; /*!< Standard device descriptor */
+    usb_host_pipe_handle controlPipe;          /*!< Device's control pipe */
+    uint8_t *configurationDesc;                /*!< Configuration descriptor pointer */
+    uint16_t configurationLen;                 /*!< Configuration descriptor length */
+    uint16_t configurationValue;               /*!< Configuration index */
+    uint8_t interfaceStatus[USB_HOST_CONFIG_CONFIGURATION_MAX_INTERFACE]; /*!< Interfaces' status, please reference to
+                                                                             #usb_host_interface_state_t */
+    uint8_t *enumBuffer;                                                  /*!< Buffer for enumeration */
+    uint8_t state;                                                        /*!< Device state for enumeration */
+    uint8_t enumRetries;       /*!< Re-enumeration when error in control transfer */
+    uint8_t stallRetries;      /*!< Re-transfer when stall */
+    uint8_t speed;             /*!< Device speed */
+    uint8_t allocatedAddress;  /*!< Temporary address for the device. When set address request succeeds, setAddress is
+                                  a value, 1 - 127 */
+    uint8_t setAddress;        /*!< The address has been set to the device successfully, 1 - 127 */
+    uint8_t deviceAttachState; /*!< See the usb_host_device_state_t */
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+    /* hub related */
+    uint8_t hubNumber;   /*!< Device's first connected hub address (root hub = 0) */
+    uint8_t portNumber;  /*!< Device's first connected hub's port no (1 - 8) */
+    uint8_t hsHubNumber; /*!< Device's first connected high-speed hub's address (1 - 8) */
+    uint8_t hsHubPort;   /*!< Device's first connected high-speed hub's port no (1 - 8) */
+    uint8_t level;       /*!< Device's level (root device = 0) */
+#endif
+} usb_host_device_instance_t;
+
+typedef struct _usb_host_enum_process_entry
+{
+    uint8_t successState; /*!< When the last step is successful, the next state value */
+    uint8_t retryState;   /*!< When the last step need retry, the next state value */
+    usb_status_t (*process)(usb_host_device_instance_t *deviceInstance); /*!< When the last step transfer is done, the
+                                                                            function is used to process the transfer
+                                                                            data */
+} usb_host_enum_process_entry_t;
+
+/*******************************************************************************
+ * API
+ ******************************************************************************/
+
+/*!
+ * @brief Calls this function when device attach.
+ *
+ * @param hostHandle    Host instance handle.
+ * @param speed         Device speed.
+ * @param hubNumber     Device hub no. root device's hub no. is 0.
+ * @param portNumber    Device port no. root device's port no. is 0.
+ * @param level         Device level. root device's level is 1.
+ * @param deviceHandle  Return device handle.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+extern usb_status_t USB_HostAttachDevice(usb_host_handle hostHandle,
+                                         uint8_t speed,
+                                         uint8_t hubNumber,
+                                         uint8_t portNumber,
+                                         uint8_t level,
+                                         usb_device_handle *deviceHandle);
+
+/*!
+ * @brief Call this function when device detaches.
+ *
+ * @param hostHandle   Host instance handle.
+ * @param hubNumber    Device hub no. root device's hub no. is 0.
+ * @param portNumber   Device port no. root device's port no. is 0.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+extern usb_status_t USB_HostDetachDevice(usb_host_handle hostHandle, uint8_t hubNumber, uint8_t portNumber);
+
+/*!
+ * @brief Call this function when device detaches.
+ *
+ * @param hostHandle    Host instance handle.
+ * @param deviceHandle  Device handle.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+extern usb_status_t USB_HostDetachDeviceInternal(usb_host_handle hostHandle, usb_device_handle deviceHandle);
+
+/*!
+ * @brief Gets the device attach/detach state.
+ *
+ * @param deviceHandle    Device handle.
+ *
+ * @return 0x01 - attached; 0x00 - detached.
+ */
+extern uint8_t USB_HostGetDeviceAttachState(usb_device_handle deviceHandle);
+
+/*!
+ * @brief Determine whether the device is attached.
+ *
+ * @param hostHandle    Host instance pointer.
+ * @param deviceHandle    Device handle.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+extern usb_status_t USB_HostValidateDevice(usb_host_handle hostHandle, usb_device_handle deviceHandle);
+
+/*! @}*/
+#endif /* _USB_HOST_DEV_MNG_H_ */

+ 4747 - 0
bsp/imxrt1052-evk/drivers/usb/host/usb_host_ehci.c

@@ -0,0 +1,4747 @@
+/*
+ * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
+ * Copyright 2016 NXP
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright notice, this list
+ *   of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright notice, this
+ *   list of conditions and the following disclaimer in the documentation and/or
+ *   other materials provided with the distribution.
+ *
+ * o Neither the name of the copyright holder nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <usb/include/usb_device_config.h>
+#if ((defined USB_HOST_CONFIG_EHCI) && (USB_HOST_CONFIG_EHCI > 0U))
+#include "usb_host.h"
+#include "usb_host_hci.h"
+#include "usb_host_devices.h"
+#include "fsl_device_registers.h"
+#include "usb_host_ehci.h"
+#include "usb_phy.h"
+#if ((defined USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST))
+#include "usb_host.h"
+#endif
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+#if defined(USB_STACK_USE_DEDICATED_RAM) && (USB_STACK_USE_DEDICATED_RAM > 0U)
+
+#error The SOC does not suppoort dedicated RAM case.
+
+#endif
+
+#define USB_HOST_EHCI_BANDWIDTH_DELAY (3500U)
+#define USB_HOST_EHCI_BANDWIDTH_HUB_LS_SETUP (333U)
+#define USB_HOST_EHCI_BANDWIDTH_FRAME_TOTOAL_TIME (900U)
+
+#if ((defined USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST))
+#define USB_HOST_EHCI_TEST_DESCRIPTOR_LENGTH (18U)
+#define USB_HOST_EHCI_PORTSC_PTC_J_STATE (0x01U)
+#define USB_HOST_EHCI_PORTSC_PTC_K_STATE (0x02U)
+#define USB_HOST_EHCI_PORTSC_PTC_SE0_NAK (0x03U)
+#define USB_HOST_EHCI_PORTSC_PTC_PACKET (0x04U)
+#define USB_HOST_EHCI_PORTSC_PTC_FORCE_ENABLE_HS (0x05U)
+#define USB_HOST_EHCI_PORTSC_PTC_FORCE_ENABLE_FS (0x06U)
+#define USB_HOST_EHCI_PORTSC_PTC_FORCE_ENABLE_LS (0x07U)
+#endif
+
+/*******************************************************************************
+ * Prototypes
+ ******************************************************************************/
+/*!
+ * @brief compute data bandwidth time.
+ *
+ * @param speed       data speed.
+ * @param pipeType    data type.
+ * @param direction   data direction.
+ * @param dataLength  data length.
+ *
+ *@return time value.
+ */
+static uint32_t USB_HostBandwidthComputeTime(uint8_t speed, uint8_t pipeType, uint8_t direction, uint32_t dataLength);
+
+/*!
+ * @brief compute current allocated bandwidth when ehci work as full-speed or low-speed host.
+ *
+ * @param ehciInstance    ehci instance pointer.
+ * @param frameIndex      frame index.
+ * @param frameBandwidths return frame bandwidth data.
+ */
+static void USB_HostBandwidthFslsHostComputeCurrent(usb_host_ehci_instance_t *ehciInstance,
+                                                    uint16_t frameIndex,
+                                                    uint16_t *frameBandwidth);
+
+/*!
+ * @brief compute current hub's allocated FS/LS bandwidth when ehci work as hi-speed host.
+ *
+ * @param ehciInstance    ehci instance pointer.
+ * @param hubNumber       hub address.
+ * @param frameIndex      frame index.
+ * @param frameBandwidths return frame bandwidth data.
+ */
+static void USB_HostBandwidthHsHostComputeCurrentFsls(usb_host_ehci_instance_t *ehciInstance,
+                                                      uint32_t hubNumber,
+                                                      uint16_t frameIndex,
+                                                      uint8_t frameBandwidths[8]);
+
+/*!
+ * @brief compute current allocated HS bandwidth when ehci work as hi-speed host.
+ *
+ * @param ehciInstance         ehci instance pointer.
+ * @param frameIndex      frame index.
+ * @param frameBandwidths return frame bandwidth data.
+ */
+static void USB_HostBandwidthHsHostComputeCurrentHsAll(usb_host_ehci_instance_t *ehciInstance,
+                                                       uint16_t frameIndex,
+                                                       uint8_t frameBandwidths[8]);
+
+/*!
+ * @brief allocate HS bandwidth when host work as high-speed host.
+ *
+ * @param ehciInstance         ehci instance pointer.
+ * @param uframeInterval  micro-frame interval.
+ * @param timeData        time for allocating.
+ * @param uframe_index_out return start uframe index.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+static usb_status_t USB_HostBandwidthHsHostAllocateHsCommon(usb_host_ehci_instance_t *ehciInstance,
+                                                            uint16_t uframeInterval,
+                                                            uint16_t timeData,
+                                                            uint16_t *uframeIndexOut);
+
+/*!
+ * @brief allocate HS interrupt bandwidth when host work as high-speed host.
+ *
+ * @param ehciInstance         ehci instance pointer.
+ * @param ehciPipePointer    ehci pipe pointer.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+static usb_status_t USB_HostBandwidthHsHostAllocateInterrupt(usb_host_ehci_instance_t *ehciInstance,
+                                                             usb_host_ehci_pipe_t *ehciPipePointer);
+
+/*!
+ * @brief allocate bandwidth when host work as full-speed or low-speed host.
+ *
+ * @param ehciInstance         ehci instance pointer.
+ * @param ehciPipePointer    ehci pipe pointer.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+static usb_status_t USB_HostBandwidthFslsHostAllocate(usb_host_ehci_instance_t *ehciInstance,
+                                                      usb_host_ehci_pipe_t *ehciPipePointer);
+
+/*!
+ * @brief get the 2 power value of uint8_t.
+ *
+ * @param value     input uint8_t value.
+ */
+static uint8_t USB_HostEhciGet2PowerValue(uint8_t value);
+
+/*!
+ * @brief memory zero.
+ *
+ * @param buffer     buffer pointer.
+ * @param length     buffer length.
+ */
+static void USB_HostEhciZeroMem(uint32_t *buffer, uint32_t length);
+
+/*!
+ * @brief host ehci delay.
+ *
+ * @param ehciIpBase     ehci ip base address.
+ * @param ms          millisecond.
+ */
+static void USB_HostEhciDelay(USBHS_Type *ehciIpBase, uint32_t ms);
+
+/*!
+ * @brief host ehci start async schedule.
+ *
+ * @param ehciInstance    ehci instance pointer.
+ */
+static void USB_HostEhciStartAsync(usb_host_ehci_instance_t *ehciInstance);
+
+/*!
+ * @brief host ehci stop async schedule.
+ *
+ * @param ehciInstance    ehci instance pointer.
+ */
+static void USB_HostEhciStopAsync(usb_host_ehci_instance_t *ehciInstance);
+
+/*!
+ * @brief host ehci start periodic schedule.
+ *
+ * @param ehciInstance    ehci instance pointer.
+ */
+static void USB_HostEhciStartPeriodic(usb_host_ehci_instance_t *ehciInstance);
+
+/*!
+ * @brief host ehci stop periodic schedule.
+ *
+ * @param ehciInstance    ehci instance pointer.
+ */
+static void USB_HostEhciStopPeriodic(usb_host_ehci_instance_t *ehciInstance);
+
+/*!
+ * @brief initialize the qtd for one transfer.
+ *
+ * @param ehciInstance      ehci instance pointer.
+ * @param ehciPipePointer ehci pipe pointer.
+ * @param transfer      transfer information.
+ *
+ *@return kStatus_USB_Success or error codes.
+ */
+static usb_status_t USB_HostEhciQhQtdListInit(usb_host_ehci_instance_t *ehciInstance,
+                                              usb_host_ehci_pipe_t *ehciPipePointer,
+                                              usb_host_transfer_t *transfer);
+
+/*!
+ * @brief release the qtd list.
+ *
+ * @param ehciInstance   ehci instance pointer.
+ * @param ehciQtdStart   qtd list start pointer.
+ * @param ehciQtdEnd     qtd list end pointer.
+ *
+ *@return the transfer's length.
+ */
+static uint32_t USB_HostEhciQtdListRelease(usb_host_ehci_instance_t *ehciInstance,
+                                           usb_host_ehci_qtd_t *ehciQtdStart,
+                                           usb_host_ehci_qtd_t *ehciQtdEnd);
+
+/*!
+ * @brief de-initialize qh's linking qtd list.
+ * 1. remove qtd from qh; 2. remove transfer from qh; 3. release qtd; 4. transfer callback.
+ *
+ * @param ehciInstance    ehci instance pointer.
+ * @param ehciPipePointer ehci pipe.
+ *
+ *@return kStatus_USB_Success or error codes.
+ */
+static usb_status_t USB_HostEhciQhQtdListDeinit(usb_host_ehci_instance_t *ehciInstance,
+                                                usb_host_ehci_pipe_t *ehciPipePointer);
+
+/*!
+ * @brief de-initialize transfer's linking qtd list.
+ * 1. stop this qh schedule; 2. remove qtd from qh; 3. remove transfer from qh; 4. release qtd; 5. transfer callback; 6.
+ *start this qh schedule.
+ *
+ * @param ehciInstance    ehci instance pointer.
+ * @param ehciPipePointer ehci pipe pointer.
+ * @param transfer        transfer information.
+ *
+ *@return kStatus_USB_Success or error codes.
+ */
+static usb_status_t USB_HostEhciTransferQtdListDeinit(usb_host_ehci_instance_t *ehciInstance,
+                                                      usb_host_ehci_pipe_t *ehciPipePointer,
+                                                      usb_host_transfer_t *transfer);
+
+/*!
+ * @brief initialize QH when opening one control, bulk or interrupt pipe.
+ *
+ * @param ehciInstance       ehci instance pointer.
+ * @param ehciPipePointer    ehci pipe pointer.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+static usb_status_t USB_HostEhciQhInit(usb_host_ehci_instance_t *ehciInstance, usb_host_ehci_pipe_t *ehciPipePointer);
+
+/*!
+ * @brief de-initialize QH when closing one control, bulk or interrupt pipe.
+ *
+ * @param ehciInstance       ehci instance pointer.
+ * @param ehciPipePointer    ehci pipe pointer.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+static usb_status_t USB_HostEhciQhDeinit(usb_host_ehci_instance_t *ehciInstance, usb_host_ehci_pipe_t *ehciPipePointer);
+
+/*!
+ * @brief add qh to one frame entry.
+ *
+ * @param ehciInstance      ehci instance pointer.
+ * @param entryPointerValue entry pointer value.
+ * @param framePos          frame index.
+ * @param uframeInterval    micro-frame interval.
+ */
+static void USB_HostEhciAddQhToFrame(usb_host_ehci_instance_t *ehciInstance,
+                                     uint32_t entryPointerValue,
+                                     uint16_t framePos,
+                                     uint16_t uframeInterval);
+
+/*!
+ * @brief remove entry from frame list.
+ *
+ * @param ehciInstance      ehci instance pointer.
+ * @param entryPointerValue entry pointer value.
+ * @param framePos          frame index.
+ */
+static void USB_HostEhciRemoveFromFrame(usb_host_ehci_instance_t *ehciInstance,
+                                        uint32_t entryPointerValue,
+                                        uint16_t framePos);
+
+#if ((defined USB_HOST_CONFIG_EHCI_MAX_SITD) && (USB_HOST_CONFIG_EHCI_MAX_SITD))
+/*!
+ * @brief add sitd array to the frame list.
+ *
+ * @param ehciInstance      ehci instance pointer.
+ * @param entryPointerValue entry pointer value.
+ * @param startEntryPointer sitd entry pointer.
+ */
+static void USB_HostEhciLinkSitd(usb_host_ehci_instance_t *ehciInstance,
+                                 usb_host_ehci_pipe_t *ehciPipePointer,
+                                 void *startEntryPointer);
+
+/*!
+ * @brief initialize sitd array for one transfer.
+ *
+ * @param ehciInstance      ehci instance pointer.
+ * @param ehciPipePointer   ehci pipe pointer.
+ * @param transfer          transfer information.
+ */
+static usb_status_t USB_HostEhciSitdArrayInit(usb_host_ehci_instance_t *ehciInstance,
+                                              usb_host_ehci_pipe_t *ehciPipePointer,
+                                              usb_host_transfer_t *transfer);
+
+/*!
+ * @brief release sitd list.
+ *
+ * @param ehciInstance     ehci instance pointer.
+ * @param startSitdPointer start sitd pointer.
+ * @param endSitdPointer   end sitd pointer.
+ *
+ * @return transfer's result length.
+ */
+static uint32_t USB_HostEhciSitdArrayRelease(usb_host_ehci_instance_t *ehciInstance,
+                                             usb_host_ehci_sitd_t *startSitdPointer,
+                                             usb_host_ehci_sitd_t *endSitdPointer);
+
+/*!
+ * @brief de-initialize sitd list.
+ * 1. remove transfer; 2. remove sitd from frame list and release sitd; 3. transfer callback
+ *
+ * @param ehciInstance    ehci instance pointer.
+ * @param ehciPipePointer ehci pipe pointer.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+static usb_status_t USB_HostEhciSitdArrayDeinit(usb_host_ehci_instance_t *ehciInstance,
+                                                usb_host_ehci_pipe_t *ehciPipePointer);
+#endif /* USB_HOST_CONFIG_EHCI_MAX_SITD */
+
+#if ((defined USB_HOST_CONFIG_EHCI_MAX_ITD) && (USB_HOST_CONFIG_EHCI_MAX_ITD))
+/*!
+ * @brief compute the frame index when inserting itd.
+ *
+ * @param ehciInstance    ehci instance pointer.
+ * @param lastLinkUframe  last inserted micro-frame.
+ * @param startUframe     start micro-frame.
+ * @param uframeInterval  micro-frame interval.
+ *
+ * @return frame index
+ */
+static uint32_t USB_HostEhciGetItdLinkFrame(usb_host_ehci_instance_t *ehciInstance,
+                                            uint32_t lastLinkUframe,
+                                            uint16_t startUframe,
+                                            uint16_t uframeInterval);
+
+/*!
+ * @brief initialize itd list for one transfer.
+ * 1. initialize itd list; 2. insert itd to frame list.
+ *
+ * @param ehciInstance    ehci instance pointer.
+ * @param ehciPipePointer ehci pipe pointer.
+ * @param transfer        transfer information.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+static usb_status_t USB_HostEhciItdArrayInit(usb_host_ehci_instance_t *ehciInstance,
+                                             usb_host_ehci_pipe_t *ehciPipePointer,
+                                             usb_host_transfer_t *transfer);
+
+/*!
+ * @brief release itd list.
+ *
+ * @param ehciInstance    ehci instance pointer.
+ * @param startItdPointer start itd pointer.
+ * @param endItdPointer   end itd pointer.
+ *
+ * @return transfer's result length.
+ */
+static uint32_t USB_HostEhciItdArrayRelease(usb_host_ehci_instance_t *ehciInstance,
+                                            usb_host_ehci_itd_t *startItdPointer,
+                                            usb_host_ehci_itd_t *endItdPointer);
+
+/*!
+ * @brief de-initialize itd list.
+ * 1. remove transfer; 2. remove itd from frame list and release itd; 3. transfer callback
+ *
+ * @param ehciInstance    ehci instance pointer.
+ * @param ehciPipePointer ehci pipe pointer.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+static usb_status_t USB_HostEhciItdArrayDeinit(usb_host_ehci_instance_t *ehciInstance,
+                                               usb_host_ehci_pipe_t *ehciPipePointer);
+#endif /* USB_HOST_CONFIG_EHCI_MAX_ITD */
+
+/*!
+ * @brief open control or bulk pipe.
+ *
+ * @param ehciInstance    ehci instance pointer.
+ * @param ehciPipePointer ehci pipe pointer.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+static usb_status_t USB_HostEhciOpenControlBulk(usb_host_ehci_instance_t *ehciInstance,
+                                                usb_host_ehci_pipe_t *ehciPipePointer);
+
+/*!
+ * @brief close control or bulk pipe.
+ *
+ * @param ehciInstance    ehci instance pointer.
+ * @param ehciPipePointer ehci pipe pointer.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+static usb_status_t USB_HostEhciCloseControlBulk(usb_host_ehci_instance_t *ehciInstance,
+                                                 usb_host_ehci_pipe_t *ehciPipePointer);
+
+/*!
+ * @brief open interrupt pipe.
+ *
+ * @param ehciInstance    ehci instance pointer.
+ * @param ehciPipePointer ehci pipe pointer.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+static usb_status_t USB_HostEhciOpenInterrupt(usb_host_ehci_instance_t *ehciInstance,
+                                              usb_host_ehci_pipe_t *ehciPipePointer);
+
+/*!
+ * @brief close interrupt pipe.
+ *
+ * @param ehciInstance    ehci instance pointer.
+ * @param ehciPipePointer ehci pipe pointer.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+static usb_status_t USB_HostEhciCloseInterrupt(usb_host_ehci_instance_t *ehciInstance,
+                                               usb_host_ehci_pipe_t *ehciPipePointer);
+
+#if (((defined USB_HOST_CONFIG_EHCI_MAX_ITD) && (USB_HOST_CONFIG_EHCI_MAX_ITD)) || \
+     ((defined USB_HOST_CONFIG_EHCI_MAX_SITD) && (USB_HOST_CONFIG_EHCI_MAX_SITD)))
+/*!
+ * @brief open iso pipe.
+ *
+ * @param ehciInstance    ehci instance pointer.
+ * @param ehciPipePointer ehci pipe pointer.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+static usb_status_t USB_HostEhciOpenIso(usb_host_ehci_instance_t *ehciInstance, usb_host_ehci_pipe_t *ehciPipePointer);
+
+/*!
+ * @brief close iso pipe.
+ *
+ * @param ehciInstance    ehci instance pointer.
+ * @param ehciPipePointer ehci pipe pointer.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+static usb_status_t USB_HostEhciCloseIso(usb_host_ehci_instance_t *ehciInstance, usb_host_ehci_pipe_t *ehciPipePointer);
+
+/*!
+ * @brief allocate HS iso bandwidth when host work as high-speed host.
+ *
+ * @param ehciInstance         ehci instance pointer.
+ * @param ehciPipePointer    ehci pipe pointer.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+static usb_status_t USB_HostBandwidthHsHostAllocateIso(usb_host_ehci_instance_t *ehciInstance,
+                                                       usb_host_ehci_pipe_t *ehciPipePointer);
+
+#endif
+
+/*!
+ * @brief reset ehci ip.
+ *
+ * @param ehciInstance      ehci instance pointer.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+static usb_status_t USB_HostEhciResetIP(usb_host_ehci_instance_t *ehciInstance);
+
+/*!
+ * @brief start ehci ip.
+ *
+ * @param ehciInstance      ehci instance pointer.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+static usb_status_t USB_HostEhciStartIP(usb_host_ehci_instance_t *ehciInstance);
+
+/*!
+ * @brief cancel pipe's transfers.
+ *
+ * @param ehciInstance    ehci instance pointer.
+ * @param ehciPipePointer ehci pipe pointer.
+ * @param transfer        the canceling transfer.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+static usb_status_t USB_HostEhciCancelPipe(usb_host_ehci_instance_t *ehciInstance,
+                                           usb_host_ehci_pipe_t *ehciPipePointer,
+                                           usb_host_transfer_t *transfer);
+
+/*!
+ * @brief control ehci bus.
+ *
+ * @param ehciInstance  ehci instance pointer.
+ * @param bus_control   control code.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+static usb_status_t USB_HostEhciControlBus(usb_host_ehci_instance_t *ehciInstance, uint8_t busControl);
+
+/*!
+ * @brief ehci transaction done process function.
+ *
+ * @param ehciInstance      ehci instance pointer.
+ */
+void USB_HostEhciTransactionDone(usb_host_ehci_instance_t *ehciInstance);
+
+/*!
+ * @brief ehci port change interrupt process function.
+ *
+ * @param ehciInstance      ehci instance pointer.
+ */
+static void USB_HostEhciPortChange(usb_host_ehci_instance_t *ehciInstance);
+
+/*!
+ * @brief ehci timer0 interrupt process function.
+ * cancel control/bulk transfer that time out.
+ *
+ * @param ehciInstance      ehci instance pointer.
+ */
+static void USB_HostEhciTimer0(usb_host_ehci_instance_t *ehciInstance);
+
+#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
+/*!
+ * @brief ehci timer1 interrupt process function.
+ * cancel control/bulk transfer that time out.
+ *
+ * @param ehciInstance      ehci instance pointer.
+ */
+static void USB_HostEhciTimer1(usb_host_ehci_instance_t *ehciInstance);
+#endif
+
+#if ((defined USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST))
+/*!
+ * @brief suspend bus.
+ *
+ * @param ehciInstance      ehci instance pointer.
+ */
+static void USB_HostEhciSuspendBus(usb_host_ehci_instance_t *ehciInstance);
+
+/*!
+ * @brief resume bus.
+ *
+ * @param ehciInstance      ehci instance pointer.
+ */
+static void USB_HostEhciResumeBus(usb_host_ehci_instance_t *ehciInstance);
+
+extern usb_status_t USB_HostStandardSetGetDescriptor(usb_host_device_instance_t *deviceInstance,
+                                                     usb_host_transfer_t *transfer,
+                                                     void *param);
+#endif /* USB_HOST_CONFIG_COMPLIANCE_TEST */
+
+/*******************************************************************************
+ * Variables
+ ******************************************************************************/
+
+/* EHCI controller driver instances. */
+#if (USB_HOST_CONFIG_EHCI == 1U)
+USB_RAM_ADDRESS_ALIGNMENT(4096)
+USB_CONTROLLER_DATA static uint8_t s_UsbHostEhciFrameList1[USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE * 4];
+
+#define USB_HOST_EHCI_FRAME_LIST_ARRAY \
+    {                                  \
+        &s_UsbHostEhciFrameList1[0]    \
+    }
+
+USB_RAM_ADDRESS_ALIGNMENT(64) USB_CONTROLLER_DATA static usb_host_ehci_data_t s_UsbHostEhciData1;
+#define USB_HOST_EHCI_DATA_ARRAY \
+    {                            \
+        &s_UsbHostEhciData1      \
+    }
+#elif(USB_HOST_CONFIG_EHCI == 2U)
+USB_RAM_ADDRESS_ALIGNMENT(4096)
+USB_CONTROLLER_DATA static uint8_t s_UsbHostEhciFrameList1[USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE * 4];
+USB_RAM_ADDRESS_ALIGNMENT(4096)
+USB_CONTROLLER_DATA static uint8_t s_UsbHostEhciFrameList2[USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE * 4];
+#define USB_HOST_EHCI_FRAME_LIST_ARRAY                           \
+    {                                                            \
+        &s_UsbHostEhciFrameList1[0], &s_UsbHostEhciFrameList2[0] \
+    }
+
+USB_RAM_ADDRESS_ALIGNMENT(64) USB_CONTROLLER_DATA static usb_host_ehci_data_t s_UsbHostEhciData1;
+USB_RAM_ADDRESS_ALIGNMENT(64) USB_CONTROLLER_DATA static usb_host_ehci_data_t s_UsbHostEhciData2;
+#define USB_HOST_EHCI_DATA_ARRAY                 \
+    {                                            \
+        &s_UsbHostEhciData1, &s_UsbHostEhciData2 \
+    }
+#else
+#error "Please increase the instance count."
+#endif
+
+static uint8_t s_SlotMaxBandwidth[8] = {125, 125, 125, 125, 125, 125, 50, 0};
+
+/*******************************************************************************
+ * Code
+ ******************************************************************************/
+/*!
+* @brief EHCI NC get USB NC bass address.
+*
+* This function is used to get USB NC bass address.
+*
+* @param[in] controllerId    EHCI controller ID; See the #usb_controller_index_t.
+*
+* @retval USB NC bass address.
+*/
+#if (defined(USB_HOST_CONFIG_LOW_POWER_MODE) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
+#if (defined(FSL_FEATURE_SOC_USBNC_COUNT) && (FSL_FEATURE_SOC_USBNC_COUNT > 0U))
+void *USB_EhciNCGetBase(uint8_t controllerId)
+{
+    void *usbNCBase = NULL;
+#if ((defined FSL_FEATURE_SOC_USBNC_COUNT) && (FSL_FEATURE_SOC_USBNC_COUNT > 0U))
+    uint32_t instance;
+    uint32_t newinstance = 0;
+    uint32_t usbnc_base_temp[] = USBNC_BASE_ADDRS;
+    uint32_t usbnc_base[] = USBNC_BASE_ADDRS;
+
+    if (controllerId < kUSB_ControllerEhci0)
+    {
+        return NULL;
+    }
+
+    controllerId = controllerId - kUSB_ControllerEhci0;
+
+    for (instance = 0; instance < (sizeof(usbnc_base_temp) / sizeof(usbnc_base_temp[0])); instance++)
+    {
+        if (usbnc_base_temp[instance])
+        {
+            usbnc_base[newinstance++] = usbnc_base_temp[instance];
+        }
+    }
+    if (controllerId > newinstance)
+    {
+        return NULL;
+    }
+
+    usbNCBase = (void *)usbnc_base[controllerId];
+#endif
+    return usbNCBase;
+}
+#endif
+#endif
+
+#if ((defined USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST))
+
+usb_status_t USB_HostEhciTestSetMode(usb_host_ehci_instance_t *ehciInstance, uint32_t testMode)
+{
+    uint32_t ehciPortSC;
+
+    ehciPortSC = ehciInstance->ehciIpBase->PORTSC1;
+    ehciPortSC &= ~((uint32_t)USBHS_PORTSC1_PTC_MASK);   /* clear test mode bits */
+    ehciPortSC |= (testMode << USBHS_PORTSC1_PTC_SHIFT); /* set test mode bits */
+    ehciInstance->ehciIpBase->PORTSC1 = ehciPortSC;
+    return kStatus_USB_Success;
+}
+
+static void USB_HostEhciTestSuspendResume(usb_host_ehci_instance_t *ehciInstance)
+{
+    uint8_t timeCount;
+    timeCount = 15; /* 15s */
+    while (timeCount--)
+    {
+        USB_HostEhciDelay(ehciInstance->ehciIpBase, 1000U);
+    }
+    USB_HostEhciSuspendBus(ehciInstance);
+    timeCount = 15; /* 15s */
+    while (timeCount--)
+    {
+        USB_HostEhciDelay(ehciInstance->ehciIpBase, 1000U);
+    }
+
+    USB_HostEhciResumeBus(ehciInstance);
+}
+
+static void USB_HostEhciTestCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
+{
+    USB_HostFreeTransfer(param, transfer);
+}
+
+static void USB_HostEhciTestSingleStepGetDeviceDesc(usb_host_ehci_instance_t *ehciInstance,
+                                                    usb_device_handle deviceHandle)
+{
+    usb_host_process_descriptor_param_t getDescriptorParam;
+    usb_host_device_instance_t *deviceInstance = (usb_host_device_instance_t *)deviceHandle;
+    usb_host_transfer_t *transfer;
+    uint8_t timeCount;
+
+    /* disable periodic shedule */
+    USB_HostEhciStopPeriodic(ehciInstance);
+
+    timeCount = 15; /* 15s */
+    while (timeCount--)
+    {
+        USB_HostEhciDelay(ehciInstance->ehciIpBase, 1000U);
+    }
+
+    /* malloc one transfer */
+    if (USB_HostMallocTransfer(ehciInstance->hostHandle, &transfer) != kStatus_USB_Success)
+    {
+#ifdef HOST_ECHO
+        usb_echo("allocate transfer error\r\n");
+#endif
+        return;
+    }
+
+    getDescriptorParam.descriptorLength = sizeof(usb_descriptor_device_t);
+    getDescriptorParam.descriptorLength = 18;
+    getDescriptorParam.descriptorBuffer = (uint8_t *)&deviceInstance->deviceDescriptor;
+    getDescriptorParam.descriptorType = USB_DESCRIPTOR_TYPE_DEVICE;
+    getDescriptorParam.descriptorIndex = 0;
+    getDescriptorParam.languageId = 0;
+    transfer->callbackFn = USB_HostEhciTestCallback;
+    transfer->callbackParam = ehciInstance->hostHandle;
+    transfer->setupPacket->bmRequestType = USB_REQUEST_TYPE_DIR_IN;
+    transfer->setupPacket->bRequest = USB_REQUEST_STANDARD_GET_DESCRIPTOR;
+    transfer->setupPacket->wIndex = 0;
+    transfer->setupPacket->wLength = 0;
+    transfer->setupPacket->wValue = 0;
+    USB_HostStandardSetGetDescriptor(deviceInstance, transfer, &getDescriptorParam);
+}
+
+static usb_status_t USB_HostEhciSingleStepQtdListInit(usb_host_ehci_instance_t *ehciInstance,
+                                                      usb_host_ehci_pipe_t *ehciPipePointer,
+                                                      usb_host_transfer_t *transfer,
+                                                      uint8_t setupPhase)
+{
+    volatile usb_host_ehci_qh_t *vltQhPointer;
+    usb_host_ehci_qtd_t *qtdPointer = NULL;
+    volatile uint32_t *entryPointer;
+    uint32_t qtdNumber;
+    uint32_t dataLength;
+    uint32_t dataAddress;
+    uint8_t index;
+
+    /* compute the qtd number */
+    qtdNumber = 1;
+
+    vltQhPointer = (volatile usb_host_ehci_qh_t *)ehciPipePointer->ehciQh;
+    /* get qtd list */
+    USB_HostEhciLock();
+    if (qtdNumber <= ehciInstance->ehciQtdNumber)
+    {
+        ehciInstance->ehciQtdNumber -= qtdNumber;
+        qtdPointer = NULL;
+        do
+        {
+            if (qtdPointer != NULL)
+            {
+                qtdPointer->nextQtdPointer = (uint32_t)ehciInstance->ehciQtdHead;
+            }
+            qtdPointer = ehciInstance->ehciQtdHead;
+            ehciInstance->ehciQtdHead = (usb_host_ehci_qtd_t *)qtdPointer->nextQtdPointer;
+            qtdPointer->nextQtdPointer = 0;
+        } while (--qtdNumber);
+    }
+    else
+    {
+        USB_HostEhciUnlock();
+        return kStatus_USB_Error;
+    }
+    USB_HostEhciUnlock();
+
+    /* int qTD */
+    if (setupPhase == 1) /* setup transaction qtd init */
+    {
+        qtdPointer->alternateNextQtdPointer = EHCI_HOST_T_INVALID_VALUE;
+        /* dt: need set; ioc: 0; C_Page: 0; PID Code: SETUP; Status: Active */
+        qtdPointer->transferResults[0] = qtdPointer->transferResults[1] = 0;
+        qtdPointer->transferResults[0] =
+            ((0x00000000 << EHCI_HOST_QTD_DT_SHIFT) | (8 << EHCI_HOST_QTD_TOTAL_BYTES_SHIFT) |
+             (EHCI_HOST_PID_SETUP << EHCI_HOST_QTD_PID_CODE_SHIFT) | (EHCI_HOST_QTD_STATUS_ACTIVE_MASK));
+        dataAddress = (uint32_t)(transfer->setupPacket);
+        qtdPointer->transferResults[1] = dataAddress; /* current offset is set too */
+        /* set buffer pointer no matter data length */
+        for (index = 0; index < 4; ++index)
+        {
+            qtdPointer->bufferPointers[index] = ((dataAddress + (index + 1) * 4 * 1024) & 0xFFFFF000);
+        }
+    }
+    else if (setupPhase == 2) /* data transaction qtd */
+    {
+        dataLength = transfer->transferLength;
+        if (dataLength != 0)
+        {
+            qtdPointer->alternateNextQtdPointer = EHCI_HOST_T_INVALID_VALUE;
+            /* dt: need set; ioc: 0; C_Page: 0; PID Code: IN/OUT; Status: Active */
+            qtdPointer->transferResults[0] = qtdPointer->transferResults[1] = 0;
+
+            qtdPointer->transferResults[0] =
+                ((0x00000001U << EHCI_HOST_QTD_DT_SHIFT) | (dataLength << EHCI_HOST_QTD_TOTAL_BYTES_SHIFT) |
+                 (EHCI_HOST_PID_IN << EHCI_HOST_QTD_PID_CODE_SHIFT) | (EHCI_HOST_QTD_STATUS_ACTIVE_MASK));
+
+            dataAddress = (uint32_t)(transfer->transferBuffer);
+            qtdPointer->transferResults[1] = dataAddress; /* current offset is set too */
+            /* set buffer pointer no matter data length */
+            for (index = 0; index < 4; ++index)
+            {
+                qtdPointer->bufferPointers[index] = ((dataAddress + (index + 1) * 4 * 1024) & 0xFFFFF000);
+            }
+        }
+    }
+    else if (setupPhase == 3)
+    {
+        /* status transaction qtd */
+        qtdPointer->alternateNextQtdPointer = EHCI_HOST_T_INVALID_VALUE;
+        /* dt: dont care; ioc: 1; C_Page: 0; PID Code: IN/OUT; Status: Active */
+        qtdPointer->transferResults[0] = qtdPointer->transferResults[1] = 0;
+
+        qtdPointer->transferResults[0] =
+            ((0x00000001U << EHCI_HOST_QTD_DT_SHIFT) | (EHCI_HOST_PID_OUT << EHCI_HOST_QTD_PID_CODE_SHIFT) |
+             (EHCI_HOST_QTD_IOC_MASK) | (EHCI_HOST_QTD_STATUS_ACTIVE_MASK));
+
+        qtdPointer->nextQtdPointer |= EHCI_HOST_T_INVALID_VALUE;
+    }
+    qtdPointer->nextQtdPointer |= EHCI_HOST_T_INVALID_VALUE;
+    qtdPointer->transferResults[0] |= EHCI_HOST_QTD_IOC_MASK; /* set IOC */
+
+    /* save qtd to transfer */
+    transfer->union1.unitHead = (uint32_t)qtdPointer;
+    transfer->union2.unitTail = (uint32_t)qtdPointer;
+    /* link transfer to qh */
+    transfer->next = NULL;
+    if (vltQhPointer->ehciTransferHead == NULL)
+    {
+        transfer->next = NULL;
+        vltQhPointer->ehciTransferHead = vltQhPointer->ehciTransferTail = transfer;
+    }
+    else
+    {
+        transfer->next = NULL;
+        vltQhPointer->ehciTransferTail->next = transfer;
+        vltQhPointer->ehciTransferTail = transfer;
+    }
+
+    USB_HostEhciLock();
+    /* link qtd to qh (link to end) */
+    entryPointer = &(vltQhPointer->nextQtdPointer);
+    dataAddress = *entryPointer; /* dataAddress variable means entry value here */
+    while ((dataAddress) && (!(dataAddress & EHCI_HOST_T_INVALID_VALUE)))
+    {
+        entryPointer = (volatile uint32_t *)dataAddress;
+        dataAddress = *entryPointer;
+    }
+    *entryPointer = (uint32_t)qtdPointer;
+    USB_HostEhciUnlock();
+    USB_HostEhciStartAsync(ehciInstance);
+
+    return kStatus_USB_Success;
+}
+
+static void USB_HostEhciTestSingleStepGetDeviceDescData(usb_host_ehci_instance_t *ehciInstance,
+                                                        usb_device_handle deviceHandle)
+{
+    static uint8_t buffer[USB_HOST_EHCI_TEST_DESCRIPTOR_LENGTH];
+    usb_host_device_instance_t *deviceInstance = (usb_host_device_instance_t *)deviceHandle;
+    usb_host_transfer_t *transfer;
+    uint8_t timeCount;
+
+    USB_HostEhciStopPeriodic(ehciInstance);
+
+    if (USB_HostMallocTransfer(ehciInstance->hostHandle, &transfer) != kStatus_USB_Success)
+    {
+        return;
+    }
+    transfer->callbackFn = USB_HostEhciTestCallback;
+    transfer->callbackParam = ehciInstance->hostHandle;
+    transfer->setupPacket->bmRequestType = USB_REQUEST_TYPE_DIR_IN;
+    transfer->setupPacket->bRequest = USB_REQUEST_STANDARD_GET_DESCRIPTOR;
+    transfer->setupPacket->wLength = USB_SHORT_TO_LITTLE_ENDIAN(USB_HOST_EHCI_TEST_DESCRIPTOR_LENGTH);
+    transfer->setupPacket->wValue = USB_SHORT_TO_LITTLE_ENDIAN((uint16_t)((uint16_t)USB_DESCRIPTOR_TYPE_DEVICE << 8));
+    transfer->setupPacket->wIndex = 0;
+    USB_HostEhciSingleStepQtdListInit(ehciInstance, (usb_host_ehci_pipe_t *)(deviceInstance->controlPipe), transfer, 1);
+
+    timeCount = 15; /* 15s */
+    while (timeCount--)
+    {
+        USB_HostEhciDelay(ehciInstance->ehciIpBase, 1000U);
+    }
+
+    if (USB_HostMallocTransfer(ehciInstance->hostHandle, &transfer) != kStatus_USB_Success)
+    {
+        return;
+    }
+    transfer->callbackFn = USB_HostEhciTestCallback;
+    transfer->callbackParam = ehciInstance->hostHandle;
+    transfer->transferBuffer = buffer;
+    transfer->transferLength = USB_HOST_EHCI_TEST_DESCRIPTOR_LENGTH;
+    USB_HostEhciSingleStepQtdListInit(ehciInstance, (usb_host_ehci_pipe_t *)(deviceInstance->controlPipe), transfer, 2);
+
+    if (USB_HostMallocTransfer(ehciInstance->hostHandle, &transfer) != kStatus_USB_Success)
+    {
+        return;
+    }
+    transfer->callbackFn = USB_HostEhciTestCallback;
+    transfer->callbackParam = ehciInstance->hostHandle;
+    transfer->transferBuffer = NULL;
+    transfer->transferLength = 0;
+    USB_HostEhciSingleStepQtdListInit(ehciInstance, (usb_host_ehci_pipe_t *)(deviceInstance->controlPipe), transfer, 3);
+
+    timeCount = 15; /* 15s */
+    while (timeCount--)
+    {
+        USB_HostEhciDelay(ehciInstance->ehciIpBase, 1000U);
+    }
+
+    usb_echo("test_single_step_get_dev_desc_data finished\r\n");
+
+    return;
+}
+
+void USB_HostEhciTestModeInit(usb_device_handle deviceHandle)
+{
+    uint32_t productId;
+    usb_host_device_instance_t *deviceInstance = (usb_host_device_instance_t *)deviceHandle;
+    usb_host_ehci_instance_t *ehciInstance =
+        (usb_host_ehci_instance_t *)(((usb_host_instance_t *)(deviceInstance->hostHandle))->controllerHandle);
+
+    USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDevicePID, &productId);
+
+    usb_echo("usb host ehci test mode init  product id:0x%x\r\n", productId);
+
+    switch (productId)
+    {
+        case 0x0101U:
+            USB_HostEhciTestSetMode(ehciInstance, USB_HOST_EHCI_PORTSC_PTC_SE0_NAK);
+            break;
+        case 0x0102U:
+            USB_HostEhciTestSetMode(ehciInstance, USB_HOST_EHCI_PORTSC_PTC_J_STATE);
+            break;
+        case 0x0103U:
+            USB_HostEhciTestSetMode(ehciInstance, USB_HOST_EHCI_PORTSC_PTC_K_STATE);
+            break;
+        case 0x0104U:
+            USB_HostEhciTestSetMode(ehciInstance, USB_HOST_EHCI_PORTSC_PTC_PACKET);
+            break;
+        case 0x0105U:
+            usb_echo("set test mode FORCE_ENALBE_HS\r\n");
+            USB_HostEhciTestSetMode(ehciInstance, USB_HOST_EHCI_PORTSC_PTC_FORCE_ENABLE_HS);
+            break;
+        case 0x0106U:
+            USB_HostEhciTestSuspendResume(ehciInstance);
+            break;
+        case 0x0107U:
+            usb_echo("start test SINGLE_STEP_GET_DEV_DESC\r\n");
+            USB_HostEhciTestSingleStepGetDeviceDesc(ehciInstance, deviceHandle);
+            break;
+        case 0x0108U:
+            usb_echo("start test SINGLE_STEP_GET_DEV_DESC_DATA\r\n");
+            USB_HostEhciTestSingleStepGetDeviceDescData(ehciInstance, deviceHandle);
+            break;
+        default:
+            break;
+    }
+
+    return;
+}
+
+static void USB_HostEhciSuspendBus(usb_host_ehci_instance_t *ehciInstance)
+{
+    uint32_t ehciPortSC;
+
+    USB_HostEhciLock();
+    ehciPortSC = ehciInstance->ehciIpBase->PORTSC1;
+    if (ehciPortSC & USBHS_PORTSC1_PE_MASK)
+    {
+        ehciPortSC = ehciInstance->ehciIpBase->PORTSC1;
+        ehciPortSC &= (uint32_t)(~EHCI_PORTSC1_W1_BITS);
+        ehciInstance->ehciIpBase->PORTSC1 = (ehciPortSC | USBHS_PORTSC1_SUSP_MASK);
+    }
+    USB_HostEhciUnlock();
+}
+
+static void USB_HostEhciResumeBus(usb_host_ehci_instance_t *ehciInstance)
+{
+    uint32_t ehciPortSC;
+
+    USB_HostEhciLock();
+    /* Resume port */
+    ehciPortSC = ehciInstance->ehciIpBase->PORTSC1;
+    if (ehciPortSC & USBHS_PORTSC1_PE_MASK)
+    {
+        ehciPortSC &= (uint32_t)(~EHCI_PORTSC1_W1_BITS);
+        ehciInstance->ehciIpBase->PORTSC1 = (ehciPortSC | USBHS_PORTSC1_FPR_MASK);
+    }
+    USB_HostEhciUnlock();
+}
+#endif
+
+static uint32_t USB_HostBandwidthComputeTime(uint8_t speed, uint8_t pipeType, uint8_t direction, uint32_t dataLength)
+{
+    uint32_t result = (3167 + ((1000 * dataLength) * 7U * 8U / 6U)) / 1000;
+
+    if (pipeType == USB_ENDPOINT_ISOCHRONOUS) /* iso */
+    {
+        if (speed == USB_SPEED_HIGH)
+        {
+            result = 38 * 8 * 2083 + 2083 * result + USB_HOST_EHCI_BANDWIDTH_DELAY;
+        }
+        else if (speed == USB_SPEED_FULL)
+        {
+            if (direction == USB_IN)
+            {
+                result = 7268000 + 83540 * result + USB_HOST_EHCI_BANDWIDTH_DELAY;
+            }
+            else
+            {
+                result = 6265000 + 83540 * result + USB_HOST_EHCI_BANDWIDTH_DELAY;
+            }
+        }
+        else
+        {
+        }
+    }
+    else /* interrupt */
+    {
+        if (speed == USB_SPEED_HIGH)
+        {
+            result = 55 * 8 * 2083 + 2083 * result + USB_HOST_EHCI_BANDWIDTH_DELAY;
+        }
+        else if (speed == USB_SPEED_FULL)
+        {
+            result = 9107000 + 83540 * result + USB_HOST_EHCI_BANDWIDTH_DELAY;
+        }
+        else if (speed == USB_SPEED_LOW)
+        {
+            if (direction == USB_IN)
+            {
+                result = 64060000 + 2000 * USB_HOST_EHCI_BANDWIDTH_HUB_LS_SETUP + 676670 * result +
+                         USB_HOST_EHCI_BANDWIDTH_DELAY;
+            }
+            else
+            {
+                result = 6265000 + 83540 * result + USB_HOST_EHCI_BANDWIDTH_DELAY;
+            }
+        }
+        else
+        {
+        }
+    }
+
+    result /= 1000000;
+    if (result == 0)
+    {
+        result = 1;
+    }
+
+    return result;
+}
+
+static void USB_HostBandwidthFslsHostComputeCurrent(usb_host_ehci_instance_t *ehciInstance,
+                                                    uint16_t frameIndex,
+                                                    uint16_t *frameBandwidth)
+{
+    usb_host_ehci_pipe_t *ehciPipePointer;
+
+    /* clear the bandwidth */
+    *frameBandwidth = 0;
+
+    ehciPipePointer = ehciInstance->ehciRunningPipeList;
+    while (ehciPipePointer != NULL)
+    {
+        /* only compute iso and interrupt pipe */
+        if ((ehciPipePointer->pipeCommon.pipeType == USB_ENDPOINT_ISOCHRONOUS) ||
+            (ehciPipePointer->pipeCommon.pipeType == USB_ENDPOINT_INTERRUPT))
+        {
+            /* does pipe allocate bandwidth in frameIndex frame? note: interval is power of 2. */
+            if ((frameIndex >= ehciPipePointer->startFrame) &&
+                (!((uint32_t)(frameIndex - ehciPipePointer->startFrame) &
+                   (uint32_t)(ehciPipePointer->pipeCommon.interval - 1))))
+            {
+                *frameBandwidth += ehciPipePointer->dataTime;
+            }
+        }
+        ehciPipePointer = (usb_host_ehci_pipe_t *)ehciPipePointer->pipeCommon.next;
+    }
+}
+
+static void USB_HostBandwidthHsHostComputeCurrentFsls(usb_host_ehci_instance_t *ehciInstance,
+                                                      uint32_t hubNumber,
+                                                      uint16_t frameIndex,
+                                                      uint8_t frameBandwidths[8])
+{
+    usb_host_ehci_pipe_t *ehciPipePointer;
+    uint8_t index;
+    uint32_t deviceInfo;
+
+    for (index = 0; index < 8; ++index)
+    {
+        frameBandwidths[index] = 0;
+    }
+
+    ehciPipePointer = ehciInstance->ehciRunningPipeList;
+    while (ehciPipePointer != NULL)
+    {
+        /* only compute iso and interrupt pipe */
+        if ((ehciPipePointer->pipeCommon.pipeType == USB_ENDPOINT_ISOCHRONOUS) ||
+            (ehciPipePointer->pipeCommon.pipeType == USB_ENDPOINT_INTERRUPT))
+        {
+            /* compute FS/LS bandwidth that blong to same high-speed hub, because FS/LS bandwidth is allocated from
+             * first parent high-speed hub */
+            USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle,
+                                                   kUSB_HostGetDeviceHSHubNumber, &deviceInfo);
+            if (deviceInfo != hubNumber)
+            {
+                ehciPipePointer = (usb_host_ehci_pipe_t *)ehciPipePointer->pipeCommon.next;
+                continue;
+            }
+            USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetDeviceSpeed,
+                                                   &deviceInfo);
+            if (deviceInfo == USB_SPEED_HIGH)
+            {
+                ehciPipePointer = (usb_host_ehci_pipe_t *)ehciPipePointer->pipeCommon.next;
+                continue;
+            }
+
+            /* does pipe allocate bandwidth in frameIndex frame? note: interval is power of 2. */
+            if ((frameIndex >= ehciPipePointer->startFrame) &&
+                (!((uint32_t)(frameIndex - ehciPipePointer->startFrame) &
+                   (uint32_t)(ehciPipePointer->pipeCommon.interval - 1))))
+            {
+                if (ehciPipePointer->pipeCommon.pipeType ==
+                    USB_ENDPOINT_ISOCHRONOUS) /* iso bandwidth is allocated once */
+                {
+                    frameBandwidths[ehciPipePointer->startUframe + 1] += ehciPipePointer->dataTime;
+                }
+                else /* iso bandwidth is allocated three times */
+                {
+                    frameBandwidths[ehciPipePointer->startUframe + 1] += ehciPipePointer->dataTime;
+                    frameBandwidths[ehciPipePointer->startUframe + 2] += ehciPipePointer->dataTime;
+                    frameBandwidths[ehciPipePointer->startUframe + 3] += ehciPipePointer->dataTime;
+                }
+            }
+        }
+        ehciPipePointer = (usb_host_ehci_pipe_t *)ehciPipePointer->pipeCommon.next;
+    }
+
+    for (index = 0; index < 7; ++index) /*  */
+    {
+        if (frameBandwidths[index] > s_SlotMaxBandwidth[index])
+        {
+            frameBandwidths[index + 1] += (frameBandwidths[index] - s_SlotMaxBandwidth[index]);
+            frameBandwidths[index] = s_SlotMaxBandwidth[index];
+        }
+    }
+}
+
+static void USB_HostBandwidthHsHostComputeCurrentHsAll(usb_host_ehci_instance_t *ehciInstance,
+                                                       uint16_t frameIndex,
+                                                       uint8_t frameBandwidths[8])
+{
+    usb_host_ehci_pipe_t *ehciPipePointer;
+    uint8_t index;
+    uint32_t deviceInfo;
+    uint16_t frameInterval;
+
+    for (index = 0; index < 8; ++index)
+    {
+        frameBandwidths[index] = 0;
+    }
+
+    ehciPipePointer = ehciInstance->ehciRunningPipeList;
+    while (ehciPipePointer != NULL)
+    {
+        /* only compute iso and interrupt pipe */
+        if ((ehciPipePointer->pipeCommon.pipeType == USB_ENDPOINT_ISOCHRONOUS) ||
+            (ehciPipePointer->pipeCommon.pipeType == USB_ENDPOINT_INTERRUPT))
+        {
+            frameInterval = ehciPipePointer->pipeCommon.interval;
+            USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetDeviceSpeed,
+                                                   &deviceInfo);
+            if (deviceInfo == USB_SPEED_HIGH) /* high-speed data bandwidth */
+            {
+                /* frameInterval means micro-frame here */
+                if (frameIndex >= ehciPipePointer->startFrame)
+                {
+                    if ((frameInterval > 8) &&
+                        (frameIndex * 8 - ehciPipePointer->startFrame * 8 >= ehciPipePointer->startUframe))
+                    {
+                        if (!((uint32_t)(frameIndex * 8 - ehciPipePointer->startFrame * 8 -
+                                         ehciPipePointer->startUframe) &
+                              (uint32_t)(frameInterval - 1)))
+                        {
+                            frameBandwidths[ehciPipePointer->startUframe] += ehciPipePointer->dataTime;
+                        }
+                    }
+                    else
+                    {
+                        for (index = ehciPipePointer->startUframe; index < 8; index += frameInterval)
+                        {
+                            frameBandwidths[index] += ehciPipePointer->dataTime;
+                        }
+                    }
+                }
+            }
+            else /* full-speed split bandwidth */
+            {
+                if ((frameIndex >= ehciPipePointer->startFrame) &&
+                    (!((uint32_t)(frameIndex - ehciPipePointer->startFrame) & (uint32_t)(frameInterval - 1))))
+                {
+                    for (index = 0; index < 8; ++index)
+                    {
+                        if ((uint32_t)(ehciPipePointer->uframeSmask) &
+                            (uint32_t)(0x01 << index)) /* start-split micro-frames */
+                        {
+                            frameBandwidths[index] += ehciPipePointer->startSplitTime;
+                        }
+                        if ((uint32_t)(ehciPipePointer->uframeCmask) &
+                            (uint32_t)(0x01 << index)) /* complete-split micro-frames */
+                        {
+                            frameBandwidths[index] += ehciPipePointer->completeSplitTime;
+                        }
+                    }
+                }
+            }
+        }
+        ehciPipePointer = (usb_host_ehci_pipe_t *)ehciPipePointer->pipeCommon.next;
+    }
+
+    for (index = 0; index < 7; ++index) /*  */
+    {
+        if (frameBandwidths[index] > s_SlotMaxBandwidth[index])
+        {
+            frameBandwidths[index + 1] += (frameBandwidths[index] - s_SlotMaxBandwidth[index]);
+            frameBandwidths[index] = s_SlotMaxBandwidth[index];
+        }
+    }
+}
+
+/*!
+ * @brief allocate HS bandwidth when host work as high-speed host.
+ *
+ * @param ehciInstance         ehci instance pointer.
+ * @param uframeInterval  micro-frame interval.
+ * @param timeData        time for allocating.
+ * @param uframeIndexOut return start uframe index.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+static usb_status_t USB_HostBandwidthHsHostAllocateHsCommon(usb_host_ehci_instance_t *ehciInstance,
+                                                            uint16_t uframeInterval,
+                                                            uint16_t timeData,
+                                                            uint16_t *uframeIndexOut)
+{
+    uint16_t uframeIntervalIndex;
+    uint16_t uframeIndex;
+    uint16_t frameIndex;
+    uint8_t frameTimes[8];
+
+    frameIndex = 0;
+    USB_HostBandwidthHsHostComputeCurrentHsAll(
+        ehciInstance, frameIndex, frameTimes); /* compute the allocated bandwidths in the frameIndex frame */
+    for (uframeIntervalIndex = 0; (uframeIntervalIndex < uframeInterval); ++uframeIntervalIndex) /* start micro-frame */
+    {
+        /* for all the micro-frame in interval uframeInterval */
+        for (uframeIndex = uframeIntervalIndex; uframeIndex < (USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE * 8);
+             uframeIndex += uframeInterval)
+        {
+            if (frameIndex != (uframeIndex >> 3))
+            {
+                frameIndex = (uframeIndex >> 3);
+                USB_HostBandwidthHsHostComputeCurrentHsAll(
+                    ehciInstance, frameIndex,
+                    frameTimes); /* compute the allocated bandwidths in the new frameIndex frame */
+            }
+            if (frameTimes[uframeIndex & 0x0007] + timeData >
+                s_SlotMaxBandwidth[(uframeIndex & 0x0007)]) /* micro-frame has enough idle bandwidth? */
+            {
+                break; /* fail */
+            }
+        }
+        if (uframeIndex >= (USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE * 8)) /* success? */
+        {
+            break;
+        }
+    }
+
+    if (uframeIntervalIndex < uframeInterval)
+    {
+        *uframeIndexOut = (uframeIntervalIndex);
+        return kStatus_USB_Success;
+    }
+    else
+    {
+        return kStatus_USB_Error;
+    }
+}
+
+#if (((defined USB_HOST_CONFIG_EHCI_MAX_ITD) && (USB_HOST_CONFIG_EHCI_MAX_ITD)) || \
+     ((defined USB_HOST_CONFIG_EHCI_MAX_SITD) && (USB_HOST_CONFIG_EHCI_MAX_SITD)))
+
+static usb_status_t USB_HostBandwidthHsHostAllocateIso(usb_host_ehci_instance_t *ehciInstance,
+                                                       usb_host_ehci_pipe_t *ehciPipePointer)
+{
+    usb_status_t status;
+    uint32_t deviceInfo;
+    uint32_t hubNumber;
+    uint16_t uframeIntervalIndex = 0;
+    uint16_t frameIntervalIndex = 0;
+    uint16_t frameIndex;
+    uint16_t timeCompleteSplit;
+    uint16_t timeStartSplit;
+    uint32_t timeData;
+    uint8_t SsCsNumber = 0;
+    uint16_t frameInterval;
+    uint8_t frameTimes[8];
+    uint8_t allocateOk = 1;
+    uint8_t index;
+
+    USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetDeviceSpeed,
+                                           &deviceInfo);
+
+    timeData = USB_HostBandwidthComputeTime(
+        deviceInfo, USB_ENDPOINT_ISOCHRONOUS, ehciPipePointer->pipeCommon.direction,
+        ehciPipePointer->pipeCommon.maxPacketSize * ehciPipePointer->pipeCommon.numberPerUframe);
+    /* pipe is high-speed */
+    if (deviceInfo == USB_SPEED_HIGH)
+    {
+        uframeIntervalIndex = 0;
+        status = USB_HostBandwidthHsHostAllocateHsCommon(ehciInstance, ehciPipePointer->uframeInterval, timeData,
+                                                         &uframeIntervalIndex);
+        if (status == kStatus_USB_Success)
+        {
+            ehciPipePointer->startFrame = (uframeIntervalIndex / 8);
+            ehciPipePointer->startUframe = (uframeIntervalIndex & 0x0007);
+            ehciPipePointer->dataTime = timeData;
+
+            return kStatus_USB_Success;
+        }
+    }
+    else /* pipe is full-speed or low-speed */
+    {
+        USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetHubThinkTime,
+                                               &deviceInfo); /* deviceInfo variable means hub think time */
+        timeData += (deviceInfo * 7 / (6 * 12));
+        USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetDeviceHSHubNumber,
+                                               &hubNumber);
+        frameInterval = ehciPipePointer->pipeCommon.interval;
+
+        /* compute start-split and complete-split bandwidth */
+        if (ehciPipePointer->pipeCommon.direction == USB_OUT)
+        {
+            timeStartSplit = USB_HostBandwidthComputeTime(USB_SPEED_HIGH, USB_ENDPOINT_ISOCHRONOUS, USB_OUT,
+                                                          ehciPipePointer->pipeCommon.maxPacketSize);
+            timeCompleteSplit = 0;
+        }
+        else
+        {
+            timeStartSplit = USB_HostBandwidthComputeTime(USB_SPEED_HIGH, USB_ENDPOINT_ISOCHRONOUS, USB_IN, 1);
+            timeCompleteSplit = USB_HostBandwidthComputeTime(USB_SPEED_HIGH, USB_ENDPOINT_ISOCHRONOUS, USB_IN,
+                                                             ehciPipePointer->pipeCommon.maxPacketSize);
+        }
+        /* note: bandwidth must put in one frame */
+        for (uframeIntervalIndex = 0; uframeIntervalIndex <= 5; ++uframeIntervalIndex) /* uframe interval */
+        {
+            for (frameIntervalIndex = 0; frameIntervalIndex < frameInterval; ++frameIntervalIndex) /* frame interval */
+            {
+                allocateOk = 1;
+                for (frameIndex = frameIntervalIndex; frameIndex < USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE;
+                     frameIndex += frameInterval) /* check all the frames */
+                {
+                    /* compute start-split and complete-split number */
+                    SsCsNumber = (ehciPipePointer->pipeCommon.maxPacketSize + 187) /
+                                 188; /* ss number for iso out; cs number for iso in */
+                    if (ehciPipePointer->pipeCommon.direction == USB_OUT) /* ISO OUT */
+                    {
+                        if (uframeIntervalIndex + SsCsNumber > 8)
+                        {
+                            allocateOk = 0;
+                        }
+                    }
+                    else
+                    {
+                        if (uframeIntervalIndex + 2 + SsCsNumber >
+                            8) /* ISO IN: there are two micro-frame interval between start-split and complete-split */
+                        {
+                            allocateOk = 0;
+                        }
+                    }
+                    if (allocateOk)
+                    {
+                        /* allocate start-split and complete-split bandwidth */
+                        USB_HostBandwidthHsHostComputeCurrentHsAll(ehciInstance, frameIndex, frameTimes);
+                        if (ehciPipePointer->pipeCommon.direction == USB_OUT) /* ISO OUT */
+                        {
+                            index = uframeIntervalIndex;
+                            for (; index < (uframeIntervalIndex + SsCsNumber); ++index)
+                            {
+                                if (frameTimes[index] + timeStartSplit > s_SlotMaxBandwidth[index])
+                                {
+                                    allocateOk = 0;
+                                    break;
+                                }
+                            }
+                        }
+                        else /* ISO IN */
+                        {
+                            index = uframeIntervalIndex;
+                            if (frameTimes[index] + timeStartSplit > s_SlotMaxBandwidth[index])
+                            {
+                                allocateOk = 0;
+                            }
+                            if (allocateOk)
+                            {
+                                index =
+                                    uframeIntervalIndex +
+                                    2; /* there are two micro-frames interval between start-split and complete-split */
+                                for (; index < (uframeIntervalIndex + 2 + SsCsNumber); ++index)
+                                {
+                                    if (frameTimes[index] + timeCompleteSplit > s_SlotMaxBandwidth[index])
+                                    {
+                                        allocateOk = 0;
+                                        break;
+                                    }
+                                }
+                            }
+                        }
+                    }
+
+                    /* allocate data bandwidth */
+                    if (allocateOk)
+                    {
+                        USB_HostBandwidthHsHostComputeCurrentFsls(ehciInstance, hubNumber, frameIndex, frameTimes);
+                        index = uframeIntervalIndex + 1; /* timeData bandwidth start position */
+                        /* iso must occupy all the uframe bandwidth */
+                        {
+                            deviceInfo = timeData; /* note: deviceInfo variable means bandwidth here */
+                            while ((index < 8) && (deviceInfo > s_SlotMaxBandwidth[index]))
+                            {
+                                if (frameTimes[index] > 0)
+                                {
+                                    allocateOk = 0;
+                                    break;
+                                }
+                                else
+                                {
+                                    deviceInfo -= s_SlotMaxBandwidth[index];
+                                }
+                                ++index;
+                            }
+                        }
+                    }
+                    if (allocateOk)
+                    {
+                        /* data bandwidth can be put in the frame? */
+                        index = uframeIntervalIndex + 1; /* timeData bandwidth start position */
+                        frameTimes[index] += timeData;
+                        for (; index < 7; ++index)
+                        {
+                            if (frameTimes[index] > s_SlotMaxBandwidth[index])
+                            {
+                                frameTimes[index + 1] += (frameTimes[index] - s_SlotMaxBandwidth[index]);
+                                frameTimes[index] = s_SlotMaxBandwidth[index];
+                            }
+                            else
+                            {
+                                break;
+                            }
+                        }
+                        if (frameTimes[index] > s_SlotMaxBandwidth[index])
+                        {
+                            allocateOk = 0;
+                        }
+                    }
+
+                    if (allocateOk)
+                    {
+                        break;
+                    }
+                }
+                if (allocateOk)
+                {
+                    break;
+                }
+            }
+            if (allocateOk)
+            {
+                break;
+            }
+        }
+
+        if (allocateOk)
+        {
+            ehciPipePointer->startFrame = frameIntervalIndex;
+            ehciPipePointer->startUframe = uframeIntervalIndex;
+            ehciPipePointer->dataTime = timeData;
+            ehciPipePointer->startSplitTime = timeStartSplit;
+            ehciPipePointer->completeSplitTime = timeCompleteSplit;
+            if (ehciPipePointer->pipeCommon.direction == USB_OUT)
+            {
+                index = uframeIntervalIndex;
+                for (; index < (uframeIntervalIndex + SsCsNumber); ++index)
+                {
+                    ehciPipePointer->uframeSmask = (uint32_t)ehciPipePointer->uframeSmask | (uint32_t)(0x01 << index);
+                }
+            }
+            else
+            {
+                index = uframeIntervalIndex;
+                ehciPipePointer->uframeSmask = (uint32_t)ehciPipePointer->uframeSmask | (uint32_t)(0x01 << index);
+                index = uframeIntervalIndex + 2;
+                for (; index < (uframeIntervalIndex + 2 + SsCsNumber); ++index)
+                {
+                    ehciPipePointer->uframeCmask = (uint32_t)ehciPipePointer->uframeCmask | (uint32_t)(0x01 << index);
+                }
+            }
+
+            return kStatus_USB_Success;
+        }
+    }
+
+    return kStatus_USB_Error;
+}
+
+#endif
+
+static usb_status_t USB_HostBandwidthHsHostAllocateInterrupt(usb_host_ehci_instance_t *ehciInstance,
+                                                             usb_host_ehci_pipe_t *ehciPipePointer)
+{
+    usb_status_t status;
+    uint32_t deviceInfo;
+    uint32_t hubNumber;
+    uint16_t uframeIntervalIndex = 0;
+    uint16_t frameIntervalIndex = 0;
+    uint16_t frameIndex;
+    uint16_t timeCompleteSplit;
+    uint16_t timeStartSplit;
+    uint32_t timeData;
+    uint8_t SsCsNumber;
+    uint16_t frameInterval;
+    uint8_t frameTimes[8];
+    uint8_t allocateOk = 1;
+    uint8_t index;
+
+    USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetDeviceSpeed,
+                                           &deviceInfo);
+
+    timeData = USB_HostBandwidthComputeTime(
+        deviceInfo, USB_ENDPOINT_INTERRUPT, ehciPipePointer->pipeCommon.direction,
+        ehciPipePointer->pipeCommon.maxPacketSize * ehciPipePointer->pipeCommon.numberPerUframe);
+    /* pipe is high-speed */
+    if (deviceInfo == USB_SPEED_HIGH)
+    {
+        uframeIntervalIndex = 0;
+        status = USB_HostBandwidthHsHostAllocateHsCommon(ehciInstance, ehciPipePointer->uframeInterval, timeData,
+                                                         &uframeIntervalIndex);
+        if (status == kStatus_USB_Success)
+        {
+            ehciPipePointer->startFrame = (uframeIntervalIndex / 8);
+            ehciPipePointer->startUframe = (uframeIntervalIndex & 0x0007);
+            /* for HS interrupt start transaction position */
+            if (ehciPipePointer->uframeInterval >= 8)
+            {
+                ehciPipePointer->uframeSmask = (0x01 << ehciPipePointer->startUframe);
+            }
+            else
+            {
+                ehciPipePointer->uframeSmask = 0x00u;
+                for (index = ehciPipePointer->startUframe; index < 8; index += ehciPipePointer->uframeInterval)
+                {
+                    ehciPipePointer->uframeSmask |= (0x01U << index);
+                }
+            }
+            ehciPipePointer->dataTime = timeData;
+
+            return kStatus_USB_Success;
+        }
+    }
+    else /* pipe is full-speed or low-speed */
+    {
+        USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetHubThinkTime,
+                                               &deviceInfo);
+        timeData += (deviceInfo * 7 / (6 * 12));
+        USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetDeviceHSHubNumber,
+                                               &hubNumber);
+        frameInterval = ehciPipePointer->pipeCommon.interval;
+        SsCsNumber = 3; /* complete split number */
+
+        /* compute start-split and complete-split bandwidth */
+        if (ehciPipePointer->pipeCommon.direction == USB_OUT)
+        {
+            timeStartSplit = USB_HostBandwidthComputeTime(USB_SPEED_HIGH, USB_ENDPOINT_INTERRUPT, USB_OUT,
+                                                          ehciPipePointer->pipeCommon.maxPacketSize) +
+                             USB_HostBandwidthComputeTime(USB_SPEED_HIGH, USB_ENDPOINT_INTERRUPT, USB_OUT, 1);
+            timeCompleteSplit = USB_HostBandwidthComputeTime(USB_SPEED_HIGH, USB_ENDPOINT_INTERRUPT, USB_OUT, 0);
+        }
+        else
+        {
+            timeStartSplit = USB_HostBandwidthComputeTime(USB_SPEED_HIGH, USB_ENDPOINT_INTERRUPT, USB_IN, 1);
+            timeCompleteSplit = USB_HostBandwidthComputeTime(USB_SPEED_HIGH, USB_ENDPOINT_INTERRUPT, USB_IN,
+                                                             ehciPipePointer->pipeCommon.maxPacketSize) +
+                                USB_HostBandwidthComputeTime(USB_SPEED_HIGH, USB_ENDPOINT_INTERRUPT, USB_IN, 0);
+        }
+        /* note: bandwidth must put in one frame */
+        for (uframeIntervalIndex = 0; uframeIntervalIndex <= 4; ++uframeIntervalIndex) /* uframe interval */
+        {
+            for (frameIntervalIndex = 0; frameIntervalIndex < frameInterval; ++frameIntervalIndex) /* frame interval */
+            {
+                allocateOk = 1;
+                for (frameIndex = frameIntervalIndex; frameIndex < USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE;
+                     frameIndex += frameInterval) /* check all the frames */
+                {
+                    /* allocate data bandwidth */
+                    USB_HostBandwidthHsHostComputeCurrentFsls(ehciInstance, hubNumber, frameIndex, frameTimes);
+                    index = uframeIntervalIndex + 1;
+                    for (; index <= (uframeIntervalIndex + 3); ++index) /* data bandwidth number is 3.
+                                                                             uframeIntervalIndex don't exceed 4, so
+                                                                             index cannot exceed 7 */
+                    {
+                        if (frameTimes[index] + timeData > s_SlotMaxBandwidth[index])
+                        {
+                            allocateOk = 0;
+                            break;
+                        }
+                    }
+
+                    if (allocateOk)
+                    {
+                        USB_HostBandwidthHsHostComputeCurrentHsAll(ehciInstance, frameIndex, frameTimes);
+                        /* allocate start_split bandwidth */
+                        if (frameTimes[uframeIntervalIndex] + timeStartSplit > s_SlotMaxBandwidth[uframeIntervalIndex])
+                        {
+                            allocateOk = 0;
+                        }
+                        if (allocateOk)
+                        {
+                            /* allocate complete_split bandwidth */
+                            index = uframeIntervalIndex + 2;
+                            /* complete-split number is normal 3. When uframeIntervalIndex is 4, complete-split number
+                             * is 2. */
+                            for (; (index <= (uframeIntervalIndex + 1 + SsCsNumber)) && (index < 8); ++index)
+                            {
+                                if (frameTimes[index] + timeCompleteSplit > s_SlotMaxBandwidth[index])
+                                {
+                                    allocateOk = 0;
+                                    break;
+                                }
+                            }
+                        }
+                    }
+
+                    if (!allocateOk)
+                    {
+                        break; /* allocate fail */
+                    }
+                }
+                if (allocateOk)
+                {
+                    break;
+                }
+            }
+            if (allocateOk)
+            {
+                break;
+            }
+        }
+
+        if (allocateOk)
+        {
+            ehciPipePointer->startFrame = frameIntervalIndex;
+            ehciPipePointer->startUframe = uframeIntervalIndex;
+            ehciPipePointer->uframeSmask = (0x01 << ehciPipePointer->startUframe);
+            ehciPipePointer->uframeCmask = 0;
+            index = uframeIntervalIndex + 2;
+            for (; (index <= (uframeIntervalIndex + 1 + SsCsNumber)) && (index < 8); ++index)
+            {
+                ehciPipePointer->uframeCmask = (uint32_t)ehciPipePointer->uframeCmask | (uint32_t)(0x01 << index);
+            }
+            ehciPipePointer->dataTime = timeData;
+            ehciPipePointer->startSplitTime = timeStartSplit;
+            ehciPipePointer->completeSplitTime = timeCompleteSplit;
+
+            return kStatus_USB_Success;
+        }
+    }
+
+    return kStatus_USB_BandwidthFail;
+}
+
+static usb_status_t USB_HostBandwidthFslsHostAllocate(usb_host_ehci_instance_t *ehciInstance,
+                                                      usb_host_ehci_pipe_t *ehciPipePointer)
+{
+    uint32_t FslsTime = 0;
+    uint32_t speed = 0;
+    uint16_t uframeIntervalIndex;
+    uint16_t frameIndex;
+    uint16_t frameInterval;
+    uint16_t frameTime;
+
+    USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetHubThinkTime,
+                                           &FslsTime);
+    FslsTime += (FslsTime * 7 / (6 * 12));
+    USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetDeviceSpeed, &speed);
+    FslsTime = FslsTime + USB_HostBandwidthComputeTime(speed, ehciPipePointer->pipeCommon.pipeType,
+                                                       ehciPipePointer->pipeCommon.direction,
+                                                       ehciPipePointer->pipeCommon.maxPacketSize);
+
+    frameInterval = ehciPipePointer->pipeCommon.interval;
+    for (uframeIntervalIndex = 0; uframeIntervalIndex < ehciPipePointer->uframeInterval;
+         ++uframeIntervalIndex) /* uframeIntervalIndex can exceed 8 */
+    {
+        for (frameIndex = (uframeIntervalIndex >> 3); frameIndex < USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE;
+             frameIndex += frameInterval)
+        {
+            USB_HostBandwidthFslsHostComputeCurrent(ehciInstance, frameIndex, &frameTime);
+            if (frameTime + FslsTime > USB_HOST_EHCI_BANDWIDTH_FRAME_TOTOAL_TIME)
+            {
+                break;
+            }
+        }
+        if (frameIndex >= USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE)
+        {
+            break;
+        }
+    }
+    if (uframeIntervalIndex < ehciPipePointer->uframeInterval)
+    {
+        ehciPipePointer->startFrame = (uframeIntervalIndex >> 3);
+        ehciPipePointer->startUframe = (uframeIntervalIndex & 0x0007);
+        ehciPipePointer->uframeSmask = 0; /* useless */
+        ehciPipePointer->uframeCmask = 0;
+        ehciPipePointer->dataTime = FslsTime;
+
+        return kStatus_USB_Success;
+    }
+
+    return kStatus_USB_BandwidthFail;
+}
+
+static uint8_t USB_HostEhciGet2PowerValue(uint8_t value)
+{
+    if ((value == 0) || (value == 1))
+    {
+        return value;
+    }
+    if (value & 0xf0)
+    {
+        if (value & 0x80)
+        {
+            return 128;
+        }
+        else if (value & 0x40)
+        {
+            return 64;
+        }
+        else if (value & 0x20)
+        {
+            return 32;
+        }
+        else
+        {
+            return 16;
+        }
+    }
+    else
+    {
+        if (value & 0x08)
+        {
+            return 8;
+        }
+        else if (value & 0x04)
+        {
+            return 4;
+        }
+        else if (value & 0x02)
+        {
+            return 2;
+        }
+        else
+        {
+            return 1;
+        }
+    }
+}
+
+static void USB_HostEhciZeroMem(uint32_t *buffer, uint32_t length)
+{
+    /* note: the zero unit is uint32_t */
+    while (length--)
+    {
+        *buffer = 0;
+        buffer++;
+    }
+}
+
+static void USB_HostEhciDelay(USBHS_Type *ehciIpBase, uint32_t ms)
+{
+    /* note: the max delay time cannot exceed half of max value (0x4000) */
+    int32_t sofStart;
+    int32_t SofEnd;
+    uint32_t distance;
+
+    sofStart = (int32_t)(ehciIpBase->FRINDEX & EHCI_MAX_UFRAME_VALUE);
+
+    do
+    {
+        SofEnd = (int32_t)(ehciIpBase->FRINDEX & EHCI_MAX_UFRAME_VALUE);
+        distance = (uint32_t)(SofEnd - sofStart + EHCI_MAX_UFRAME_VALUE + 1);
+    } while ((distance & EHCI_MAX_UFRAME_VALUE) < (ms * 8)); /* compute the distance between sofStart and SofEnd */
+}
+
+static void USB_HostEhciStartAsync(usb_host_ehci_instance_t *ehciInstance)
+{
+    uint32_t stateSync;
+
+    if (!(ehciInstance->ehciIpBase->USBSTS & USBHS_USBSTS_AS_MASK))
+    {
+        /* the status must be same when change USBCMD->ASE */
+        do
+        {
+            stateSync = ((ehciInstance->ehciIpBase->USBSTS & USBHS_USBSTS_AS_MASK) |
+                         (ehciInstance->ehciIpBase->USBCMD & USBHS_USBCMD_ASE_MASK));
+        } while ((stateSync == USBHS_USBSTS_AS_MASK) || (stateSync == USBHS_USBCMD_ASE_MASK));
+
+        ehciInstance->ehciIpBase->ASYNCLISTADDR = (uint32_t)(ehciInstance->shedFirstQh);
+        ehciInstance->ehciIpBase->USBCMD |= USBHS_USBCMD_ASE_MASK;
+        while (!(ehciInstance->ehciIpBase->USBSTS & USBHS_USBSTS_AS_MASK))
+        {
+        }
+    }
+}
+
+static void USB_HostEhciStopAsync(usb_host_ehci_instance_t *ehciInstance)
+{
+    uint32_t stateSync;
+
+    /* the status must be same when change USBCMD->ASE */
+    do
+    {
+        stateSync = ((ehciInstance->ehciIpBase->USBSTS & USBHS_USBSTS_AS_MASK) |
+                     (ehciInstance->ehciIpBase->USBCMD & USBHS_USBCMD_ASE_MASK));
+    } while ((stateSync == USBHS_USBSTS_AS_MASK) || (stateSync == USBHS_USBCMD_ASE_MASK));
+
+    ehciInstance->ehciIpBase->USBCMD &= (uint32_t)(~(uint32_t)USBHS_USBCMD_ASE_MASK); /* disable async schedule */
+    while (ehciInstance->ehciIpBase->USBSTS & USBHS_USBSTS_AS_MASK)
+    {
+    }
+}
+
+static void USB_HostEhciStartPeriodic(usb_host_ehci_instance_t *ehciInstance)
+{
+    uint32_t stateSync;
+
+    if (!(ehciInstance->ehciIpBase->USBSTS & USBHS_USBSTS_PS_MASK))
+    {
+        /* the status must be same when change USBCMD->PSE */
+        do
+        {
+            stateSync = ((ehciInstance->ehciIpBase->USBSTS & USBHS_USBSTS_PS_MASK) |
+                         (ehciInstance->ehciIpBase->USBCMD & USBHS_USBCMD_PSE_MASK));
+        } while ((stateSync == USBHS_USBSTS_PS_MASK) || (stateSync == USBHS_USBCMD_PSE_MASK));
+        ehciInstance->ehciIpBase->PERIODICLISTBASE = (uint32_t)(ehciInstance->ehciFrameList);
+        if (!(ehciInstance->ehciIpBase->USBCMD & USBHS_USBCMD_PSE_MASK))
+        {
+            ehciInstance->ehciIpBase->USBCMD |= USBHS_USBCMD_PSE_MASK; /* start periodic schedule */
+        }
+        while (!(ehciInstance->ehciIpBase->USBSTS & USBHS_USBSTS_PS_MASK))
+        {
+        }
+    }
+    return;
+}
+
+static void USB_HostEhciStopPeriodic(usb_host_ehci_instance_t *ehciInstance)
+{
+    uint32_t stateSync;
+
+    /* the status must be same when change USBCMD->PSE */
+    do
+    {
+        stateSync = ((ehciInstance->ehciIpBase->USBSTS & USBHS_USBSTS_PS_MASK) |
+                     (ehciInstance->ehciIpBase->USBCMD & USBHS_USBCMD_PSE_MASK));
+    } while ((stateSync == USBHS_USBSTS_PS_MASK) || (stateSync == USBHS_USBCMD_PSE_MASK));
+
+    ehciInstance->ehciIpBase->USBCMD &= (~USBHS_USBCMD_PSE_MASK); /* stop periodic schedule */
+    while (ehciInstance->ehciIpBase->USBSTS & USBHS_USBSTS_PS_MASK)
+    {
+    }
+}
+
+static usb_status_t USB_HostEhciQhQtdListInit(usb_host_ehci_instance_t *ehciInstance,
+                                              usb_host_ehci_pipe_t *ehciPipePointer,
+                                              usb_host_transfer_t *transfer)
+{
+    volatile usb_host_ehci_qh_t *vltQhPointer;
+    usb_host_ehci_qtd_t *qtdPointer = NULL;
+    usb_host_ehci_qtd_t *BaseQtdPointer = NULL;
+    volatile uint32_t *entryPointer;
+    uint32_t qtdNumber;
+    uint32_t dataLength;
+    uint32_t dataAddress;
+    uint32_t endAddress;
+    uint8_t index;
+
+    /* compute the qtd number */
+    if (ehciPipePointer->pipeCommon.pipeType == USB_ENDPOINT_CONTROL)
+    {
+        /* assume setup data don't exceed one qtd data size, one qtd can transfer least 16k data */
+        if (transfer->transferLength == 0)
+        {
+            qtdNumber = 2;
+        }
+        else
+        {
+            qtdNumber = 3;
+        }
+    }
+    else
+    {
+        qtdNumber =
+            (((transfer->transferLength) & 0xFFFFC000U) >> 14) + (((transfer->transferLength) & 0x00003FFF) ? 1 : 0);
+    }
+
+    vltQhPointer = (volatile usb_host_ehci_qh_t *)ehciPipePointer->ehciQh;
+    /* get qtd list */
+    USB_HostEhciLock();
+    if (qtdNumber <= ehciInstance->ehciQtdNumber)
+    {
+        ehciInstance->ehciQtdNumber -= qtdNumber;
+        BaseQtdPointer = ehciInstance->ehciQtdHead;
+        qtdPointer = NULL;
+        do
+        {
+            if (qtdPointer != NULL)
+            {
+                qtdPointer->nextQtdPointer = (uint32_t)ehciInstance->ehciQtdHead;
+            }
+            qtdPointer = ehciInstance->ehciQtdHead;
+            ehciInstance->ehciQtdHead = (usb_host_ehci_qtd_t *)qtdPointer->nextQtdPointer;
+            qtdPointer->nextQtdPointer = 0;
+        } while (--qtdNumber);
+        if (ehciInstance->ehciQtdNumber == 0)
+        {
+            ehciInstance->ehciQtdTail = NULL;
+        }
+    }
+    else
+    {
+        USB_HostEhciUnlock();
+        return kStatus_USB_Error;
+    }
+    USB_HostEhciUnlock();
+
+    /* int qTD list */
+    if (ehciPipePointer->pipeCommon.pipeType == USB_ENDPOINT_CONTROL)
+    {
+        /* setup transaction qtd */
+        qtdPointer = BaseQtdPointer;
+        qtdPointer->alternateNextQtdPointer = EHCI_HOST_T_INVALID_VALUE;
+        /* dt: need set; ioc: 0; C_Page: 0; PID Code: SETUP; Status: Active */
+        qtdPointer->transferResults[0] = qtdPointer->transferResults[1] = 0;
+        qtdPointer->transferResults[0] =
+            ((0x00000000 << EHCI_HOST_QTD_DT_SHIFT) | (8 << EHCI_HOST_QTD_TOTAL_BYTES_SHIFT) |
+             (EHCI_HOST_PID_SETUP << EHCI_HOST_QTD_PID_CODE_SHIFT) | (EHCI_HOST_QTD_STATUS_ACTIVE_MASK));
+        dataAddress = ((uint32_t)transfer->setupPacket);
+        qtdPointer->transferResults[1] = dataAddress; /* current offset is set too */
+        /* set buffer pointer no matter data length */
+        for (index = 0; index < 4; ++index)
+        {
+            qtdPointer->bufferPointers[index] = ((dataAddress + (index + 1) * 4 * 1024) & 0xFFFFF000U);
+        }
+
+        /* data transaction qtd */
+        dataLength = transfer->transferLength;
+        if (dataLength != 0)
+        {
+            qtdPointer = (usb_host_ehci_qtd_t *)(qtdPointer->nextQtdPointer);
+
+            qtdPointer->alternateNextQtdPointer = EHCI_HOST_T_INVALID_VALUE;
+            /* dt: need set; ioc: 0; C_Page: 0; PID Code: IN/OUT; Status: Active */
+            qtdPointer->transferResults[0] = qtdPointer->transferResults[1] = 0;
+            if (transfer->direction == USB_OUT)
+            {
+                qtdPointer->transferResults[0] =
+                    ((0x00000001U << EHCI_HOST_QTD_DT_SHIFT) | (dataLength << EHCI_HOST_QTD_TOTAL_BYTES_SHIFT) |
+                     (EHCI_HOST_PID_OUT << EHCI_HOST_QTD_PID_CODE_SHIFT) | (EHCI_HOST_QTD_STATUS_ACTIVE_MASK));
+            }
+            else
+            {
+                qtdPointer->transferResults[0] =
+                    ((0x00000001U << EHCI_HOST_QTD_DT_SHIFT) | (dataLength << EHCI_HOST_QTD_TOTAL_BYTES_SHIFT) |
+                     (EHCI_HOST_PID_IN << EHCI_HOST_QTD_PID_CODE_SHIFT) | (EHCI_HOST_QTD_STATUS_ACTIVE_MASK));
+            }
+
+            dataAddress = (uint32_t)transfer->transferBuffer;
+            qtdPointer->transferResults[1] = dataAddress; /* current offset is set too */
+            /* set buffer pointer no matter data length */
+            for (index = 0; index < 4; ++index)
+            {
+                qtdPointer->bufferPointers[index] = ((dataAddress + (index + 1) * 4 * 1024) & 0xFFFFF000U);
+            }
+        }
+
+        /* status transaction qtd */
+        qtdPointer = (usb_host_ehci_qtd_t *)(qtdPointer->nextQtdPointer);
+        qtdPointer->alternateNextQtdPointer = EHCI_HOST_T_INVALID_VALUE;
+        /* dt: dont care; ioc: 1; C_Page: 0; PID Code: IN/OUT; Status: Active */
+        qtdPointer->transferResults[0] = qtdPointer->transferResults[1] = 0;
+        if ((dataLength == 0) || (transfer->direction == USB_OUT))
+        {
+            qtdPointer->transferResults[0] =
+                ((0x00000001U << EHCI_HOST_QTD_DT_SHIFT) | (EHCI_HOST_PID_IN << EHCI_HOST_QTD_PID_CODE_SHIFT) |
+                 (EHCI_HOST_QTD_IOC_MASK) | (EHCI_HOST_QTD_STATUS_ACTIVE_MASK));
+        }
+        else
+        {
+            qtdPointer->transferResults[0] =
+                ((0x00000001U << EHCI_HOST_QTD_DT_SHIFT) | (EHCI_HOST_PID_OUT << EHCI_HOST_QTD_PID_CODE_SHIFT) |
+                 (EHCI_HOST_QTD_IOC_MASK) | (EHCI_HOST_QTD_STATUS_ACTIVE_MASK));
+        }
+        qtdPointer->nextQtdPointer |= EHCI_HOST_T_INVALID_VALUE;
+    }
+    else
+    {
+        dataLength = transfer->transferLength;
+        dataAddress = (uint32_t)transfer->transferBuffer;
+        qtdPointer = BaseQtdPointer;
+        while (1)
+        {
+            endAddress = dataAddress + (16 * 1024);
+            if (endAddress > (uint32_t)(transfer->transferBuffer + transfer->transferLength))
+            {
+                endAddress = (uint32_t)(transfer->transferBuffer + transfer->transferLength);
+            }
+
+            qtdPointer->alternateNextQtdPointer = EHCI_HOST_T_INVALID_VALUE;
+            /* dt: set; ioc: 0; C_Page: 0; PID Code: IN/OUT; Status: Active */
+            qtdPointer->transferResults[0] = qtdPointer->transferResults[1] = 0;
+            if (transfer->direction == USB_OUT)
+            {
+                qtdPointer->transferResults[0] =
+                    (((endAddress - dataAddress) << EHCI_HOST_QTD_TOTAL_BYTES_SHIFT) |
+                     ((uint32_t)ehciPipePointer->pipeCommon.nextdata01 << EHCI_HOST_QTD_DT_SHIFT) |
+                     (EHCI_HOST_QTD_CERR_MAX_VALUE << EHCI_HOST_QTD_CERR_SHIFT) |
+                     (EHCI_HOST_PID_OUT << EHCI_HOST_QTD_PID_CODE_SHIFT) | (EHCI_HOST_QTD_STATUS_ACTIVE_MASK));
+            }
+            else
+            {
+                qtdPointer->transferResults[0] =
+                    (((endAddress - dataAddress) << EHCI_HOST_QTD_TOTAL_BYTES_SHIFT) |
+                     ((uint32_t)ehciPipePointer->pipeCommon.nextdata01 << EHCI_HOST_QTD_DT_SHIFT) |
+                     (EHCI_HOST_QTD_CERR_MAX_VALUE << EHCI_HOST_QTD_CERR_SHIFT) |
+                     (EHCI_HOST_PID_IN << EHCI_HOST_QTD_PID_CODE_SHIFT) | (EHCI_HOST_QTD_STATUS_ACTIVE_MASK));
+            }
+            qtdPointer->transferResults[1] = dataAddress; /* current offset is set too */
+            /* set buffer pointer no matter data length */
+            for (index = 0; index < 4; ++index)
+            {
+                qtdPointer->bufferPointers[index] = ((dataAddress + (index + 1) * 4 * 1024) & 0xFFFFF000U);
+            }
+            dataAddress = endAddress; /* for next qtd */
+
+            if (qtdPointer->nextQtdPointer == 0)
+            {
+                break;
+            }
+            qtdPointer = (usb_host_ehci_qtd_t *)(qtdPointer->nextQtdPointer);
+        }
+
+        qtdPointer->nextQtdPointer |= EHCI_HOST_T_INVALID_VALUE;
+        qtdPointer->transferResults[0] |= EHCI_HOST_QTD_IOC_MASK; /* last one set IOC */
+    }
+
+    /* save qtd to transfer */
+    transfer->union1.unitHead = (uint32_t)BaseQtdPointer;
+    transfer->union2.unitTail = (uint32_t)qtdPointer;
+    /* link transfer to qh */
+    transfer->next = NULL;
+    if (vltQhPointer->ehciTransferHead == NULL)
+    {
+        transfer->next = NULL;
+        vltQhPointer->ehciTransferHead = vltQhPointer->ehciTransferTail = transfer;
+    }
+    else
+    {
+        transfer->next = NULL;
+        vltQhPointer->ehciTransferTail->next = transfer;
+        vltQhPointer->ehciTransferTail = transfer;
+    }
+
+    USB_HostEhciLock();
+    /* link qtd to qh (link to end) */
+    entryPointer = &(vltQhPointer->nextQtdPointer);
+    dataAddress = *entryPointer; /* dataAddress variable means entry value here */
+    while ((dataAddress) && (!(dataAddress & EHCI_HOST_T_INVALID_VALUE)))
+    {
+        entryPointer = (volatile uint32_t *)dataAddress;
+        dataAddress = *entryPointer;
+    }
+    *entryPointer = (uint32_t)BaseQtdPointer;
+    USB_HostEhciUnlock();
+    USB_HostEhciStartAsync(ehciInstance);
+
+    return kStatus_USB_Success;
+}
+
+static uint32_t USB_HostEhciQtdListRelease(usb_host_ehci_instance_t *ehciInstance,
+                                           usb_host_ehci_qtd_t *ehciQtdStart,
+                                           usb_host_ehci_qtd_t *ehciQtdEnd)
+{
+    uint32_t length = 0;
+    usb_host_ehci_qtd_t *qtdPointer;
+
+    ehciQtdEnd->nextQtdPointer = 0;
+
+    /* compute remaining length */
+    qtdPointer = ehciQtdStart;
+    while (qtdPointer != ehciQtdEnd)
+    {
+        length +=
+            ((qtdPointer->transferResults[0] & EHCI_HOST_QTD_TOTAL_BYTES_MASK) >> EHCI_HOST_QTD_TOTAL_BYTES_SHIFT);
+        qtdPointer = (usb_host_ehci_qtd_t *)qtdPointer->nextQtdPointer;
+    }
+    qtdPointer = ehciQtdEnd;
+    length += ((qtdPointer->transferResults[0] & EHCI_HOST_QTD_TOTAL_BYTES_MASK) >> EHCI_HOST_QTD_TOTAL_BYTES_SHIFT);
+
+    /* put releasing qtd to idle qtd list */
+    USB_HostEhciLock();
+    if (ehciInstance->ehciQtdNumber == 0)
+    {
+        ehciInstance->ehciQtdHead = ehciQtdStart;
+        ehciInstance->ehciQtdTail = ehciQtdEnd;
+    }
+    else
+    {
+        ehciInstance->ehciQtdTail->nextQtdPointer = (uint32_t)ehciQtdStart;
+        ehciInstance->ehciQtdTail = ehciQtdEnd;
+    }
+
+    while (ehciQtdStart != ehciQtdEnd)
+    {
+        ehciInstance->ehciQtdNumber++;
+        ehciQtdStart = (usb_host_ehci_qtd_t *)ehciQtdStart->nextQtdPointer;
+    }
+    ehciInstance->ehciQtdNumber++;
+    USB_HostEhciUnlock();
+
+    return length;
+}
+
+static usb_status_t USB_HostEhciQhQtdListDeinit(usb_host_ehci_instance_t *ehciInstance,
+                                                usb_host_ehci_pipe_t *ehciPipePointer)
+{
+    volatile usb_host_ehci_qh_t *vltQhPointer;
+    usb_host_transfer_t *transfer;
+    usb_host_transfer_t *nextTransfer;
+    uint8_t needStop = 0;
+
+    vltQhPointer = (volatile usb_host_ehci_qh_t *)ehciPipePointer->ehciQh;
+
+    USB_HostEhciLock(); /* this API is called from APP, the host task may occupy to access the same resource */
+    /* remove qtd from qh */
+    if ((!((uint32_t)vltQhPointer->nextQtdPointer & EHCI_HOST_T_INVALID_VALUE)) ||
+        (!((uint32_t)vltQhPointer->currentQtdPointer & EHCI_HOST_T_INVALID_VALUE)))
+    {
+        /* need stop async schedule */
+        if ((!(vltQhPointer->horizontalLinkPointer & EHCI_HOST_T_INVALID_VALUE)) &&
+            (ehciPipePointer->pipeCommon.pipeType != USB_ENDPOINT_INTERRUPT))
+        {
+            needStop = 1;
+        }
+        if (needStop)
+        {
+            USB_HostEhciStopAsync(ehciInstance);
+        }
+        vltQhPointer->currentQtdPointer = EHCI_HOST_T_INVALID_VALUE;             /* invalid current qtd */
+        vltQhPointer->nextQtdPointer = EHCI_HOST_T_INVALID_VALUE;                /* invalid next qtd */
+        vltQhPointer->transferOverlayResults[0] &= (~EHCI_HOST_QTD_STATUS_MASK); /* clear error status */
+        if (needStop)
+        {
+            USB_HostEhciStartAsync(ehciInstance);
+        }
+    }
+
+    /* remove transfer from the QH transfer list */
+    transfer = vltQhPointer->ehciTransferHead;
+    vltQhPointer->ehciTransferHead = vltQhPointer->ehciTransferTail = NULL;
+    USB_HostEhciUnlock();
+
+    /* release qtd  and transfer callback*/
+    while (transfer != NULL)
+    {
+        nextTransfer = transfer->next; /* the transfer is released when call back */
+        transfer->transferSofar =
+            USB_HostEhciQtdListRelease(ehciInstance, (usb_host_ehci_qtd_t *)(transfer->union1.unitHead),
+                                       (usb_host_ehci_qtd_t *)(transfer->union2.unitTail));
+        transfer->transferSofar = (transfer->transferLength < transfer->transferSofar) ?
+                                      0 :
+                                      (transfer->transferLength - transfer->transferSofar);
+        transfer->callbackFn(transfer->callbackParam, transfer, kStatus_USB_TransferCancel);
+        transfer = nextTransfer;
+    }
+
+    return kStatus_USB_Success;
+}
+
+static usb_status_t USB_HostEhciTransferQtdListDeinit(usb_host_ehci_instance_t *ehciInstance,
+                                                      usb_host_ehci_pipe_t *ehciPipePointer,
+                                                      usb_host_transfer_t *transfer)
+{
+    volatile usb_host_ehci_qh_t *vltQhPointer;
+    usb_host_transfer_t *preSearchTransfer;
+    uint32_t qhNextQtdValue;
+    uint32_t qtdPointerEntry;
+    uint32_t *searchQtdEntryPointer;
+
+    vltQhPointer = (volatile usb_host_ehci_qh_t *)ehciPipePointer->ehciQh;
+
+    USB_HostEhciLock(); /* this API is called from APP, the host task may occupy to access the same resource */
+    /* remove qtd from qh */
+    qhNextQtdValue = (uint32_t)vltQhPointer->currentQtdPointer;
+    qtdPointerEntry = *((uint32_t *)qhNextQtdValue + 2); /* note: qtdPointerEntry means qtd status */
+    if ((qhNextQtdValue & EHCI_HOST_T_INVALID_VALUE) || (!(qtdPointerEntry & EHCI_HOST_QTD_STATUS_ACTIVE_MASK)))
+    {
+        qhNextQtdValue = (uint32_t)vltQhPointer->nextQtdPointer;
+    }
+    if (!(qhNextQtdValue & EHCI_HOST_T_INVALID_VALUE)) /* there is pending qtd in the qh */
+    {
+        /* this qh don't schedule temporarily */
+        if (ehciPipePointer->pipeCommon.pipeType != USB_ENDPOINT_INTERRUPT)
+        {
+            USB_HostEhciStopAsync(ehciInstance);
+        }
+        vltQhPointer->currentQtdPointer |= EHCI_HOST_T_INVALID_VALUE; /* invalid current qtd */
+        vltQhPointer->nextQtdPointer |= EHCI_HOST_T_INVALID_VALUE;    /* invalid next qtd */
+        if (ehciPipePointer->pipeCommon.pipeType != USB_ENDPOINT_INTERRUPT)
+        {
+            USB_HostEhciStartAsync(ehciInstance);
+        }
+
+        /* remove qtd from qh one by one */
+        qtdPointerEntry = transfer->union1.unitHead;
+        while (1)
+        {
+            /* search qh's qtd list for qtdPointerEntry */
+            searchQtdEntryPointer = &qhNextQtdValue;
+            while (!((*searchQtdEntryPointer) & EHCI_HOST_T_INVALID_VALUE))
+            {
+                if ((*searchQtdEntryPointer) == qtdPointerEntry)
+                {
+                    *searchQtdEntryPointer = *((uint32_t *)qtdPointerEntry); /* remove the qtd from qh */
+                    break;
+                }
+                else
+                {
+                    searchQtdEntryPointer = (uint32_t *)(*searchQtdEntryPointer);
+                }
+            }
+            if (qtdPointerEntry == transfer->union2.unitTail)
+            {
+                break;
+            }
+            qtdPointerEntry = *((uint32_t *)qtdPointerEntry);
+        }
+    }
+
+    /* remove transfer from the QH transfer list */
+    preSearchTransfer = vltQhPointer->ehciTransferHead;
+    if (preSearchTransfer == transfer)
+    {
+        vltQhPointer->ehciTransferHead = preSearchTransfer->next;
+    }
+    else
+    {
+        while (preSearchTransfer != NULL)
+        {
+            if (preSearchTransfer->next == transfer)
+            {
+                preSearchTransfer->next = transfer->next;
+                break;
+            }
+            else
+            {
+                preSearchTransfer = preSearchTransfer->next;
+            }
+        }
+    }
+    USB_HostEhciUnlock();
+
+    /* release qtd and callback */
+    transfer->transferSofar =
+        USB_HostEhciQtdListRelease(ehciInstance, (usb_host_ehci_qtd_t *)(transfer->union1.unitHead),
+                                   (usb_host_ehci_qtd_t *)(transfer->union2.unitTail));
+    transfer->transferSofar =
+        (transfer->transferLength < transfer->transferSofar) ? 0 : (transfer->transferLength - transfer->transferSofar);
+    transfer->callbackFn(transfer->callbackParam, transfer, kStatus_USB_TransferCancel);
+
+    /* start this qh schedule */
+    vltQhPointer->transferOverlayResults[0] &= (~EHCI_HOST_QTD_STATUS_MASK); /* clear error status */
+    if ((qhNextQtdValue != 0) && (!(qhNextQtdValue & EHCI_HOST_T_INVALID_VALUE)))
+    {
+        vltQhPointer->nextQtdPointer = qhNextQtdValue;
+    }
+
+    return kStatus_USB_Success;
+}
+
+static usb_status_t USB_HostEhciQhInit(usb_host_ehci_instance_t *ehciInstance, usb_host_ehci_pipe_t *ehciPipePointer)
+{
+    usb_host_ehci_qh_t *qhPointer = NULL;
+    uint32_t address, speed, portNumber, hubNumber;
+    uint32_t controlBits1 = 0;
+    uint32_t controlBits2 = 0;
+    /* get qh */
+    USB_HostEhciLock();
+    if (ehciInstance->ehciQhList != NULL)
+    {
+        qhPointer = (usb_host_ehci_qh_t *)ehciInstance->ehciQhList;
+        ehciInstance->ehciQhList =
+            (usb_host_ehci_qh_t *)(ehciInstance->ehciQhList->horizontalLinkPointer & EHCI_HOST_POINTER_ADDRESS_MASK);
+    }
+    USB_HostEhciUnlock();
+    if (qhPointer == NULL)
+    {
+#ifdef HOST_EHCO
+        usb_echo("get qh error\r\n");
+#endif
+        return kStatus_USB_Error;
+    }
+    ehciPipePointer->ehciQh = (void *)qhPointer;
+
+    /* initialize qh */
+    USB_HostEhciZeroMem((uint32_t *)qhPointer, sizeof(usb_host_ehci_qh_t) / 4);
+    qhPointer->horizontalLinkPointer = EHCI_HOST_T_INVALID_VALUE;
+    qhPointer->currentQtdPointer = EHCI_HOST_T_INVALID_VALUE;
+    qhPointer->nextQtdPointer = EHCI_HOST_T_INVALID_VALUE;
+    qhPointer->alternateNextQtdPointer = EHCI_HOST_T_INVALID_VALUE;
+    qhPointer->ehciPipePointer = ehciPipePointer;
+    qhPointer->timeOutLabel = 0;
+    qhPointer->timeOutValue = USB_HOST_EHCI_CONTROL_BULK_TIME_OUT_VALUE;
+    USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetDeviceSpeed, &speed);
+    /* initialize staticEndpointStates[0] */
+    if (ehciPipePointer->pipeCommon.pipeType == USB_ENDPOINT_INTERRUPT)
+    {
+        /* Software should set the RL field to zero if the queue head is an interrupt endpoint. */
+        controlBits1 |= ((0U << EHCI_HOST_QH_RL_SHIFT) & EHCI_HOST_QH_RL_MASK);
+    }
+    else
+    {
+        if (ehciPipePointer->pipeCommon.nakCount >= 16)
+        {
+            controlBits1 |= ((15U << EHCI_HOST_QH_RL_SHIFT) & EHCI_HOST_QH_RL_MASK);
+        }
+        else
+        {
+            controlBits1 |=
+                (((uint32_t)ehciPipePointer->pipeCommon.nakCount << EHCI_HOST_QH_RL_SHIFT) & EHCI_HOST_QH_RL_MASK);
+        }
+    }
+    if (ehciPipePointer->pipeCommon.pipeType == USB_ENDPOINT_CONTROL)
+    {
+        if (speed != USB_SPEED_HIGH)
+        {
+            controlBits1 |= (1 << EHCI_HOST_QH_C_SHIFT);
+        }
+        controlBits1 |= (1 << EHCI_HOST_QH_DTC_SHIFT);
+    }
+    controlBits1 |= ((uint32_t)ehciPipePointer->pipeCommon.maxPacketSize << EHCI_HOST_QH_MAX_PACKET_LENGTH_SHIFT);
+    controlBits1 |= (speed << EHCI_HOST_QH_EPS_SHIFT);
+    controlBits1 |= ((uint32_t)ehciPipePointer->pipeCommon.endpointAddress << EHCI_HOST_QH_ENDPT_SHIFT);
+    USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetDeviceAddress,
+                                           &address);
+    controlBits1 |= (address << EHCI_HOST_QH_DEVICE_ADDRESS_SHIFT);
+    qhPointer->staticEndpointStates[0] = controlBits1;
+    if (speed == USB_SPEED_HIGH)
+    {
+        controlBits2 |= ((uint32_t)ehciPipePointer->pipeCommon.numberPerUframe << EHCI_HOST_QH_MULT_SHIFT);
+    }
+    else
+    {
+        controlBits2 |= (0x00000001U << EHCI_HOST_QH_MULT_SHIFT);
+    }
+    /*initialize staticEndpointStates[1] */
+    if (speed != USB_SPEED_HIGH)
+    {
+        USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetDeviceHSHubNumber,
+                                               &hubNumber);
+        USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetDeviceHSHubPort,
+                                               &portNumber);
+    }
+    else
+    {
+        USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetDeviceHubNumber,
+                                               &hubNumber);
+        USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetDevicePortNumber,
+                                               &portNumber);
+    }
+    controlBits2 |= (portNumber << EHCI_HOST_QH_PORT_NUMBER_SHIFT);
+    controlBits2 |= (hubNumber << EHCI_HOST_QH_HUB_ADDR_SHIFT);
+    controlBits2 |= ((uint32_t)ehciPipePointer->uframeCmask << EHCI_HOST_QH_UFRAME_CMASK_SHIFT);
+    controlBits2 |= ((uint32_t)ehciPipePointer->uframeSmask << EHCI_HOST_QH_UFRAME_SMASK_SHIFT);
+    qhPointer->staticEndpointStates[1] = controlBits2;
+
+    return kStatus_USB_Success;
+}
+
+static usb_status_t USB_HostEhciQhDeinit(usb_host_ehci_instance_t *ehciInstance, usb_host_ehci_pipe_t *ehciPipePointer)
+{
+    usb_host_ehci_qh_t *qhPointer;
+
+    qhPointer = (usb_host_ehci_qh_t *)ehciPipePointer->ehciQh;
+    /* de-initialize qtd from qh */
+    USB_HostEhciQhQtdListDeinit(ehciInstance, ehciPipePointer);
+
+    /* release QH */
+    USB_HostEhciLock();
+    qhPointer->horizontalLinkPointer = (uint32_t)ehciInstance->ehciQhList;
+    ehciInstance->ehciQhList = qhPointer;
+    USB_HostEhciUnlock();
+
+    return kStatus_USB_Success;
+}
+
+static void USB_HostEhciAddQhToFrame(usb_host_ehci_instance_t *ehciInstance,
+                                     uint32_t entryPointerValue,
+                                     uint16_t framePos,
+                                     uint16_t uframeInterval)
+{
+    volatile uint32_t *frameEntryPointer;
+    uint32_t frameEntryValue;
+
+    /* search for the inserting point by interval */
+    frameEntryPointer = (volatile uint32_t *)(&((uint32_t *)ehciInstance->ehciFrameList)[framePos]);
+    while (frameEntryPointer)
+    {
+        frameEntryValue = *frameEntryPointer;
+        if (frameEntryValue & EHCI_HOST_T_INVALID_VALUE)
+        {
+            /* insert into the end */
+            *((uint32_t *)entryPointerValue) = EHCI_HOST_T_INVALID_VALUE;
+            *frameEntryPointer = (entryPointerValue | EHCI_HOST_POINTER_TYPE_QH);
+            break;
+        }
+
+        if ((frameEntryValue & EHCI_HOST_POINTER_ADDRESS_MASK) == entryPointerValue)
+        {
+            return; /* has inserted */
+        }
+        if (((frameEntryValue & EHCI_HOST_POINTER_TYPE_MASK) == EHCI_HOST_POINTER_TYPE_QH) &&
+            (((usb_host_ehci_qh_t *)(frameEntryValue & EHCI_HOST_POINTER_ADDRESS_MASK))
+                 ->ehciPipePointer->uframeInterval <= uframeInterval))
+        {
+            /* insert into this point */
+            *((uint32_t *)entryPointerValue) = frameEntryValue;
+            *frameEntryPointer = (entryPointerValue | EHCI_HOST_POINTER_TYPE_QH);
+            return;
+        }
+        else
+        {
+            frameEntryPointer = (volatile uint32_t *)(frameEntryValue & EHCI_HOST_POINTER_ADDRESS_MASK);
+        }
+    }
+}
+
+static void USB_HostEhciRemoveFromFrame(usb_host_ehci_instance_t *ehciInstance,
+                                        uint32_t entryPointerValue,
+                                        uint16_t framePos)
+{
+    volatile uint32_t *frameEntryPointer;
+    uint32_t frameEntryValue;
+
+    /* search for the qh/itd/sitd entry */
+    frameEntryPointer = (volatile uint32_t *)(&((uint32_t *)ehciInstance->ehciFrameList)[framePos]);
+
+    while (frameEntryPointer)
+    {
+        frameEntryValue = *frameEntryPointer;
+        if (frameEntryValue & EHCI_HOST_T_INVALID_VALUE)
+        {
+            return;
+        }
+
+        if ((frameEntryValue & EHCI_HOST_POINTER_ADDRESS_MASK) == entryPointerValue)
+        {
+            /* remove the entry */
+            *frameEntryPointer = *((uint32_t *)entryPointerValue);
+            break;
+        }
+        else
+        {
+            frameEntryPointer = (volatile uint32_t *)(frameEntryValue & EHCI_HOST_POINTER_ADDRESS_MASK);
+        }
+    }
+}
+
+#if ((defined USB_HOST_CONFIG_EHCI_MAX_SITD) && (USB_HOST_CONFIG_EHCI_MAX_SITD))
+static void USB_HostEhciLinkSitd(usb_host_ehci_instance_t *ehciInstance,
+                                 usb_host_ehci_pipe_t *ehciPipePointer,
+                                 void *startEntryPointer)
+{
+    usb_host_ehci_iso_t *isoPointer = (usb_host_ehci_iso_t *)ehciPipePointer->ehciQh;
+    usb_host_ehci_sitd_t *sitdPointer;
+    uint32_t distance;
+    uint32_t frameInterval;
+    int32_t shouldLinkFrame;
+    int32_t currentFrame;
+
+    frameInterval = (ehciPipePointer->uframeInterval >> 3);
+
+    if (isoPointer->lastLinkFrame == 0xFFFF) /* first link */
+    {
+        currentFrame = ((ehciInstance->ehciIpBase->FRINDEX & EHCI_MAX_UFRAME_VALUE) >> 3);
+        currentFrame = ((uint32_t)(currentFrame + USB_HOST_EHCI_ISO_BOUNCE_FRAME_NUMBER) &
+                        (EHCI_MAX_UFRAME_VALUE >> 3)); /* add USB_HOST_EHCI_ISO_BOUNCE_FRAME_NUMBER */
+        /* frame should align with interval */
+        currentFrame -= ehciPipePointer->startFrame;
+        currentFrame =
+            ((uint32_t)(currentFrame + frameInterval - 1) & (~(frameInterval - 1))); /* frameInterval is power of 2 */
+        currentFrame += ehciPipePointer->startFrame;
+    }
+    else
+    {
+        shouldLinkFrame = isoPointer->lastLinkFrame + frameInterval; /* continuous next should link frame */
+        if (shouldLinkFrame > (int32_t)(EHCI_MAX_UFRAME_VALUE >> 3))
+        {
+            shouldLinkFrame = shouldLinkFrame - ((EHCI_MAX_UFRAME_VALUE >> 3) + 1);
+        }
+        currentFrame = ((ehciInstance->ehciIpBase->FRINDEX & EHCI_MAX_UFRAME_VALUE) >> 3);
+        distance = ((shouldLinkFrame - currentFrame + (EHCI_MAX_UFRAME_VALUE >> 3) + 1) &
+                    (EHCI_MAX_UFRAME_VALUE >> 3)); /* get the distance from shouldLinkFrame to currentFrame */
+        /* shouldLinkFrame has add frameInterval, think about the align with interval, so here add (frameInterval *
+         * 2) */
+        if ((distance <= (USB_HOST_EHCI_ISO_BOUNCE_FRAME_NUMBER + frameInterval * 2)) && (distance > 0))
+        {
+            currentFrame = shouldLinkFrame;
+        }
+        else /* re-link */
+        {
+            currentFrame =
+                ((uint32_t)(currentFrame + USB_HOST_EHCI_ISO_BOUNCE_FRAME_NUMBER) & (EHCI_MAX_UFRAME_VALUE >> 3));
+            if (currentFrame > (int32_t)(EHCI_MAX_UFRAME_VALUE >> 3))
+            {
+                currentFrame = currentFrame - ((EHCI_MAX_UFRAME_VALUE >> 3) + 1);
+            }
+            /* frame should align with interval */
+            currentFrame -= ehciPipePointer->startFrame;
+            currentFrame = ((uint32_t)(currentFrame + frameInterval - 1) & (~(frameInterval - 1)));
+            currentFrame += ehciPipePointer->startFrame;
+        }
+    }
+    if (currentFrame >= (int32_t)USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE) /* frame turn around */
+    {
+        shouldLinkFrame =
+            (currentFrame - USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE); /* shouldLinkFrame means inserted frame position */
+    }
+    else
+    {
+        shouldLinkFrame = currentFrame; /* shouldLinkFrame means inserted frame position */
+    }
+
+    sitdPointer = (usb_host_ehci_sitd_t *)startEntryPointer;
+    while (sitdPointer)
+    {
+        sitdPointer->frameEntryIndex = shouldLinkFrame;
+        /* add to frame list head */
+        sitdPointer->nextLinkPointer = ((uint32_t *)ehciInstance->ehciFrameList)[shouldLinkFrame];
+        ((uint32_t *)ehciInstance->ehciFrameList)[shouldLinkFrame] =
+            ((uint32_t)sitdPointer | EHCI_HOST_POINTER_TYPE_SITD);
+        if (sitdPointer->nextSitdIndex == 0xFF) /* 0xFF is invalid value */
+        {
+            break;
+        }
+        sitdPointer = &(ehciInstance->ehciSitdIndexBase[sitdPointer->nextSitdIndex]); /* next sitd */
+
+        shouldLinkFrame += frameInterval;
+        currentFrame += frameInterval;
+        if (shouldLinkFrame >= (int32_t)USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE)
+        {
+            shouldLinkFrame = (shouldLinkFrame - USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE);
+        }
+    }
+
+    if (currentFrame > (int32_t)(EHCI_MAX_UFRAME_VALUE >> 3))
+    {
+        currentFrame = currentFrame - ((EHCI_MAX_UFRAME_VALUE >> 3) + 1);
+    }
+    isoPointer->lastLinkFrame = currentFrame; /* save the last link frame value */
+}
+
+static usb_status_t USB_HostEhciSitdArrayInit(usb_host_ehci_instance_t *ehciInstance,
+                                              usb_host_ehci_pipe_t *ehciPipePointer,
+                                              usb_host_transfer_t *transfer)
+{
+    usb_host_ehci_iso_t *isoPointer;
+    uint32_t sitdNumber = 0;
+    usb_host_ehci_sitd_t *sitdPointer;
+    uint32_t dataLength = 0;
+    uint32_t sitdLength = 0;
+    uint32_t dataBufferValue;
+    uint32_t hubNumber;
+    uint32_t portNumber;
+    uint32_t address;
+    uint32_t tmp;
+    uint8_t index;
+
+    USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetDeviceAddress,
+                                           &address);
+
+    sitdNumber = ((transfer->transferLength - 1 + (ehciPipePointer->pipeCommon.maxPacketSize)) /
+                  (ehciPipePointer->pipeCommon.maxPacketSize));
+    /* get sitd array */
+    tmp = ehciPipePointer - ehciInstance->ehciPipeIndexBase; /* pipe index */
+    /* USB_HostEhciLock(); */
+    if (ehciInstance->ehciSitdNumber >= sitdNumber)
+    {
+        sitdPointer = ehciInstance->ehciSitdList;
+        transfer->union1.unitHead = (uint32_t)sitdPointer;
+        for (index = 1; index < sitdNumber; ++index)
+        {
+            sitdPointer->nextSitdIndex =
+                (((usb_host_ehci_sitd_t *)sitdPointer->nextLinkPointer) - ehciInstance->ehciSitdIndexBase);
+            sitdPointer = (usb_host_ehci_sitd_t *)sitdPointer->nextLinkPointer;
+        }
+        sitdPointer->nextSitdIndex = 0xFF;
+        ehciInstance->ehciSitdList = (usb_host_ehci_sitd_t *)sitdPointer->nextLinkPointer;
+        ehciInstance->ehciSitdNumber -= sitdNumber;
+    }
+    else
+    {
+        /* USB_HostEhciUnlock(); */
+        return kStatus_USB_Error;
+    }
+    /* USB_HostEhciUnlock(); */
+    transfer->union2.unitTail = (uint32_t)sitdPointer;
+    /* initialize sitd array */
+    USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetDeviceHubNumber,
+                                           &hubNumber);
+    USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetDevicePortNumber,
+                                           &portNumber);
+    sitdPointer = (usb_host_ehci_sitd_t *)transfer->union1.unitHead;
+    dataLength = transfer->transferLength;
+    while (sitdNumber--)
+    {
+        USB_HostEhciZeroMem((uint32_t *)sitdPointer, 7);
+        sitdLength = dataLength;
+        if (sitdLength > ehciPipePointer->pipeCommon.maxPacketSize)
+        {
+            sitdLength = ehciPipePointer->pipeCommon.maxPacketSize;
+        }
+        dataBufferValue = (uint32_t)(transfer->transferBuffer + (transfer->transferLength - dataLength));
+        dataLength -= sitdLength; /* update left data length */
+        sitdPointer->transferResults[1] = dataBufferValue;
+        sitdPointer->transferResults[2] = ((dataBufferValue + 4 * 1024) & 0xFFFFF000U);
+        sitdPointer->endpointStates[0] =
+            (((uint32_t)ehciPipePointer->pipeCommon.direction << EHCI_HOST_SITD_DIRECTION_SHIFT) |
+             (portNumber << EHCI_HOST_SITD_PORT_NUMBER_SHIFT) | (hubNumber << EHCI_HOST_SITD_HUB_ADDR_SHIFT) |
+             ((uint32_t)ehciPipePointer->pipeCommon.endpointAddress << EHCI_HOST_SITD_ENDPT_SHIFT) |
+             (address << EHCI_HOST_SITD_DEVICE_ADDRESS_SHIFT));
+        sitdPointer->transferResults[0] =
+            ((sitdLength << EHCI_HOST_SITD_TOTAL_BYTES_SHIFT) | (EHCI_HOST_SITD_STATUS_ACTIVE_MASK));
+
+        if (ehciInstance->firstDeviceSpeed == USB_SPEED_HIGH)
+        {
+            sitdPointer->endpointStates[1] = (((uint32_t)ehciPipePointer->uframeCmask << EHCI_HOST_SITD_CMASK_SHIFT) |
+                                              ((uint32_t)ehciPipePointer->uframeSmask << EHCI_HOST_SITD_SMASK_SHIFT));
+
+            tmp = (sitdLength + 187) / 188;
+            if (tmp > 1)
+            {
+                sitdPointer->transferResults[2] |= (0x01 << EHCI_HOST_SITD_TP_SHIFT); /* for iso split */
+            }
+            else
+            {
+                sitdPointer->transferResults[2] |= (0x00 << EHCI_HOST_SITD_TP_SHIFT); /* for iso split */
+            }
+            sitdPointer->transferResults[2] |= (tmp << EHCI_HOST_SITD_TCOUNT_SHIFT); /* for iso split */
+        }
+
+        sitdPointer->backPointer = EHCI_HOST_T_INVALID_VALUE;
+
+        sitdPointer = (ehciInstance->ehciSitdIndexBase + sitdPointer->nextSitdIndex);
+    }
+    sitdPointer = (usb_host_ehci_sitd_t *)transfer->union2.unitTail;
+    sitdPointer->transferResults[0] |= (1U << EHCI_HOST_SITD_IOC_SHIFT); /* last set IOC */
+
+    /* link transfer to usb_host_ehci_iso_t transfer list */
+    isoPointer = (usb_host_ehci_iso_t *)ehciPipePointer->ehciQh;
+    USB_HostEhciLock();
+    if (isoPointer->ehciTransferHead == NULL)
+    {
+        transfer->next = NULL;
+        isoPointer->ehciTransferHead = isoPointer->ehciTransferTail = transfer;
+    }
+    else
+    {
+        transfer->next = NULL;
+        isoPointer->ehciTransferTail->next = transfer;
+        isoPointer->ehciTransferTail = transfer;
+    }
+    USB_HostEhciUnlock();
+
+    /* link itd to frame list (note: initialize frameEntryIndex)*/
+    USB_HostEhciLinkSitd(ehciInstance, ehciPipePointer, (void *)transfer->union1.unitHead);
+
+    return kStatus_USB_Success;
+}
+
+static uint32_t USB_HostEhciSitdArrayRelease(usb_host_ehci_instance_t *ehciInstance,
+                                             usb_host_ehci_sitd_t *startSitdPointer,
+                                             usb_host_ehci_sitd_t *endSitdPointer)
+{
+    usb_host_ehci_sitd_t *sitdPointer = startSitdPointer;
+    uint32_t leftLength = 0;
+    /* remove itd from frame list */
+    while (1)
+    {
+        /* record the transfer's result length */
+        leftLength +=
+            ((sitdPointer->transferResults[0] & EHCI_HOST_SITD_TOTAL_BYTES_MASK) >> EHCI_HOST_SITD_TOTAL_BYTES_SHIFT);
+        USB_HostEhciRemoveFromFrame(ehciInstance, (uint32_t)sitdPointer,
+                                    sitdPointer->frameEntryIndex); /* remove from the inserted frame list */
+
+        /* release itd */
+        /* USB_HostEhciLock(); */
+        sitdPointer->nextLinkPointer = (uint32_t)ehciInstance->ehciSitdList;
+        ehciInstance->ehciSitdList = sitdPointer;
+        ehciInstance->ehciSitdNumber++;
+        /* USB_HostEhciUnlock(); */
+
+        if (sitdPointer == endSitdPointer)
+        {
+            break;
+        }
+
+        sitdPointer = &(ehciInstance->ehciSitdIndexBase[sitdPointer->nextSitdIndex]);
+    }
+
+    return leftLength;
+}
+
+static usb_status_t USB_HostEhciSitdArrayDeinit(usb_host_ehci_instance_t *ehciInstance,
+                                                usb_host_ehci_pipe_t *ehciPipePointer)
+{
+    usb_host_ehci_iso_t *isoPointer = (usb_host_ehci_iso_t *)ehciPipePointer->ehciQh;
+    usb_host_transfer_t *transfer;
+    usb_host_transfer_t *nextTransfer;
+
+    /* firstly remove the transfer (because host task may occupy to access the resource) */
+    USB_HostEhciLock();
+    transfer = isoPointer->ehciTransferHead;
+    isoPointer->ehciTransferHead = isoPointer->ehciTransferTail = NULL;
+    USB_HostEhciUnlock();
+
+    while (transfer != NULL)
+    {
+        nextTransfer = transfer->next;
+        /* remove sitd from frame list and release itd */
+        transfer->transferSofar =
+            transfer->transferLength - USB_HostEhciSitdArrayRelease(ehciInstance,
+                                                                    (usb_host_ehci_sitd_t *)transfer->union1.unitHead,
+                                                                    (usb_host_ehci_sitd_t *)transfer->union2.unitTail);
+        /* transfer callback */
+        transfer->callbackFn(transfer->callbackParam, transfer, kStatus_USB_TransferCancel);
+        /* next transfer */
+        transfer = nextTransfer;
+    }
+
+    return kStatus_USB_Success;
+}
+#endif /* USB_HOST_CONFIG_EHCI_MAX_SITD */
+
+#if ((defined USB_HOST_CONFIG_EHCI_MAX_ITD) && (USB_HOST_CONFIG_EHCI_MAX_ITD))
+static uint32_t USB_HostEhciGetItdLinkFrame(usb_host_ehci_instance_t *ehciInstance,
+                                            uint32_t lastLinkUframe,
+                                            uint16_t startUframe,
+                                            uint16_t uframeInterval)
+{
+    int32_t shouldLinkUframe;
+    int32_t currentUframe;
+    int32_t distance;
+
+    if (lastLinkUframe != 0xFFFF)
+    {
+        shouldLinkUframe = lastLinkUframe + uframeInterval;
+        if (shouldLinkUframe > (int32_t)EHCI_MAX_UFRAME_VALUE)
+        {
+            shouldLinkUframe = shouldLinkUframe - (EHCI_MAX_UFRAME_VALUE + 1);
+        }
+        currentUframe = (ehciInstance->ehciIpBase->FRINDEX & EHCI_MAX_UFRAME_VALUE);
+        distance = ((shouldLinkUframe - currentUframe + EHCI_MAX_UFRAME_VALUE + 1) &
+                    EHCI_MAX_UFRAME_VALUE); /* get the distance */
+        /* shouldLinkUframe has add uframeInterval, think about the align with interval, so here add (uframeInterval
+         * * 2) */
+        if ((distance <= (int32_t)(USB_HOST_EHCI_ISO_BOUNCE_UFRAME_NUMBER + (uframeInterval * 2))) && (distance > 2))
+        {
+            currentUframe = shouldLinkUframe;
+        }
+        else /* re-link */
+        {
+            currentUframe =
+                ((uint32_t)(currentUframe + USB_HOST_EHCI_ISO_BOUNCE_UFRAME_NUMBER) & EHCI_MAX_UFRAME_VALUE);
+            if (currentUframe > (int32_t)EHCI_MAX_UFRAME_VALUE)
+            {
+                currentUframe = currentUframe - (EHCI_MAX_UFRAME_VALUE + 1);
+            }
+            /* uframe should align with interval */
+            currentUframe -= startUframe;
+            currentUframe = ((uint32_t)(currentUframe + uframeInterval - 1) &
+                             (~((uint32_t)uframeInterval - 1))); /* uframeInterval is power of 2 */
+            currentUframe += startUframe;
+        }
+    }
+    else
+    {
+        currentUframe = (ehciInstance->ehciIpBase->FRINDEX & EHCI_MAX_UFRAME_VALUE);
+        currentUframe = ((uint32_t)(currentUframe + USB_HOST_EHCI_ISO_BOUNCE_UFRAME_NUMBER) & EHCI_MAX_UFRAME_VALUE);
+        /* uframe should align with interval */
+        currentUframe -= startUframe;
+        currentUframe = ((uint32_t)(currentUframe + uframeInterval - 1) &
+                         (~((uint32_t)uframeInterval - 1))); /* uframeInterval is power of 2 */
+        currentUframe += startUframe;
+    }
+
+    return currentUframe;
+}
+
+static usb_status_t USB_HostEhciItdArrayInit(usb_host_ehci_instance_t *ehciInstance,
+                                             usb_host_ehci_pipe_t *ehciPipePointer,
+                                             usb_host_transfer_t *transfer)
+{
+    usb_host_ehci_iso_t *isoPointer;
+    usb_host_ehci_itd_t *itdPointer = NULL;
+    usb_host_ehci_itd_t *tmpItdPointer;
+    uint32_t dataLength;        /* the remaining data for sending */
+    uint32_t transactionLength; /* the initializing transaction descriptor data length */
+    uint32_t itdBufferValue;
+    uint32_t itdBufferBaseValue; /* for calculating PG value */
+    uint32_t address;
+    uint32_t lastShouldLinkUframe;
+    uint32_t linkUframe;
+    uint32_t minDataPerItd = ehciPipePointer->pipeCommon.numberPerUframe * ehciPipePointer->pipeCommon.maxPacketSize;
+    uint8_t maxItdNumber;
+    uint8_t index = 0;
+
+    isoPointer = (usb_host_ehci_iso_t *)ehciPipePointer->ehciQh;
+    USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetDeviceAddress,
+                                           &address);
+
+    /* max needed itd number, the actual needed number may be less because micro-frame interval may be less than 8 */
+    maxItdNumber = ((transfer->transferLength - 1 + minDataPerItd) / minDataPerItd);
+    if (ehciPipePointer->uframeInterval < 8)
+    {
+        maxItdNumber = ((maxItdNumber * ehciPipePointer->uframeInterval + 7) / 8) + 1;
+    }
+    if (maxItdNumber > ehciInstance->ehciItdNumber)
+    {
+        return kStatus_USB_Error;
+    }
+
+    /* link transfer to usb_host_ehci_iso_t transfer list */
+    transfer->next = NULL;
+    /* USB_HostEhciLock(); */
+    if (isoPointer->ehciTransferHead == NULL)
+    {
+        isoPointer->ehciTransferHead = isoPointer->ehciTransferTail = transfer;
+    }
+    else
+    {
+        isoPointer->ehciTransferTail->next = transfer;
+        isoPointer->ehciTransferTail = transfer;
+    }
+    /* USB_HostEhciUnlock(); */
+
+    dataLength = transfer->transferLength;
+    transfer->union1.unitHead = (uint32_t)NULL;
+    /* get the link micro-frame */
+    lastShouldLinkUframe = USB_HostEhciGetItdLinkFrame(
+        ehciInstance, isoPointer->lastLinkFrame,
+        (uint16_t)((ehciPipePointer->startFrame << 3) + ehciPipePointer->startUframe), ehciPipePointer->uframeInterval);
+    if (lastShouldLinkUframe > EHCI_MAX_UFRAME_VALUE)
+    {
+        linkUframe = lastShouldLinkUframe - (EHCI_MAX_UFRAME_VALUE + 1);
+    }
+    else
+    {
+        linkUframe = lastShouldLinkUframe;
+    }
+    while (dataLength)
+    {
+        /* get one idle itd */
+        tmpItdPointer = ehciInstance->ehciItdList;
+        ehciInstance->ehciItdList = (usb_host_ehci_itd_t *)tmpItdPointer->nextLinkPointer;
+        ehciInstance->ehciItdNumber -= 1;
+        if (tmpItdPointer == NULL)
+        {
+            return kStatus_USB_Error; /* this should not reach */
+        }
+        tmpItdPointer->nextItdPointer = NULL;
+
+        /* use the itd */
+        if (transfer->union1.unitHead == (uint32_t)NULL) /* first itd */
+        {
+            transfer->union1.unitHead = (uint32_t)tmpItdPointer;
+        }
+        else /* link itd list */
+        {
+            itdPointer->nextItdPointer = tmpItdPointer;
+        }
+        itdPointer = tmpItdPointer;
+
+        /* itd has been set to all zero when releasing */
+        itdBufferBaseValue = itdBufferValue =
+            (uint32_t)(transfer->transferBuffer + (transfer->transferLength - dataLength));
+        for (index = 0; index < 7; ++index)
+        {
+            itdPointer->bufferPointers[index] = ((itdBufferBaseValue + (index * 4 * 1024)) & 0xFFFFF000U);
+        }
+        /* initialize iTD common fields */
+        itdPointer->bufferPointers[0] |=
+            (((uint32_t)ehciPipePointer->pipeCommon.endpointAddress << EHCI_HOST_ITD_ENDPT_SHIFT) |
+             (address << EHCI_HOST_ITD_DEVICE_ADDRESS_SHIFT));
+        itdPointer->bufferPointers[1] |=
+            (((uint32_t)ehciPipePointer->pipeCommon.direction << EHCI_HOST_ITD_DIRECTION_SHIFT) |
+             ((uint32_t)ehciPipePointer->pipeCommon.maxPacketSize << EHCI_HOST_ITD_MAX_PACKET_SIZE_SHIFT));
+        itdPointer->bufferPointers[2] |= (ehciPipePointer->pipeCommon.numberPerUframe);
+        /* initialize transaction descriptors */
+        for (index = (linkUframe & 0x0007); index < 8; index += ehciPipePointer->uframeInterval)
+        {
+            transactionLength = ((dataLength > minDataPerItd) ? minDataPerItd : dataLength);
+            /* initialize the uframeIndex's transaction descriptor in itd */
+            itdPointer->transactions[index] =
+                ((EHCI_HOST_ITD_STATUS_ACTIVE_MASK) | (transactionLength << EHCI_HOST_ITD_TRANSACTION_LEN_SHIFT) |
+                 ((((itdBufferValue & 0xFFFFF000U) - (itdBufferBaseValue & 0xFFFFF000U)) >>
+                   EHCI_HOST_ITD_BUFFER_POINTER_SHIFT)
+                  << EHCI_HOST_ITD_PG_SHIFT) |
+                 (itdBufferValue & EHCI_HOST_ITD_TRANSACTION_OFFSET_MASK));
+            dataLength -= transactionLength;
+            itdBufferValue += transactionLength;
+            if (dataLength <= 0)
+            {
+                break;
+            }
+        }
+    }
+
+    transfer->union2.unitTail = (uint32_t)itdPointer;
+    itdPointer->transactions[index] |= (1 << EHCI_HOST_ITD_IOC_SHIFT); /* last set IOC */
+
+    /* link itd to frame list (note: initialize frameEntryIndex)*/
+    while (itdPointer)
+    {
+        itdPointer->frameEntryIndex = linkUframe;
+        /* add to frame head */
+        itdPointer->nextLinkPointer = ((uint32_t *)ehciInstance->ehciFrameList)[linkUframe >> 3];
+        *(uint32_t *)((uint32_t *)ehciInstance->ehciFrameList)[linkUframe >> 3] =
+            ((uint32_t)itdPointer | EHCI_HOST_POINTER_TYPE_ITD);
+        itdPointer = itdPointer->nextItdPointer;
+        if (itdPointer == NULL)
+        {
+            break;
+        }
+
+        linkUframe += ehciPipePointer->uframeInterval;
+        lastShouldLinkUframe += ehciPipePointer->uframeInterval;
+        if (linkUframe >= (USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE << 3))
+        {
+            linkUframe = (linkUframe - (USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE << 3));
+        }
+    }
+
+    if (lastShouldLinkUframe > EHCI_MAX_UFRAME_VALUE)
+    {
+        lastShouldLinkUframe = lastShouldLinkUframe - (EHCI_MAX_UFRAME_VALUE + 1);
+    }
+    isoPointer->lastLinkFrame = lastShouldLinkUframe;
+
+    return kStatus_USB_Success;
+}
+
+static uint32_t USB_HostEhciItdArrayRelease(usb_host_ehci_instance_t *ehciInstance,
+                                            usb_host_ehci_itd_t *startItdPointer,
+                                            usb_host_ehci_itd_t *endItdPointer)
+{
+    usb_host_ehci_itd_t *itdPointer = startItdPointer;
+    uint8_t index;
+    uint32_t doneLength = 0;
+
+    /* remove itd from frame list */
+    while (1)
+    {
+        /* record the transfer's result length */
+        for (index = 0; index < 8; ++index)
+        {
+            doneLength += ((itdPointer->transactions[index] & EHCI_HOST_ITD_TRANSACTION_LEN_MASK) >>
+                           EHCI_HOST_ITD_TRANSACTION_LEN_SHIFT);
+        }
+
+        USB_HostEhciRemoveFromFrame(ehciInstance, (uint32_t)itdPointer,
+                                    itdPointer->frameEntryIndex); /* remove from the inserted frame list */
+
+        /* release itd */
+        /* USB_HostEhciLock(); */
+        USB_HostEhciZeroMem((uint32_t *)itdPointer, sizeof(usb_host_ehci_itd_t) >> 2);
+        itdPointer->nextLinkPointer = (uint32_t)ehciInstance->ehciItdList;
+        ehciInstance->ehciItdList = itdPointer;
+        ehciInstance->ehciItdNumber++;
+        /* USB_HostEhciUnlock(); */
+
+        if (itdPointer == endItdPointer)
+        {
+            break;
+        }
+        itdPointer = itdPointer->nextItdPointer;
+    }
+
+    return doneLength;
+}
+
+static usb_status_t USB_HostEhciItdArrayDeinit(usb_host_ehci_instance_t *ehciInstance,
+                                               usb_host_ehci_pipe_t *ehciPipePointer)
+{
+    usb_host_ehci_iso_t *isoPointer = (usb_host_ehci_iso_t *)ehciPipePointer->ehciQh;
+    usb_host_transfer_t *transfer;
+    usb_host_transfer_t *nextTransfer;
+    uint32_t doneLength = 0;
+
+    /* firstly remove the transfer (because host task may occupy to access the resource) */
+    USB_HostEhciLock();
+    transfer = isoPointer->ehciTransferHead;
+    isoPointer->ehciTransferHead = isoPointer->ehciTransferTail = NULL;
+    USB_HostEhciUnlock();
+
+    while (transfer != NULL)
+    {
+        nextTransfer = transfer->next;
+        doneLength = 0;
+        /* remove itd from frame list and release itd */
+        doneLength = USB_HostEhciItdArrayRelease(ehciInstance, (usb_host_ehci_itd_t *)transfer->union1.unitHead,
+                                                 (usb_host_ehci_itd_t *)transfer->union2.unitTail);
+
+        /* transfer callback */
+        if (ehciPipePointer->pipeCommon.direction == USB_OUT)
+        {
+            doneLength = transfer->transferLength;
+        }
+        transfer->transferSofar = doneLength;
+        transfer->callbackFn(transfer->callbackParam, transfer, kStatus_USB_TransferCancel);
+
+        /* next transfer */
+        transfer = nextTransfer;
+    }
+
+    return kStatus_USB_Success;
+}
+#endif /* USB_HOST_CONFIG_EHCI_MAX_ITD */
+
+static usb_status_t USB_HostEhciOpenControlBulk(usb_host_ehci_instance_t *ehciInstance,
+                                                usb_host_ehci_pipe_t *ehciPipePointer)
+{
+    usb_host_ehci_qh_t *qhPointer;
+
+    if (USB_HostEhciQhInit(ehciInstance, ehciPipePointer) != kStatus_USB_Success) /* initialize control/bulk qh */
+    {
+        return kStatus_USB_Error;
+    }
+
+    qhPointer = (usb_host_ehci_qh_t *)ehciPipePointer->ehciQh;
+
+    /* add qh to async */
+    qhPointer->horizontalLinkPointer = ehciInstance->shedFirstQh->horizontalLinkPointer;
+    ehciInstance->shedFirstQh->horizontalLinkPointer = ((uint32_t)qhPointer | EHCI_HOST_POINTER_TYPE_QH);
+
+    return kStatus_USB_Success;
+}
+
+static usb_status_t USB_HostEhciCloseControlBulk(usb_host_ehci_instance_t *ehciInstance,
+                                                 usb_host_ehci_pipe_t *ehciPipePointer)
+{
+    volatile usb_host_ehci_qh_t *vltPrevQhPointer;
+    uint32_t horizontalLinkValue;
+
+    /* remove qh from async schedule */
+    if ((ehciInstance->shedFirstQh->horizontalLinkPointer & EHCI_HOST_POINTER_ADDRESS_MASK) ==
+        (uint32_t)ehciPipePointer->ehciQh) /* the removing qh is the first qh in the async list */
+    {
+        USB_HostEhciStopAsync(ehciInstance);
+        ehciInstance->shedFirstQh->horizontalLinkPointer =
+            ((usb_host_ehci_qh_t *)ehciPipePointer->ehciQh)->horizontalLinkPointer;
+        USB_HostEhciStartAsync(ehciInstance);
+    }
+    else
+    {
+        /* search for the removing qh from the async list */
+        vltPrevQhPointer = ehciInstance->shedFirstQh;
+        while (vltPrevQhPointer != NULL)
+        {
+            horizontalLinkValue = vltPrevQhPointer->horizontalLinkPointer;
+            if ((horizontalLinkValue & EHCI_HOST_T_INVALID_VALUE) ||
+                ((horizontalLinkValue & EHCI_HOST_POINTER_ADDRESS_MASK) == (uint32_t)ehciPipePointer->ehciQh) ||
+                ((horizontalLinkValue & EHCI_HOST_POINTER_ADDRESS_MASK) == (uint32_t)ehciInstance->shedFirstQh))
+            {
+                break;
+            }
+
+            vltPrevQhPointer = (volatile usb_host_ehci_qh_t *)(horizontalLinkValue & EHCI_HOST_POINTER_ADDRESS_MASK);
+        }
+
+        /* remove the qh from async list */
+        if ((vltPrevQhPointer != NULL) && (!(horizontalLinkValue & EHCI_HOST_T_INVALID_VALUE)) &&
+            ((horizontalLinkValue & EHCI_HOST_POINTER_ADDRESS_MASK) == (uint32_t)ehciPipePointer->ehciQh))
+        {
+            USB_HostEhciStopAsync(ehciInstance);
+            vltPrevQhPointer->horizontalLinkPointer =
+                ((usb_host_ehci_qh_t *)ehciPipePointer->ehciQh)->horizontalLinkPointer;
+            USB_HostEhciStartAsync(ehciInstance);
+        }
+    }
+    ((usb_host_ehci_qh_t *)ehciPipePointer->ehciQh)->horizontalLinkPointer =
+        EHCI_HOST_T_INVALID_VALUE;                              /* invalid next qh link */
+    return USB_HostEhciQhDeinit(ehciInstance, ehciPipePointer); /* de-initialize qh and release qh */
+}
+
+static usb_status_t USB_HostEhciOpenInterrupt(usb_host_ehci_instance_t *ehciInstance,
+                                              usb_host_ehci_pipe_t *ehciPipePointer)
+{
+    usb_status_t status = kStatus_USB_Success;
+    uint32_t frameIndex;
+
+    /* allocate bandwidth */
+    if (ehciInstance->firstDeviceSpeed == USB_SPEED_HIGH)
+    {
+        status = USB_HostBandwidthHsHostAllocateInterrupt(ehciInstance, ehciPipePointer); /* host works as high-speed */
+    }
+    else
+    {
+        status = USB_HostBandwidthFslsHostAllocate(ehciInstance,
+                                                   ehciPipePointer); /* host works as full-speed or low-speed */
+    }
+
+    if (status != kStatus_USB_Success)
+    {
+        return status;
+    }
+    if (USB_HostEhciQhInit(ehciInstance, ehciPipePointer) != kStatus_USB_Success)
+    {
+        return kStatus_USB_Error;
+    }
+
+    /* insert QH to frame list */
+    for (frameIndex = ehciPipePointer->startFrame; frameIndex < USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE;
+         frameIndex += (ehciPipePointer->uframeInterval / 8))
+    {
+        USB_HostEhciAddQhToFrame(ehciInstance, (uint32_t)ehciPipePointer->ehciQh, frameIndex,
+                                 ehciPipePointer->uframeInterval);
+    }
+
+    return kStatus_USB_Success;
+}
+
+static usb_status_t USB_HostEhciCloseInterrupt(usb_host_ehci_instance_t *ehciInstance,
+                                               usb_host_ehci_pipe_t *ehciPipePointer)
+{
+    uint32_t frameIndex;
+
+    /* remove from frame list */
+    for (frameIndex = ehciPipePointer->startFrame; frameIndex < USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE;
+         frameIndex += (ehciPipePointer->uframeInterval / 8))
+    {
+        USB_HostEhciRemoveFromFrame(ehciInstance, (uint32_t)ehciPipePointer->ehciQh, frameIndex);
+    }
+    ((usb_host_ehci_qh_t *)ehciPipePointer->ehciQh)->horizontalLinkPointer |=
+        EHCI_HOST_T_INVALID_VALUE; /* invalid next qh link */
+
+    return USB_HostEhciQhDeinit(ehciInstance, ehciPipePointer); /* de-initilaze qh and release qh */
+}
+
+#if (((defined USB_HOST_CONFIG_EHCI_MAX_ITD) && (USB_HOST_CONFIG_EHCI_MAX_ITD)) || \
+     ((defined USB_HOST_CONFIG_EHCI_MAX_SITD) && (USB_HOST_CONFIG_EHCI_MAX_SITD)))
+
+static usb_status_t USB_HostEhciOpenIso(usb_host_ehci_instance_t *ehciInstance, usb_host_ehci_pipe_t *ehciPipePointer)
+{
+    usb_host_ehci_iso_t *isoPointer;
+    usb_status_t status = kStatus_USB_Success;
+
+    if (ehciInstance->firstDeviceSpeed == USB_SPEED_HIGH)
+    {
+        status = USB_HostBandwidthHsHostAllocateIso(
+            ehciInstance, ehciPipePointer); /* allocate iso bandwidth when host works as high-speed */
+    }
+    else
+    {
+        status = USB_HostBandwidthFslsHostAllocate(
+            ehciInstance, ehciPipePointer); /* allocate iso bandwidth when host works as full-speed or low-speed */
+    }
+
+    if (status != kStatus_USB_Success)
+    {
+        return status;
+    }
+
+    /* get usb_host_ehci_iso_t */
+    if (ehciInstance->ehciIsoList == NULL)
+    {
+        return kStatus_USB_Error;
+    }
+    USB_HostEhciLock();
+    isoPointer = ehciInstance->ehciIsoList;
+    ehciInstance->ehciIsoList = ehciInstance->ehciIsoList->next;
+    USB_HostEhciUnlock();
+    isoPointer->lastLinkFrame = 0xFFFF;
+    ehciPipePointer->ehciQh = isoPointer;
+
+    return status;
+}
+
+static usb_status_t USB_HostEhciCloseIso(usb_host_ehci_instance_t *ehciInstance, usb_host_ehci_pipe_t *ehciPipePointer)
+{
+    usb_host_ehci_iso_t *isoPointer;
+    uint32_t speed;
+
+    isoPointer = (usb_host_ehci_iso_t *)ehciPipePointer->ehciQh;
+
+    if (isoPointer->ehciTransferHead != NULL)
+    {
+        USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetDeviceSpeed,
+                                               &speed);
+        if (speed == USB_SPEED_HIGH)
+        {
+#if ((defined USB_HOST_CONFIG_EHCI_MAX_ITD) && (USB_HOST_CONFIG_EHCI_MAX_ITD))
+            USB_HostEhciItdArrayDeinit(ehciInstance, ehciPipePointer); /* de-initialize itd list and free them */
+#endif
+        }
+        else
+        {
+#if ((defined USB_HOST_CONFIG_EHCI_MAX_SITD) && (USB_HOST_CONFIG_EHCI_MAX_SITD))
+            USB_HostEhciSitdArrayDeinit(ehciInstance, ehciPipePointer); /* de-initialize sitd list and free them */
+#endif
+        }
+    }
+
+    /* release usb_host_ehci_iso_t */
+    USB_HostEhciLock();
+    isoPointer->next = ehciInstance->ehciIsoList;
+    ehciInstance->ehciIsoList = isoPointer;
+    USB_HostEhciUnlock();
+    return kStatus_USB_Success;
+}
+
+#endif
+
+static usb_status_t USB_HostEhciResetIP(usb_host_ehci_instance_t *ehciInstance)
+{
+    /* reset controller */
+    ehciInstance->ehciIpBase->USBCMD = USBHS_USBCMD_RST_MASK;
+    while (ehciInstance->ehciIpBase->USBCMD & USBHS_USBCMD_RST_MASK)
+    {
+    }
+/* set host mode */
+#if (ENDIANNESS == USB_LITTLE_ENDIAN)
+    ehciInstance->ehciIpBase->USBMODE |= 0x03;
+#else
+    ehciInstance->ehciIpBase->USBMODE |= (0x03 | (0x01 << USBHS_USBMODE_ES_SHIFT));
+#endif
+    /* check frame list size */
+    if (!(ehciInstance->ehciIpBase->HCCPARAMS & USBHS_HCCPARAMS_PFL_MASK))
+    {
+#if ((USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE < 8) || (USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE > 1024))
+        return kStatus_USB_Error;
+#endif
+#if (USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE & (USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE - 1))
+        return kStatus_USB_Error; /* frame size must be 1024/512/256/128/64/32/16/8 */
+#endif
+    }
+    return kStatus_USB_Success;
+}
+
+static usb_status_t USB_HostEhciStartIP(usb_host_ehci_instance_t *ehciInstance)
+{
+    uint32_t tmp = 0;
+
+    if (ehciInstance->ehciIpBase->HCSPARAMS & USBHS_HCSPARAMS_PPC_MASK) /* Ports have power port switches */
+    {
+        /* only has one port */
+        tmp = ehciInstance->ehciIpBase->PORTSC1;
+        tmp &= (~EHCI_PORTSC1_W1_BITS);
+        ehciInstance->ehciIpBase->PORTSC1 = (tmp | USBHS_PORTSC1_PP_MASK); /* turn on port power */
+    }
+
+    /* set frame list size */
+    if (ehciInstance->ehciIpBase->HCCPARAMS & USBHS_HCCPARAMS_PFL_MASK)
+    {
+#if (USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE <= 64)
+        ehciInstance->ehciIpBase->USBCMD |= (USBHS_USBCMD_FS2_MASK);
+#if (USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE == 64)
+        ehciInstance->ehciIpBase->USBCMD |= (0x00 << USBHS_USBCMD_FS_SHIFT);
+#elif(USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE == 32)
+        ehciInstance->ehciIpBase->USBCMD |= (0x01 << USBHS_USBCMD_FS_SHIFT);
+#elif(USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE == 16)
+        ehciInstance->ehciIpBase->USBCMD |= (0x02 << USBHS_USBCMD_FS_SHIFT);
+#elif(USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE == 8)
+        ehciInstance->ehciIpBase->USBCMD |= (0x03 << USBHS_USBCMD_FS_SHIFT);
+#endif
+#else
+#if (USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE == 1024)
+        ehciInstance->ehciIpBase->USBCMD |= (0x00 << USBHS_USBCMD_FS_SHIFT);
+#elif(USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE == 512)
+        ehciInstance->ehciIpBase->USBCMD |= (0x01 << USBHS_USBCMD_FS_SHIFT);
+#elif(USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE == 256)
+        ehciInstance->ehciIpBase->USBCMD |= (0x02 << USBHS_USBCMD_FS_SHIFT);
+#elif(USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE == 128)
+        ehciInstance->ehciIpBase->USBCMD |= (0x03 << USBHS_USBCMD_FS_SHIFT);
+#endif
+#endif
+    }
+
+    /* start the controller */
+    ehciInstance->ehciIpBase->USBCMD = USBHS_USBCMD_RS_MASK;
+
+    /* set timer0 */
+    ehciInstance->ehciIpBase->GPTIMER0LD = (300 * 1000 - 1); /* 100ms */
+
+    /* enable interrupt (USB interrupt enable + USB error interrupt enable + port change detect enable + system error
+     * enable + interrupt on async advance enable) + general purpos Timer 0 Interrupt enable */
+    ehciInstance->ehciIpBase->USBINTR |= (0x1000037);
+
+    return kStatus_USB_Success;
+}
+
+static usb_status_t USB_HostEhciCancelPipe(usb_host_ehci_instance_t *ehciInstance,
+                                           usb_host_ehci_pipe_t *ehciPipePointer,
+                                           usb_host_transfer_t *transfer)
+{
+    usb_host_ehci_qh_t *qhPointer;
+#if (((defined USB_HOST_CONFIG_EHCI_MAX_ITD) && (USB_HOST_CONFIG_EHCI_MAX_ITD)) || \
+     ((defined USB_HOST_CONFIG_EHCI_MAX_SITD) && (USB_HOST_CONFIG_EHCI_MAX_SITD)))
+    usb_host_ehci_iso_t *isoPointer;
+    uint32_t speed;
+#endif
+    uint8_t cancelPipe = 0;
+
+    switch (ehciPipePointer->pipeCommon.pipeType)
+    {
+        case USB_ENDPOINT_BULK:
+        case USB_ENDPOINT_CONTROL:
+        case USB_ENDPOINT_INTERRUPT:
+            qhPointer = (usb_host_ehci_qh_t *)ehciPipePointer->ehciQh;
+            if (qhPointer->ehciTransferHead == NULL) /* there is no transfer to cancel */
+            {
+                return kStatus_USB_Success;
+            }
+            if (transfer != NULL)
+            {
+                if ((qhPointer->ehciTransferHead == transfer) &&
+                    (qhPointer->ehciTransferHead == qhPointer->ehciTransferTail)) /* only has this one transfer */
+                {
+                    cancelPipe = 1;
+                }
+                else
+                {
+                    cancelPipe = 0;
+                }
+            }
+            else
+            {
+                cancelPipe = 1;
+            }
+            if (cancelPipe == 1) /* cancel all pipe */
+            {
+                USB_HostEhciQhQtdListDeinit(ehciInstance, ehciPipePointer); /* release all the qtd */
+            }
+            else /* cancel one transfer */
+            {
+                USB_HostEhciTransferQtdListDeinit(ehciInstance, ehciPipePointer, transfer);
+            }
+            break;
+
+#if (((defined USB_HOST_CONFIG_EHCI_MAX_ITD) && (USB_HOST_CONFIG_EHCI_MAX_ITD)) || \
+     ((defined USB_HOST_CONFIG_EHCI_MAX_SITD) && (USB_HOST_CONFIG_EHCI_MAX_SITD)))
+        case USB_ENDPOINT_ISOCHRONOUS:
+            isoPointer = (usb_host_ehci_iso_t *)ehciPipePointer->ehciQh;
+            if (isoPointer->ehciTransferHead == NULL) /* there is no transfer to cancel */
+            {
+                return kStatus_USB_Success;
+            }
+            /* cancel all pipe, don't implement canceling transfer for iso */
+            USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetDeviceSpeed,
+                                                   &speed);
+            if (speed == USB_SPEED_HIGH)
+            {
+#if ((defined USB_HOST_CONFIG_EHCI_MAX_ITD) && (USB_HOST_CONFIG_EHCI_MAX_ITD))
+                USB_HostEhciItdArrayDeinit(ehciInstance, ehciPipePointer); /* de-initialize itd */
+#endif
+            }
+            else
+            {
+#if ((defined USB_HOST_CONFIG_EHCI_MAX_SITD) && (USB_HOST_CONFIG_EHCI_MAX_SITD))
+                USB_HostEhciSitdArrayDeinit(ehciInstance, ehciPipePointer); /* de-initialize sitd */
+#endif
+            }
+            break;
+#endif
+
+        default:
+            break;
+    }
+
+    return kStatus_USB_Success;
+}
+
+static usb_status_t USB_HostEhciControlBus(usb_host_ehci_instance_t *ehciInstance, uint8_t busControl)
+{
+    usb_status_t status = kStatus_USB_Success;
+    uint32_t portScRegister;
+
+    switch (busControl)
+    {
+        case kUSB_HostBusReset:
+            /* reset port */
+            portScRegister = ehciInstance->ehciIpBase->PORTSC1;
+            portScRegister &= (~EHCI_PORTSC1_W1_BITS);
+            ehciInstance->ehciIpBase->PORTSC1 = (portScRegister | USBHS_PORTSC1_PR_MASK);
+            while (ehciInstance->ehciIpBase->PORTSC1 & USBHS_PORTSC1_PR_MASK)
+            {
+            }
+            break;
+
+        case kUSB_HostBusRestart:
+            ehciInstance->deviceAttached = kEHCIDeviceDetached;
+            ehciInstance->ehciIpBase->USBINTR |= (USBHS_USBINTR_PCE_MASK); /* enable ehci port change interrupt */
+            break;
+
+        case kUSB_HostBusEnableAttach: /* enable device attach */
+            if (ehciInstance->deviceAttached == kEHCIDeviceDetached)
+            {
+                ehciInstance->ehciIpBase->USBINTR |= (USBHS_USBINTR_PCE_MASK); /* enable ehci port change interrupt */
+            }
+            break;
+
+        case kUSB_HostBusDisableAttach:                                     /* disable device attach */
+            ehciInstance->ehciIpBase->USBINTR &= (~USBHS_USBINTR_PCE_MASK); /* disable ehci port change interrupt */
+            break;
+#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
+        case kUSB_HostBusSuspend:
+            if (ehciInstance->ehciIpBase->PORTSC1 && USBHS_PORTSC1_CCS_MASK)
+            {
+                /* set timer1 */
+                ehciInstance->ehciIpBase->GPTIMER1LD = (1 * 1000); /* 1ms */
+                ehciInstance->ehciIpBase->GPTIMER1CTL |=
+                    (USBHS_GPTIMER0CTL_RUN_MASK | USBHS_GPTIMER0CTL_MODE_MASK | USBHS_GPTIMER0CTL_RST_MASK);
+
+                USB_HostEhciStopAsync(ehciInstance);
+                USB_HostEhciStopPeriodic(ehciInstance);
+                while (ehciInstance->ehciIpBase->USBSTS & (USBHS_USBSTS_PS_MASK | USBHS_USBSTS_AS_MASK))
+                {
+                    __ASM("nop");
+                }
+                ehciInstance->ehciIpBase->PORTSC1 &= ~USBHS_PORTSC1_WKCN_MASK;
+                ehciInstance->ehciIpBase->PORTSC1 |= USBHS_PORTSC1_WKDS_MASK;
+                ehciInstance->ehciIpBase->PORTSC1 |= (USBHS_PORTSC1_SUSP_MASK); /* Suspend the device */
+
+                ehciInstance->matchTick = 0U;
+                ehciInstance->ehciIpBase->USBINTR |= (USBHS_USBINTR_TIE1_MASK);
+                ehciInstance->busSuspendStatus = kBus_EhciStartSuspend;
+            }
+            else
+            {
+                status = kStatus_USB_Error;
+            }
+            break;
+        case kUSB_HostBusResume:
+            ehciInstance->ehciIpBase->PORTSC1 &= ~(USBHS_PORTSC1_SUSP_MASK); /* Clear Suspend bit */
+            ehciInstance->ehciIpBase->PORTSC1 &= ~USBHS_PORTSC1_PHCD_MASK;
+            if (ehciInstance->deviceAttached != kEHCIDeviceDetached)
+            {
+                ehciInstance->busSuspendStatus = kBus_EhciStartResume;
+#if (defined(FSL_FEATURE_SOC_USBNC_COUNT) && (FSL_FEATURE_SOC_USBNC_COUNT > 0U))
+                ehciInstance->registerNcBase->USB_OTGn_CTRL &= ~USBNC_USB_OTGn_CTRL_WIE_MASK;
+#else
+                ehciInstance->ehciIpBase->USBGENCTRL &= ~USBHS_USBGENCTRL_WU_IE_MASK;
+#endif
+                ehciInstance->ehciIpBase->USBCMD |= (USBHS_USBCMD_RS_MASK);
+                ehciInstance->ehciIpBase->PORTSC1 |= (USBHS_PORTSC1_FPR_MASK); /* Resume the device */
+            }
+            else
+            {
+                status = kStatus_USB_Error;
+            }
+            break;
+#endif
+        default:
+            status = kStatus_USB_Error;
+            break;
+    }
+    return status;
+}
+
+void USB_HostEhciTransactionDone(usb_host_ehci_instance_t *ehciInstance)
+{
+    /* process async QH */
+    usb_host_ehci_pipe_t *ehciPipePointer;
+    usb_host_ehci_pipe_t *ehciClearPipePointer = NULL;
+    volatile usb_host_ehci_qh_t *vltQhPointer;
+    volatile usb_host_ehci_qtd_t *vltQtdPointer;
+    usb_host_transfer_t *transfer;
+    usb_host_transfer_t *nextTransfer;
+    uint32_t qtdStatus = 0;
+#if ((defined USB_HOST_CONFIG_EHCI_MAX_ITD) && (USB_HOST_CONFIG_EHCI_MAX_ITD))
+    volatile usb_host_ehci_itd_t *vltItdPointer;
+    uint8_t index = 0;
+#endif
+#if ((defined USB_HOST_CONFIG_EHCI_MAX_SITD) && (USB_HOST_CONFIG_EHCI_MAX_SITD))
+    volatile usb_host_ehci_sitd_t *vltSitdPointer;
+#endif
+#if (((defined USB_HOST_CONFIG_EHCI_MAX_ITD) && (USB_HOST_CONFIG_EHCI_MAX_ITD)) || \
+     ((defined USB_HOST_CONFIG_EHCI_MAX_SITD) && (USB_HOST_CONFIG_EHCI_MAX_SITD)))
+    usb_host_ehci_iso_t *isoPointer;
+    uint32_t dataLength;
+    uint32_t speed;
+#endif
+
+    ehciPipePointer = ehciInstance->ehciRunningPipeList; /* check all the running pipes */
+    while (ehciPipePointer != NULL)
+    {
+        switch (ehciPipePointer->pipeCommon.pipeType)
+        {
+            case USB_ENDPOINT_BULK:
+            case USB_ENDPOINT_INTERRUPT:
+            case USB_ENDPOINT_CONTROL:
+                vltQhPointer = (volatile usb_host_ehci_qh_t *)ehciPipePointer->ehciQh; /* pipe's qh */
+                transfer = vltQhPointer->ehciTransferHead;                             /* qh's transfer */
+                while (transfer != NULL)
+                {
+                    nextTransfer = transfer->next;
+                    /* normal case */
+                    vltQtdPointer = (volatile usb_host_ehci_qtd_t *)transfer->union2.unitTail;
+                    if ((vltQtdPointer->transferResults[0] & (EHCI_HOST_QTD_IOC_MASK)) &&
+                        (!(vltQtdPointer->transferResults[0] &
+                           EHCI_HOST_QTD_STATUS_ACTIVE_MASK))) /* transfer is done */
+                    {
+                        qtdStatus = (vltQtdPointer->transferResults[0] & EHCI_HOST_QTD_STATUS_ERROR_MASK);
+                        transfer->transferSofar =
+                            USB_HostEhciQtdListRelease(ehciInstance, (usb_host_ehci_qtd_t *)(transfer->union1.unitHead),
+                                                       (usb_host_ehci_qtd_t *)(transfer->union2.unitTail));
+                        transfer->transferSofar = (transfer->transferLength < transfer->transferSofar) ?
+                                                      0 :
+                                                      (transfer->transferLength - transfer->transferSofar);
+
+                        vltQhPointer->ehciTransferHead = transfer->next;
+                        vltQhPointer->timeOutLabel = 0;
+                        vltQhPointer->timeOutValue = USB_HOST_EHCI_CONTROL_BULK_TIME_OUT_VALUE;
+                        if (qtdStatus) /* has errors */
+                        {
+                            if (!(vltQhPointer->transferOverlayResults[0] & EHCI_HOST_QTD_STATUS_ACTIVE_MASK))
+                            {
+                                vltQhPointer->transferOverlayResults[0] &=
+                                    (~EHCI_HOST_QTD_STATUS_MASK); /* clear error status */
+                            }
+                            if (qtdStatus & EHCI_HOST_QH_STATUS_NOSTALL_ERROR_MASK)
+                            {
+                                transfer->callbackFn(transfer->callbackParam, transfer,
+                                                     kStatus_USB_TransferFailed); /* transfer fail */
+                            }
+                            else
+                            {
+                                transfer->callbackFn(transfer->callbackParam, transfer,
+                                                     kStatus_USB_TransferStall); /* transfer stall */
+                            }
+                        }
+                        else
+                        {
+                            if ((ehciPipePointer->pipeCommon.pipeType == USB_ENDPOINT_CONTROL) &&
+                                (transfer->setupPacket->bRequest == USB_REQUEST_STANDARD_CLEAR_FEATURE) &&
+                                (transfer->setupPacket->bmRequestType == USB_REQUEST_TYPE_RECIPIENT_ENDPOINT) &&
+                                ((USB_SHORT_FROM_LITTLE_ENDIAN(transfer->setupPacket->wValue) & 0x00FFu) ==
+                                 USB_REQUEST_STANDARD_FEATURE_SELECTOR_ENDPOINT_HALT))
+                            {
+                                ehciClearPipePointer = ehciInstance->ehciRunningPipeList;
+                                while (ehciClearPipePointer != NULL)
+                                {
+                                    /* only compute bulk and interrupt pipe */
+                                    if (((ehciClearPipePointer->pipeCommon.endpointAddress |
+                                          (ehciClearPipePointer->pipeCommon.direction
+                                           << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT)) ==
+                                         (uint8_t)(USB_SHORT_FROM_LITTLE_ENDIAN(transfer->setupPacket->wIndex))) &&
+                                        (ehciClearPipePointer->pipeCommon.deviceHandle ==
+                                         ehciPipePointer->pipeCommon.deviceHandle))
+                                    {
+                                        break;
+                                    }
+                                    ehciClearPipePointer =
+                                        (usb_host_ehci_pipe_t *)ehciClearPipePointer->pipeCommon.next;
+                                }
+
+                                if ((ehciClearPipePointer != NULL) &&
+                                    ((ehciClearPipePointer->pipeCommon.pipeType == USB_ENDPOINT_INTERRUPT) ||
+                                     (ehciClearPipePointer->pipeCommon.pipeType == USB_ENDPOINT_BULK)))
+                                {
+                                    ((volatile usb_host_ehci_qh_t *)(ehciClearPipePointer->ehciQh))
+                                        ->transferOverlayResults[0] &= (~EHCI_HOST_QTD_DT_MASK);
+                                }
+                            }
+                            transfer->callbackFn(transfer->callbackParam, transfer,
+                                                 kStatus_USB_Success); /* transfer success */
+                        }
+                    }
+                    else if ((!(vltQhPointer->transferOverlayResults[0] & EHCI_HOST_QTD_STATUS_ACTIVE_MASK)) &&
+                             (vltQhPointer->transferOverlayResults[0] &
+                              EHCI_HOST_QH_STATUS_ERROR_MASK)) /* there is error and transfer is done */
+                    {
+                        qtdStatus = (vltQhPointer->transferOverlayResults[0] & EHCI_HOST_QH_STATUS_ERROR_MASK);
+                        vltQtdPointer = (volatile usb_host_ehci_qtd_t *)(vltQhPointer->currentQtdPointer);
+
+                        if (((uint32_t)vltQtdPointer & EHCI_HOST_T_INVALID_VALUE) ||
+                            (vltQtdPointer == NULL)) /* the error status is unreasonable */
+                        {
+                            vltQhPointer->transferOverlayResults[0] &=
+                                (~EHCI_HOST_QTD_STATUS_MASK); /* clear error status */
+                        }
+                        else
+                        {
+                            /* remove qtd from qh */
+                            while ((vltQtdPointer != NULL) && (!(vltQtdPointer->transferResults[0] &
+                                                                 EHCI_HOST_QTD_IOC_MASK))) /* find the IOC qtd */
+                            {
+                                vltQtdPointer = (volatile usb_host_ehci_qtd_t *)vltQtdPointer->nextQtdPointer;
+                            }
+
+                            vltQhPointer->nextQtdPointer = EHCI_HOST_T_INVALID_VALUE;
+                            vltQhPointer->currentQtdPointer = EHCI_HOST_T_INVALID_VALUE;
+                            vltQhPointer->transferOverlayResults[0] &=
+                                (~EHCI_HOST_QTD_STATUS_MASK); /* clear error status */
+                            if (vltQtdPointer != NULL)
+                            {
+                                vltQhPointer->nextQtdPointer = vltQtdPointer->nextQtdPointer;
+                            }
+
+                            transfer->transferSofar = USB_HostEhciQtdListRelease(
+                                ehciInstance, (usb_host_ehci_qtd_t *)(transfer->union1.unitHead),
+                                (usb_host_ehci_qtd_t *)(transfer->union2.unitTail));
+                            transfer->transferSofar = (transfer->transferLength < transfer->transferSofar) ?
+                                                          0 :
+                                                          (transfer->transferLength - transfer->transferSofar);
+                            vltQhPointer->ehciTransferHead = transfer->next;
+                            vltQhPointer->timeOutLabel = 0;
+                            vltQhPointer->timeOutValue = USB_HOST_EHCI_CONTROL_BULK_TIME_OUT_VALUE;
+                            if (qtdStatus & EHCI_HOST_QH_STATUS_NOSTALL_ERROR_MASK)
+                            {
+                                transfer->callbackFn(transfer->callbackParam, transfer,
+                                                     kStatus_USB_TransferFailed); /* transfer fail */
+                            }
+                            else
+                            {
+                                transfer->callbackFn(transfer->callbackParam, transfer,
+                                                     kStatus_USB_TransferStall); /* transfer stall */
+                            }
+                        }
+                    }
+                    else
+                    {
+                        break;
+                    }
+                    transfer = nextTransfer;
+                }
+                break;
+#if (((defined USB_HOST_CONFIG_EHCI_MAX_ITD) && (USB_HOST_CONFIG_EHCI_MAX_ITD)) || \
+     ((defined USB_HOST_CONFIG_EHCI_MAX_SITD) && (USB_HOST_CONFIG_EHCI_MAX_SITD)))
+            case USB_ENDPOINT_ISOCHRONOUS:
+                qtdStatus = 0; /* qtdStatus means break here, because there is only one break in while for misra */
+                isoPointer = (usb_host_ehci_iso_t *)ehciPipePointer->ehciQh; /* pipe's usb_host_ehci_iso_t */
+                transfer = isoPointer->ehciTransferHead;                     /* usb_host_ehci_iso_t's transfer */
+                while (transfer != NULL)
+                {
+                    nextTransfer = transfer->next;
+                    USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle,
+                                                           kUSB_HostGetDeviceSpeed, &speed);
+                    if (speed == USB_SPEED_HIGH)
+                    {
+#if ((defined USB_HOST_CONFIG_EHCI_MAX_ITD) && (USB_HOST_CONFIG_EHCI_MAX_ITD))
+                        vltItdPointer =
+                            (volatile usb_host_ehci_itd_t *)(transfer->union2.unitTail); /* transfer's last itd */
+                        for (index = 0; index < 8; ++index)
+                        {
+                            if (vltItdPointer->transactions[index] & EHCI_HOST_ITD_STATUS_ACTIVE_MASK)
+                            {
+                                break;
+                            }
+                        }
+                        if (index == 8) /* transfer is done */
+                        {
+                            /* remove itd from frame list and release itd */
+                            dataLength = USB_HostEhciItdArrayRelease(ehciInstance,
+                                                                     (usb_host_ehci_itd_t *)transfer->union1.unitHead,
+                                                                     (usb_host_ehci_itd_t *)transfer->union2.unitTail);
+                            transfer->transferSofar = dataLength;
+                            isoPointer->ehciTransferHead = transfer->next;
+                            transfer->callbackFn(transfer->callbackParam, transfer,
+                                                 kStatus_USB_Success); /* transfer callback success */
+                            /* TODO: iso callback error */
+                        }
+                        else
+                        {
+                            qtdStatus = 1; /* break */
+                        }
+#endif
+                    }
+                    else
+                    {
+#if ((defined USB_HOST_CONFIG_EHCI_MAX_SITD) && (USB_HOST_CONFIG_EHCI_MAX_SITD))
+                        vltSitdPointer =
+                            (volatile usb_host_ehci_sitd_t *)(transfer->union2.unitTail); /* transfer's last sitd */
+                        if (!(vltSitdPointer->transferResults[0] &
+                              EHCI_HOST_SITD_STATUS_ACTIVE_MASK)) /* transfer is done */
+                        {
+                            /* remove sitd from frame list and release itd */
+                            dataLength = USB_HostEhciSitdArrayRelease(
+                                ehciInstance, (usb_host_ehci_sitd_t *)transfer->union1.unitHead,
+                                (usb_host_ehci_sitd_t *)transfer->union2.unitTail);
+                            transfer->transferSofar = dataLength;
+                            isoPointer->ehciTransferHead = transfer->next;
+                            transfer->callbackFn(transfer->callbackParam, transfer,
+                                                 kStatus_USB_Success); /* transfer callback success */
+                            /* TODO: iso callback error */
+                        }
+                        else
+                        {
+                            qtdStatus = 1; /* break */
+                        }
+#endif
+                    }
+                    if (qtdStatus == 1)
+                    {
+                        break;
+                    }
+                    transfer = nextTransfer;
+                }
+                break;
+#endif
+
+            default:
+                break;
+        }
+        ehciPipePointer = (usb_host_ehci_pipe_t *)ehciPipePointer->pipeCommon.next;
+    }
+}
+
+static void USB_HostEhciPortChange(usb_host_ehci_instance_t *ehciInstance)
+{
+    /* note: only has one port */
+    uint32_t portScRegister = ehciInstance->ehciIpBase->PORTSC1;
+    int32_t sofStart = 0;
+    int32_t sofCount = 0;
+    uint32_t index;
+
+    if (portScRegister & USBHS_PORTSC1_CSC_MASK) /* connection status change */
+    {
+        sofStart = (int32_t)(ehciInstance->ehciIpBase->FRINDEX & EHCI_MAX_UFRAME_VALUE);
+
+        /* process CSC bit */
+        while (1)
+        {
+            portScRegister = ehciInstance->ehciIpBase->PORTSC1;
+            if (portScRegister & USBHS_PORTSC1_CSC_MASK)
+            {
+                /* clear csc bit */
+                portScRegister = ehciInstance->ehciIpBase->PORTSC1;
+                portScRegister &= (~EHCI_PORTSC1_W1_BITS);
+                ehciInstance->ehciIpBase->PORTSC1 = (portScRegister | USBHS_PORTSC1_CSC_MASK);
+            }
+            sofCount = (int32_t)(ehciInstance->ehciIpBase->FRINDEX & EHCI_MAX_UFRAME_VALUE);
+            if (((sofCount - sofStart + EHCI_MAX_UFRAME_VALUE + 1) & EHCI_MAX_UFRAME_VALUE) >
+                (1 * 8)) /* delay 1ms to clear CSC */
+            {
+                break;
+            }
+        }
+    }
+
+    /* process CCS bit */
+    portScRegister = ehciInstance->ehciIpBase->PORTSC1;
+    if (portScRegister & USBHS_PORTSC1_CCS_MASK) /* process attach */
+    {
+        if ((ehciInstance->deviceAttached == kEHCIDevicePhyAttached) ||
+            (ehciInstance->deviceAttached == kEHCIDeviceAttached))
+        {
+            return;
+        }
+#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
+        ehciInstance->busSuspendStatus = kBus_EhciIdle;
+        ehciInstance->ehciIpBase->USBINTR &= ~(USBHS_USBINTR_TIE1_MASK);
+#endif
+        for (index = 0; index < USB_HOST_EHCI_PORT_CONNECT_DEBOUNCE_DELAY; ++index)
+        {
+            USB_HostEhciDelay(ehciInstance->ehciIpBase, 1);
+            if (!(ehciInstance->ehciIpBase->PORTSC1 & USBHS_PORTSC1_CCS_MASK))
+            {
+                break;
+            }
+        }
+        if (index < USB_HOST_EHCI_PORT_CONNECT_DEBOUNCE_DELAY) /* CCS is cleared */
+        {
+            ehciInstance->deviceAttached = kEHCIDeviceDetached;
+            return;
+        }
+        /* reset port */
+        portScRegister = ehciInstance->ehciIpBase->PORTSC1;
+        portScRegister &= (~EHCI_PORTSC1_W1_BITS);
+        ehciInstance->ehciIpBase->PORTSC1 = (portScRegister | USBHS_PORTSC1_PR_MASK);
+        while (ehciInstance->ehciIpBase->PORTSC1 & USBHS_PORTSC1_PR_MASK)
+        {
+        }
+        ehciInstance->firstDeviceSpeed =
+            ((ehciInstance->ehciIpBase->PORTSC1 & USBHS_PORTSC1_PSPD_MASK) >> USBHS_PORTSC1_PSPD_SHIFT);
+        /* enable ehci phy disconnection */
+        if (ehciInstance->firstDeviceSpeed == USB_SPEED_HIGH)
+        {
+            USB_EhcihostPhyDisconnectDetectCmd(ehciInstance->controllerId, 1);
+        }
+
+        /* wait for reset */
+        USB_HostEhciDelay(ehciInstance->ehciIpBase, USB_HOST_EHCI_PORT_RESET_DELAY);
+        /* process attach */
+        USB_OsaEventSet(ehciInstance->taskEventHandle, EHCI_TASK_EVENT_DEVICE_ATTACH);
+        /* gpt timer start */
+        ehciInstance->ehciIpBase->GPTIMER0CTL |=
+            (USBHS_GPTIMER0CTL_RUN_MASK | USBHS_GPTIMER0CTL_MODE_MASK | USBHS_GPTIMER0CTL_RST_MASK);
+        ehciInstance->deviceAttached = kEHCIDevicePhyAttached;
+    }
+    else
+    {
+        if ((ehciInstance->deviceAttached == kEHCIDevicePhyAttached) ||
+            (ehciInstance->deviceAttached == kEHCIDeviceAttached))
+        {
+#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
+            ehciInstance->busSuspendStatus = kBus_EhciIdle;
+            ehciInstance->ehciIpBase->USBINTR &= ~(USBHS_USBINTR_TIE1_MASK);
+#endif
+            /* disable ehci phy disconnection */
+            USB_EhcihostPhyDisconnectDetectCmd(ehciInstance->controllerId, 0);
+            /* disable async and periodic */
+            USB_HostEhciStopAsync(ehciInstance);
+            USB_HostEhciStopPeriodic(ehciInstance);
+            USB_OsaEventSet(ehciInstance->taskEventHandle, EHCI_TASK_EVENT_DEVICE_DETACH);
+        }
+    }
+}
+
+static void USB_HostEhciTimer0(usb_host_ehci_instance_t *ehciInstance)
+{
+    volatile usb_host_ehci_qh_t *vltQhPointer;
+    volatile usb_host_ehci_qtd_t *vltQtdPointer;
+    usb_host_transfer_t *transfer;
+    uint32_t backValue;
+    volatile uint32_t *totalBytesAddress = NULL;
+    usb_host_ehci_pipe_t *ehciPipePointer = ehciInstance->ehciRunningPipeList;
+    uint8_t timeoutLabel;
+
+    while (ehciPipePointer != NULL)
+    {
+        switch (ehciPipePointer->pipeCommon.pipeType)
+        {
+            case USB_ENDPOINT_BULK:
+            case USB_ENDPOINT_CONTROL:
+                vltQhPointer = (volatile usb_host_ehci_qh_t *)ehciPipePointer->ehciQh; /* pipe's qh */
+                transfer = vltQhPointer->ehciTransferHead;                             /* qh's transfer */
+                if ((transfer != NULL))                                                /* there is transfering data */
+                {
+                    timeoutLabel = 0;
+                    if (ehciInstance->deviceAttached != kEHCIDeviceAttached)
+                    {
+                        vltQtdPointer = (volatile usb_host_ehci_qtd_t *)transfer->union2.unitTail;
+
+                        vltQhPointer->nextQtdPointer = EHCI_HOST_T_INVALID_VALUE; /* invalid next qtd */
+                        vltQhPointer->transferOverlayResults[0] &=
+                            (~EHCI_HOST_QTD_STATUS_MASK); /* clear error status */
+                        timeoutLabel = 1;
+                    }
+                    else
+                    {
+                        if (vltQhPointer->transferOverlayResults[0] & EHCI_HOST_QTD_STATUS_ACTIVE_MASK)
+                        {
+                            vltQtdPointer = (volatile usb_host_ehci_qtd_t *)vltQhPointer->currentQtdPointer;
+                            totalBytesAddress = &(vltQhPointer->transferOverlayResults[0]);
+                        }
+                        else
+                        {
+                            vltQtdPointer = (volatile usb_host_ehci_qtd_t *)transfer->union2.unitTail;
+                            totalBytesAddress = ((uint32_t *)vltQtdPointer + 2);
+                        }
+
+                        backValue =
+                            (((*totalBytesAddress) & EHCI_HOST_QTD_TOTAL_BYTES_MASK) >>
+                             EHCI_HOST_QTD_TOTAL_BYTES_SHIFT);       /* backValue is used for total bytes to transfer */
+                        if (vltQhPointer->timeOutLabel != backValue) /* use total bytes to reflect the time out */
+                        {
+                            vltQhPointer->timeOutValue = USB_HOST_EHCI_CONTROL_BULK_TIME_OUT_VALUE;
+                            vltQhPointer->timeOutLabel = backValue;
+                        }
+                        else
+                        {
+                            /* time out when the total bytes don't change for the duration
+                             * USB_HOST_EHCI_CONTROL_BULK_TIME_OUT_VALUE
+                             */
+                            (vltQhPointer->timeOutValue)--;
+                            if (vltQhPointer->timeOutValue == 0)
+                            {
+                                /* stop the qh schedule */
+                                USB_HostEhciStopAsync(ehciInstance);
+                                if (backValue != (((*totalBytesAddress) & EHCI_HOST_QTD_TOTAL_BYTES_MASK) >>
+                                                  EHCI_HOST_QTD_TOTAL_BYTES_SHIFT))
+                                {
+                                    USB_HostEhciStartAsync(ehciInstance);
+                                }
+                                else
+                                {
+                                    vltQhPointer->nextQtdPointer = EHCI_HOST_T_INVALID_VALUE; /* invalid next qtd */
+                                    vltQhPointer->transferOverlayResults[0] &=
+                                        (~EHCI_HOST_QTD_STATUS_MASK); /* clear error status */
+                                    USB_HostEhciStartAsync(ehciInstance);
+                                    timeoutLabel = 1;
+                                }
+                            }
+                        }
+                    }
+
+                    if (timeoutLabel == 1)
+                    {
+                        /* remove qtd from qh */
+                        while ((vltQtdPointer != NULL) &&
+                               (!(vltQtdPointer->transferResults[0] & EHCI_HOST_QTD_IOC_MASK)) &&
+                               (vltQtdPointer != (usb_host_ehci_qtd_t *)vltQhPointer->ehciTransferTail))
+                        {
+                            vltQtdPointer = (volatile usb_host_ehci_qtd_t *)vltQtdPointer->nextQtdPointer;
+                        }
+                        if ((vltQtdPointer != NULL) && (!(vltQtdPointer->nextQtdPointer & EHCI_HOST_T_INVALID_VALUE)))
+                        {
+                            vltQhPointer->nextQtdPointer =
+                                vltQtdPointer->nextQtdPointer; /* start qh if there are other qtd that don't belong to
+                                                                  the transfer */
+                        }
+                        transfer->transferSofar =
+                            USB_HostEhciQtdListRelease(ehciInstance, (usb_host_ehci_qtd_t *)(transfer->union1.unitHead),
+                                                       (usb_host_ehci_qtd_t *)(transfer->union2.unitTail));
+                        transfer->transferSofar = (transfer->transferLength < transfer->transferSofar) ?
+                                                      0 :
+                                                      (transfer->transferLength - transfer->transferSofar);
+
+                        vltQhPointer->ehciTransferHead = transfer->next;
+                        vltQhPointer->timeOutValue = USB_HOST_EHCI_CONTROL_BULK_TIME_OUT_VALUE;
+                        transfer->callbackFn(transfer->callbackParam, transfer, kStatus_USB_TransferFailed);
+                    }
+                }
+                break;
+            default:
+                break;
+        }
+        ehciPipePointer = (usb_host_ehci_pipe_t *)ehciPipePointer->pipeCommon.next;
+    }
+}
+
+#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
+static void USB_HostEhciTimer1(usb_host_ehci_instance_t *ehciInstance)
+{
+    if (ehciInstance->deviceAttached != kEHCIDeviceDetached)
+    {
+        if (kBus_EhciStartSuspend == ehciInstance->busSuspendStatus)
+        {
+            usb_host_instance_t *hostPointer = (usb_host_instance_t *)ehciInstance->hostHandle;
+
+            if (0 == ehciInstance->matchTick)
+            {
+                ehciInstance->matchTick = hostPointer->hwTick;
+            }
+            else
+            {
+                if ((hostPointer->hwTick - ehciInstance->matchTick) >= 5)
+                {
+                    ehciInstance->ehciIpBase->USBCMD &= ~USBHS_USBCMD_RS_MASK;
+                    ehciInstance->ehciIpBase->USBSTS |= USBHS_USBSTS_SRI_MASK;
+#if (defined(FSL_FEATURE_SOC_USBNC_COUNT) && (FSL_FEATURE_SOC_USBNC_COUNT > 0U))
+#if 0
+                    ehciInstance->registerPhyBase->CTRL |= USBPHY_CTRL_ENVBUSCHG_WKUP_MASK
+                                                      | USBPHY_CTRL_ENIDCHG_WKUP_MASK
+                                                      | USBPHY_CTRL_ENDPDMCHG_WKUP_MASK
+                                                      | USBPHY_CTRL_ENIRQRESUMEDETECT_MASK
+                                                      ;
+#endif
+#endif
+                    ehciInstance->ehciIpBase->PORTSC1 |= USBHS_PORTSC1_PHCD_MASK;
+
+                    ehciInstance->registerPhyBase->PWD = 0xFFFFFFFFU;
+
+                    while (ehciInstance->registerPhyBase->CTRL & (USBPHY_CTRL_UTMI_SUSPENDM_MASK))
+                    {
+                        __ASM("nop");
+                    }
+
+#if (defined(FSL_FEATURE_SOC_USBNC_COUNT) && (FSL_FEATURE_SOC_USBNC_COUNT > 0U))
+                    ehciInstance->registerNcBase->USB_OTGn_CTRL |= USBNC_USB_OTGn_CTRL_WKUP_ID_EN_MASK |
+                                                                   USBNC_USB_OTGn_CTRL_WKUP_VBUS_EN_MASK |
+                                                                   USBNC_USB_OTGn_CTRL_WKUP_DPDM_EN_MASK;
+                    ehciInstance->registerNcBase->USB_OTGn_CTRL |= USBNC_USB_OTGn_CTRL_WIE_MASK;
+#else
+                    ehciInstance->ehciIpBase->USBGENCTRL = USBHS_USBGENCTRL_WU_IE_MASK;
+#endif
+                    ehciInstance->registerPhyBase->CTRL |= USBPHY_CTRL_CLKGATE_MASK;
+                    hostPointer->deviceCallback(hostPointer->suspendedDevice, NULL,
+                                                kUSB_HostEventSuspended); /* call host callback function */
+                    ehciInstance->busSuspendStatus = kBus_EhciSuspended;
+                }
+            }
+        }
+        else if (kBus_EhciStartResume == ehciInstance->busSuspendStatus)
+        {
+            usb_host_instance_t *hostPointer = (usb_host_instance_t *)ehciInstance->hostHandle;
+            if (!(ehciInstance->ehciIpBase->PORTSC1 & USBHS_PORTSC1_FPR_MASK))
+            {
+                ehciInstance->ehciIpBase->PORTSC1 &= ~USBHS_PORTSC1_WKDS_MASK;
+                if (ehciInstance->ehciIpBase->PORTSC1 & USBHS_PORTSC1_CCS_MASK)
+                {
+                    USB_HostEhciStartAsync(ehciInstance);
+                    USB_HostEhciStartPeriodic(ehciInstance);
+                }
+                hostPointer->deviceCallback(hostPointer->suspendedDevice, NULL,
+                                            kUSB_HostEventResumed); /* call host callback function */
+                hostPointer->suspendedDevice = NULL;
+                ehciInstance->busSuspendStatus = kBus_EhciIdle;
+                ehciInstance->ehciIpBase->USBINTR &= ~(USBHS_USBINTR_TIE1_MASK);
+            }
+        }
+        else
+        {
+        }
+    }
+    else
+    {
+        ehciInstance->busSuspendStatus = kBus_EhciIdle;
+        ehciInstance->ehciIpBase->USBINTR &= ~(USBHS_USBINTR_TIE1_MASK);
+    }
+}
+#endif
+
+usb_status_t USB_HostEhciCreate(uint8_t controllerId,
+                                usb_host_handle upperLayerHandle,
+                                usb_host_controller_handle *controllerHandle)
+{
+    uint32_t index = 0;
+    usb_osa_status_t osaStatus;
+    usb_host_ehci_instance_t *ehciInstance;
+    uint32_t usbhsBaseAddrs[] = USBHS_BASE_ADDRS;
+    usb_host_ehci_data_t *usbHostEhciData[] = USB_HOST_EHCI_DATA_ARRAY;
+    uint8_t *usbHostEhciFrameList[] = USB_HOST_EHCI_FRAME_LIST_ARRAY;
+    uint32_t *framePointer;
+
+    if ((uint32_t)(controllerId - kUSB_ControllerEhci0) >= (sizeof(usbhsBaseAddrs) / sizeof(usbhsBaseAddrs[0])))
+    {
+        return kStatus_USB_ControllerNotFound;
+    }
+
+    *controllerHandle = NULL;
+    ehciInstance = (usb_host_ehci_instance_t *)USB_OsaMemoryAllocate(
+        sizeof(usb_host_ehci_instance_t)); /* malloc host ehci instance */
+    if (ehciInstance == NULL)
+    {
+        return kStatus_USB_AllocFail;
+    }
+    ehciInstance->controllerId = controllerId;
+    ehciInstance->hostHandle = upperLayerHandle;
+    ehciInstance->deviceAttached = kEHCIDeviceDetached;
+    ehciInstance->ehciIpBase = (USBHS_Type *)
+        usbhsBaseAddrs[controllerId - kUSB_ControllerEhci0]; /* operate ehci ip through the base address */
+#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
+    ehciInstance->busSuspendStatus = kBus_EhciIdle;
+
+#if (defined(USB_HOST_CONFIG_LOW_POWER_MODE) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
+    ehciInstance->registerPhyBase = (USBPHY_Type *)USB_EhciPhyGetBase(controllerId);
+
+#if (defined(FSL_FEATURE_SOC_USBNC_COUNT) && (FSL_FEATURE_SOC_USBNC_COUNT > 0U))
+    ehciInstance->registerNcBase = (USBNC_Type *)USB_EhciNCGetBase(controllerId);
+#endif
+
+#endif
+
+#endif
+
+    if (USB_HostEhciResetIP(ehciInstance) != kStatus_USB_Success) /* reset ehci ip */
+    {
+        USB_OsaMemoryFree(ehciInstance);
+        return kStatus_USB_Error;
+    }
+
+    /* initialize ehci frame list */
+    ehciInstance->ehciFrameList = usbHostEhciFrameList[ehciInstance->controllerId - kUSB_ControllerEhci0];
+
+    /* initialize ehci units */
+    ehciInstance->ehciUnitBase = (uint32_t *)(usbHostEhciData[ehciInstance->controllerId - kUSB_ControllerEhci0]);
+    /* initialize qh/qtd/itd/sitd/iso list */
+    ehciInstance->ehciQhList = (usb_host_ehci_qh_t *)((uint32_t)(ehciInstance->ehciUnitBase));
+    ehciInstance->ehciQtdHead = (usb_host_ehci_qtd_t *)((uint32_t)ehciInstance->ehciQhList +
+                                                        (sizeof(usb_host_ehci_qh_t) * USB_HOST_CONFIG_EHCI_MAX_QH));
+    ehciInstance->ehciItdList = (usb_host_ehci_itd_t *)((uint32_t)ehciInstance->ehciQtdHead +
+                                                        (sizeof(usb_host_ehci_qtd_t) * USB_HOST_CONFIG_EHCI_MAX_QTD));
+    ehciInstance->ehciSitdList = ehciInstance->ehciSitdIndexBase =
+        (usb_host_ehci_sitd_t *)((uint32_t)ehciInstance->ehciItdList +
+                                 (sizeof(usb_host_ehci_itd_t) * USB_HOST_CONFIG_EHCI_MAX_ITD));
+    ehciInstance->ehciIsoList = (usb_host_ehci_iso_t *)((uint32_t)ehciInstance->ehciSitdList +
+                                                        (sizeof(usb_host_ehci_sitd_t) * USB_HOST_CONFIG_EHCI_MAX_SITD));
+    ehciInstance->ehciPipeIndexBase =
+        (usb_host_ehci_pipe_t *)((uint32_t)ehciInstance->ehciIsoList +
+                                 (sizeof(usb_host_ehci_iso_t) * USB_HOST_EHCI_ISO_NUMBER));
+    for (index = 1; index < USB_HOST_CONFIG_EHCI_MAX_QH; ++index)
+    {
+        ehciInstance->ehciQhList[index - 1].horizontalLinkPointer = (uint32_t)(&ehciInstance->ehciQhList[index]);
+    }
+    ehciInstance->ehciQhList[USB_HOST_CONFIG_EHCI_MAX_QH - 1].horizontalLinkPointer = (uint32_t)NULL;
+    for (index = 1; index < USB_HOST_CONFIG_EHCI_MAX_QTD; ++index)
+    {
+        ehciInstance->ehciQtdHead[index - 1].nextQtdPointer = (uint32_t)(&ehciInstance->ehciQtdHead[index]);
+    }
+    ehciInstance->ehciQtdNumber = USB_HOST_CONFIG_EHCI_MAX_QTD;
+    ehciInstance->ehciQtdHead[USB_HOST_CONFIG_EHCI_MAX_QTD - 1].nextQtdPointer = (uint32_t)NULL;
+    ehciInstance->ehciQtdTail = &ehciInstance->ehciQtdHead[USB_HOST_CONFIG_EHCI_MAX_QTD - 1];
+
+#if ((defined USB_HOST_CONFIG_EHCI_MAX_ITD) && (USB_HOST_CONFIG_EHCI_MAX_ITD))
+    for (index = 1; index < USB_HOST_CONFIG_EHCI_MAX_ITD; ++index)
+    {
+        ehciInstance->ehciItdList[index - 1].nextLinkPointer = (uint32_t)(&ehciInstance->ehciItdList[index]);
+    }
+    ehciInstance->ehciItdNumber = USB_HOST_CONFIG_EHCI_MAX_ITD;
+    ehciInstance->ehciItdList[USB_HOST_CONFIG_EHCI_MAX_ITD - 1].nextLinkPointer = (uint32_t)NULL;
+#endif /* USB_HOST_CONFIG_EHCI_MAX_ITD */
+
+#if ((defined USB_HOST_CONFIG_EHCI_MAX_SITD) && (USB_HOST_CONFIG_EHCI_MAX_SITD))
+    for (index = 1; index < USB_HOST_CONFIG_EHCI_MAX_SITD; ++index)
+    {
+        ehciInstance->ehciSitdList[index - 1].nextLinkPointer = (uint32_t)(&ehciInstance->ehciSitdList[index]);
+    }
+    ehciInstance->ehciSitdNumber = USB_HOST_CONFIG_EHCI_MAX_SITD;
+    ehciInstance->ehciSitdList[USB_HOST_CONFIG_EHCI_MAX_SITD - 1].nextLinkPointer = (uint32_t)NULL;
+#endif /* USB_HOST_CONFIG_EHCI_MAX_SITD */
+
+#if ((defined USB_HOST_CONFIG_EHCI_MAX_ITD) && (USB_HOST_CONFIG_EHCI_MAX_ITD))
+    for (index = 1; index < USB_HOST_EHCI_ISO_NUMBER; ++index)
+    {
+        ehciInstance->ehciIsoList[index - 1].next = &ehciInstance->ehciIsoList[index];
+    }
+    ehciInstance->ehciIsoList[USB_HOST_EHCI_ISO_NUMBER - 1].next = NULL;
+#endif
+
+    /* initialize pipes */
+    ehciInstance->ehciPipeList = ehciInstance->ehciPipeIndexBase;
+    for (index = 1; index < USB_HOST_CONFIG_MAX_PIPES; ++index)
+    {
+        ehciInstance->ehciPipeList[index - 1].pipeCommon.next = (usb_host_pipe_t *)&ehciInstance->ehciPipeList[index];
+    }
+    /* initialize mutext */
+    osaStatus = USB_OsaMutexCreate(&ehciInstance->ehciMutex);
+    if (osaStatus != kStatus_USB_OSA_Success)
+    {
+#ifdef HOST_ECHO
+        usb_echo("ehci mutex init fail\r\n");
+#endif
+        USB_OsaMemoryFree(ehciInstance);
+        return kStatus_USB_Error;
+    }
+    /* initialize task event */
+    osaStatus = USB_OsaEventCreate(&ehciInstance->taskEventHandle, 1);
+    if (osaStatus != kStatus_USB_OSA_Success)
+    {
+#ifdef HOST_ECHO
+        usb_echo("ehci event init fail\r\n");
+#endif
+        USB_OsaMutexDestroy(ehciInstance->ehciMutex);
+        USB_OsaMemoryFree(ehciInstance);
+        return kStatus_USB_Error;
+    }
+
+    /* initialize first qh */
+    ehciInstance->shedFirstQh = ehciInstance->ehciQhList;
+    ehciInstance->ehciQhList =
+        (usb_host_ehci_qh_t *)(ehciInstance->ehciQhList->horizontalLinkPointer & EHCI_HOST_POINTER_ADDRESS_MASK);
+    ehciInstance->shedFirstQh->staticEndpointStates[0] |= (1 << EHCI_HOST_QH_H_SHIFT); /* first qh */
+    ehciInstance->shedFirstQh->horizontalLinkPointer = EHCI_HOST_T_INVALID_VALUE;
+    ehciInstance->shedFirstQh->currentQtdPointer = EHCI_HOST_T_INVALID_VALUE;
+    ehciInstance->shedFirstQh->nextQtdPointer = EHCI_HOST_T_INVALID_VALUE;
+    ehciInstance->shedFirstQh->alternateNextQtdPointer = EHCI_HOST_T_INVALID_VALUE;
+    ehciInstance->shedFirstQh->horizontalLinkPointer =
+        (uint32_t)((uint32_t)(ehciInstance->shedFirstQh) | EHCI_HOST_POINTER_TYPE_QH);
+
+    /* initialize periodic list */
+    framePointer = (uint32_t *)ehciInstance->ehciFrameList;
+    for (index = 0; index < USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE; ++index)
+    {
+        framePointer[index] = EHCI_HOST_T_INVALID_VALUE;
+    }
+
+    USB_HostEhciStartIP(ehciInstance); /* start ehci ip */
+
+    *controllerHandle = ehciInstance;
+
+    return kStatus_USB_Success;
+}
+
+usb_status_t USB_HostEhciDestory(usb_host_controller_handle controllerHandle)
+{
+    usb_host_ehci_instance_t *ehciInstance = (usb_host_ehci_instance_t *)controllerHandle;
+
+    /* disable all interrupts */
+    ehciInstance->ehciIpBase->USBINTR = 0;
+    /* stop the controller */
+    ehciInstance->ehciIpBase->USBCMD = 0;
+    /* free memory */
+    USB_OsaMutexDestroy(ehciInstance->ehciMutex);
+    USB_OsaEventDestroy(ehciInstance->taskEventHandle);
+    USB_OsaMemoryFree(ehciInstance);
+
+    return kStatus_USB_Success;
+}
+
+usb_status_t USB_HostEhciOpenPipe(usb_host_controller_handle controllerHandle,
+                                  usb_host_pipe_handle *pipeHandle,
+                                  usb_host_pipe_init_t *pipeInit)
+{
+    usb_host_ehci_pipe_t *ehciPipePointer = NULL;
+    usb_status_t status;
+    uint32_t speed;
+    usb_host_ehci_instance_t *ehciInstance = (usb_host_ehci_instance_t *)controllerHandle;
+
+    /* get one pipe */
+    USB_HostEhciLock();
+    if (ehciInstance->ehciPipeList != NULL)
+    {
+        ehciPipePointer = ehciInstance->ehciPipeList;
+        ehciInstance->ehciPipeList = (usb_host_ehci_pipe_t *)ehciPipePointer->pipeCommon.next;
+    }
+    USB_HostEhciUnlock();
+    if (ehciPipePointer == NULL)
+    {
+#ifdef HOST_ECHO
+        usb_echo("ehci open pipe failed\r\n");
+#endif
+        return kStatus_USB_Busy;
+    }
+
+    /* initialize pipe informations */
+    USB_HostEhciZeroMem((uint32_t *)ehciPipePointer, sizeof(usb_host_ehci_pipe_t) / 4);
+    ehciPipePointer->pipeCommon.deviceHandle = pipeInit->devInstance;
+    ehciPipePointer->pipeCommon.endpointAddress = pipeInit->endpointAddress;
+    ehciPipePointer->pipeCommon.direction = pipeInit->direction;
+    ehciPipePointer->pipeCommon.interval = pipeInit->interval;
+    ehciPipePointer->pipeCommon.maxPacketSize = pipeInit->maxPacketSize;
+    ehciPipePointer->pipeCommon.pipeType = pipeInit->pipeType;
+    ehciPipePointer->pipeCommon.numberPerUframe = pipeInit->numberPerUframe;
+    if (ehciPipePointer->pipeCommon.numberPerUframe == 0)
+    {
+        ehciPipePointer->pipeCommon.numberPerUframe = 1;
+    }
+    ehciPipePointer->pipeCommon.nakCount = pipeInit->nakCount;
+    ehciPipePointer->pipeCommon.nextdata01 = 0;
+    ehciPipePointer->ehciQh = NULL;
+    USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetDeviceSpeed, &speed);
+    if (ehciPipePointer->pipeCommon.pipeType == USB_ENDPOINT_ISOCHRONOUS)
+    {
+        ehciPipePointer->pipeCommon.interval =
+            (1 << (ehciPipePointer->pipeCommon.interval - 1)); /* iso interval is the power of 2 */
+    }
+    else if (ehciPipePointer->pipeCommon.pipeType == USB_ENDPOINT_INTERRUPT)
+    {
+        if (speed == USB_SPEED_HIGH)
+        {
+            ehciPipePointer->pipeCommon.interval =
+                (1 << (ehciPipePointer->pipeCommon.interval - 1)); /* HS interrupt interval is the power of 2 */
+        }
+        else
+        {
+            ehciPipePointer->pipeCommon.interval = USB_HostEhciGet2PowerValue(
+                ehciPipePointer->pipeCommon
+                    .interval); /* FS/LS interrupt interval should be the power of 2, it is used for ehci bandwidth */
+        }
+    }
+    else
+    {
+    }
+
+    /* save the micro-frame interval, it is convenient for the interval process */
+    if (speed == USB_SPEED_HIGH)
+    {
+        ehciPipePointer->uframeInterval = ehciPipePointer->pipeCommon.interval;
+    }
+    else
+    {
+        ehciPipePointer->uframeInterval = 8 * ehciPipePointer->pipeCommon.interval;
+    }
+
+    /* open pipe */
+    switch (ehciPipePointer->pipeCommon.pipeType)
+    {
+        case USB_ENDPOINT_CONTROL:
+        case USB_ENDPOINT_BULK:
+            status = USB_HostEhciOpenControlBulk(ehciInstance, ehciPipePointer);
+            break;
+
+#if (((defined USB_HOST_CONFIG_EHCI_MAX_ITD) && (USB_HOST_CONFIG_EHCI_MAX_ITD)) || \
+     ((defined USB_HOST_CONFIG_EHCI_MAX_SITD) && (USB_HOST_CONFIG_EHCI_MAX_SITD)))
+        case USB_ENDPOINT_ISOCHRONOUS:
+            status = USB_HostEhciOpenIso(ehciInstance, ehciPipePointer);
+            break;
+#endif
+
+        case USB_ENDPOINT_INTERRUPT:
+            status = USB_HostEhciOpenInterrupt(ehciInstance, ehciPipePointer);
+            break;
+
+        default:
+            status = kStatus_USB_Error;
+            break;
+    }
+
+    if (status != kStatus_USB_Success)
+    {
+        /* release pipe */
+        USB_HostEhciLock();
+        ehciPipePointer->pipeCommon.next = (usb_host_pipe_t *)ehciInstance->ehciPipeList;
+        ehciInstance->ehciPipeList = ehciPipePointer;
+        USB_HostEhciUnlock();
+        return status;
+    }
+
+    /* add pipe to run pipe list */
+    USB_HostEhciLock();
+    ehciPipePointer->pipeCommon.next = (usb_host_pipe_t *)ehciInstance->ehciRunningPipeList;
+    ehciInstance->ehciRunningPipeList = ehciPipePointer;
+    USB_HostEhciUnlock();
+
+    *pipeHandle = ehciPipePointer;
+    return status;
+}
+
+usb_status_t USB_HostEhciClosePipe(usb_host_controller_handle controllerHandle, usb_host_pipe_handle pipeHandle)
+{
+    usb_host_ehci_instance_t *ehciInstance = (usb_host_ehci_instance_t *)controllerHandle;
+    usb_host_ehci_pipe_t *ehciPipePointer = (usb_host_ehci_pipe_t *)pipeHandle;
+    usb_host_pipe_t *prevPointer = NULL;
+
+    switch (ehciPipePointer->pipeCommon.pipeType)
+    {
+        case USB_ENDPOINT_BULK:
+        case USB_ENDPOINT_CONTROL:
+            USB_HostEhciCloseControlBulk(ehciInstance, ehciPipePointer);
+            break;
+
+        case USB_ENDPOINT_INTERRUPT:
+            USB_HostEhciCloseInterrupt(ehciInstance, ehciPipePointer);
+            break;
+
+#if (((defined USB_HOST_CONFIG_EHCI_MAX_ITD) && (USB_HOST_CONFIG_EHCI_MAX_ITD)) || \
+     ((defined USB_HOST_CONFIG_EHCI_MAX_SITD) && (USB_HOST_CONFIG_EHCI_MAX_SITD)))
+        case USB_ENDPOINT_ISOCHRONOUS:
+            USB_HostEhciCloseIso(ehciInstance, ehciPipePointer);
+            break;
+#endif
+
+        default:
+            break;
+    }
+
+    /* delete pipe from run pipe list */
+    USB_HostEhciLock();
+    prevPointer = (usb_host_pipe_t *)ehciInstance->ehciRunningPipeList;
+    if (prevPointer == (usb_host_pipe_t *)ehciPipePointer)
+    {
+        ehciInstance->ehciRunningPipeList = (usb_host_ehci_pipe_t *)(prevPointer->next);
+    }
+    else
+    {
+        while (prevPointer != NULL)
+        {
+            if (prevPointer->next == (usb_host_pipe_t *)ehciPipePointer)
+            {
+                prevPointer->next = ehciPipePointer->pipeCommon.next;
+                break;
+            }
+            else
+            {
+                prevPointer = prevPointer->next;
+            }
+        }
+    }
+    USB_HostEhciUnlock();
+
+    /* release pipe */
+    USB_HostEhciLock();
+    ehciPipePointer->pipeCommon.next = (usb_host_pipe_t *)ehciInstance->ehciPipeList;
+    ehciInstance->ehciPipeList = ehciPipePointer;
+    USB_HostEhciUnlock();
+
+    return kStatus_USB_Success;
+}
+
+usb_status_t USB_HostEhciWritePipe(usb_host_controller_handle controllerHandle,
+                                   usb_host_pipe_handle pipeHandle,
+                                   usb_host_transfer_t *transfer)
+{
+    usb_host_ehci_instance_t *ehciInstance = (usb_host_ehci_instance_t *)controllerHandle;
+    usb_host_ehci_pipe_t *ehciPipePointer = (usb_host_ehci_pipe_t *)pipeHandle;
+    usb_status_t status = kStatus_USB_Success;
+#if (((defined USB_HOST_CONFIG_EHCI_MAX_ITD) && (USB_HOST_CONFIG_EHCI_MAX_ITD)) || \
+     ((defined USB_HOST_CONFIG_EHCI_MAX_SITD) && (USB_HOST_CONFIG_EHCI_MAX_SITD)))
+    uint32_t speed;
+#endif
+
+    switch (ehciPipePointer->pipeCommon.pipeType)
+    {
+        case USB_ENDPOINT_BULK:
+        case USB_ENDPOINT_CONTROL:
+        case USB_ENDPOINT_INTERRUPT:
+            status = USB_HostEhciQhQtdListInit(ehciInstance, ehciPipePointer,
+                                               transfer); /* initialize qtd for control/bulk transfer */
+            break;
+
+#if (((defined USB_HOST_CONFIG_EHCI_MAX_ITD) && (USB_HOST_CONFIG_EHCI_MAX_ITD)) || \
+     ((defined USB_HOST_CONFIG_EHCI_MAX_SITD) && (USB_HOST_CONFIG_EHCI_MAX_SITD)))
+        case USB_ENDPOINT_ISOCHRONOUS:
+            USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetDeviceSpeed,
+                                                   &speed);
+            if (speed == USB_SPEED_HIGH)
+            {
+#if ((defined USB_HOST_CONFIG_EHCI_MAX_ITD) && (USB_HOST_CONFIG_EHCI_MAX_ITD))
+                status = USB_HostEhciItdArrayInit(ehciInstance, ehciPipePointer,
+                                                  transfer); /* initialize itd for iso transfer */
+#endif
+            }
+            else
+            {
+#if ((defined USB_HOST_CONFIG_EHCI_MAX_SITD) && (USB_HOST_CONFIG_EHCI_MAX_SITD))
+                status = USB_HostEhciSitdArrayInit(ehciInstance, ehciPipePointer,
+                                                   transfer); /* initialize sitd for iso transfer */
+#endif
+            }
+            break;
+#endif
+
+        default:
+            break;
+    }
+    return status;
+}
+
+usb_status_t USB_HostEhciReadpipe(usb_host_controller_handle controllerHandle,
+                                  usb_host_pipe_handle pipeHandle,
+                                  usb_host_transfer_t *transfer)
+{
+    return USB_HostEhciWritePipe(controllerHandle, pipeHandle, transfer); /* same as write */
+}
+
+usb_status_t USB_HostEhciIoctl(usb_host_controller_handle controllerHandle, uint32_t ioctlEvent, void *ioctlParam)
+{
+    usb_status_t status = kStatus_USB_Success;
+    usb_host_ehci_instance_t *ehciInstance = (usb_host_ehci_instance_t *)controllerHandle;
+    usb_host_cancel_param_t *param;
+    usb_host_ehci_pipe_t *ehciPipePointer;
+    volatile usb_host_ehci_qh_t *vltQhPointer;
+    uint32_t deviceAddress;
+
+    if (controllerHandle == NULL)
+    {
+        return kStatus_USB_InvalidHandle;
+    }
+
+    switch (ioctlEvent)
+    {
+        case kUSB_HostCancelTransfer: /* cancel pipe or one transfer */
+            param = (usb_host_cancel_param_t *)ioctlParam;
+            status = USB_HostEhciCancelPipe(ehciInstance, (usb_host_ehci_pipe_t *)param->pipeHandle, param->transfer);
+            break;
+
+        case kUSB_HostBusControl: /* bus control */
+            status = USB_HostEhciControlBus(ehciInstance, *((uint8_t *)ioctlParam));
+            break;
+
+        case kUSB_HostGetFrameNumber: /* get frame number */
+            *((uint32_t *)ioctlParam) = ((ehciInstance->ehciIpBase->FRINDEX & EHCI_MAX_UFRAME_VALUE) >> 3);
+            break;
+
+        case kUSB_HostUpdateControlEndpointAddress:
+            ehciPipePointer = (usb_host_ehci_pipe_t *)ioctlParam;
+            vltQhPointer = (volatile usb_host_ehci_qh_t *)ehciPipePointer->ehciQh;
+            /* update address */
+            USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetDeviceAddress,
+                                                   &deviceAddress);
+            vltQhPointer->staticEndpointStates[0] |= deviceAddress;
+            break;
+
+        case kUSB_HostUpdateControlPacketSize:
+            ehciPipePointer = (usb_host_ehci_pipe_t *)ioctlParam;
+            vltQhPointer = (volatile usb_host_ehci_qh_t *)ehciPipePointer->ehciQh;
+            USB_HostEhciLock();
+            if (ehciInstance->ehciIpBase->USBSTS & USBHS_USBSTS_AS_MASK)
+            {
+                USB_HostEhciStopAsync(ehciInstance);
+                /* update max packet size */
+                vltQhPointer->staticEndpointStates[0] =
+                    (((vltQhPointer->staticEndpointStates[0]) & (~EHCI_HOST_QH_MAX_PACKET_LENGTH_MASK)) |
+                     ((uint32_t)ehciPipePointer->pipeCommon.maxPacketSize << EHCI_HOST_QH_MAX_PACKET_LENGTH_SHIFT));
+                USB_HostEhciStartAsync(ehciInstance);
+            }
+            else
+            {
+                /* update max packet size */
+                vltQhPointer->staticEndpointStates[0] =
+                    (((vltQhPointer->staticEndpointStates[0]) & (~EHCI_HOST_QH_MAX_PACKET_LENGTH_MASK)) |
+                     ((uint32_t)ehciPipePointer->pipeCommon.maxPacketSize << EHCI_HOST_QH_MAX_PACKET_LENGTH_SHIFT));
+            }
+            USB_HostEhciUnlock();
+            break;
+
+        default:
+            break;
+    }
+    return status;
+}
+
+void USB_HostEhciTaskFunction(void *hostHandle)
+{
+    usb_host_ehci_instance_t *ehciInstance;
+    uint32_t bitSet;
+    usb_device_handle deviceHandle;
+
+    if (hostHandle == NULL)
+    {
+        return;
+    }
+    ehciInstance = (usb_host_ehci_instance_t *)((usb_host_instance_t *)hostHandle)->controllerHandle;
+
+    if (USB_OsaEventWait(ehciInstance->taskEventHandle, 0xFF, 0, 0, &bitSet) ==
+        kStatus_USB_OSA_Success) /* wait all event */
+    {
+        if (bitSet & EHCI_TASK_EVENT_PORT_CHANGE) /* port change */
+        {
+            USB_HostEhciPortChange(ehciInstance);
+        }
+
+        if (bitSet & EHCI_TASK_EVENT_TIMER0) /* timer0 */
+        {
+            USB_HostEhciTimer0(ehciInstance);
+        }
+
+#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
+        if (bitSet & EHCI_TASK_EVENT_TIMER1) /* timer1 */
+        {
+            USB_HostEhciTimer1(ehciInstance);
+        }
+#endif
+
+        if (ehciInstance->deviceAttached == kEHCIDeviceAttached)
+        {
+            if (bitSet & EHCI_TASK_EVENT_TRANSACTION_DONE) /* transaction done */
+            {
+                USB_HostEhciTransactionDone(ehciInstance);
+            }
+
+            if (bitSet & EHCI_TASK_EVENT_DEVICE_DETACH) /* device detach */
+            {
+                ehciInstance->ehciIpBase->USBINTR &=
+                    (~USBHS_USBINTR_PCE_MASK); /* disable attach, enable when the detach process is done */
+                ehciInstance->deviceAttached = kEHCIDeviceDetached;
+                USB_HostDetachDevice(ehciInstance->hostHandle, 0, 0);
+            }
+        }
+        else if (ehciInstance->deviceAttached != kEHCIDeviceAttached)
+        {
+            if (bitSet & EHCI_TASK_EVENT_DEVICE_ATTACH) /* device is attached */
+            {
+                USB_HostEhciStartAsync(ehciInstance);
+                USB_HostEhciStartPeriodic(ehciInstance);
+
+                if (USB_HostAttachDevice(ehciInstance->hostHandle, ehciInstance->firstDeviceSpeed, 0, 0, 1,
+                                         &deviceHandle) == kStatus_USB_Success)
+                {
+                    ehciInstance->deviceAttached = kEHCIDeviceAttached;
+                }
+            }
+        }
+        else
+        {
+        }
+    }
+}
+
+void USB_HostEhciIsrFunction(void *hostHandle)
+{
+    usb_host_ehci_instance_t *ehciInstance;
+    static uint32_t interruptStatus = 0;
+
+    if (hostHandle == NULL)
+    {
+        return;
+    }
+
+    ehciInstance = (usb_host_ehci_instance_t *)((usb_host_instance_t *)hostHandle)->controllerHandle;
+
+#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
+
+#if (defined(FSL_FEATURE_SOC_USBNC_COUNT) && (FSL_FEATURE_SOC_USBNC_COUNT > 0U))
+    if (ehciInstance->registerNcBase->USB_OTGn_CTRL & USBNC_USB_OTGn_CTRL_WIE_MASK)
+    {
+        usb_host_instance_t *hostPointer = (usb_host_instance_t *)ehciInstance->hostHandle;
+        ehciInstance->registerNcBase->USB_OTGn_CTRL &= ~USBNC_USB_OTGn_CTRL_WIE_MASK;
+        hostPointer->deviceCallback(hostPointer->suspendedDevice, NULL,
+                                    kUSB_HostEventDetectResume); /* call host callback function */
+
+        while (!(ehciInstance->registerNcBase->USB_OTGn_PHY_CTRL_0 & USBNC_USB_OTGn_PHY_CTRL_0_UTMI_CLK_VLD_MASK))
+        {
+        }
+
+        if (ehciInstance->ehciIpBase->PORTSC1 & USBHS_PORTSC1_CCS_MASK)
+        {
+            USB_HostEhciStartAsync(ehciInstance);
+            USB_HostEhciStartPeriodic(ehciInstance);
+        }
+        ehciInstance->ehciIpBase->USBCMD |= (USBHS_USBCMD_RS_MASK);
+        if ((kBus_EhciSuspended == ehciInstance->busSuspendStatus))
+        {
+            /* ehciInstance->ehciIpBase->PORTSC1 |= USBHS_PORTSC1_FPR_MASK; */
+            ehciInstance->busSuspendStatus = kBus_EhciStartResume;
+        }
+        else
+        {
+        }
+    }
+    else
+    {
+    }
+#else
+    if (ehciInstance->ehciIpBase->USBGENCTRL & USBHS_USBGENCTRL_WU_IE_MASK)
+    {
+        usb_host_instance_t *hostPointer = (usb_host_instance_t *)ehciInstance->hostHandle;
+
+        hostPointer->deviceCallback(hostPointer->suspendedDevice, NULL,
+                                    kUSB_HostEventDetectResume); /* call host callback function */
+
+        while (!(USBPHY->PLL_SIC & USBPHY_PLL_SIC_PLL_LOCK_MASK))
+        {
+        }
+        ehciInstance->ehciIpBase->USBGENCTRL |= USBHS_USBGENCTRL_WU_INT_CLR_MASK;
+        ehciInstance->ehciIpBase->USBGENCTRL &= ~USBHS_USBGENCTRL_WU_IE_MASK;
+        if (ehciInstance->ehciIpBase->PORTSC1 & USBHS_PORTSC1_CCS_MASK)
+        {
+            USB_HostEhciStartAsync(ehciInstance);
+            USB_HostEhciStartPeriodic(ehciInstance);
+        }
+        ehciInstance->ehciIpBase->USBCMD |= (USBHS_USBCMD_RS_MASK);
+        if ((kBus_EhciSuspended == ehciInstance->busSuspendStatus))
+        {
+            ehciInstance->busSuspendStatus = kBus_EhciStartResume;
+            /*ehciInstance->ehciIpBase->PORTSC1 |= USBHS_PORTSC1_FPR_MASK; */
+        }
+        else
+        {
+        }
+    }
+    else
+    {
+    }
+#endif /* FSL_FEATURE_SOC_USBNC_COUNT */
+
+#endif /* USB_HOST_CONFIG_LOW_POWER_MODE */
+
+    interruptStatus = ehciInstance->ehciIpBase->USBSTS;
+    interruptStatus &= ehciInstance->ehciIpBase->USBINTR;
+    while (interruptStatus) /* there are usb interrupts */
+    {
+        ehciInstance->ehciIpBase->USBSTS = interruptStatus; /* clear interrupt */
+
+        if (interruptStatus & USBHS_USBSTS_SRI_MASK) /* SOF interrupt */
+        {
+        }
+
+        if (interruptStatus & USBHS_USBSTS_SEI_MASK) /* system error interrupt */
+        {
+        }
+
+        if ((interruptStatus & USBHS_USBSTS_UI_MASK) ||
+            (interruptStatus & USBHS_USBSTS_UEI_MASK)) /* USB interrupt or USB error interrupt */
+        {
+            USB_OsaEventSet(ehciInstance->taskEventHandle, EHCI_TASK_EVENT_TRANSACTION_DONE);
+        }
+
+        if (interruptStatus & USBHS_USBSTS_PCI_MASK) /* port change detect interrupt */
+        {
+#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
+            usb_host_instance_t *hostPointer = (usb_host_instance_t *)ehciInstance->hostHandle;
+            if (ehciInstance->ehciIpBase->PORTSC1 & USBHS_PORTSC1_FPR_MASK)
+            {
+                if (kBus_EhciStartSuspend == ehciInstance->busSuspendStatus)
+                {
+                    if (ehciInstance->ehciIpBase->PORTSC1 & USBHS_PORTSC1_CCS_MASK)
+                    {
+                        USB_HostEhciStartAsync(ehciInstance);
+                        USB_HostEhciStartPeriodic(ehciInstance);
+                    }
+                    hostPointer->deviceCallback(hostPointer->suspendedDevice, NULL,
+                                                kUSB_HostEventNotSuspended); /* call host callback function */
+                    hostPointer->suspendedDevice = NULL;
+                    ehciInstance->busSuspendStatus = kBus_EhciIdle;
+                    ehciInstance->ehciIpBase->USBINTR &= ~(USBHS_USBINTR_TIE1_MASK);
+                }
+                else
+                {
+                }
+            }
+#endif
+            USB_OsaEventSet(ehciInstance->taskEventHandle, EHCI_TASK_EVENT_PORT_CHANGE);
+        }
+
+        if (interruptStatus & USBHS_USBSTS_TI0_MASK) /* timer 0 interrupt */
+        {
+            USB_OsaEventSet(ehciInstance->taskEventHandle, EHCI_TASK_EVENT_TIMER0);
+        }
+
+#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
+        if (interruptStatus & USBHS_USBSTS_TI1_MASK) /* timer 1 interrupt */
+        {
+            USB_OsaEventSet(ehciInstance->taskEventHandle, EHCI_TASK_EVENT_TIMER1);
+        }
+#endif
+
+        interruptStatus = ehciInstance->ehciIpBase->USBSTS;
+        interruptStatus &= ehciInstance->ehciIpBase->USBINTR;
+    }
+}
+
+#endif /* USB_HOST_CONFIG_EHCI */

+ 499 - 0
bsp/imxrt1052-evk/drivers/usb/host/usb_host_ehci.h

@@ -0,0 +1,499 @@
+/*
+ * Copyright (c) 2015, Freescale Semiconductor, Inc.
+ * Copyright 2016 NXP
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright notice, this list
+ *   of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright notice, this
+ *   list of conditions and the following disclaimer in the documentation and/or
+ *   other materials provided with the distribution.
+ *
+ * o Neither the name of the copyright holder nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _USB_HOST_CONTROLLER_EHCI_H_
+#define _USB_HOST_CONTROLLER_EHCI_H_
+
+/*******************************************************************************
+ * KHCI private public structures, enumerations, macros, functions
+ ******************************************************************************/
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+/* EHCI host macros */
+#define EHCI_HOST_T_INVALID_VALUE (1U)
+#define EHCI_HOST_POINTER_TYPE_ITD (0x00U)
+#define EHCI_HOST_POINTER_TYPE_QH (0x00000002U)
+#define EHCI_HOST_POINTER_TYPE_SITD (0x00000004U)
+#define EHCI_HOST_POINTER_TYPE_FSTN (0x00000006U)
+#define EHCI_HOST_POINTER_TYPE_MASK (0x00000006U)
+#define EHCI_HOST_POINTER_ADDRESS_MASK (0xFFFFFFE0U)
+#define EHCI_HOST_PID_OUT (0U)
+#define EHCI_HOST_PID_IN (1U)
+#define EHCI_HOST_PID_SETUP (2U)
+
+#define EHCI_HOST_QH_RL_SHIFT (28U)
+#define EHCI_HOST_QH_RL_MASK (0xF0000000U)
+#define EHCI_HOST_QH_C_SHIFT (27U)
+#define EHCI_HOST_QH_MAX_PACKET_LENGTH_SHIFT (16U)
+#define EHCI_HOST_QH_MAX_PACKET_LENGTH_MASK (0x07FF0000U)
+#define EHCI_HOST_QH_H_SHIFT (15U)
+#define EHCI_HOST_QH_DTC_SHIFT (14U)
+#define EHCI_HOST_QH_EPS_SHIFT (12U)
+#define EHCI_HOST_QH_ENDPT_SHIFT (8U)
+#define EHCI_HOST_QH_I_SHIFT (7U)
+#define EHCI_HOST_QH_DEVICE_ADDRESS_SHIFT (0U)
+#define EHCI_HOST_QH_MULT_SHIFT (30U)
+#define EHCI_HOST_QH_PORT_NUMBER_SHIFT (23U)
+#define EHCI_HOST_QH_HUB_ADDR_SHIFT (16U)
+#define EHCI_HOST_QH_UFRAME_CMASK_SHIFT (8U)
+#define EHCI_HOST_QH_UFRAME_SMASK_SHIFT (0U)
+#define EHCI_HOST_QH_STATUS_ERROR_MASK (0x0000007EU)
+#define EHCI_HOST_QH_STATUS_NOSTALL_ERROR_MASK (0x0000003EU)
+
+#define EHCI_HOST_QTD_DT_SHIFT (31U)
+#define EHCI_HOST_QTD_DT_MASK (0x80000000U)
+#define EHCI_HOST_QTD_TOTAL_BYTES_SHIFT (16U)
+#define EHCI_HOST_QTD_TOTAL_BYTES_MASK (0x7FFF0000U)
+#define EHCI_HOST_QTD_IOC_MASK (0x00008000U)
+#define EHCI_HOST_QTD_C_PAGE_SHIFT (12U)
+#define EHCI_HOST_QTD_CERR_SHIFT (10U)
+#define EHCI_HOST_QTD_CERR_MAX_VALUE (0x00000003U)
+#define EHCI_HOST_QTD_PID_CODE_SHIFT (8U)
+#define EHCI_HOST_QTD_STATUS_SHIFT (0U)
+#define EHCI_HOST_QTD_CURRENT_OFFSET_MASK (0x00000FFFU)
+#define EHCI_HOST_QTD_BUFFER_POINTER_SHIFT (12U)
+#define EHCI_HOST_QTD_STATUS_ACTIVE_MASK (0x00000080U)
+#define EHCI_HOST_QTD_STATUS_MASK (0x000000ffU)
+#define EHCI_HOST_QTD_STATUS_ERROR_MASK (0x0000007EU)
+#define EHCI_HOST_QTD_STATUS_STALL_ERROR_MASK (0x00000040U)
+
+#define EHCI_HOST_ITD_STATUS_ACTIVE_MASK (0x80000000U)
+#define EHCI_HOST_ITD_TRANSACTION_LEN_SHIFT (16U)
+#define EHCI_HOST_ITD_TRANSACTION_LEN_MASK (0x0FFF0000U)
+#define EHCI_HOST_ITD_IOC_SHIFT (15U)
+#define EHCI_HOST_ITD_PG_SHIFT (12U)
+#define EHCI_HOST_ITD_TRANSACTION_OFFSET_SHIFT (0U)
+#define EHCI_HOST_ITD_TRANSACTION_OFFSET_MASK (0x00000FFFU)
+#define EHCI_HOST_ITD_BUFFER_POINTER_SHIFT (12U)
+#define EHCI_HOST_ITD_ENDPT_SHIFT (8U)
+#define EHCI_HOST_ITD_DEVICE_ADDRESS_SHIFT (0U)
+#define EHCI_HOST_ITD_MAX_PACKET_SIZE_SHIFT (0U)
+#define EHCI_HOST_ITD_MULT_SHIFT (0U)
+#define EHCI_HOST_ITD_DIRECTION_SHIFT (11U)
+
+#define EHCI_HOST_SITD_STATUS_ACTIVE_MASK (0x00000080U)
+#define EHCI_HOST_SITD_DIRECTION_SHIFT (31U)
+#define EHCI_HOST_SITD_PORT_NUMBER_SHIFT (24U)
+#define EHCI_HOST_SITD_HUB_ADDR_SHIFT (16U)
+#define EHCI_HOST_SITD_ENDPT_SHIFT (8U)
+#define EHCI_HOST_SITD_DEVICE_ADDRESS_SHIFT (0U)
+#define EHCI_HOST_SITD_CMASK_SHIFT (8U)
+#define EHCI_HOST_SITD_SMASK_SHIFT (0U)
+#define EHCI_HOST_SITD_TOTAL_BYTES_SHIFT (16U)
+#define EHCI_HOST_SITD_TOTAL_BYTES_MASK (0x03FF0000U)
+#define EHCI_HOST_SITD_TP_SHIFT (3U)
+#define EHCI_HOST_SITD_TCOUNT_SHIFT (0U)
+#define EHCI_HOST_SITD_IOC_SHIFT (31U)
+
+/* register related MACROs */
+#define EHCI_PORTSC1_W1_BITS (0x0000002AU)
+#define EHCI_MAX_UFRAME_VALUE (0x00003FFFU)
+
+/* task event */
+#define EHCI_TASK_EVENT_DEVICE_ATTACH (0x01U)
+#define EHCI_TASK_EVENT_TRANSACTION_DONE (0x02U)
+#define EHCI_TASK_EVENT_DEVICE_DETACH (0x04U)
+#define EHCI_TASK_EVENT_PORT_CHANGE (0x08U)
+#define EHCI_TASK_EVENT_TIMER0 (0x10U)
+#define EHCI_TASK_EVENT_TIMER1 (0x20U)
+
+#define USB_HostEhciLock() USB_OsaMutexLock(ehciInstance->ehciMutex)
+#define USB_HostEhciUnlock() USB_OsaMutexUnlock(ehciInstance->ehciMutex)
+
+/*******************************************************************************
+ * KHCI driver public structures, enumerations, macros, functions
+ ******************************************************************************/
+
+/*!
+ * @addtogroup usb_host_controller_ehci
+ * @{
+ */
+
+/*! @brief The maximum supported ISO pipe number */
+#define USB_HOST_EHCI_ISO_NUMBER USB_HOST_CONFIG_EHCI_MAX_ITD
+/*! @brief Check the port connect state delay if the state is unstable */
+#define USB_HOST_EHCI_PORT_CONNECT_DEBOUNCE_DELAY (101U)
+/*! @brief Delay for port reset */
+#define USB_HOST_EHCI_PORT_RESET_DELAY (11U)
+/*! @brief The SITD inserts a frame interval for putting more SITD continuously.
+ * There is an interval when an application sends two FS/LS ISO transfers.
+ * When the interval is less than the macro, the two transfers are continuous in the frame list. Otherwise, the two
+ * transfers
+ * are not continuous.
+ * For example:
+ * - Use case 1: when inserting the SITD first, the inserted frame = the current frame value + this MACRO value.
+ * - Use case 2: when inserting SITD is not first, choose between the last inserted frame value and the
+ * current frame value according to the following criteria:
+ *           If the interval is less than the MACRO value, the new SITD is continuous with the last SITD.
+ *           If not, the new SITD inserting frame = the current frame value + this MACRO value.
+ */
+#define USB_HOST_EHCI_ISO_BOUNCE_FRAME_NUMBER (2U)
+/*! @brief The ITD inserts a micro-frame interval for putting more ITD continuously.
+ * There is an interval when an application sends two HS ISO transfers.
+ * When the interval is less than the macro, the two transfers are continuous in the frame list. Otherwise, the two
+ * transfers
+ * are not continuous.
+ * For example:
+ * - Use case 1: when inserting ITD first, the inserted micro-frame = the current micro-frame value + this MACRO value.
+ * - Use case 2: when inserting ITD is not first, choose between the last inserted micro-frame value and the
+ * current micro-frame value according to the following criteria:
+ *           If the interval is less than this MACRO value, the new ITD is continuous with the last ITD.
+ *           If not, the new ITD inserting micro-frame = the current micro-frame value + this MACRO value.
+ */
+#define USB_HOST_EHCI_ISO_BOUNCE_UFRAME_NUMBER (16U)
+/*! @brief Control or bulk transaction timeout value (unit: 100 ms) */
+#define USB_HOST_EHCI_CONTROL_BULK_TIME_OUT_VALUE (20U)
+
+#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
+typedef enum _bus_ehci_suspend_request_state
+{
+    kBus_EhciIdle = 0U,
+    kBus_EhciStartSuspend,
+    kBus_EhciSuspended,
+    kBus_EhciStartResume,
+} bus_ehci_suspend_request_state_t;
+#endif
+
+/*! @brief EHCI state for device attachment/detachment. */
+typedef enum _host_ehci_device_state_
+{
+    kEHCIDevicePhyAttached = 1, /*!< Device is physically attached */
+    kEHCIDeviceAttached,        /*!< Device is attached and initialized */
+    kEHCIDeviceDetached,        /*!< Device is detached and de-initialized */
+} host_ehci_device_state_t;
+
+/*! @brief EHCI pipe structure */
+typedef struct _usb_host_ehci_pipe
+{
+    usb_host_pipe_t pipeCommon; /*!< Common pipe information */
+    void *ehciQh;               /*!< Control/bulk/interrupt: QH; ISO: usb_host_ehci_iso_t*/
+
+    /* bandwidth */
+    uint16_t uframeInterval;    /*!< Micro-frame interval value */
+    uint16_t startFrame;        /*!<
+                                     Bandwidth start frame: its value is from 0 to frame_list.
+                                 */
+    uint16_t dataTime;          /*!<
+                                     Bandwidth time value:
+                                     - When the host works as HS: it's the data bandwidth value.
+                                     - When the host works as FS/LS:
+                                         - For FS/LS device, it's the data bandwidth value when transferring the data by FS/LS.
+                                         - For HS device, it's the data bandwidth value when transferring the data by HS.
+                                 */
+    uint16_t startSplitTime;    /*!<
+                                      Start splitting the bandwidth time value:
+                                      - When the host works as HS, it is the start split bandwidth value.
+                                  */
+    uint16_t completeSplitTime; /*!<
+                                      Complete splitting the bandwidth time value:
+                                      - When host works as HS, it is the complete split bandwidth value.
+                                  */
+    uint8_t startUframe;        /*!<
+                                     Bandwidth start micro-frame: its value is from 0 to 7.
+                                 */
+    uint8_t uframeSmask;        /*!<
+                                     Start micro-frame.
+                                     - When host works as an HS:
+                                        - For FS/LS device, it's the interrupt or ISO transfer start-split mask.
+                                         - For HS device, it's the interrupt transfer start micro-frame mask.
+                                     - When host works as FS/LS, it's the interrupt and ISO start micro-frame mask
+                                 */
+    uint8_t uframeCmask;        /*!<
+                                     Complete micro-frame
+                                     - When host works as HS:
+                                         - For FS/LS device, it's the interrupt or ISO transfer complete-split mask.
+                                 */
+} usb_host_ehci_pipe_t;
+
+/*! @brief EHCI QH structure. See the USB EHCI specification */
+typedef struct _usb_host_ehci_qh
+{
+    uint32_t horizontalLinkPointer; /*!< QH specification filed, queue head a horizontal link pointer */
+    uint32_t
+        staticEndpointStates[2]; /*!< QH specification filed, static endpoint state and configuration information */
+    uint32_t currentQtdPointer;  /*!< QH specification filed, current qTD pointer */
+    uint32_t nextQtdPointer;     /*!< QH specification filed, next qTD pointer */
+    uint32_t alternateNextQtdPointer; /*!< QH specification filed, alternate next qTD pointer */
+    uint32_t
+        transferOverlayResults[6]; /*!< QH specification filed, transfer overlay configuration and transfer results */
+
+    /* reserved space */
+    usb_host_ehci_pipe_t *ehciPipePointer; /*!< EHCI pipe pointer */
+    usb_host_transfer_t *ehciTransferHead; /*!< Transfer list head on this QH */
+    usb_host_transfer_t *ehciTransferTail; /*!< Transfer list tail on this QH */
+    uint16_t timeOutValue; /*!< Its maximum value is USB_HOST_EHCI_CONTROL_BULK_TIME_OUT_VALUE. When the value is
+                                zero, the transfer times out. */
+    uint16_t timeOutLabel; /*!< It's used to judge the transfer timeout. The EHCI driver maintain the value */
+} usb_host_ehci_qh_t;
+
+/*! @brief EHCI QTD structure. See the USB EHCI specification. */
+typedef struct _usb_host_ehci_qtd
+{
+    uint32_t nextQtdPointer;          /*!< QTD specification filed, the next QTD pointer */
+    uint32_t alternateNextQtdPointer; /*!< QTD specification filed, alternate next QTD pointer */
+    uint32_t transferResults[2];      /*!< QTD specification filed, transfer results fields */
+    uint32_t bufferPointers[4];       /*!< QTD specification filed, transfer buffer fields */
+} usb_host_ehci_qtd_t;
+
+/*! @brief EHCI ITD structure. See the USB EHCI specification. */
+typedef struct _usb_host_ehci_itd
+{
+    uint32_t nextLinkPointer;   /*!< ITD specification filed, the next linker pointer */
+    uint32_t transactions[8];   /*!< ITD specification filed, transactions information */
+    uint32_t bufferPointers[7]; /*!< ITD specification filed, transfer buffer fields */
+
+    /* add space */
+    struct _usb_host_ehci_itd *nextItdPointer; /*!< Next ITD pointer */
+    uint32_t frameEntryIndex;                  /*!< The ITD inserted frame value */
+    uint32_t reserved[6];                      /*!< Reserved fields for 32 bytes align */
+} usb_host_ehci_itd_t;
+
+/*! @brief EHCI SITD structure. See the USB EHCI specification. */
+typedef struct _usb_host_ehci_sitd
+{
+    uint32_t nextLinkPointer;    /*!< SITD specification filed, the next linker pointer */
+    uint32_t endpointStates[2];  /*!< SITD specification filed, endpoint configuration information */
+    uint32_t transferResults[3]; /*!< SITD specification filed, transfer result fields */
+    uint32_t backPointer;        /*!< SITD specification filed, back pointer */
+
+    /* reserved space */
+    uint16_t frameEntryIndex; /*!< The SITD inserted frame value */
+    uint8_t nextSitdIndex;    /*!< The next SITD index; Get the next SITD pointer through adding base address with the
+                                 index. 0xFF means invalid. */
+    uint8_t reserved;         /*!< Reserved fields for 32 bytes align */
+} usb_host_ehci_sitd_t;
+
+/*! @brief EHCI ISO structure; An ISO pipe has an instance of this structure to keep the ISO pipe-specific information.
+ */
+typedef struct _usb_host_ehci_iso
+{
+    struct _usb_host_ehci_iso *next;       /*!< Next instance pointer */
+    usb_host_pipe_t *ehciPipePointer;      /*!< This ISO's EHCI pipe pointer */
+    usb_host_transfer_t *ehciTransferHead; /*!< Transfer list head on this ISO pipe */
+    usb_host_transfer_t *ehciTransferTail; /*!< Transfer list head on this ISO pipe */
+
+    uint16_t lastLinkFrame; /*!< It means that the inserted frame for ISO ITD/SITD. 0xFFFF is invalid. For ITD, it is a
+                               micro-frame value. For SITD, it is a frame value */
+} usb_host_ehci_iso_t;
+
+/*! @brief EHCI instance structure */
+typedef struct _usb_host_ehci_instance
+{
+    usb_host_handle hostHandle;                /*!< Related host handle*/
+    uint32_t *ehciUnitBase;                    /*!< Keep the QH/QTD/ITD/SITD buffer pointer for release*/
+    uint8_t *ehciFrameList;                    /*!< The frame list of the current ehci instance*/
+    usb_host_ehci_qh_t *ehciQhList;            /*!< Idle QH list pointer */
+    usb_host_ehci_qtd_t *ehciQtdHead;          /*!< Idle QTD list pointer head */
+    usb_host_ehci_qtd_t *ehciQtdTail;          /*!< Idle QTD list pointer tail (recently used qTD will be used)*/
+    usb_host_ehci_itd_t *ehciItdList;          /*!< Idle ITD list pointer*/
+    usb_host_ehci_sitd_t *ehciSitdIndexBase;   /*!< SITD buffer's start pointer*/
+    usb_host_ehci_sitd_t *ehciSitdList;        /*!< Idle SITD list pointer*/
+    usb_host_ehci_iso_t *ehciIsoList;          /*!< Idle ISO list pointer*/
+    USBHS_Type *ehciIpBase;                    /*!< EHCI IP base address*/
+    usb_host_ehci_qh_t *shedFirstQh;           /*!< First async QH*/
+    usb_host_ehci_pipe_t *ehciPipeIndexBase;   /*!< Pipe buffer's start pointer*/
+    usb_host_ehci_pipe_t *ehciPipeList;        /*!< Idle pipe list pointer*/
+    usb_host_ehci_pipe_t *ehciRunningPipeList; /*!< Running pipe list pointer*/
+    usb_osa_mutex_handle ehciMutex;            /*!< EHCI mutex*/
+    usb_osa_event_handle taskEventHandle;      /*!< EHCI task event*/
+#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
+    uint64_t matchTick;
+    USBPHY_Type *registerPhyBase; /*!< The base address of the PHY register */
+#if (defined(FSL_FEATURE_SOC_USBNC_COUNT) && (FSL_FEATURE_SOC_USBNC_COUNT > 0U))
+    USBNC_Type *registerNcBase; /*!< The base address of the USBNC register */
+#endif
+
+#endif
+    uint8_t controllerId;     /*!< EHCI controller ID*/
+    uint8_t deviceAttached;   /*!< Device attach/detach state, see #host_ehci_device_state_t */
+    uint8_t firstDeviceSpeed; /*!< The first device's speed, the controller's work speed*/
+    uint8_t ehciItdNumber;    /*!< Idle ITD number*/
+    uint8_t ehciSitdNumber;   /*!< Idle SITD number*/
+    uint8_t ehciQtdNumber;    /*!< Idle QTD number*/
+#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
+    bus_ehci_suspend_request_state_t busSuspendStatus; /*!< Bus Suspend Status*/
+#endif
+} usb_host_ehci_instance_t;
+
+/*! @brief EHCI data structure */
+typedef struct _usb_host_ehci_data
+{
+#if ((defined(USB_HOST_CONFIG_EHCI_MAX_QH)) && (USB_HOST_CONFIG_EHCI_MAX_QH > 0U))
+    usb_host_ehci_qh_t ehciQh[USB_HOST_CONFIG_EHCI_MAX_QH]; /*!< Idle QH list array*/
+#endif
+#if ((defined(USB_HOST_CONFIG_EHCI_MAX_QTD)) && (USB_HOST_CONFIG_EHCI_MAX_QTD > 0U))
+    usb_host_ehci_qtd_t ehciQtd[USB_HOST_CONFIG_EHCI_MAX_QTD]; /*!< Idle QTD list array*/
+#endif
+#if ((defined(USB_HOST_CONFIG_EHCI_MAX_ITD)) && (USB_HOST_CONFIG_EHCI_MAX_ITD > 0U))
+    usb_host_ehci_itd_t ehciItd[USB_HOST_CONFIG_EHCI_MAX_ITD]; /*!< Idle ITD list array*/
+#endif
+#if ((defined(USB_HOST_CONFIG_EHCI_MAX_SITD)) && (USB_HOST_CONFIG_EHCI_MAX_SITD > 0U))
+    usb_host_ehci_sitd_t ehciSitd[USB_HOST_CONFIG_EHCI_MAX_SITD]; /*!< Idle SITD list array*/
+#endif
+#if ((defined(USB_HOST_EHCI_ISO_NUMBER)) && (USB_HOST_EHCI_ISO_NUMBER > 0U))
+    usb_host_ehci_iso_t ehciIso[USB_HOST_EHCI_ISO_NUMBER]; /*!< Idle ISO list array*/
+#endif
+#if ((defined(USB_HOST_CONFIG_MAX_PIPES)) && (USB_HOST_CONFIG_MAX_PIPES > 0U))
+    usb_host_ehci_pipe_t ehciPipe[USB_HOST_CONFIG_MAX_PIPES]; /*!< Idle pipe list array*/
+#endif
+} usb_host_ehci_data_t;
+
+/*******************************************************************************
+ * API
+ ******************************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*!
+ * @name USB host EHCI APIs
+ * @{
+ */
+
+/*!
+ * @brief Creates the USB host EHCI instance.
+ *
+ * This function initializes the USB host EHCI controller driver.
+ *
+ * @param[in] controllerId      The controller ID of the USB IP. Please refer to the enumeration usb_controller_index_t.
+ * @param[in] upperLayerHandle  The host level handle.
+ * @param[out] controllerHandle return the controller instance handle.
+ *
+ * @retval kStatus_USB_Success              The host is initialized successfully.
+ * @retval kStatus_USB_AllocFail            Allocating memory failed.
+ * @retval kStatus_USB_Error                Host mutex create fail, KHCI/EHCI mutex or KHCI/EHCI event create fail.
+ *                                          Or, KHCI/EHCI IP initialize fail.
+ */
+extern usb_status_t USB_HostEhciCreate(uint8_t controllerId,
+                                       usb_host_handle upperLayerHandle,
+                                       usb_host_controller_handle *controllerHandle);
+
+/*!
+ * @brief Destroys the USB host EHCI instance.
+ *
+ * This function de-initializes The USB host EHCI controller driver.
+ *
+ * @param[in] controllerHandle  The controller handle.
+ *
+ * @retval kStatus_USB_Success              The host is initialized successfully.
+ */
+extern usb_status_t USB_HostEhciDestory(usb_host_controller_handle controllerHandle);
+
+/*!
+ * @brief Opens the USB host pipe.
+ *
+ * This function opens a pipe according to the pipe_init_ptr parameter.
+ *
+ * @param[in] controllerHandle The controller handle.
+ * @param[out] pipeHandle      The pipe handle pointer, it is used to return the pipe handle.
+ * @param[in] pipeInit         It is used to initialize the pipe.
+ *
+ * @retval kStatus_USB_Success              The host is initialized successfully.
+ * @retval kStatus_USB_Error                There is no idle pipe.
+ *                                          Or, there is no idle QH for EHCI.
+ *                                          Or, bandwidth allocate fail for EHCI.
+ */
+extern usb_status_t USB_HostEhciOpenPipe(usb_host_controller_handle controllerHandle,
+                                         usb_host_pipe_handle *pipeHandle,
+                                         usb_host_pipe_init_t *pipeInit);
+
+/*!
+ * @brief Closes the USB host pipe.
+ *
+ * This function closes a pipe and releases related resources.
+ *
+ * @param[in] controllerHandle The controller handle.
+ * @param[in] pipeHandle       The closing pipe handle.
+ *
+ * @retval kStatus_USB_Success              The host is initialized successfully.
+ */
+extern usb_status_t USB_HostEhciClosePipe(usb_host_controller_handle controllerHandle, usb_host_pipe_handle pipeHandle);
+
+/*!
+ * @brief Sends data to the pipe.
+ *
+ * This function requests to send the transfer to the specified pipe.
+ *
+ * @param[in] controllerHandle The controller handle.
+ * @param[in] pipeHandle       The sending pipe handle.
+ * @param[in] transfer          The transfer information.
+ *
+ * @retval kStatus_USB_Success              Sent successfully.
+ * @retval kStatus_USB_LackSwapBuffer       There is no swap buffer for KHCI.
+ * @retval kStatus_USB_Error                There is no idle QTD/ITD/SITD for EHCI.
+ */
+extern usb_status_t USB_HostEhciWritePipe(usb_host_controller_handle controllerHandle,
+                                          usb_host_pipe_handle pipeHandle,
+                                          usb_host_transfer_t *transfer);
+
+/*!
+ * @brief Receives data from the pipe.
+ *
+ * This function requests to receive the transfer from the specified pipe.
+ *
+ * @param[in] controllerHandle The controller handle.
+ * @param[in] pipeHandle       The receiving pipe handle.
+ * @param[in] transfer         The transfer information.
+
+ * @retval kStatus_USB_Success              Send successfully.
+ * @retval kStatus_USB_LackSwapBuffer       There is no swap buffer for KHCI.
+ * @retval kStatus_USB_Error                There is no idle QTD/ITD/SITD for EHCI.
+ */
+extern usb_status_t USB_HostEhciReadpipe(usb_host_controller_handle controllerHandle,
+                                         usb_host_pipe_handle pipeHandle,
+                                         usb_host_transfer_t *transfer);
+
+/*!
+ * @brief Controls the EHCI.
+ *
+ * This function controls the EHCI.
+ *
+ * @param[in] controllerHandle The controller handle.
+ * @param[in] ioctlEvent       See enumeration host_bus_control_t.
+ * @param[in] ioctlParam       The control parameter.
+ *
+ * @retval kStatus_USB_Success              Cancel successfully.
+ * @retval kStatus_USB_InvalidHandle        The controllerHandle is a NULL pointer.
+ */
+extern usb_status_t USB_HostEhciIoctl(usb_host_controller_handle controllerHandle,
+                                      uint32_t ioctlEvent,
+                                      void *ioctlParam);
+
+/*! @}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+/*! @}*/
+
+#endif /* _USB_HOST_CONTROLLER_EHCI_H_ */

+ 1052 - 0
bsp/imxrt1052-evk/drivers/usb/host/usb_host_hci.c

@@ -0,0 +1,1052 @@
+/*
+ * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
+ * Copyright 2016 NXP
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright notice, this list
+ *   of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright notice, this
+ *   list of conditions and the following disclaimer in the documentation and/or
+ *   other materials provided with the distribution.
+ *
+ * o Neither the name of the copyright holder nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <usb/include/usb_device_config.h>
+#include "fsl_common.h"
+#include "usb_host.h"
+#include "usb_host_hci.h"
+#include "usb_host_devices.h"
+#include "fsl_device_registers.h"
+#if ((defined USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE))
+#include "fsl_cache.h"
+#endif
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/*******************************************************************************
+ * Prototypes
+ ******************************************************************************/
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+
+extern uint32_t USB_HostHubGetTotalThinkTime(usb_host_handle hostHandle, uint8_t parentHubNo);
+
+extern usb_status_t USB_HostHubSuspendDevice(usb_host_handle hostHandle);
+
+extern usb_status_t USB_HostHubResumeDevice(usb_host_handle hostHandle);
+#endif
+
+/*!
+ * @brief get the idle host instance.
+ *
+ * @return  host instance pointer.
+ */
+static usb_host_instance_t *USB_HostGetInstance(void);
+
+/*!
+ * @brief release host instance.
+ *
+ * @param hostInstance  host instance pointer.
+ */
+static void USB_HostReleaseInstance(usb_host_instance_t *hostInstance);
+
+/*!
+ * @brief get the khci/ehci interface.
+ *
+ * @param controllerId    controller id.
+ * @param controllerTable return controller interface structure.
+ */
+static void USB_HostGetControllerInterface(uint8_t controllerId,
+                                           const usb_host_controller_interface_t **controllerTable);
+
+#if ((defined USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST))
+#if ((defined USB_HOST_CONFIG_EHCI) && (USB_HOST_CONFIG_EHCI))
+extern void USB_HostEhciTestModeInit(usb_device_handle devHandle);
+#endif /* USB_HOST_CONFIG_COMPLIANCE_TEST */
+#if ((defined USB_HOST_CONFIG_IP3516HS) && (USB_HOST_CONFIG_IP3516HS))
+extern void USB_HostIp3516HsTestModeInit(usb_device_handle devHandle);
+#endif /* USB_HOST_CONFIG_COMPLIANCE_TEST */
+#endif /* USB_HOST_CONFIG_EHCI */
+
+/*******************************************************************************
+ * Variables
+ ******************************************************************************/
+/*! @brief USB host instance resource */
+usb_host_instance_t g_UsbHostInstance[USB_HOST_CONFIG_MAX_HOST];
+
+#if ((defined USB_HOST_CONFIG_EHCI) && (USB_HOST_CONFIG_EHCI))
+#include "usb_host_ehci.h"
+static const usb_host_controller_interface_t s_EhciInterface = \
+{
+    USB_HostEhciCreate,    USB_HostEhciDestory,  USB_HostEhciOpenPipe, USB_HostEhciClosePipe,
+    USB_HostEhciWritePipe, USB_HostEhciReadpipe, USB_HostEhciIoctl,
+};
+#endif /* USB_HOST_CONFIG_EHCI */
+
+#if ((defined USB_HOST_CONFIG_KHCI) && (USB_HOST_CONFIG_KHCI))
+#include "usb_host_khci.h"
+static const usb_host_controller_interface_t s_KhciInterface = \
+{
+    USB_HostKhciCreate,    USB_HostKhciDestory,  USB_HostKhciOpenPipe, USB_HostKhciClosePipe,
+    USB_HostKhciWritePipe, USB_HostKhciReadpipe, USB_HostKciIoctl,
+};
+#endif /* USB_HOST_CONFIG_KHCI */
+
+#if ((defined USB_HOST_CONFIG_OHCI) && (USB_HOST_CONFIG_OHCI > 0U))
+#include "usb_host_ohci.h"
+static const usb_host_controller_interface_t s_OhciInterface = \
+{
+    USB_HostOhciCreate,    USB_HostOhciDestory,  USB_HostOhciOpenPipe, USB_HostOhciClosePipe,
+    USB_HostOhciWritePipe, USB_HostOhciReadPipe, USB_HostOhciIoctl,
+};
+#endif /* USB_HOST_CONFIG_OHCI */
+
+#if ((defined USB_HOST_CONFIG_IP3516HS) && (USB_HOST_CONFIG_IP3516HS > 0U))
+#include "usb_host_ip3516hs.h"
+static const usb_host_controller_interface_t s_Ip3516HsInterface = \
+{
+    USB_HostIp3516HsCreate,    USB_HostIp3516HsDestory,  USB_HostIp3516HsOpenPipe, USB_HostIp3516HsClosePipe,
+    USB_HostIp3516HsWritePipe, USB_HostIp3516HsReadPipe, USB_HostIp3516HsIoctl,
+};
+#endif /* USB_HOST_CONFIG_IP3516HS */
+
+USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE) static uint8_t s_Setupbuffer[USB_HOST_CONFIG_MAX_HOST][USB_HOST_CONFIG_MAX_TRANSFERS][USB_DATA_ALIGN_SIZE_MULTIPLE(8)];
+/*******************************************************************************
+* Code
+******************************************************************************/
+
+#if ((defined USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST))
+/*FUNCTION*----------------------------------------------------------------
+*
+* Function Name  : usb_test_mode_init
+* Returned Value : None
+* Comments       :
+*     This function is called by common class to initialize the class driver. It
+*     is called in response to a select interface call by application
+*
+*END*--------------------------------------------------------------------*/
+usb_status_t USB_HostTestModeInit(usb_device_handle deviceHandle)
+{
+#if (((defined USB_HOST_CONFIG_EHCI) && (USB_HOST_CONFIG_EHCI)) || \
+     ((defined USB_HOST_CONFIG_IP3516HS) && (USB_HOST_CONFIG_IP3516HS)))
+    usb_host_device_instance_t *deviceInstance = (usb_host_device_instance_t *)deviceHandle;
+    usb_host_instance_t *hostInstance = (usb_host_instance_t *)deviceInstance->hostHandle;
+#endif
+    uint32_t productId;
+    uint32_t vendorId;
+
+    usb_echo("usb host test init\r\n");
+    USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDevicePID, &productId);
+    USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDeviceVID, &vendorId);
+    usb_echo(" vendor id :0x%x product id:0x%x \r\n", vendorId, productId);
+
+    if ((productId != 0x0200U) && (productId != 0x0101) && (productId != 0x0102) && (productId != 0x0103) &&
+        (productId != 0x0104) && (productId != 0x0105) && (productId != 0x0106) && (productId != 0x0107) &&
+        (productId != 0x0108))
+    {
+        usb_echo("Unsupported Device\r\n");
+    }
+
+    if (productId == 0x0200U)
+    {
+        usb_echo("PET test device attached\r\n");
+    }
+    else
+    {
+#if ((defined USB_HOST_CONFIG_EHCI) && (USB_HOST_CONFIG_EHCI))
+        if (hostInstance->controllerTable == &s_EhciInterface)
+        {
+            USB_HostEhciTestModeInit(deviceHandle);
+        }
+#elif((defined USB_HOST_CONFIG_IP3516HS) && (USB_HOST_CONFIG_IP3516HS))
+        if (hostInstance->controllerTable == &s_Ip3516HsInterface)
+        {
+            USB_HostIp3516HsTestModeInit(deviceHandle);
+        }
+#endif
+    }
+
+    return kStatus_USB_Success;
+}
+#endif
+
+static usb_host_instance_t *USB_HostGetInstance(void)
+{
+    uint8_t i = 0;
+    uint32_t index = 0;
+    USB_OSA_SR_ALLOC();
+    USB_OSA_ENTER_CRITICAL();
+    for (; i < USB_HOST_CONFIG_MAX_HOST; i++)
+    {
+        if (g_UsbHostInstance[i].occupied != 1)
+        {
+            uint8_t *buffer = (uint8_t *)&g_UsbHostInstance[i];
+            for (uint32_t j = 0U; j < sizeof(usb_host_instance_t); j++)
+            {
+                buffer[j] = 0x00U;
+            }
+            g_UsbHostInstance[i].occupied = 1;
+            USB_OSA_EXIT_CRITICAL();
+            for (index = 0; index < USB_HOST_CONFIG_MAX_TRANSFERS; ++index)
+            {
+                g_UsbHostInstance[i].transferList[index].setupPacket =
+                    (usb_setup_struct_t *)&(s_Setupbuffer[i][index][0]);
+            }
+            return &g_UsbHostInstance[i];
+        }
+    }
+    USB_OSA_EXIT_CRITICAL();
+    return NULL;
+}
+
+static void USB_HostReleaseInstance(usb_host_instance_t *hostInstance)
+{
+    USB_OSA_SR_ALLOC();
+    USB_OSA_ENTER_CRITICAL();
+    hostInstance->occupied = 0;
+    USB_OSA_EXIT_CRITICAL();
+}
+
+static void USB_HostGetControllerInterface(uint8_t controllerId,
+                                           const usb_host_controller_interface_t **controllerTable)
+{
+#if ((defined USB_HOST_CONFIG_KHCI) && (USB_HOST_CONFIG_KHCI))
+    if (controllerId == kUSB_ControllerKhci0)
+    {
+        *controllerTable = &s_KhciInterface;
+    }
+#endif /* USB_HOST_CONFIG_KHCI */
+
+#if ((defined USB_HOST_CONFIG_EHCI) && (USB_HOST_CONFIG_EHCI))
+    if ((controllerId == kUSB_ControllerEhci0) || (controllerId == kUSB_ControllerEhci1))
+    {
+        *controllerTable = &s_EhciInterface;
+    }
+#endif /* USB_HOST_CONFIG_EHCI */
+
+#if ((defined USB_HOST_CONFIG_OHCI) && (USB_HOST_CONFIG_OHCI > 0U))
+    if (controllerId == kUSB_ControllerOhci0)
+    {
+        *controllerTable = &s_OhciInterface;
+    }
+#endif /* USB_HOST_CONFIG_OHCI */
+
+#if ((defined USB_HOST_CONFIG_IP3516HS) && (USB_HOST_CONFIG_IP3516HS > 0U))
+    if (controllerId == kUSB_ControllerIp3516Hs0)
+    {
+        *controllerTable = &s_Ip3516HsInterface;
+    }
+#endif /* USB_HOST_CONFIG_IP3516HS */
+}
+
+usb_status_t USB_HostInit(uint8_t controllerId, usb_host_handle *hostHandle, host_callback_t callbackFn)
+{
+    usb_status_t status = kStatus_USB_Success;
+    usb_host_instance_t *hostInstance = NULL;
+    usb_host_transfer_t *transferPrev = NULL;
+    uint8_t i = 0;
+
+    hostInstance = USB_HostGetInstance(); /* get one host instance */
+    if (hostInstance == NULL)
+    {
+        return kStatus_USB_InvalidHandle;
+    }
+
+    /* get khci/ehci API table */
+    USB_HostGetControllerInterface(controllerId, &hostInstance->controllerTable);
+    if (hostInstance->controllerTable == NULL)
+    {
+        USB_HostReleaseInstance(hostInstance);
+        return kStatus_USB_ControllerNotFound;
+    }
+
+    /* judge the controller interface one time at here */
+    if ((hostInstance->controllerTable->controllerCreate == NULL) ||
+        (hostInstance->controllerTable->controllerDestory == NULL) ||
+        (hostInstance->controllerTable->controllerOpenPipe == NULL) ||
+        (hostInstance->controllerTable->controllerClosePipe == NULL) ||
+        (hostInstance->controllerTable->controllerWritePipe == NULL) ||
+        (hostInstance->controllerTable->controllerReadPipe == NULL) ||
+        (hostInstance->controllerTable->controllerIoctl == NULL))
+    {
+        return kStatus_USB_Error;
+    }
+
+    /* HOST instance init*/
+    hostInstance->controllerId = controllerId;
+    hostInstance->deviceCallback = callbackFn;
+    hostInstance->deviceList = NULL;
+    if (kStatus_USB_OSA_Success != USB_OsaMutexCreate(&hostInstance->hostMutex))
+    {
+        USB_HostReleaseInstance(hostInstance);
+#ifdef HOST_ECHO
+        usb_echo("host init: create host mutex fail\r\n");
+#endif
+        return kStatus_USB_Error;
+    }
+
+    /* initialize transfer list */
+
+    hostInstance->transferHead = &hostInstance->transferList[0];
+    transferPrev = hostInstance->transferHead;
+    for (i = 1; i < USB_HOST_CONFIG_MAX_TRANSFERS; ++i)
+    {
+        transferPrev->next = &hostInstance->transferList[i];
+        transferPrev = transferPrev->next;
+    }
+
+    /* controller create */
+    status =
+        hostInstance->controllerTable->controllerCreate(controllerId, hostInstance, &(hostInstance->controllerHandle));
+    if ((status != kStatus_USB_Success) || (hostInstance->controllerHandle == NULL))
+    {
+        USB_OsaMutexDestroy(hostInstance->hostMutex);
+        USB_HostReleaseInstance(hostInstance);
+#ifdef HOST_ECHO
+        usb_echo("host init: controller init fail\r\n");
+#endif
+        return kStatus_USB_Error;
+    }
+
+    *hostHandle = hostInstance;
+    return kStatus_USB_Success;
+}
+
+usb_status_t USB_HostDeinit(usb_host_handle hostHandle)
+{
+    usb_status_t status = kStatus_USB_Success;
+    usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle;
+    usb_host_device_instance_t *deviceInstance = NULL;
+
+    if (hostHandle == NULL)
+    {
+        return kStatus_USB_InvalidHandle;
+    }
+
+    /* device list detach */
+    deviceInstance = (usb_host_device_instance_t *)hostInstance->deviceList;
+    while (deviceInstance != NULL)
+    {
+        deviceInstance = (usb_host_device_instance_t *)hostInstance->deviceList;
+        USB_HostDetachDeviceInternal(hostHandle, deviceInstance);
+    }
+
+    /* controller instance destory */
+    status = hostInstance->controllerTable->controllerDestory(hostInstance->controllerHandle);
+    hostInstance->controllerHandle = NULL;
+    if (status != kStatus_USB_Success)
+    {
+#ifdef HOST_ECHO
+        usb_echo("host controller destory fail\r\n");
+#endif
+    }
+
+    /* resource release */
+    if (hostInstance->hostMutex)
+    {
+        USB_OsaMutexDestroy(hostInstance->hostMutex);
+        hostInstance->hostMutex = NULL;
+    }
+    USB_HostReleaseInstance(hostInstance);
+
+    return status;
+}
+
+usb_status_t USB_HostOpenPipe(usb_host_handle hostHandle,
+                              usb_host_pipe_handle *pipeHandle,
+                              usb_host_pipe_init_t *pipeInit)
+{
+    usb_status_t status = kStatus_USB_Success;
+    usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle;
+
+    if ((hostHandle == NULL) || (pipeInit == NULL))
+    {
+        return kStatus_USB_InvalidHandle;
+    }
+
+    /* call controller open pipe interface */
+    status = hostInstance->controllerTable->controllerOpenPipe(hostInstance->controllerHandle, pipeHandle, pipeInit);
+
+    return status;
+}
+
+usb_status_t USB_HostClosePipe(usb_host_handle hostHandle, usb_host_pipe_handle pipeHandle)
+{
+    usb_status_t status = kStatus_USB_Success;
+    usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle;
+
+    if ((hostHandle == NULL) || (pipeHandle == NULL))
+    {
+        return kStatus_USB_InvalidHandle;
+    }
+
+    /* call controller close pipe interface */
+    status = hostInstance->controllerTable->controllerClosePipe(hostInstance->controllerHandle, pipeHandle);
+
+    return status;
+}
+
+usb_status_t USB_HostSend(usb_host_handle hostHandle, usb_host_pipe_handle pipeHandle, usb_host_transfer_t *transfer)
+{
+    usb_status_t status = kStatus_USB_Success;
+    usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle;
+
+    if ((hostHandle == NULL) || (pipeHandle == NULL) || (transfer == NULL))
+    {
+        return kStatus_USB_InvalidHandle;
+    }
+
+    /* initialize transfer */
+    transfer->transferSofar = 0;
+    transfer->direction = USB_OUT;
+
+    USB_HostLock(); /* This api can be called by host task and app task */
+/* keep this code: in normal situation application will guarantee the device is attached when call send/receive function
+ */
+#if 0
+    if ((USB_HostValidateDevice(pipe_ptr->deviceHandle) != kStatus_USB_Success) || (!(USB_HostGetDeviceAttachState(pipe_ptr->deviceHandle))))
+    {
+        USB_HostUnlock();
+        return status;
+    }
+#endif
+/* call controller write pipe interface */
+#if ((defined USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE))
+    if (transfer->transferLength > 0)
+    {
+        DCACHE_CleanByRange((uint32_t)transfer->transferBuffer, transfer->transferLength);
+    }
+#endif
+    status = hostInstance->controllerTable->controllerWritePipe(hostInstance->controllerHandle, pipeHandle, transfer);
+
+    USB_HostUnlock();
+    return status;
+}
+
+usb_status_t USB_HostSendSetup(usb_host_handle hostHandle,
+                               usb_host_pipe_handle pipeHandle,
+                               usb_host_transfer_t *transfer)
+{
+    usb_status_t status = kStatus_USB_Success;
+    usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle;
+
+    if ((hostHandle == NULL) || (pipeHandle == NULL) || (transfer == NULL))
+    {
+        return kStatus_USB_InvalidHandle;
+    }
+
+    /* initialize transfer */
+    transfer->transferSofar = 0;
+    transfer->next = NULL;
+    transfer->setupStatus = 0;
+    if ((transfer->setupPacket->bmRequestType & USB_REQUEST_TYPE_DIR_MASK) == USB_REQUEST_TYPE_DIR_IN)
+    {
+        transfer->direction = USB_IN;
+    }
+    else
+    {
+        transfer->direction = USB_OUT;
+    }
+
+    USB_HostLock(); /* This API can be called by host task and application task */
+/* keep this code: in normal situation application will guarantee the device is attached when call send/receive function
+ */
+#if 0
+    if ((USB_HostValidateDevice(pipe_ptr->deviceHandle) != kStatus_USB_Success) || (!(USB_HostGetDeviceAttachState(pipe_ptr->deviceHandle))))
+    {
+        USB_HostUnlock();
+        return status;
+    }
+#endif
+/* call controller write pipe interface */
+#if ((defined USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE))
+    DCACHE_CleanByRange((uint32_t)&transfer->setupPacket->bmRequestType, sizeof(usb_setup_struct_t));
+    if (transfer->transferLength > 0)
+    {
+        DCACHE_CleanInvalidateByRange((uint32_t)transfer->transferBuffer, transfer->transferLength);
+    }
+#endif
+    status = hostInstance->controllerTable->controllerWritePipe(hostInstance->controllerHandle, pipeHandle, transfer);
+
+    USB_HostUnlock();
+    return status;
+}
+
+usb_status_t USB_HostRecv(usb_host_handle hostHandle, usb_host_pipe_handle pipeHandle, usb_host_transfer_t *transfer)
+{
+    usb_status_t status = kStatus_USB_Success;
+    usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle;
+
+    if ((hostHandle == NULL) || (pipeHandle == NULL) || (transfer == NULL))
+    {
+        return kStatus_USB_InvalidHandle;
+    }
+
+    /* initialize transfer */
+    transfer->transferSofar = 0;
+    transfer->direction = USB_IN;
+
+    USB_HostLock(); /* This API can be called by host task and application task */
+/* keep this code: in normal situation application will guarantee the device is attached when call send/receive function
+ */
+#if 0
+    if ((USB_HostValidateDevice(pipe_ptr->deviceHandle) != kStatus_USB_Success) || (!(USB_HostGetDeviceAttachState(pipe_ptr->deviceHandle))))
+    {
+        USB_HostUnlock();
+        return status;
+    }
+#endif
+
+#if ((defined USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE))
+    if (transfer->transferLength > 0)
+    {
+        DCACHE_CleanInvalidateByRange((uint32_t)transfer->transferBuffer, transfer->transferLength);
+    }
+#endif
+    status = hostInstance->controllerTable->controllerReadPipe(hostInstance->controllerHandle, pipeHandle, transfer);
+
+    USB_HostUnlock();
+    return status;
+}
+
+usb_status_t USB_HostCancelTransfer(usb_host_handle hostHandle,
+                                    usb_host_pipe_handle pipeHandle,
+                                    usb_host_transfer_t *transfer)
+{
+    usb_status_t status = kStatus_USB_Success;
+    usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle;
+    usb_host_cancel_param_t cancelParam;
+
+    if ((hostHandle == NULL) || (pipeHandle == NULL))
+    {
+        return kStatus_USB_InvalidHandle;
+    }
+
+    /* initialize cancel parameter */
+    cancelParam.pipeHandle = pipeHandle;
+    cancelParam.transfer = transfer;
+
+    /* USB_HostLock(); This api can be called by host task and app task */
+    status = hostInstance->controllerTable->controllerIoctl(hostInstance->controllerHandle, kUSB_HostCancelTransfer,
+                                                            &cancelParam);
+    /* USB_HostUnlock(); */
+
+    return status;
+}
+
+usb_status_t USB_HostMallocTransfer(usb_host_handle hostHandle, usb_host_transfer_t **transfer)
+{
+    usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle;
+
+    if ((hostHandle == NULL) || (transfer == NULL))
+    {
+        return kStatus_USB_InvalidHandle;
+    }
+
+    /* get one from the transfer_head */
+    USB_HostLock();
+    if (hostInstance->transferHead != NULL)
+    {
+        *transfer = hostInstance->transferHead;
+        hostInstance->transferHead = hostInstance->transferHead->next;
+        USB_HostUnlock();
+        return kStatus_USB_Success;
+    }
+    else
+    {
+        *transfer = NULL;
+        USB_HostUnlock();
+        return kStatus_USB_Error;
+    }
+}
+
+usb_status_t USB_HostFreeTransfer(usb_host_handle hostHandle, usb_host_transfer_t *transfer)
+{
+    usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle;
+
+    if (hostHandle == NULL)
+    {
+        return kStatus_USB_InvalidHandle;
+    }
+    if (transfer == NULL)
+    {
+        return kStatus_USB_Success;
+    }
+
+    /* release one to the transfer_head */
+    USB_HostLock();
+    transfer->next = hostInstance->transferHead;
+    hostInstance->transferHead = transfer;
+    USB_HostUnlock();
+    return kStatus_USB_Success;
+}
+
+usb_status_t USB_HostHelperGetPeripheralInformation(usb_device_handle deviceHandle,
+                                                    uint32_t infoCode,
+                                                    uint32_t *infoValue)
+{
+    usb_host_device_instance_t *deviceInstance = (usb_host_device_instance_t *)deviceHandle;
+    if ((deviceHandle == NULL) || (infoValue == NULL))
+    {
+        return kStatus_USB_InvalidParameter;
+    }
+
+    switch (infoCode)
+    {
+        case kUSB_HostGetDeviceAddress: /* device address */
+            *infoValue = (uint32_t)deviceInstance->setAddress;
+            break;
+
+        case kUSB_HostGetDeviceControlPipe: /* device control pipe */
+            *infoValue = (uint32_t)deviceInstance->controlPipe;
+            break;
+
+        case kUSB_HostGetHostHandle: /* device host handle */
+            *infoValue = (uint32_t)deviceInstance->hostHandle;
+            break;
+
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+        case kUSB_HostGetDeviceHubNumber: /* device hub address */
+            *infoValue = (uint32_t)deviceInstance->hubNumber;
+            break;
+
+        case kUSB_HostGetDevicePortNumber: /* device port no */
+            *infoValue = (uint32_t)deviceInstance->portNumber;
+            break;
+
+        case kUSB_HostGetDeviceLevel: /* device level */
+            *infoValue = (uint32_t)deviceInstance->level;
+            break;
+
+        case kUSB_HostGetDeviceHSHubNumber: /* device high-speed hub address */
+            *infoValue = (uint32_t)deviceInstance->hsHubNumber;
+            break;
+
+        case kUSB_HostGetDeviceHSHubPort: /* device high-speed hub port no */
+            *infoValue = (uint32_t)deviceInstance->hsHubPort;
+            break;
+
+        case kUSB_HostGetHubThinkTime: /* device hub think time */
+            *infoValue = USB_HostHubGetTotalThinkTime(deviceInstance->hostHandle, deviceInstance->hubNumber);
+            break;
+#else
+        case kUSB_HostGetDeviceHubNumber:   /* device hub address */
+        case kUSB_HostGetDevicePortNumber:  /* device port no */
+        case kUSB_HostGetDeviceHSHubNumber: /* device high-speed hub address */
+        case kUSB_HostGetDeviceHSHubPort:   /* device high-speed hub port no */
+        case kUSB_HostGetHubThinkTime:      /* device hub think time */
+            *infoValue = 0;
+            break;
+        case kUSB_HostGetDeviceLevel: /* device level */
+            *infoValue = 1;
+            break;
+#endif /* USB_HOST_CONFIG_HUB */
+
+        case kUSB_HostGetDeviceSpeed: /* device speed */
+            *infoValue = (uint32_t)deviceInstance->speed;
+            break;
+
+        case kUSB_HostGetDevicePID: /* device pid */
+            *infoValue = (uint32_t)USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(deviceInstance->deviceDescriptor->idProduct);
+            break;
+
+        case kUSB_HostGetDeviceVID: /* device vid */
+            *infoValue = (uint32_t)USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(deviceInstance->deviceDescriptor->idVendor);
+            break;
+
+        case kUSB_HostGetDeviceConfigIndex: /* device config index */
+            *infoValue = (uint32_t)deviceInstance->configurationValue - 1U;
+            break;
+
+        case kUSB_HostGetConfigurationDes: /* configuration descriptor pointer */
+            *infoValue = (uint32_t)deviceInstance->configurationDesc;
+            break;
+
+        case kUSB_HostGetConfigurationLength: /* configuration descriptor length */
+            *infoValue = (uint32_t)deviceInstance->configurationLen;
+            break;
+
+        default:
+            return kStatus_USB_Error;
+    }
+
+    return kStatus_USB_Success;
+}
+
+usb_status_t USB_HostHelperParseAlternateSetting(usb_host_interface_handle interfaceHandle,
+                                                 uint8_t alternateSetting,
+                                                 usb_host_interface_t *interface)
+{
+    uint32_t endPosition;
+    usb_descriptor_union_t *unionDes;
+    usb_host_ep_t *epParse;
+
+    if (interfaceHandle == NULL)
+    {
+        return kStatus_USB_InvalidHandle;
+    }
+
+    if (alternateSetting == 0)
+    {
+        return kStatus_USB_InvalidParameter;
+    }
+
+    /* parse configuration descriptor */
+    unionDes = (usb_descriptor_union_t *)((usb_host_interface_t *)interfaceHandle)
+                   ->interfaceDesc; /* interface extend descriptor start */
+    endPosition =
+        (uint32_t)unionDes +
+        ((usb_host_interface_t *)interfaceHandle)->interfaceExtensionLength; /* interface extend descriptor end */
+    unionDes = (usb_descriptor_union_t *)((uint32_t)unionDes + unionDes->common.bLength);
+
+    /* search for the alternate setting interface descritpor */
+    while ((uint32_t)unionDes < endPosition)
+    {
+        if (unionDes->interface.bDescriptorType == USB_DESCRIPTOR_TYPE_INTERFACE)
+        {
+            if (unionDes->interface.bAlternateSetting == alternateSetting)
+            {
+                break;
+            }
+            else
+            {
+                unionDes = (usb_descriptor_union_t *)((uint32_t)unionDes + unionDes->common.bLength);
+            }
+        }
+        else
+        {
+            unionDes = (usb_descriptor_union_t *)((uint32_t)unionDes + unionDes->common.bLength);
+        }
+    }
+    if ((uint32_t)unionDes >= endPosition)
+    {
+        return kStatus_USB_Error;
+    }
+
+    /* initialize interface handle structure instance */
+    interface->interfaceDesc = &unionDes->interface;
+    interface->alternateSettingNumber = 0;
+    interface->epCount = 0;
+    interface->interfaceExtension = NULL;
+    interface->interfaceExtensionLength = 0;
+    interface->interfaceIndex = unionDes->interface.bInterfaceNumber;
+
+    /* search for endpoint descriptor start position */
+    unionDes = (usb_descriptor_union_t *)((uint32_t)unionDes + unionDes->common.bLength);
+    while ((uint32_t)unionDes < endPosition)
+    {
+        if ((unionDes->common.bDescriptorType != USB_DESCRIPTOR_TYPE_INTERFACE) &&
+            (unionDes->common.bDescriptorType != USB_DESCRIPTOR_TYPE_ENDPOINT))
+        {
+            if (interface->interfaceExtension == NULL)
+            {
+                interface->interfaceExtension = (uint8_t *)unionDes;
+            }
+            interface->interfaceExtensionLength += unionDes->common.bLength;
+            unionDes = (usb_descriptor_union_t *)((uint32_t)unionDes + unionDes->common.bLength);
+        }
+        else
+        {
+            break;
+        }
+    }
+
+    /* parse endpoint descriptor */
+    if (interface->interfaceDesc->bNumEndpoints != 0)
+    {
+        if ((unionDes->common.bDescriptorType != USB_DESCRIPTOR_TYPE_ENDPOINT) ||
+            (interface->interfaceDesc->bNumEndpoints > USB_HOST_CONFIG_INTERFACE_MAX_EP))
+        {
+#ifdef HOST_ECHO
+            usb_echo("interface descriptor error\n");
+#endif
+            return kStatus_USB_Error;
+        }
+        for (; interface->epCount < interface->interfaceDesc->bNumEndpoints; (interface->epCount)++)
+        {
+            if (((uint32_t)unionDes >= endPosition) ||
+                (unionDes->common.bDescriptorType != USB_DESCRIPTOR_TYPE_ENDPOINT))
+            {
+#ifdef HOST_ECHO
+                usb_echo("endpoint descriptor error\n");
+#endif
+                return kStatus_USB_Error;
+            }
+            epParse = (usb_host_ep_t *)&interface->epList[interface->epCount];
+            epParse->epDesc = (usb_descriptor_endpoint_t *)unionDes;
+            epParse->epExtensionLength = 0;
+            epParse->epExtension = NULL;
+            unionDes = (usb_descriptor_union_t *)((uint32_t)unionDes + unionDes->common.bLength);
+            while ((uint32_t)unionDes < endPosition)
+            {
+                if ((unionDes->common.bDescriptorType != USB_DESCRIPTOR_TYPE_ENDPOINT) &&
+                    (unionDes->common.bDescriptorType != USB_DESCRIPTOR_TYPE_INTERFACE))
+                {
+                    if (epParse->epExtension == NULL)
+                    {
+                        epParse->epExtension = (uint8_t *)unionDes;
+                    }
+                    epParse->epExtensionLength += unionDes->common.bLength;
+                    unionDes = (usb_descriptor_union_t *)((uint32_t)unionDes + unionDes->common.bLength);
+                }
+                else
+                {
+                    break;
+                }
+            }
+        }
+    }
+
+    return kStatus_USB_Success;
+}
+
+void USB_HostGetVersion(uint32_t *version)
+{
+    if (version)
+    {
+        *version =
+            (uint32_t)USB_MAKE_VERSION(USB_STACK_VERSION_MAJOR, USB_STACK_VERSION_MINOR, USB_STACK_VERSION_BUGFIX);
+    }
+}
+
+#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
+/* Send BUS or specific device suepend request */
+usb_status_t USB_HostSuspendDeviceResquest(usb_host_handle hostHandle, usb_device_handle deviceHandle)
+{
+    usb_host_instance_t *hostInstance;
+    usb_host_device_instance_t *deviceInstance;
+    usb_status_t status = kStatus_USB_Error;
+    usb_host_bus_control_t type = kUSB_HostBusSuspend;
+
+    if (hostHandle == NULL)
+    {
+        return kStatus_USB_InvalidHandle;
+    }
+    hostInstance = (usb_host_instance_t *)hostHandle;
+
+    hostInstance->suspendedDevice = (void *)deviceHandle;
+
+    if (NULL == deviceHandle)
+    {
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+        status = USB_HostHubSuspendDevice(hostInstance);
+#else
+        status =
+            hostInstance->controllerTable->controllerIoctl(hostInstance->controllerHandle, kUSB_HostBusControl, &type);
+#endif
+    }
+    else
+    {
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+        deviceInstance = (usb_host_device_instance_t *)deviceHandle;
+        if (0 == deviceInstance->hubNumber)
+        {
+#endif
+            if (hostInstance->deviceList == deviceHandle)
+            {
+                status = hostInstance->controllerTable->controllerIoctl(hostInstance->controllerHandle,
+                                                                        kUSB_HostBusControl, &type);
+            }
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+        }
+        else
+        {
+            if (kStatus_USB_Success == USB_HostValidateDevice(hostInstance, deviceHandle))
+            {
+                status = USB_HostHubSuspendDevice(hostInstance);
+            }
+        }
+#endif
+    }
+    if (kStatus_USB_Error == status)
+    {
+        hostInstance->suspendedDevice = NULL;
+    }
+    return status;
+}
+
+/* Send BUS or specific device resume request */
+usb_status_t USB_HostResumeDeviceResquest(usb_host_handle hostHandle, usb_device_handle deviceHandle)
+{
+    usb_host_instance_t *hostInstance;
+    usb_host_device_instance_t *deviceInstance;
+    usb_status_t status = kStatus_USB_Error;
+    usb_host_bus_control_t type = kUSB_HostBusResume;
+
+    if (hostHandle == NULL)
+    {
+        return kStatus_USB_InvalidHandle;
+    }
+    hostInstance = (usb_host_instance_t *)hostHandle;
+
+    if (hostInstance->suspendedDevice != deviceHandle)
+    {
+        return kStatus_USB_InvalidParameter;
+    }
+    hostInstance->suspendedDevice = (void *)deviceHandle;
+
+    if (NULL == deviceHandle)
+    {
+        status =
+            hostInstance->controllerTable->controllerIoctl(hostInstance->controllerHandle, kUSB_HostBusControl, &type);
+    }
+    else
+    {
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+        deviceInstance = (usb_host_device_instance_t *)deviceHandle;
+        if (0 == deviceInstance->hubNumber)
+        {
+#endif
+            if (hostInstance->deviceList == deviceHandle)
+            {
+                status = hostInstance->controllerTable->controllerIoctl(hostInstance->controllerHandle,
+                                                                        kUSB_HostBusControl, &type);
+            }
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+        }
+        else
+        {
+            if (kStatus_USB_Success == USB_HostValidateDevice(hostInstance, deviceHandle))
+            {
+                status = USB_HostHubResumeDevice(hostInstance);
+            }
+        }
+#endif
+    }
+
+    return status;
+}
+#if ((defined(USB_HOST_CONFIG_LPM_L1)) && (USB_HOST_CONFIG_LPM_L1 > 0U))
+/* Send BUS or specific device suepend request */
+usb_status_t USB_HostL1SleepDeviceResquest(usb_host_handle hostHandle,
+                                           usb_device_handle deviceHandle,
+                                           uint8_t sleepType)
+{
+    usb_host_instance_t *hostInstance;
+    usb_status_t status = kStatus_USB_Error;
+    usb_host_bus_control_t type = kUSB_HostBusL1Sleep;
+
+    if (hostHandle == NULL)
+    {
+        return kStatus_USB_InvalidHandle;
+    }
+    hostInstance = (usb_host_instance_t *)hostHandle;
+
+    hostInstance->suspendedDevice = (void *)deviceHandle;
+
+    if (1U == sleepType)
+    {
+        /*#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))*/
+        /*To do, implete hub L1 suspend device*/
+        /*#else*/
+        status =
+            hostInstance->controllerTable->controllerIoctl(hostInstance->controllerHandle, kUSB_HostBusControl, &type);
+        /*#endif*/
+    }
+    else
+    {
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+/*To do, if device hub number is 0, need suspend the bus ,else suspend the corresponding device*/
+#endif
+        if (hostInstance->deviceList == deviceHandle)
+        {
+            status = hostInstance->controllerTable->controllerIoctl(hostInstance->controllerHandle, kUSB_HostBusControl,
+                                                                    &type);
+        }
+    }
+    if (kStatus_USB_Error == status)
+    {
+        hostInstance->suspendedDevice = NULL;
+    }
+    return status;
+}
+/* Send BUS or specific device suepend request */
+usb_status_t USB_HostL1SleepDeviceResquestConfig(usb_host_handle hostHandle, uint8_t *lpmParam)
+{
+    usb_host_instance_t *hostInstance;
+    usb_status_t status = kStatus_USB_Error;
+
+    if (hostHandle == NULL)
+    {
+        return kStatus_USB_InvalidHandle;
+    }
+    hostInstance = (usb_host_instance_t *)hostHandle;
+
+    status =
+        hostInstance->controllerTable->controllerIoctl(hostInstance->controllerHandle, kUSB_HostL1Config, lpmParam);
+
+    return status;
+}
+
+/* Send BUS or specific device resume request */
+usb_status_t USB_HostL1ResumeDeviceResquest(usb_host_handle hostHandle,
+                                            usb_device_handle deviceHandle,
+                                            uint8_t sleepType)
+{
+    usb_host_instance_t *hostInstance;
+
+    usb_status_t status = kStatus_USB_Error;
+    usb_host_bus_control_t type = kUSB_HostBusL1Resume;
+
+    if (hostHandle == NULL)
+    {
+        return kStatus_USB_InvalidHandle;
+    }
+    hostInstance = (usb_host_instance_t *)hostHandle;
+
+    if (1U == sleepType)
+    {
+        status =
+            hostInstance->controllerTable->controllerIoctl(hostInstance->controllerHandle, kUSB_HostBusControl, &type);
+    }
+    else
+    {
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+/*To do, if device hub number is 0, need suspend the bus ,else suspend the corresponding device*/
+
+#endif
+        if (hostInstance->deviceList == deviceHandle)
+        {
+            status = hostInstance->controllerTable->controllerIoctl(hostInstance->controllerHandle, kUSB_HostBusControl,
+                                                                    &type);
+        }
+    }
+
+    return status;
+}
+#endif
+/* Update HW tick(unit is ms) */
+usb_status_t USB_HostUpdateHwTick(usb_host_handle hostHandle, uint64_t tick)
+{
+    usb_host_instance_t *hostInstance;
+    usb_status_t status = kStatus_USB_Success;
+
+    if (hostHandle == NULL)
+    {
+        return kStatus_USB_InvalidHandle;
+    }
+    hostInstance = (usb_host_instance_t *)hostHandle;
+
+    hostInstance->hwTick = tick;
+
+    return status;
+}
+#endif

+ 131 - 0
bsp/imxrt1052-evk/drivers/usb/host/usb_host_hci.h

@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2015, Freescale Semiconductor, Inc.
+ * Copyright 2016 NXP
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright notice, this list
+ *   of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright notice, this
+ *   list of conditions and the following disclaimer in the documentation and/or
+ *   other materials provided with the distribution.
+ *
+ * o Neither the name of the copyright holder nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _USB_HOST_HCI_H_
+#define _USB_HOST_HCI_H_
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/*! @brief USB host lock */
+#define USB_HostLock() USB_OsaMutexLock(hostInstance->hostMutex)
+/*! @brief USB host unlock */
+#define USB_HostUnlock() USB_OsaMutexUnlock(hostInstance->hostMutex)
+
+/*!
+ * @addtogroup usb_host_controller_driver
+ * @{
+ */
+
+/*! @brief USB host controller control code */
+typedef enum _usb_host_controller_control
+{
+    kUSB_HostCancelTransfer = 1U,          /*!< Cancel transfer code */
+    kUSB_HostBusControl,                   /*!< Bus control code */
+    kUSB_HostGetFrameNumber,               /*!< Get frame number code */
+    kUSB_HostUpdateControlEndpointAddress, /*!< Update control endpoint address */
+    kUSB_HostUpdateControlPacketSize,      /*!< Update control endpoint maximum  packet size */
+    kUSB_HostPortAttachDisable,            /*!< Disable the port attach event */
+    kUSB_HostPortAttachEnable,             /*!< Enable the port attach event */
+    kUSB_HostL1Config,                     /*!< L1 suspend Bus control code */
+} usb_host_controller_control_t;
+
+/*! @brief USB host controller bus control code */
+typedef enum _usb_host_bus_control
+{
+    kUSB_HostBusReset = 1U,    /*!< Reset bus */
+    kUSB_HostBusRestart,       /*!< Restart bus */
+    kUSB_HostBusEnableAttach,  /*!< Enable attach */
+    kUSB_HostBusDisableAttach, /*!< Disable attach */
+    kUSB_HostBusSuspend,       /*!< Suspend BUS */
+    kUSB_HostBusResume,        /*!< Resume BUS */
+    kUSB_HostBusL1SuspendInit, /*!< L1 Suspend BUS */
+    kUSB_HostBusL1Sleep,       /*!< L1 Suspend BUS */
+    kUSB_HostBusL1Resume,      /*!< L1 Resume BUS */
+} usb_host_bus_control_t;
+
+/*! @brief USB host controller interface structure */
+typedef struct _usb_host_controller_interface
+{
+    usb_status_t (*controllerCreate)(
+        uint8_t controllerId,
+        usb_host_handle upperLayerHandle,
+        usb_host_controller_handle *controllerHandle); /*!< Create a controller instance function prototype*/
+    usb_status_t (*controllerDestory)(
+        usb_host_controller_handle controllerHandle); /*!< Destroy a controller instance function prototype*/
+    usb_status_t (*controllerOpenPipe)(usb_host_controller_handle controllerHandle,
+                                       usb_host_pipe_handle *pipeHandle,
+                                       usb_host_pipe_init_t *pipeInit); /*!< Open a controller pipe function prototype*/
+    usb_status_t (*controllerClosePipe)(
+        usb_host_controller_handle controllerHandle,
+        usb_host_pipe_handle pipeHandle); /*!< Close a controller pipe function prototype*/
+    usb_status_t (*controllerWritePipe)(usb_host_controller_handle controllerHandle,
+                                        usb_host_pipe_handle pipeHandle,
+                                        usb_host_transfer_t *transfer); /*!< Write data to a pipe function prototype*/
+    usb_status_t (*controllerReadPipe)(usb_host_controller_handle controllerHandle,
+                                       usb_host_pipe_handle pipeHandle,
+                                       usb_host_transfer_t *transfer); /*!< Read data from a pipe function prototype*/
+    usb_status_t (*controllerIoctl)(usb_host_controller_handle controllerHandle,
+                                    uint32_t ioctlEvent,
+                                    void *ioctlParam); /*!< Control a controller function prototype*/
+} usb_host_controller_interface_t;
+
+/*! @}*/
+
+/*!
+ * @addtogroup usb_host_drv
+ * @{
+ */
+
+/*! @brief USB host instance structure */
+typedef struct _usb_host_instance
+{
+    void *controllerHandle;                                          /*!< The low level controller handle*/
+    host_callback_t deviceCallback;                                  /*!< Device attach/detach callback*/
+    usb_osa_mutex_handle hostMutex;                                  /*!< Host layer mutex*/
+    usb_host_transfer_t transferList[USB_HOST_CONFIG_MAX_TRANSFERS]; /*!< Transfer resource*/
+    usb_host_transfer_t *transferHead;                               /*!< Idle transfer head*/
+    const usb_host_controller_interface_t *controllerTable;          /*!< KHCI/EHCI interface*/
+    void *deviceList;                                                /*!< Device list*/
+#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
+    void *suspendedDevice;    /*!< Suspended device handle*/
+    volatile uint64_t hwTick; /*!< Current hw tick(ms)*/
+    uint8_t sleepType;        /*!< L1 LPM device handle*/
+#endif
+    uint8_t addressBitMap[16]; /*!< Used for address allocation. The first bit is the address 1, second bit is the
+                                  address 2*/
+    uint8_t occupied;          /*!< 0 - the instance is not occupied; 1 - the instance is occupied*/
+    uint8_t controllerId;      /*!< The controller ID*/
+} usb_host_instance_t;
+
+/*! @}*/
+
+#endif /* _USB_HOST_HCI_H_ */

+ 140 - 0
bsp/imxrt1052-evk/drivers/usb/include/usb.h

@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2015, Freescale Semiconductor, Inc.
+ * Copyright 2016 NXP
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright notice, this list
+ *   of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright notice, this
+ *   list of conditions and the following disclaimer in the documentation and/or
+ *   other materials provided with the distribution.
+ *
+ * o Neither the name of the copyright holder nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __USB_H__
+#define __USB_H__
+
+#include <stdint.h>
+#include <stdio.h>
+#include <fsl_common.h>
+#include "usb_misc.h"
+#include "usb_spec.h"
+
+/*!
+ * @addtogroup usb_drv
+ * @{
+ */
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+/*! @brief Defines USB stack major version */
+#define USB_STACK_VERSION_MAJOR (1U)
+/*! @brief Defines USB stack minor version */
+#define USB_STACK_VERSION_MINOR (6U)
+/*! @brief Defines USB stack bugfix version */
+#define USB_STACK_VERSION_BUGFIX (3U)
+
+/*! @brief USB stack version definition */
+#define USB_MAKE_VERSION(major, minor, bugfix) (((major) << 16) | ((minor) << 8) | (bugfix))
+
+/*! @brief USB error code */
+typedef enum _usb_status
+{
+    kStatus_USB_Success = 0x00U, /*!< Success */
+    kStatus_USB_Error,           /*!< Failed */
+
+    kStatus_USB_Busy,                       /*!< Busy */
+    kStatus_USB_InvalidHandle,              /*!< Invalid handle */
+    kStatus_USB_InvalidParameter,           /*!< Invalid parameter */
+    kStatus_USB_InvalidRequest,             /*!< Invalid request */
+    kStatus_USB_ControllerNotFound,         /*!< Controller cannot be found */
+    kStatus_USB_InvalidControllerInterface, /*!< Invalid controller interface */
+
+    kStatus_USB_NotSupported,   /*!< Configuration is not supported */
+    kStatus_USB_Retry,          /*!< Enumeration get configuration retry */
+    kStatus_USB_TransferStall,  /*!< Transfer stalled */
+    kStatus_USB_TransferFailed, /*!< Transfer failed */
+    kStatus_USB_AllocFail,      /*!< Allocation failed */
+    kStatus_USB_LackSwapBuffer, /*!< Insufficient swap buffer for KHCI */
+    kStatus_USB_TransferCancel, /*!< The transfer cancelled */
+    kStatus_USB_BandwidthFail,  /*!< Allocate bandwidth failed */
+    kStatus_USB_MSDStatusFail,  /*!< For MSD, the CSW status means fail */
+    kStatus_USB_EHCIAttached,
+    kStatus_USB_EHCIDetached,
+} usb_status_t;
+
+/*! @brief USB host handle type define */
+typedef void *usb_host_handle;
+
+/*! @brief USB device handle type define. For device stack it is the whole device handle; for host stack it is the
+ * attached device instance handle*/
+typedef void *usb_device_handle;
+
+/*! @brief USB OTG handle type define */
+typedef void *usb_otg_handle;
+
+/*! @brief USB controller ID */
+typedef enum _usb_controller_index
+{
+    kUSB_ControllerKhci0 = 0U, /*!< KHCI 0U */
+    kUSB_ControllerKhci1 = 1U, /*!< KHCI 1U, Currently, there are no platforms which have two KHCI IPs, this is reserved
+                                  to be used in the future. */
+    kUSB_ControllerEhci0 = 2U, /*!< EHCI 0U */
+    kUSB_ControllerEhci1 = 3U, /*!< EHCI 1U, Currently, there are no platforms which have two EHCI IPs, this is reserved
+                                  to be used in the future. */
+
+    kUSB_ControllerLpcIp3511Fs0 = 4U, /*!< LPC USB IP3511 FS controller 0 */
+    kUSB_ControllerLpcIp3511Fs1 =
+        5U, /*!< LPC USB IP3511 FS controller 1, there are no platforms which have two IP3511 IPs, this is reserved
+              to be used in the future. */
+
+    kUSB_ControllerLpcIp3511Hs0 = 6U, /*!< LPC USB IP3511 HS controller 0 */
+    kUSB_ControllerLpcIp3511Hs1 =
+        7U, /*!< LPC USB IP3511 HS controller 1, there are no platforms which have two IP3511 IPs, this is reserved
+              to be used in the future. */
+
+    kUSB_ControllerOhci0 = 8U, /*!< OHCI 0U */
+    kUSB_ControllerOhci1 = 9U, /*!< OHCI 1U, Currently, there are no platforms which have two OHCI IPs, this is reserved
+                                  to be used in the future. */
+
+    kUSB_ControllerIp3516Hs0 = 10U, /*!< IP3516HS 0U */
+    kUSB_ControllerIp3516Hs1 =
+        11U, /*!< IP3516HS 1U, Currently, there are no platforms which have two IP3516HS IPs, this is reserved
+           to be used in the future. */
+} usb_controller_index_t;
+
+/**
+* @brief USB stack version fields
+*/
+typedef struct _usb_version
+{
+    uint8_t major;  /*!< Major */
+    uint8_t minor;  /*!< Minor */
+    uint8_t bugfix; /*!< Bug fix */
+} usb_version_t;
+
+/*******************************************************************************
+ * API
+ ******************************************************************************/
+
+/*! @} */
+
+#endif /* __USB_H__ */

+ 185 - 0
bsp/imxrt1052-evk/drivers/usb/include/usb_device_config.h

@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2015, Freescale Semiconductor, Inc.
+ * Copyright 2016 - 2017 NXP
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright notice, this list
+ *   of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright notice, this
+ *   list of conditions and the following disclaimer in the documentation and/or
+ *   other materials provided with the distribution.
+ *
+ * o Neither the name of the copyright holder nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _USB_DEVICE_CONFIG_H_
+#define _USB_DEVICE_CONFIG_H_
+
+/*******************************************************************************
+* Definitions
+******************************************************************************/
+/*!
+ * @addtogroup usb_device_configuration
+ * @{
+ */
+
+/*!
+ * @name Hardware instance define
+ * @{
+ */
+
+/*! @brief KHCI instance count */
+#define USB_DEVICE_CONFIG_KHCI (0U)
+
+/*! @brief EHCI instance count */
+#define USB_DEVICE_CONFIG_EHCI (2U)
+
+/*! @brief LPC USB IP3511 FS instance count */
+#define USB_DEVICE_CONFIG_LPCIP3511FS (0U)
+
+/*! @brief LPC USB IP3511 HS instance count */
+#define USB_DEVICE_CONFIG_LPCIP3511HS (0U)
+
+/*! @brief Device instance count, the sum of KHCI and EHCI instance counts*/
+#define USB_DEVICE_CONFIG_NUM \
+    (USB_DEVICE_CONFIG_KHCI + USB_DEVICE_CONFIG_EHCI + USB_DEVICE_CONFIG_LPCIP3511FS + USB_DEVICE_CONFIG_LPCIP3511HS)
+
+/* @} */
+
+/*!
+ * @name class instance define
+ * @{
+ */
+
+/*! @brief HID instance count */
+#define USB_DEVICE_CONFIG_HID (0U)
+
+/*! @brief CDC ACM instance count */
+#define USB_DEVICE_CONFIG_CDC_ACM (1U)
+
+/*! @brief MSC instance count */
+#define USB_DEVICE_CONFIG_MSC (0U)
+
+/*! @brief Audio instance count */
+#define USB_DEVICE_CONFIG_AUDIO (0U)
+
+/*! @brief PHDC instance count */
+#define USB_DEVICE_CONFIG_PHDC (0U)
+
+/*! @brief Video instance count */
+#define USB_DEVICE_CONFIG_VIDEO (0U)
+
+/*! @brief CCID instance count */
+#define USB_DEVICE_CONFIG_CCID (0U)
+
+/*! @brief Printer instance count */
+#define USB_DEVICE_CONFIG_PRINTER (0U)
+
+/*! @brief DFU instance count */
+#define USB_DEVICE_CONFIG_DFU (0U)
+
+/* @} */
+
+/*! @brief Whether device is self power. 1U supported, 0U not supported */
+#define USB_DEVICE_CONFIG_SELF_POWER (1U)
+
+/*! @brief How many endpoints are supported in the stack. */
+#define USB_DEVICE_CONFIG_ENDPOINTS (4U)
+
+/*! @brief Whether the device task is enabled. */
+#define USB_DEVICE_CONFIG_USE_TASK (0U)
+
+/*! @brief How many the notification message are supported when the device task is enabled. */
+#define USB_DEVICE_CONFIG_MAX_MESSAGES (8U)
+
+/*! @brief Whether test mode enabled. */
+#define USB_DEVICE_CONFIG_USB20_TEST_MODE (0U)
+
+/*! @brief Whether device CV test is enabled. */
+#define USB_DEVICE_CONFIG_CV_TEST (0U)
+
+/*! @brief Whether device compliance test is enabled. If the macro is enabled,
+    the test mode and CV test macroes will be set.*/
+#define USB_DEVICE_CONFIG_COMPLIANCE_TEST (0U)
+
+#if ((defined(USB_DEVICE_CONFIG_COMPLIANCE_TEST)) && (USB_DEVICE_CONFIG_COMPLIANCE_TEST > 0U))
+
+/*! @brief Undefine the marco USB_DEVICE_CONFIG_USB20_TEST_MODE. */
+#undef USB_DEVICE_CONFIG_USB20_TEST_MODE
+/*! @brief Undefine the marco USB_DEVICE_CONFIG_CV_TEST. */
+#undef USB_DEVICE_CONFIG_CV_TEST
+
+/*! @brief enable the test mode. */
+#define USB_DEVICE_CONFIG_USB20_TEST_MODE (1U)
+
+/*! @brief enable the CV test */
+#define USB_DEVICE_CONFIG_CV_TEST (1U)
+
+#endif
+
+#if ((defined(USB_DEVICE_CONFIG_KHCI)) && (USB_DEVICE_CONFIG_KHCI > 0U))
+
+/*! @brief The MAX buffer length for the KHCI DMA workaround.*/
+#define USB_DEVICE_CONFIG_KHCI_DMA_ALIGN_BUFFER_LENGTH (64U)
+#endif
+
+#if ((defined(USB_DEVICE_CONFIG_EHCI)) && (USB_DEVICE_CONFIG_EHCI > 0U))
+/*! @brief How many the DTD are supported. */
+#define USB_DEVICE_CONFIG_EHCI_MAX_DTD (16U)
+
+/*! @brief Whether the EHCI ID pin detect feature enabled. */
+#define USB_DEVICE_CONFIG_EHCI_ID_PIN_DETECT (0U)
+#endif
+
+/*! @brief Whether the keep alive feature enabled. */
+#define USB_DEVICE_CONFIG_KEEP_ALIVE_MODE (0U)
+
+/*! @brief Whether the transfer buffer is cache-enabled or not. */
+#define USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE (1U)
+
+/*! @brief Whether the low power mode is enabled or not. */
+#define USB_DEVICE_CONFIG_LOW_POWER_MODE (0U)
+
+#if ((defined(USB_DEVICE_CONFIG_LOW_POWER_MODE)) && (USB_DEVICE_CONFIG_LOW_POWER_MODE > 0U))
+/*! @brief Whether device remote wakeup supported. 1U supported, 0U not supported */
+#define USB_DEVICE_CONFIG_REMOTE_WAKEUP (0U)
+
+/*! @brief Whether LPM is supported. 1U supported, 0U not supported */
+#define USB_DEVICE_CONFIG_LPM_L1 (0U)
+#else
+/*! @brief The device remote wakeup is unsupported. */
+#define USB_DEVICE_CONFIG_REMOTE_WAKEUP (0U)
+#endif
+
+/*! @brief Whether the device detached feature is enabled or not. */
+#define USB_DEVICE_CONFIG_DETACH_ENABLE (0U)
+
+/*! @brief Whether handle the USB bus error. */
+#define USB_DEVICE_CONFIG_ERROR_HANDLING (0U)
+
+/* @} */
+/*! @brief rt-thread port alloc */
+#include <rtthread.h>
+#define USB_OSA_SR_ALLOC(...)
+/*! @brief rt-thread port enter critical */
+#define USB_OSA_ENTER_CRITICAL  rt_enter_critical
+/*! @brief rt-thread port exit critical */
+#define USB_OSA_EXIT_CRITICAL   rt_exit_critical
+
+#endif /* _USB_DEVICE_CONFIG_H_ */

+ 140 - 0
bsp/imxrt1052-evk/drivers/usb/include/usb_ehci.h

@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2015, Freescale Semiconductor, Inc.
+ * Copyright 2016 NXP
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright notice, this list
+ *   of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright notice, this
+ *   list of conditions and the following disclaimer in the documentation and/or
+ *   other materials provided with the distribution.
+ *
+ * o Neither the name of the copyright holder nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __USB_EHCI_H__
+#define __USB_EHCI_H__
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/* Device QH */
+#define USB_DEVICE_EHCI_QH_POINTER_MASK (0xFFFFFFC0U)
+#define USB_DEVICE_EHCI_QH_MULT_MASK (0xC0000000U)
+#define USB_DEVICE_EHCI_QH_ZLT_MASK (0x20000000U)
+#define USB_DEVICE_EHCI_QH_MAX_PACKET_SIZE_MASK (0x07FF0000U)
+#define USB_DEVICE_EHCI_QH_MAX_PACKET_SIZE (0x00000800U)
+#define USB_DEVICE_EHCI_QH_IOS_MASK (0x00008000U)
+
+/* Device DTD */
+#define USB_DEVICE_ECHI_DTD_POINTER_MASK (0xFFFFFFE0U)
+#define USB_DEVICE_ECHI_DTD_TERMINATE_MASK (0x00000001U)
+#define USB_DEVICE_ECHI_DTD_PAGE_MASK (0xFFFFF000U)
+#define USB_DEVICE_ECHI_DTD_PAGE_OFFSET_MASK (0x00000FFFU)
+#define USB_DEVICE_ECHI_DTD_PAGE_BLOCK (0x00001000U)
+#define USB_DEVICE_ECHI_DTD_TOTAL_BYTES_MASK (0x7FFF0000U)
+#define USB_DEVICE_ECHI_DTD_TOTAL_BYTES (0x00004000U)
+#define USB_DEVICE_ECHI_DTD_IOC_MASK (0x00008000U)
+#define USB_DEVICE_ECHI_DTD_MULTIO_MASK (0x00000C00U)
+#define USB_DEVICE_ECHI_DTD_STATUS_MASK (0x000000FFU)
+#define USB_DEVICE_EHCI_DTD_STATUS_ERROR_MASK (0x00000068U)
+#define USB_DEVICE_ECHI_DTD_STATUS_ACTIVE (0x00000080U)
+#define USB_DEVICE_ECHI_DTD_STATUS_HALTED (0x00000040U)
+#define USB_DEVICE_ECHI_DTD_STATUS_DATA_BUFFER_ERROR (0x00000020U)
+#define USB_DEVICE_ECHI_DTD_STATUS_TRANSACTION_ERROR (0x00000008U)
+
+typedef struct _usb_device_ehci_qh_struct
+{
+    union
+    {
+        volatile uint32_t capabilttiesCharacteristics;
+        struct
+        {
+            volatile uint32_t reserved1 : 15;
+            volatile uint32_t ios : 1;
+            volatile uint32_t maxPacketSize : 11;
+            volatile uint32_t reserved2 : 2;
+            volatile uint32_t zlt : 1;
+            volatile uint32_t mult : 2;
+        } capabilttiesCharacteristicsBitmap;
+    } capabilttiesCharacteristicsUnion;
+    volatile uint32_t currentDtdPointer;
+    volatile uint32_t nextDtdPointer;
+    union
+    {
+        volatile uint32_t dtdToken;
+        struct
+        {
+            volatile uint32_t status : 8;
+            volatile uint32_t reserved1 : 2;
+            volatile uint32_t multiplierOverride : 2;
+            volatile uint32_t reserved2 : 3;
+            volatile uint32_t ioc : 1;
+            volatile uint32_t totalBytes : 15;
+            volatile uint32_t reserved3 : 1;
+        } dtdTokenBitmap;
+    } dtdTokenUnion;
+    volatile uint32_t bufferPointerPage[5];
+    volatile uint32_t reserved1;
+    uint32_t setupBuffer[2];
+    uint32_t setupBufferBack[2];
+    union
+    {
+        uint32_t endpointStatus;
+        struct
+        {
+            uint32_t isOpened : 1;
+            uint32_t : 31;
+        } endpointStatusBitmap;
+    } endpointStatusUnion;
+    uint32_t reserved2;
+} usb_device_ehci_qh_struct_t;
+
+typedef struct _usb_device_ehci_dtd_struct
+{
+    volatile uint32_t nextDtdPointer;
+    union
+    {
+        volatile uint32_t dtdToken;
+        struct
+        {
+            volatile uint32_t status : 8;
+            volatile uint32_t reserved1 : 2;
+            volatile uint32_t multiplierOverride : 2;
+            volatile uint32_t reserved2 : 3;
+            volatile uint32_t ioc : 1;
+            volatile uint32_t totalBytes : 15;
+            volatile uint32_t reserved3 : 1;
+        } dtdTokenBitmap;
+    } dtdTokenUnion;
+    volatile uint32_t bufferPointerPage[5];
+    union
+    {
+        volatile uint32_t reserved;
+        struct
+        {
+            uint32_t originalBufferOffest : 12;
+            uint32_t originalBufferLength : 19;
+            uint32_t dtdInvalid : 1;
+        } originalBufferInfo;
+    } reservedUnion;
+} usb_device_ehci_dtd_struct_t;
+
+#endif /* __USB_EHCI_H__ */

+ 452 - 0
bsp/imxrt1052-evk/drivers/usb/include/usb_misc.h

@@ -0,0 +1,452 @@
+/*
+ * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
+ * Copyright 2016 NXP
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright notice, this list
+ *   of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright notice, this
+ *   list of conditions and the following disclaimer in the documentation and/or
+ *   other materials provided with the distribution.
+ *
+ * o Neither the name of the copyright holder nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __USB_MISC_H__
+#define __USB_MISC_H__
+
+#ifndef ENDIANNESS
+
+#error ENDIANNESS should be defined, and then rebulid the project.
+
+#endif
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/*! @brief Define USB printf */
+#if defined(__cplusplus)
+extern "C" {
+#endif /* __cplusplus */
+
+extern int DbgConsole_Printf(const char *fmt_s, ...);
+
+#if defined(__cplusplus)
+}
+#endif /* __cplusplus */
+
+#if defined(SDK_DEBUGCONSOLE) && (SDK_DEBUGCONSOLE < 1)
+#define usb_echo printf
+#else
+#define usb_echo DbgConsole_Printf
+#endif
+
+#if defined(__ICCARM__)
+
+#ifndef STRUCT_PACKED
+#define STRUCT_PACKED __packed
+#endif
+
+#ifndef STRUCT_UNPACKED
+#define STRUCT_UNPACKED
+#endif
+
+#elif defined(__GNUC__)
+
+#ifndef STRUCT_PACKED
+#define STRUCT_PACKED
+#endif
+
+#ifndef STRUCT_UNPACKED
+#define STRUCT_UNPACKED __attribute__((__packed__))
+#endif
+
+#elif defined(__CC_ARM)
+
+#ifndef STRUCT_PACKED
+#define STRUCT_PACKED _Pragma("pack(1U)")
+#endif
+
+#ifndef STRUCT_UNPACKED
+#define STRUCT_UNPACKED _Pragma("pack()")
+#endif
+
+#endif
+
+#define USB_SHORT_GET_LOW(x) (((uint16_t)x) & 0xFFU)
+#define USB_SHORT_GET_HIGH(x) ((uint8_t)(((uint16_t)x) >> 8U) & 0xFFU)
+
+#define USB_LONG_GET_BYTE0(x) ((uint8_t)(((uint32_t)(x))) & 0xFFU)
+#define USB_LONG_GET_BYTE1(x) ((uint8_t)(((uint32_t)(x)) >> 8U) & 0xFFU)
+#define USB_LONG_GET_BYTE2(x) ((uint8_t)(((uint32_t)(x)) >> 16U) & 0xFFU)
+#define USB_LONG_GET_BYTE3(x) ((uint8_t)(((uint32_t)(x)) >> 24U) & 0xFFU)
+
+#define USB_MEM4_ALIGN_MASK (0x03U)
+
+/* accessory macro */
+#define USB_MEM4_ALIGN(n) ((n + 3U) & (0xFFFFFFFCu))
+#define USB_MEM32_ALIGN(n) ((n + 31U) & (0xFFFFFFE0u))
+#define USB_MEM64_ALIGN(n) ((n + 63U) & (0xFFFFFFC0u))
+
+/* big/little endian */
+#define SWAP2BYTE_CONST(n) ((((n)&0x00FFU) << 8U) | (((n)&0xFF00U) >> 8U))
+#define SWAP4BYTE_CONST(n) \
+    ((((n)&0x000000FFU) << 24U) | (((n)&0x0000FF00U) << 8U) | (((n)&0x00FF0000U) >> 8U) | (((n)&0xFF000000U) >> 24U))
+
+#define USB_ASSIGN_VALUE_ADDRESS_LONG_BY_BYTE(n, m)      \
+    {                                                    \
+        *((uint8_t *)&(n)) = *((uint8_t *)&(m));         \
+        *((uint8_t *)&(n) + 1) = *((uint8_t *)&(m) + 1); \
+        *((uint8_t *)&(n) + 2) = *((uint8_t *)&(m) + 2); \
+        *((uint8_t *)&(n) + 3) = *((uint8_t *)&(m) + 3); \
+    }
+
+#define USB_ASSIGN_VALUE_ADDRESS_SHORT_BY_BYTE(n, m)     \
+    {                                                    \
+        *((uint8_t *)&(n)) = *((uint8_t *)&(m));         \
+        *((uint8_t *)&(n) + 1) = *((uint8_t *)&(m) + 1); \
+    }
+
+#define USB_ASSIGN_MACRO_VALUE_ADDRESS_LONG_BY_BYTE(n, m) \
+    {                                                     \
+        *((uint8_t *)&(n)) = (uint8_t)m;                  \
+        *((uint8_t *)&(n) + 1) = (uint8_t)(m >> 8);       \
+        *((uint8_t *)&(n) + 2) = (uint8_t)(m >> 16);      \
+        *((uint8_t *)&(n) + 3) = (uint8_t)(m >> 24);      \
+    }
+
+#define USB_ASSIGN_MACRO_VALUE_ADDRESS_SHORT_BY_BYTE(n, m) \
+    {                                                      \
+        *((uint8_t *)&(n)) = (uint8_t)m;                   \
+        *((uint8_t *)&(n) + 1) = (uint8_t)(m >> 8);        \
+    }
+
+#if (ENDIANNESS == USB_BIG_ENDIAN)
+
+#define USB_SHORT_TO_LITTLE_ENDIAN(n) SWAP2BYTE_CONST(n)
+#define USB_LONG_TO_LITTLE_ENDIAN(n) SWAP4BYTE_CONST(n)
+#define USB_SHORT_FROM_LITTLE_ENDIAN(n) SWAP2BYTE_CONST(n)
+#define USB_LONG_FROM_LITTLE_ENDIAN(n) SWAP2BYTE_CONST(n)
+
+#define USB_SHORT_TO_BIG_ENDIAN(n) (n)
+#define USB_LONG_TO_BIG_ENDIAN(n) (n)
+#define USB_SHORT_FROM_BIG_ENDIAN(n) (n)
+#define USB_LONG_FROM_BIG_ENDIAN(n) (n)
+
+#define USB_LONG_TO_LITTLE_ENDIAN_ADDRESS(n, m) \
+    {                                           \
+        m[3] = ((n >> 24U) & 0xFFU);            \
+        m[2] = ((n >> 16U) & 0xFFU);            \
+        m[1] = ((n >> 8U) & 0xFFU);             \
+        m[0] = (n & 0xFFU);                     \
+    }
+
+#define USB_LONG_FROM_LITTLE_ENDIAN_ADDRESS(n)                                                  \
+    ((uint32_t)((((uint8_t)n[3]) << 24U) | (((uint8_t)n[2]) << 16U) | (((uint8_t)n[1]) << 8U) | \
+                (((uint8_t)n[0]) << 0U)))
+
+#define USB_LONG_TO_BIG_ENDIAN_ADDRESS(n, m) \
+    {                                        \
+        m[0] = ((n >> 24U) & 0xFFU);         \
+        m[1] = ((n >> 16U) & 0xFFU);         \
+        m[2] = ((n >> 8U) & 0xFFU);          \
+        m[3] = (n & 0xFFU);                  \
+    }
+
+#define USB_LONG_FROM_BIG_ENDIAN_ADDRESS(n)                                                     \
+    ((uint32_t)((((uint8_t)n[0]) << 24U) | (((uint8_t)n[1]) << 16U) | (((uint8_t)n[2]) << 8U) | \
+                (((uint8_t)n[3]) << 0U)))
+
+#define USB_SHORT_TO_LITTLE_ENDIAN_ADDRESS(n, m) \
+    {                                            \
+        m[1] = ((n >> 8U) & 0xFFU);              \
+        m[0] = (n & 0xFFU);                      \
+    }
+
+#define USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(n) ((uint32_t)((((uint8_t)n[1]) << 8U) | (((uint8_t)n[0]) << 0U)))
+
+#define USB_SHORT_TO_BIG_ENDIAN_ADDRESS(n, m) \
+    {                                         \
+        m[0] = ((n >> 8U) & 0xFFU);           \
+        m[1] = (n & 0xFFU);                   \
+    }
+
+#define USB_SHORT_FROM_BIG_ENDIAN_ADDRESS(n) ((uint32_t)((((uint8_t)n[0]) << 8U) | (((uint8_t)n[1]) << 0U)))
+
+#define USB_LONG_TO_LITTLE_ENDIAN_DATA(n, m)           \
+    {                                                  \
+        *((uint8_t *)&(m) + 3) = ((n >> 24U) & 0xFFU); \
+        *((uint8_t *)&(m) + 2) = ((n >> 16U) & 0xFFU); \
+        *((uint8_t *)&(m) + 1) = ((n >> 8U) & 0xFFU);  \
+        *((uint8_t *)&(m) + 0) = (n & 0xFFU);          \
+    }
+
+#define USB_LONG_FROM_LITTLE_ENDIAN_DATA(n)                                             \
+    ((uint32_t)(((*((uint8_t *)&(n) + 3)) << 24U) | ((*((uint8_t *)&(n) + 2)) << 16U) | \
+                ((*((uint8_t *)&(n) + 1)) << 8U) | ((*((uint8_t *)&(n))) << 0U)))
+
+#define USB_SHORT_TO_LITTLE_ENDIAN_DATA(n, m)         \
+    {                                                 \
+        *((uint8_t *)&(m) + 1) = ((n >> 8U) & 0xFFU); \
+        *((uint8_t *)&(m)) = ((n)&0xFFU);             \
+    }
+
+#define USB_SHORT_FROM_LITTLE_ENDIAN_DATA(n) ((uint32_t)(((*((uint8_t *)&(n) + 1)) << 8U) | ((*((uint8_t *)&(n))))))
+
+#else
+
+#define USB_SHORT_TO_LITTLE_ENDIAN(n) (n)
+#define USB_LONG_TO_LITTLE_ENDIAN(n) (n)
+#define USB_SHORT_FROM_LITTLE_ENDIAN(n) (n)
+#define USB_LONG_FROM_LITTLE_ENDIAN(n) (n)
+
+#define USB_SHORT_TO_BIG_ENDIAN(n) SWAP2BYTE_CONST(n)
+#define USB_LONG_TO_BIG_ENDIAN(n) SWAP4BYTE_CONST(n)
+#define USB_SHORT_FROM_BIG_ENDIAN(n) SWAP2BYTE_CONST(n)
+#define USB_LONG_FROM_BIG_ENDIAN(n) SWAP4BYTE_CONST(n)
+
+#define USB_LONG_TO_LITTLE_ENDIAN_ADDRESS(n, m) \
+    {                                           \
+        m[3] = ((n >> 24U) & 0xFFU);            \
+        m[2] = ((n >> 16U) & 0xFFU);            \
+        m[1] = ((n >> 8U) & 0xFFU);             \
+        m[0] = (n & 0xFFU);                     \
+    }
+
+#define USB_LONG_FROM_LITTLE_ENDIAN_ADDRESS(n)                                                  \
+    ((uint32_t)((((uint8_t)n[3]) << 24U) | (((uint8_t)n[2]) << 16U) | (((uint8_t)n[1]) << 8U) | \
+                (((uint8_t)n[0]) << 0U)))
+
+#define USB_LONG_TO_BIG_ENDIAN_ADDRESS(n, m) \
+    {                                        \
+        m[0] = ((n >> 24U) & 0xFFU);         \
+        m[1] = ((n >> 16U) & 0xFFU);         \
+        m[2] = ((n >> 8U) & 0xFFU);          \
+        m[3] = (n & 0xFFU);                  \
+    }
+
+#define USB_LONG_FROM_BIG_ENDIAN_ADDRESS(n)                                                     \
+    ((uint32_t)((((uint8_t)n[0]) << 24U) | (((uint8_t)n[1]) << 16U) | (((uint8_t)n[2]) << 8U) | \
+                (((uint8_t)n[3]) << 0U)))
+
+#define USB_SHORT_TO_LITTLE_ENDIAN_ADDRESS(n, m) \
+    {                                            \
+        m[1] = ((n >> 8U) & 0xFFU);              \
+        m[0] = (n & 0xFFU);                      \
+    }
+
+#define USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(n) ((uint32_t)((((uint8_t)n[1]) << 8U) | (((uint8_t)n[0]) << 0U)))
+
+#define USB_SHORT_TO_BIG_ENDIAN_ADDRESS(n, m) \
+    {                                         \
+        m[0] = ((n >> 8U) & 0xFFU);           \
+        m[1] = (n & 0xFFU);                   \
+    }
+
+#define USB_SHORT_FROM_BIG_ENDIAN_ADDRESS(n) ((uint32_t)((((uint8_t)n[0]) << 8U) | (((uint8_t)n[1]) << 0U)))
+
+#define USB_LONG_TO_LITTLE_ENDIAN_DATA(n, m)           \
+    {                                                  \
+        *((uint8_t *)&(m) + 3) = ((n >> 24U) & 0xFFU); \
+        *((uint8_t *)&(m) + 2) = ((n >> 16U) & 0xFFU); \
+        *((uint8_t *)&(m) + 1) = ((n >> 8U) & 0xFFU);  \
+        *((uint8_t *)&(m) + 0) = (n & 0xFFU);          \
+    }
+
+#define USB_LONG_FROM_LITTLE_ENDIAN_DATA(n)                                             \
+    ((uint32_t)(((*((uint8_t *)&(n) + 3)) << 24U) | ((*((uint8_t *)&(n) + 2)) << 16U) | \
+                ((*((uint8_t *)&(n) + 1)) << 8U) | ((*((uint8_t *)&(n))) << 0U)))
+
+#define USB_SHORT_TO_LITTLE_ENDIAN_DATA(n, m)         \
+    {                                                 \
+        *((uint8_t *)&(m) + 1) = ((n >> 8U) & 0xFFU); \
+        *((uint8_t *)&(m)) = ((n)&0xFFU);             \
+    }
+
+#define USB_SHORT_FROM_LITTLE_ENDIAN_DATA(n) ((uint32_t)(((*((uint8_t *)&(n) + 1)) << 8U) | ((*((uint8_t *)&(n))))))
+
+#endif
+
+/*
+ * The following MACROs (USB_GLOBAL, USB_BDT, USB_RAM_ADDRESS_ALIGNMENT, etc) are only used for USB device stack.
+ * The USB device global variables are put into the section m_usb_global and m_usb_bdt or the section
+ * .bss.m_usb_global and .bss.m_usb_bdt by using the MACRO USB_GLOBAL and USB_BDT. In this way, the USB device
+ * global variables can be linked into USB dedicated RAM by USB_STACK_USE_DEDICATED_RAM.
+ * The MACRO USB_STACK_USE_DEDICATED_RAM is used to decide the USB stack uses dedicated RAM or not. The value of
+ * the marco can be set as 0, USB_STACK_DEDICATED_RAM_TYPE_BDT_GLOBAL, or USB_STACK_DEDICATED_RAM_TYPE_BDT.
+ * The MACRO USB_STACK_DEDICATED_RAM_TYPE_BDT_GLOBAL means USB device global variables, including USB_BDT and
+ * USB_GLOBAL, are put into the USB dedicated RAM. This feature can only be enabled when the USB dedicated RAM
+ * is not less than 2K Bytes.
+ * The MACRO USB_STACK_DEDICATED_RAM_TYPE_BDT means USB device global variables, only including USB_BDT, are put
+ * into the USB dedicated RAM, the USB_GLOBAL will be put into .bss section. This feature is used for some SOCs,
+ * the USB dedicated RAM size is not more than 512 Bytes.
+ */
+#define USB_STACK_DEDICATED_RAM_TYPE_BDT_GLOBAL 1
+#define USB_STACK_DEDICATED_RAM_TYPE_BDT 2
+
+#if defined(__ICCARM__)
+
+#define USB_WEAK_VAR __attribute__((weak))
+#define USB_WEAK_FUN __attribute__((weak))
+/* disable misra 19.13 */
+_Pragma("diag_suppress=Pm120")
+#define USB_ALIGN_PRAGMA(x) _Pragma(#x)
+    _Pragma("diag_default=Pm120")
+
+#define USB_RAM_ADDRESS_ALIGNMENT(n) USB_ALIGN_PRAGMA(data_alignment = n)
+        _Pragma("diag_suppress=Pm120")
+#define USB_LINK_SECTION_PART(str) _Pragma(#str)
+#define USB_LINK_SECTION_SUB(sec) USB_LINK_SECTION_PART(location = #sec)
+#define USB_LINK_USB_GLOBAL _Pragma("location = \"m_usb_global\"")
+#define USB_LINK_USB_BDT _Pragma("location = \"m_usb_bdt\"")
+#define USB_LINK_USB_GLOBAL_BSS _Pragma("location = \".bss.m_usb_global\"")
+#define USB_LINK_USB_BDT_BSS _Pragma("location = \".bss.m_usb_bdt\"")
+            _Pragma("diag_default=Pm120")
+#define USB_LINK_DMA_NONINIT_DATA _Pragma("location = \"m_usb_dma_noninit_data\"")
+#define USB_LINK_NONCACHE_NONINIT_DATA _Pragma("location = \"NonCacheable\"")
+#elif defined(__CC_ARM)
+
+#define USB_WEAK_VAR __attribute__((weak))
+#define USB_WEAK_FUN __weak
+#define USB_RAM_ADDRESS_ALIGNMENT(n) __attribute__((aligned(n)))
+#define USB_LINK_SECTION_SUB(sec) __attribute__((section(#sec)))
+#define USB_LINK_USB_GLOBAL __attribute__((section("m_usb_global"))) __attribute__((zero_init))
+#define USB_LINK_USB_BDT __attribute__((section("m_usb_bdt"))) __attribute__((zero_init))
+#define USB_LINK_USB_GLOBAL_BSS __attribute__((section(".bss.m_usb_global"))) __attribute__((zero_init))
+#define USB_LINK_USB_BDT_BSS __attribute__((section(".bss.m_usb_bdt"))) __attribute__((zero_init))
+#define USB_LINK_DMA_NONINIT_DATA __attribute__((section("m_usb_dma_noninit_data"))) __attribute__((zero_init))
+#define USB_LINK_NONCACHE_NONINIT_DATA __attribute__((section("NonCacheable"))) __attribute__((zero_init))
+
+#elif defined(__GNUC__)
+
+#define USB_WEAK_VAR __attribute__((weak))
+#define USB_WEAK_FUN __attribute__((weak))
+#define USB_RAM_ADDRESS_ALIGNMENT(n) __attribute__((aligned(n)))
+#define USB_LINK_SECTION_SUB(sec) __attribute__((section(#sec)))
+#define USB_LINK_USB_GLOBAL __attribute__((section("m_usb_global, \"aw\", %nobits @")))
+#define USB_LINK_USB_BDT __attribute__((section("m_usb_bdt, \"aw\", %nobits @")))
+#define USB_LINK_USB_GLOBAL_BSS __attribute__((section(".bss.m_usb_global, \"aw\", %nobits @")))
+#define USB_LINK_USB_BDT_BSS __attribute__((section(".bss.m_usb_bdt, \"aw\", %nobits @")))
+#define USB_LINK_DMA_NONINIT_DATA __attribute__((section("m_usb_dma_noninit_data, \"aw\", %nobits @")))
+#define USB_LINK_NONCACHE_NONINIT_DATA __attribute__((section("NonCacheable, \"aw\", %nobits @")))
+
+#else
+#error The tool-chain is not supported.
+#endif
+
+#if (defined(USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE) && (USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE)) || \
+    (defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE))
+
+#if ((defined(FSL_FEATURE_L2CACHE_LINESIZE_BYTE)) && (defined(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE)))
+#define USB_CACHE_LINESIZE MAX(FSL_FEATURE_L2CACHE_LINESIZE_BYTE, FSL_FEATURE_L1DCACHE_LINESIZE_BYTE)
+#elif(defined(FSL_FEATURE_L2CACHE_LINESIZE_BYTE))
+#define USB_CACHE_LINESIZE MAX(FSL_FEATURE_L2CACHE_LINESIZE_BYTE, 0)
+#elif(defined(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE))
+#define USB_CACHE_LINESIZE MAX(0, FSL_FEATURE_L1DCACHE_LINESIZE_BYTE)
+#else
+#define USB_CACHE_LINESIZE 4
+#endif
+
+#else
+#define USB_CACHE_LINESIZE 4
+#endif
+
+#if (((defined(USB_DEVICE_CONFIG_LPCIP3511FS)) && (USB_DEVICE_CONFIG_LPCIP3511FS > 0U)) || \
+     ((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U)))
+#define USB_DATA_ALIGN 64
+#else
+#define USB_DATA_ALIGN 4
+#endif
+
+#define USB_DATA_ALIGN_SIZE MAX(USB_CACHE_LINESIZE, USB_DATA_ALIGN)
+
+#define USB_DATA_ALIGN_SIZE_MULTIPLE(n) ((n + USB_DATA_ALIGN_SIZE - 1) & (~(USB_DATA_ALIGN_SIZE - 1)))
+
+#if defined(USB_STACK_USE_DEDICATED_RAM) && (USB_STACK_USE_DEDICATED_RAM == USB_STACK_DEDICATED_RAM_TYPE_BDT_GLOBAL)
+
+#define USB_GLOBAL USB_LINK_USB_GLOBAL
+#define USB_BDT USB_LINK_USB_BDT
+
+#if (defined(USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE) && (USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE)) || \
+    (defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE))
+#define USB_DMA_DATA_NONINIT_SUB USB_LINK_DMA_NONINIT_DATA
+#define USB_DMA_DATA_INIT_SUB USB_LINK_SECTION_SUB(m_usb_dma_init_data)
+#define USB_CONTROLLER_DATA USB_LINK_NONCACHE_NONINIT_DATA
+#else
+#define USB_DMA_DATA_NONINIT_SUB
+#define USB_DMA_DATA_INIT_SUB
+#define USB_CONTROLLER_DATA USB_LINK_USB_GLOBAL
+#endif
+
+#elif defined(USB_STACK_USE_DEDICATED_RAM) && (USB_STACK_USE_DEDICATED_RAM == USB_STACK_DEDICATED_RAM_TYPE_BDT)
+
+#define USB_BDT USB_LINK_USB_BDT
+
+#if (defined(USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE) && (USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE)) || \
+    (defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE))
+#define USB_GLOBAL USB_LINK_DMA_NONINIT_DATA
+#define USB_DMA_DATA_NONINIT_SUB USB_LINK_DMA_NONINIT_DATA
+#define USB_DMA_DATA_INIT_SUB USB_LINK_SECTION_SUB(m_usb_dma_init_data)
+#define USB_CONTROLLER_DATA USB_LINK_NONCACHE_NONINIT_DATA
+#else
+#define USB_GLOBAL USB_LINK_USB_GLOBAL_BSS
+#define USB_DMA_DATA_NONINIT_SUB
+#define USB_DMA_DATA_INIT_SUB
+#define USB_CONTROLLER_DATA
+#endif
+
+#else
+
+#if (defined(USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE) && (USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE)) || \
+    (defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE))
+
+#define USB_GLOBAL USB_LINK_DMA_NONINIT_DATA
+#define USB_BDT USB_LINK_NONCACHE_NONINIT_DATA
+#define USB_DMA_DATA_NONINIT_SUB USB_LINK_DMA_NONINIT_DATA
+#define USB_DMA_DATA_INIT_SUB USB_LINK_SECTION_SUB(m_usb_dma_init_data)
+#define USB_CONTROLLER_DATA USB_LINK_NONCACHE_NONINIT_DATA
+
+#else
+#define USB_GLOBAL USB_LINK_USB_GLOBAL_BSS
+#define USB_BDT USB_LINK_USB_BDT_BSS
+#define USB_DMA_DATA_NONINIT_SUB
+#define USB_DMA_DATA_INIT_SUB
+#define USB_CONTROLLER_DATA
+#endif
+
+#endif
+
+#define USB_DMA_NONINIT_DATA_ALIGN(n) USB_RAM_ADDRESS_ALIGNMENT(n) USB_DMA_DATA_NONINIT_SUB
+#define USB_DMA_INIT_DATA_ALIGN(n) USB_RAM_ADDRESS_ALIGNMENT(n) USB_DMA_DATA_INIT_SUB
+
+#if (defined(USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE) && (USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE)) || \
+    (defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE))
+#define USB_DMA_DATA_NONCACHEABLE USB_LINK_NONCACHE_NONINIT_DATA
+
+#else
+#define USB_DMA_DATA_NONCACHEABLE
+#endif
+
+#define USB_GLOBAL_DEDICATED_RAM USB_LINK_USB_GLOBAL
+
+/* #define USB_RAM_ADDRESS_NONCACHEREG_ALIGNMENT(n, var) AT_NONCACHEABLE_SECTION_ALIGN(var, n) */
+/* #define USB_RAM_ADDRESS_NONCACHEREG(var) AT_NONCACHEABLE_SECTION(var) */
+
+#endif /* __USB_MISC_H__ */

+ 296 - 0
bsp/imxrt1052-evk/drivers/usb/include/usb_spec.h

@@ -0,0 +1,296 @@
+/*
+ * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
+ * Copyright 2016 NXP
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright notice, this list
+ *   of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright notice, this
+ *   list of conditions and the following disclaimer in the documentation and/or
+ *   other materials provided with the distribution.
+ *
+ * o Neither the name of the copyright holder nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __USB_SPEC_H__
+#define __USB_SPEC_H__
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/* USB speed (the value cannot be changed because EHCI QH use the value directly)*/
+#define USB_SPEED_FULL (0x00U)
+#define USB_SPEED_LOW (0x01U)
+#define USB_SPEED_HIGH (0x02U)
+
+/* Set up packet structure */
+typedef struct _usb_setup_struct
+{
+    uint8_t bmRequestType;
+    uint8_t bRequest;
+    uint16_t wValue;
+    uint16_t wIndex;
+    uint16_t wLength;
+} usb_setup_struct_t;
+
+/* USB  standard descriptor endpoint type */
+#define USB_ENDPOINT_CONTROL (0x00U)
+#define USB_ENDPOINT_ISOCHRONOUS (0x01U)
+#define USB_ENDPOINT_BULK (0x02U)
+#define USB_ENDPOINT_INTERRUPT (0x03U)
+
+/* USB  standard descriptor transfer direction (cannot change the value because iTD use the value directly) */
+#define USB_OUT (0U)
+#define USB_IN (1U)
+
+/* USB standard descriptor length */
+#define USB_DESCRIPTOR_LENGTH_DEVICE (0x12U)
+#define USB_DESCRIPTOR_LENGTH_CONFIGURE (0x09U)
+#define USB_DESCRIPTOR_LENGTH_INTERFACE (0x09U)
+#define USB_DESCRIPTOR_LENGTH_ENDPOINT (0x07U)
+#define USB_DESCRIPTOR_LENGTH_DEVICE_QUALITIER (0x0AU)
+#define USB_DESCRIPTOR_LENGTH_OTG_DESCRIPTOR (5U)
+#define USB_DESCRIPTOR_LENGTH_BOS_DESCRIPTOR (5U)
+
+/* USB Device Capability Type Codes */
+#define USB_DESCRIPTOR_TYPE_DEVICE_CAPABILITY_WIRELESS (0x01U)
+#define USB_DESCRIPTOR_TYPE_DEVICE_CAPABILITY_USB20_EXTENSION (0x02U)
+#define USB_DESCRIPTOR_TYPE_DEVICE_CAPABILITY_SUPERSPEED (0x03U)
+
+/* USB standard descriptor type */
+#define USB_DESCRIPTOR_TYPE_DEVICE (0x01U)
+#define USB_DESCRIPTOR_TYPE_CONFIGURE (0x02U)
+#define USB_DESCRIPTOR_TYPE_STRING (0x03U)
+#define USB_DESCRIPTOR_TYPE_INTERFACE (0x04U)
+#define USB_DESCRIPTOR_TYPE_ENDPOINT (0x05U)
+#define USB_DESCRIPTOR_TYPE_DEVICE_QUALITIER (0x06U)
+#define USB_DESCRIPTOR_TYPE_OTHER_SPEED_CONFIGURATION (0x07U)
+#define USB_DESCRIPTOR_TYPE_INTERFAACE_POWER (0x08U)
+#define USB_DESCRIPTOR_TYPE_OTG (0x09U)
+#define USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION (0x0BU)
+#define USB_DESCRIPTOR_TYPE_BOS (0x0F)
+#define USB_DESCRIPTOR_TYPE_DEVICE_CAPABILITY (0x10)
+
+#define USB_DESCRIPTOR_TYPE_HID (0x21U)
+#define USB_DESCRIPTOR_TYPE_HID_REPORT (0x22U)
+#define USB_DESCRIPTOR_TYPE_HID_PHYSICAL (0x23U)
+
+/* USB standard request type */
+#define USB_REQUEST_TYPE_DIR_MASK (0x80U)
+#define USB_REQUEST_TYPE_DIR_SHIFT (7U)
+#define USB_REQUEST_TYPE_DIR_OUT (0x00U)
+#define USB_REQUEST_TYPE_DIR_IN (0x80U)
+
+#define USB_REQUEST_TYPE_TYPE_MASK (0x60U)
+#define USB_REQUEST_TYPE_TYPE_SHIFT (5U)
+#define USB_REQUEST_TYPE_TYPE_STANDARD (0U)
+#define USB_REQUEST_TYPE_TYPE_CLASS (0x20U)
+#define USB_REQUEST_TYPE_TYPE_VENDOR (0x40U)
+
+#define USB_REQUEST_TYPE_RECIPIENT_MASK (0x1FU)
+#define USB_REQUEST_TYPE_RECIPIENT_SHIFT (0U)
+#define USB_REQUEST_TYPE_RECIPIENT_DEVICE (0x00U)
+#define USB_REQUEST_TYPE_RECIPIENT_INTERFACE (0x01U)
+#define USB_REQUEST_TYPE_RECIPIENT_ENDPOINT (0x02U)
+#define USB_REQUEST_TYPE_RECIPIENT_OTHER (0x03U)
+
+/* USB standard request */
+#define USB_REQUEST_STANDARD_GET_STATUS (0x00U)
+#define USB_REQUEST_STANDARD_CLEAR_FEATURE (0x01U)
+#define USB_REQUEST_STANDARD_SET_FEATURE (0x03U)
+#define USB_REQUEST_STANDARD_SET_ADDRESS (0x05U)
+#define USB_REQUEST_STANDARD_GET_DESCRIPTOR (0x06U)
+#define USB_REQUEST_STANDARD_SET_DESCRIPTOR (0x07U)
+#define USB_REQUEST_STANDARD_GET_CONFIGURATION (0x08U)
+#define USB_REQUEST_STANDARD_SET_CONFIGURATION (0x09U)
+#define USB_REQUEST_STANDARD_GET_INTERFACE (0x0AU)
+#define USB_REQUEST_STANDARD_SET_INTERFACE (0x0BU)
+#define USB_REQUEST_STANDARD_SYNCH_FRAME (0x0CU)
+
+/* USB standard request GET Status */
+#define USB_REQUEST_STANDARD_GET_STATUS_DEVICE_SELF_POWERED_SHIFT (0U)
+#define USB_REQUEST_STANDARD_GET_STATUS_DEVICE_REMOTE_WARKUP_SHIFT (1U)
+
+#define USB_REQUEST_STANDARD_GET_STATUS_ENDPOINT_HALT_MASK (0x01U)
+#define USB_REQUEST_STANDARD_GET_STATUS_ENDPOINT_HALT_SHIFT (0U)
+
+#define USB_REQUEST_STANDARD_GET_STATUS_OTG_STATUS_SELECTOR (0xF000U)
+
+/* USB standard request CLEAR/SET feature */
+#define USB_REQUEST_STANDARD_FEATURE_SELECTOR_ENDPOINT_HALT (0U)
+#define USB_REQUEST_STANDARD_FEATURE_SELECTOR_DEVICE_REMOTE_WAKEUP (1U)
+#define USB_REQUEST_STANDARD_FEATURE_SELECTOR_DEVICE_TEST_MODE (2U)
+#define USB_REQUEST_STANDARD_FEATURE_SELECTOR_B_HNP_ENABLE (3U)
+#define USB_REQUEST_STANDARD_FEATURE_SELECTOR_A_HNP_SUPPORT (4U)
+#define USB_REQUEST_STANDARD_FEATURE_SELECTOR_A_ALT_HNP_SUPPORT (5U)
+
+/* USB standard descriptor configure bmAttributes */
+#define USB_DESCRIPTOR_CONFIGURE_ATTRIBUTE_D7_MASK (0x80U)
+#define USB_DESCRIPTOR_CONFIGURE_ATTRIBUTE_D7_SHIFT (7U)
+
+#define USB_DESCRIPTOR_CONFIGURE_ATTRIBUTE_SELF_POWERED_MASK (0x40U)
+#define USB_DESCRIPTOR_CONFIGURE_ATTRIBUTE_SELF_POWERED_SHIFT (6U)
+
+#define USB_DESCRIPTOR_CONFIGURE_ATTRIBUTE_REMOTE_WAKEUP_MASK (0x20U)
+#define USB_DESCRIPTOR_CONFIGURE_ATTRIBUTE_REMOTE_WAKEUP_SHIFT (5U)
+
+/* USB standard descriptor endpoint bmAttributes */
+#define USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK (0x80U)
+#define USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT (7U)
+#define USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_OUT (0U)
+#define USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_IN (0x80U)
+
+#define USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK (0x0FU)
+#define USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_SHFIT (0U)
+
+#define USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_TYPE_MASK (0x03U)
+#define USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_NUMBER_SHFIT (0U)
+
+#define USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_SYNC_TYPE_MASK (0x0CU)
+#define USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_SYNC_TYPE_SHFIT (2U)
+#define USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_SYNC_TYPE_NO_SYNC (0x00U)
+#define USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_SYNC_TYPE_ASYNC (0x04U)
+#define USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_SYNC_TYPE_ADAPTIVE (0x08U)
+#define USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_SYNC_TYPE_SYNC (0x0CU)
+
+#define USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_USAGE_TYPE_MASK (0x30U)
+#define USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_USAGE_TYPE_SHFIT (4U)
+#define USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_USAGE_TYPE_DATA_ENDPOINT (0x00U)
+#define USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_USAGE_TYPE_FEEDBACK_ENDPOINT (0x10U)
+#define USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_USAGE_TYPE_IMPLICIT_FEEDBACK_DATA_ENDPOINT (0x20U)
+
+#define USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_SIZE_MASK (0x07FFu)
+#define USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_MASK (0x1800u)
+#define USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_SHFIT (11U)
+
+/* USB standard descriptor otg bmAttributes */
+#define USB_DESCRIPTOR_OTG_ATTRIBUTES_SRP_MASK (0x01u)
+#define USB_DESCRIPTOR_OTG_ATTRIBUTES_HNP_MASK (0x02u)
+#define USB_DESCRIPTOR_OTG_ATTRIBUTES_ADP_MASK (0x04u)
+
+/* USB standard descriptor device capability usb20 extension bmAttributes */
+#define USB_DESCRIPTOR_DEVICE_CAPABILITY_USB20_EXTENSION_LPM_MASK (0x02U)
+#define USB_DESCRIPTOR_DEVICE_CAPABILITY_USB20_EXTENSION_LPM_SHIFT (1U)
+#define USB_DESCRIPTOR_DEVICE_CAPABILITY_USB20_EXTENSION_BESL_MASK (0x04U)
+#define USB_DESCRIPTOR_DEVICE_CAPABILITY_USB20_EXTENSION_BESL_SHIFT (2U)
+
+
+/* Language structure */
+typedef struct _usb_language
+{
+    uint8_t **string;    /* The Strings descriptor array */
+    uint32_t *length;    /* The strings descriptor length array */
+    uint16_t languageId; /* The language id of current language */
+} usb_language_t;
+
+typedef struct _usb_language_list
+{
+    uint8_t *languageString;      /* The String 0U pointer */
+    uint32_t stringLength;        /* The String 0U Length */
+    usb_language_t *languageList; /* The language list */
+    uint8_t count;                /* The language count */
+} usb_language_list_t;
+
+typedef struct _usb_descriptor_common
+{
+    uint8_t bLength;         /* Size of this descriptor in bytes */
+    uint8_t bDescriptorType; /* DEVICE Descriptor Type */
+    uint8_t bData[1];        /* Data */
+} usb_descriptor_common_t;
+
+typedef struct _usb_descriptor_device
+{
+    uint8_t bLength;            /* Size of this descriptor in bytes */
+    uint8_t bDescriptorType;    /* DEVICE Descriptor Type */
+    uint8_t bcdUSB[2];          /* UUSB Specification Release Number in Binary-Coded Decimal, e.g. 0x0200U */
+    uint8_t bDeviceClass;       /* Class code */
+    uint8_t bDeviceSubClass;    /* Sub-Class code */
+    uint8_t bDeviceProtocol;    /* Protocol code */
+    uint8_t bMaxPacketSize0;    /* Maximum packet size for endpoint zero */
+    uint8_t idVendor[2];        /* Vendor ID (assigned by the USB-IF) */
+    uint8_t idProduct[2];       /* Product ID (assigned by the manufacturer) */
+    uint8_t bcdDevice[2];       /* Device release number in binary-coded decimal */
+    uint8_t iManufacturer;      /* Index of string descriptor describing manufacturer */
+    uint8_t iProduct;           /* Index of string descriptor describing product */
+    uint8_t iSerialNumber;      /* Index of string descriptor describing the device serial number */
+    uint8_t bNumConfigurations; /* Number of possible configurations */
+} usb_descriptor_device_t;
+
+typedef struct _usb_descriptor_configuration
+{
+    uint8_t bLength;             /* Descriptor size in bytes = 9U */
+    uint8_t bDescriptorType;     /* CONFIGURATION type = 2U or 7U */
+    uint8_t wTotalLength[2];     /* Length of concatenated descriptors */
+    uint8_t bNumInterfaces;      /* Number of interfaces, this configuration. */
+    uint8_t bConfigurationValue; /* Value to set this configuration. */
+    uint8_t iConfiguration;      /* Index to configuration string */
+    uint8_t bmAttributes;        /* Configuration characteristics */
+    uint8_t bMaxPower;           /* Maximum power from bus, 2 mA units */
+} usb_descriptor_configuration_t;
+
+typedef struct _usb_descriptor_interface
+{
+    uint8_t bLength;
+    uint8_t bDescriptorType;
+    uint8_t bInterfaceNumber;
+    uint8_t bAlternateSetting;
+    uint8_t bNumEndpoints;
+    uint8_t bInterfaceClass;
+    uint8_t bInterfaceSubClass;
+    uint8_t bInterfaceProtocol;
+    uint8_t iInterface;
+} usb_descriptor_interface_t;
+
+typedef struct _usb_descriptor_endpoint
+{
+    uint8_t bLength;
+    uint8_t bDescriptorType;
+    uint8_t bEndpointAddress;
+    uint8_t bmAttributes;
+    uint8_t wMaxPacketSize[2];
+    uint8_t bInterval;
+} usb_descriptor_endpoint_t;
+
+typedef struct _usb_descriptor_binary_device_object_store
+{
+    uint8_t bLength;            /* Descriptor size in bytes = 5U */
+    uint8_t bDescriptorType;    /* BOS Descriptor type = 0FU*/
+    uint8_t wTotalLength[2];    /*Length of this descriptor and all of its sub descriptors*/
+    uint8_t bNumDeviceCaps;     /*The number of separate device capability descriptors in the BOS*/
+} usb_descriptor_bos_t;
+
+typedef struct _usb_descriptor_usb20_extension
+{
+    uint8_t bLength;            /* Descriptor size in bytes = 7U */
+    uint8_t bDescriptorType;    /* DEVICE CAPABILITY Descriptor type = 0x10U*/
+    uint8_t bDevCapabilityType;  /*Length of this descriptor and all of its sub descriptors*/
+    uint8_t bmAttributes[4];     /*Bitmap encoding of supported device level features.*/
+} usb_descriptor_usb20_extension_t;
+
+typedef union _usb_descriptor_union
+{
+    usb_descriptor_common_t common;               /* Common descriptor */
+    usb_descriptor_device_t device;               /* Device descriptor */
+    usb_descriptor_configuration_t configuration; /* Configuration descriptor */
+    usb_descriptor_interface_t interface;         /* Interface descriptor */
+    usb_descriptor_endpoint_t endpoint;           /* Endpoint descriptor */
+} usb_descriptor_union_t;
+
+#endif /* __USB_SPEC_H__ */

+ 240 - 0
bsp/imxrt1052-evk/drivers/usb/phy/usb_phy.c

@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
+ * Copyright 2016 - 2017 NXP
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright notice, this list
+ *   of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright notice, this
+ *   list of conditions and the following disclaimer in the documentation and/or
+ *   other materials provided with the distribution.
+ *
+ * o Neither the name of the copyright holder nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <usb/include/usb.h>
+#include "fsl_device_registers.h"
+
+#include <usb/phy/usb_phy.h>
+
+void *USB_EhciPhyGetBase(uint8_t controllerId)
+{
+    void *usbPhyBase = NULL;
+#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
+    uint32_t instance;
+    uint32_t newinstance = 0;
+    uint32_t usbphy_base_temp[] = USBPHY_BASE_ADDRS;
+    uint32_t usbphy_base[] = USBPHY_BASE_ADDRS;
+
+    if (controllerId < kUSB_ControllerEhci0)
+    {
+        return NULL;
+    }
+
+    controllerId = controllerId - kUSB_ControllerEhci0;
+
+    for (instance = 0; instance < (sizeof(usbphy_base_temp) / sizeof(usbphy_base_temp[0])); instance++)
+    {
+        if (usbphy_base_temp[instance])
+        {
+            usbphy_base[newinstance++] = usbphy_base_temp[instance];
+        }
+    }
+    if (controllerId > newinstance)
+    {
+        return NULL;
+    }
+
+    usbPhyBase = (void *)usbphy_base[controllerId];
+#endif
+    return usbPhyBase;
+}
+
+/*!
+ * @brief ehci phy initialization.
+ *
+ * This function initialize ehci phy IP.
+ *
+ * @param[in] controllerId   ehci controller id, please reference to #usb_controller_index_t.
+ * @param[in] freq            the external input clock.
+ *                            for example: if the external input clock is 16M, the parameter freq should be 16000000.
+ *
+ * @retval kStatus_USB_Success      cancel successfully.
+ * @retval kStatus_USB_Error        the freq value is incorrect.
+ */
+uint32_t USB_EhciPhyInit(uint8_t controllerId, uint32_t freq, usb_phy_config_struct_t *phyConfig)
+{
+#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
+    USBPHY_Type *usbPhyBase;
+
+    usbPhyBase = (USBPHY_Type *)USB_EhciPhyGetBase(controllerId);
+    if (NULL == usbPhyBase)
+    {
+        return kStatus_USB_Error;
+    }
+
+#if ((defined FSL_FEATURE_SOC_ANATOP_COUNT) && (FSL_FEATURE_SOC_ANATOP_COUNT > 0U))    
+    ANATOP->HW_ANADIG_REG_3P0.RW =
+        (ANATOP->HW_ANADIG_REG_3P0.RW &
+         (~(ANATOP_HW_ANADIG_REG_3P0_OUTPUT_TRG(0x1F) | ANATOP_HW_ANADIG_REG_3P0_ENABLE_ILIMIT_MASK))) |
+        ANATOP_HW_ANADIG_REG_3P0_OUTPUT_TRG(0x17) | ANATOP_HW_ANADIG_REG_3P0_ENABLE_LINREG_MASK;
+    ANATOP->HW_ANADIG_USB2_CHRG_DETECT.SET =
+        ANATOP_HW_ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B_MASK | ANATOP_HW_ANADIG_USB2_CHRG_DETECT_EN_B_MASK;
+#endif
+    
+#if (defined USB_ANALOG)
+    USB_ANALOG->INSTANCE[controllerId - kUSB_ControllerEhci0].CHRG_DETECT_SET = USB_ANALOG_CHRG_DETECT_CHK_CHRG_B(1) | USB_ANALOG_CHRG_DETECT_EN_B(1); 
+#endif
+    
+#if ((!(defined FSL_FEATURE_SOC_CCM_ANALOG_COUNT)) && (!(defined FSL_FEATURE_SOC_ANATOP_COUNT)))
+
+    usbPhyBase->TRIM_OVERRIDE_EN = 0x001fU; /* override IFR value */
+#endif
+    usbPhyBase->CTRL |= USBPHY_CTRL_SET_ENUTMILEVEL2_MASK; /* support LS device. */
+    usbPhyBase->CTRL |= USBPHY_CTRL_SET_ENUTMILEVEL3_MASK; /* support external FS Hub with LS device connected. */
+    /* PWD register provides overall control of the PHY power state */
+    usbPhyBase->PWD = 0U;
+
+    /* Decode to trim the nominal 17.78mA current source for the High Speed TX drivers on USB_DP and USB_DM. */
+    usbPhyBase->TX =
+        ((usbPhyBase->TX & (~(USBPHY_TX_D_CAL_MASK | USBPHY_TX_TXCAL45DM_MASK | USBPHY_TX_TXCAL45DP_MASK))) |
+         (USBPHY_TX_D_CAL(phyConfig->D_CAL) | USBPHY_TX_TXCAL45DP(phyConfig->TXCAL45DP) |
+          USBPHY_TX_TXCAL45DM(phyConfig->TXCAL45DM)));
+#endif
+
+    return kStatus_USB_Success;
+}
+
+/*!
+ * @brief ehci phy initialization for suspend and resume.
+ *
+ * This function initialize ehci phy IP for suspend and resume.
+ *
+ * @param[in] controllerId   ehci controller id, please reference to #usb_controller_index_t.
+ * @param[in] freq            the external input clock.
+ *                            for example: if the external input clock is 16M, the parameter freq should be 16000000.
+ *
+ * @retval kStatus_USB_Success      cancel successfully.
+ * @retval kStatus_USB_Error        the freq value is incorrect.
+ */
+uint32_t USB_EhciLowPowerPhyInit(uint8_t controllerId, uint32_t freq, usb_phy_config_struct_t *phyConfig)
+{
+#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
+    USBPHY_Type *usbPhyBase;
+
+    usbPhyBase = (USBPHY_Type *)USB_EhciPhyGetBase(controllerId);
+    if (NULL == usbPhyBase)
+    {
+        return kStatus_USB_Error;
+    }
+
+#if ((!(defined FSL_FEATURE_SOC_CCM_ANALOG_COUNT)) && (!(defined FSL_FEATURE_SOC_ANATOP_COUNT)))
+    usbPhyBase->TRIM_OVERRIDE_EN = 0x001fU; /* override IFR value */
+#endif
+
+#if ((defined USBPHY_CTRL_AUTORESUME_EN_MASK) && (USBPHY_CTRL_AUTORESUME_EN_MASK > 0U))
+    usbPhyBase->CTRL |= USBPHY_CTRL_AUTORESUME_EN_MASK;
+#else
+    usbPhyBase->CTRL |= USBPHY_CTRL_ENAUTO_PWRON_PLL_MASK;
+#endif
+    usbPhyBase->CTRL |= USBPHY_CTRL_ENAUTOCLR_CLKGATE_MASK | USBPHY_CTRL_ENAUTOCLR_PHY_PWD_MASK;
+    usbPhyBase->CTRL |= USBPHY_CTRL_SET_ENUTMILEVEL2_MASK; /* support LS device. */
+    usbPhyBase->CTRL |= USBPHY_CTRL_SET_ENUTMILEVEL3_MASK; /* support external FS Hub with LS device connected. */
+    /* PWD register provides overall control of the PHY power state */
+    usbPhyBase->PWD = 0U;
+#if ((!(defined FSL_FEATURE_SOC_CCM_ANALOG_COUNT)) && (!(defined FSL_FEATURE_SOC_ANATOP_COUNT)))
+    /* now the 480MHz USB clock is up, then configure fractional divider after PLL with PFD
+     * pfd clock = 480MHz*18/N, where N=18~35
+     * Please note that USB1PFDCLK has to be less than 180MHz for RUN or HSRUN mode
+     */
+    usbPhyBase->ANACTRL |= USBPHY_ANACTRL_PFD_FRAC(24);   /* N=24 */
+    usbPhyBase->ANACTRL |= USBPHY_ANACTRL_PFD_CLK_SEL(1); /* div by 4 */
+
+    usbPhyBase->ANACTRL &= ~USBPHY_ANACTRL_DEV_PULLDOWN_MASK;
+    usbPhyBase->ANACTRL &= ~USBPHY_ANACTRL_PFD_CLKGATE_MASK;
+    while (!(usbPhyBase->ANACTRL & USBPHY_ANACTRL_PFD_STABLE_MASK))
+    {
+    }
+#endif
+    /* Decode to trim the nominal 17.78mA current source for the High Speed TX drivers on USB_DP and USB_DM. */
+    usbPhyBase->TX =
+        ((usbPhyBase->TX & (~(USBPHY_TX_D_CAL_MASK | USBPHY_TX_TXCAL45DM_MASK | USBPHY_TX_TXCAL45DP_MASK))) |
+         (USBPHY_TX_D_CAL(phyConfig->D_CAL) | USBPHY_TX_TXCAL45DP(phyConfig->TXCAL45DP) |
+          USBPHY_TX_TXCAL45DM(phyConfig->TXCAL45DM)));
+#endif
+
+    return kStatus_USB_Success;
+}
+
+/*!
+ * @brief ehci phy de-initialization.
+ *
+ * This function de-initialize ehci phy IP.
+ *
+ * @param[in] controllerId   ehci controller id, please reference to #usb_controller_index_t.
+ */
+void USB_EhciPhyDeinit(uint8_t controllerId)
+{
+#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
+    USBPHY_Type *usbPhyBase;
+
+    usbPhyBase = (USBPHY_Type *)USB_EhciPhyGetBase(controllerId);
+    if (NULL == usbPhyBase)
+    {
+        return;
+    }
+#if ((!(defined FSL_FEATURE_SOC_CCM_ANALOG_COUNT)) && (!(defined FSL_FEATURE_SOC_ANATOP_COUNT)))
+    usbPhyBase->PLL_SIC &= ~USBPHY_PLL_SIC_PLL_POWER_MASK;       /* power down PLL */
+    usbPhyBase->PLL_SIC &= ~USBPHY_PLL_SIC_PLL_EN_USB_CLKS_MASK; /* disable USB clock output from USB PHY PLL */
+#endif
+    usbPhyBase->CTRL |= USBPHY_CTRL_CLKGATE_MASK; /* set to 1U to gate clocks */
+#endif
+}
+
+/*!
+ * @brief ehci phy disconnect detection enable or disable.
+ *
+ * This function enable/disable host ehci disconnect detection.
+ *
+ * @param[in] controllerId   ehci controller id, please reference to #usb_controller_index_t.
+ * @param[in] enable
+ *            1U - enable;
+ *            0U - disable;
+ */
+void USB_EhcihostPhyDisconnectDetectCmd(uint8_t controllerId, uint8_t enable)
+{
+#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
+    USBPHY_Type *usbPhyBase;
+
+    usbPhyBase = (USBPHY_Type *)USB_EhciPhyGetBase(controllerId);
+    if (NULL == usbPhyBase)
+    {
+        return;
+    }
+
+    if (enable)
+    {
+        usbPhyBase->CTRL |= USBPHY_CTRL_ENHOSTDISCONDETECT_MASK;
+    }
+    else
+    {
+        usbPhyBase->CTRL &= (~USBPHY_CTRL_ENHOSTDISCONDETECT_MASK);
+    }
+#endif
+}

+ 113 - 0
bsp/imxrt1052-evk/drivers/usb/phy/usb_phy.h

@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2015, Freescale Semiconductor, Inc.
+ * Copyright 2016 - 2017 NXP
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright notice, this list
+ *   of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright notice, this
+ *   list of conditions and the following disclaimer in the documentation and/or
+ *   other materials provided with the distribution.
+ *
+ * o Neither the name of the copyright holder nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __USB_PHY_H__
+#define __USB_PHY_H__
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+typedef struct _usb_phy_config_struct
+{
+    uint8_t D_CAL;     /* Decode to trim the nominal 17.78mA current source */
+    uint8_t TXCAL45DP; /* Decode to trim the nominal 45-Ohm series termination resistance to the USB_DP output pin */
+    uint8_t TXCAL45DM; /* Decode to trim the nominal 45-Ohm series termination resistance to the USB_DM output pin */
+} usb_phy_config_struct_t;
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/*******************************************************************************
+ * API
+ ******************************************************************************/
+/*!
+ * @brief EHCI PHY get USB phy bass address.
+ *
+ * This function is used to get USB phy bass address.
+ *
+ * @param[in] controllerId    EHCI controller ID; See the #usb_controller_index_t.
+ *
+ * @retval USB phy bass address.
+ */
+extern void *USB_EhciPhyGetBase(uint8_t controllerId);
+
+/*!
+ * @brief EHCI PHY initialization.
+ *
+ * This function initializes the EHCI PHY IP.
+ *
+ * @param[in] controllerId    EHCI controller ID; See the #usb_controller_index_t.
+ * @param[in] freq            The external input clock.
+ *
+ * @retval kStatus_USB_Success      Cancel successfully.
+ * @retval kStatus_USB_Error        The freq value is incorrect.
+ */
+extern uint32_t USB_EhciPhyInit(uint8_t controllerId, uint32_t freq, usb_phy_config_struct_t *phyConfig);
+
+/*!
+ * @brief ehci phy initialization for suspend and resume.
+ *
+ * This function initialize ehci phy IP for suspend and resume.
+ *
+ * @param[in] controllerId   ehci controller id, please reference to #usb_controller_index_t.
+ * @param[in] freq            the external input clock.
+ *                            for example: if the external input clock is 16M, the parameter freq should be 16000000.
+ *
+ * @retval kStatus_USB_Success      cancel successfully.
+ * @retval kStatus_USB_Error        the freq value is incorrect.
+ */
+extern uint32_t USB_EhciLowPowerPhyInit(uint8_t controllerId, uint32_t freq, usb_phy_config_struct_t *phyConfig);
+
+/*!
+ * @brief EHCI PHY deinitialization.
+ *
+ * This function deinitializes the EHCI PHY IP.
+ *
+ * @param[in] controllerId   EHCI controller ID; See #usb_controller_index_t.
+ */
+extern void USB_EhciPhyDeinit(uint8_t controllerId);
+
+/*!
+ * @brief EHCI PHY disconnect detection enable or disable.
+ *
+ * This function enable/disable the host EHCI disconnect detection.
+ *
+ * @param[in] controllerId   EHCI controller ID; See #usb_controller_index_t.
+ * @param[in] enable
+ *            1U - enable;
+ *            0U - disable;
+ */
+extern void USB_EhcihostPhyDisconnectDetectCmd(uint8_t controllerId, uint8_t enable);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __USB_PHY_H__ */

+ 2 - 0
bsp/stm32f10x-HAL/drivers/drv_usb.c

@@ -28,6 +28,7 @@ static struct ep_id _ep_pool[] =
     {0x1,  USB_EP_ATTR_BULK,        USB_DIR_OUT,    64, ID_UNASSIGNED},
     {0x2,  USB_EP_ATTR_INT,         USB_DIR_OUT,    64, ID_UNASSIGNED},
     {0x2,  USB_EP_ATTR_INT,         USB_DIR_IN,     64, ID_UNASSIGNED},
+    {0x3,  USB_EP_ATTR_INT,         USB_DIR_IN,     64, ID_UNASSIGNED},
     {0xFF, USB_EP_ATTR_TYPE_MASK,   USB_DIR_MASK,   0,  ID_ASSIGNED  },
 };
 
@@ -234,6 +235,7 @@ static rt_err_t _init(rt_device_t device)
     HAL_PCDEx_PMAConfig(pcd , 0x01 , PCD_SNG_BUF, 0x118);
     HAL_PCDEx_PMAConfig(pcd , 0x82 , PCD_SNG_BUF, 0xD8);   
     HAL_PCDEx_PMAConfig(pcd , 0x02 , PCD_SNG_BUF, 0x158);
+    HAL_PCDEx_PMAConfig(pcd , 0x83 , PCD_SNG_BUF, 0x198);
     HAL_PCD_Start(pcd);
 
     return RT_EOK;

+ 0 - 4
bsp/v2m-mps2/rtconfig.py

@@ -5,9 +5,6 @@ ARCH='arm'
 CPU='cortex-m7'
 CROSS_TOOL='keil'
 
-if os.getenv('RTT_CC'):
-	CROSS_TOOL = os.getenv('RTT_CC')
-
 if CROSS_TOOL == 'keil':
 	PLATFORM 	= 'armcc'
 	EXEC_PATH 	= 'C:/Keil_v5'
@@ -48,7 +45,6 @@ if PLATFORM == 'armcc':
     CFLAGS += ' --c99'
 
     POST_ACTION = 'fromelf -z $TARGET'
-    # POST_ACTION = 'fromelf --bin $TARGET --output rtthread.bin \nfromelf -z $TARGET'
 else:
 	print("only support armcc in this bsp")
 	exit(-1)

+ 1 - 0
components/drivers/Kconfig

@@ -90,6 +90,7 @@ config RT_USING_RTC
         default n
     config RTC_SYNC_USING_NTP
         bool "Using NTP auto sync RTC time"
+        select PKG_USING_NETUTILS
         select PKG_NETUTILS_NTP
         default n
         

+ 2 - 0
components/drivers/rtc/rtc.c

@@ -225,6 +225,8 @@ int rt_rtc_ntp_sync_init(void)
     }
 
     init_ok = RT_TRUE;
+		
+    return RT_EOK;
 }
 INIT_COMPONENT_EXPORT(rt_rtc_ntp_sync_init);
 #endif /* RTC_SYNC_USING_NTP */

+ 1 - 1
components/drivers/usb/usbdevice/core/usbdevice.c

@@ -183,7 +183,7 @@ rt_err_t rt_usb_device_init(void)
 #ifdef RT_USB_DEVICE_COMPOSITE
     rt_usbd_device_set_descriptor(udevice, &compsit_desc);
     rt_usbd_device_set_string(udevice, ustring);
-    rt_usbd_device_set_qualifier(device, &dev_qualifier);
+    rt_usbd_device_set_qualifier(udevice, &dev_qualifier);
 #else
     rt_usbd_device_set_descriptor(udevice, func->dev_desc);
 #endif

+ 5 - 0
components/libc/compilers/armlibc/sys/unistd.h

@@ -4,6 +4,11 @@
 #include <rtthread.h>
 
 #ifdef RT_USING_DFS
+
+#define STDIN_FILENO    0       /* standard input file descriptor */
+#define STDOUT_FILENO   1       /* standard output file descriptor */
+#define STDERR_FILENO   2       /* standard error file descriptor */
+
 #include <dfs_posix.h>
 #else
 #define _FREAD      0x0001  /* read enabled */