summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bsp/imxrt1052-evk/Kconfig13
-rw-r--r--bsp/imxrt1052-evk/drivers/SConscript7
-rw-r--r--bsp/imxrt1052-evk/drivers/drv_hp_rtc.c2
-rw-r--r--bsp/imxrt1052-evk/drivers/drv_usbd.c503
-rw-r--r--bsp/imxrt1052-evk/drivers/usb/device/usb_device.h644
-rw-r--r--bsp/imxrt1052-evk/drivers/usb/device/usb_device_dci.c1459
-rw-r--r--bsp/imxrt1052-evk/drivers/usb/device/usb_device_dci.h177
-rw-r--r--bsp/imxrt1052-evk/drivers/usb/device/usb_device_ehci.c1807
-rw-r--r--bsp/imxrt1052-evk/drivers/usb/device/usb_device_ehci.h219
-rw-r--r--bsp/imxrt1052-evk/drivers/usb/host/usb_host.h726
-rw-r--r--bsp/imxrt1052-evk/drivers/usb/host/usb_host_devices.c1414
-rw-r--r--bsp/imxrt1052-evk/drivers/usb/host/usb_host_devices.h178
-rw-r--r--bsp/imxrt1052-evk/drivers/usb/host/usb_host_ehci.c4747
-rw-r--r--bsp/imxrt1052-evk/drivers/usb/host/usb_host_ehci.h499
-rw-r--r--bsp/imxrt1052-evk/drivers/usb/host/usb_host_hci.c1052
-rw-r--r--bsp/imxrt1052-evk/drivers/usb/host/usb_host_hci.h131
-rw-r--r--bsp/imxrt1052-evk/drivers/usb/include/usb.h140
-rw-r--r--bsp/imxrt1052-evk/drivers/usb/include/usb_device_config.h185
-rw-r--r--bsp/imxrt1052-evk/drivers/usb/include/usb_ehci.h140
-rw-r--r--bsp/imxrt1052-evk/drivers/usb/include/usb_misc.h452
-rw-r--r--bsp/imxrt1052-evk/drivers/usb/include/usb_spec.h296
-rw-r--r--bsp/imxrt1052-evk/drivers/usb/phy/usb_phy.c240
-rw-r--r--bsp/imxrt1052-evk/drivers/usb/phy/usb_phy.h113
-rw-r--r--bsp/stm32f10x-HAL/drivers/drv_usb.c2
-rw-r--r--bsp/v2m-mps2/rtconfig.py4
-rwxr-xr-xcomponents/drivers/Kconfig1
-rw-r--r--components/drivers/rtc/rtc.c2
-rw-r--r--components/drivers/usb/usbdevice/core/usbdevice.c2
-rw-r--r--components/libc/compilers/armlibc/sys/unistd.h5
29 files changed, 15153 insertions, 7 deletions
diff --git a/bsp/imxrt1052-evk/Kconfig b/bsp/imxrt1052-evk/Kconfig
index 8bfb1e2589..a5c48884a7 100644
--- a/bsp/imxrt1052-evk/Kconfig
+++ b/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
+
+
diff --git a/bsp/imxrt1052-evk/drivers/SConscript b/bsp/imxrt1052-evk/drivers/SConscript
index c18b8ca321..6ca466f3c8 100644
--- a/bsp/imxrt1052-evk/drivers/SConscript
+++ b/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']
diff --git a/bsp/imxrt1052-evk/drivers/drv_hp_rtc.c b/bsp/imxrt1052-evk/drivers/drv_hp_rtc.c
index 29093e0eb8..42448ae737 100644
--- a/bsp/imxrt1052-evk/drivers/drv_hp_rtc.c
+++ b/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;
}
diff --git a/bsp/imxrt1052-evk/drivers/drv_usbd.c b/bsp/imxrt1052-evk/drivers/drv_usbd.c
new file mode 100644
index 0000000000..118842b203
--- /dev/null
+++ b/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;
+}
+
+
+
diff --git a/bsp/imxrt1052-evk/drivers/usb/device/usb_device.h b/bsp/imxrt1052-evk/drivers/usb/device/usb_device.h
new file mode 100644
index 0000000000..99e8a879f8
--- /dev/null
+++ b/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__ */
diff --git a/bsp/imxrt1052-evk/drivers/usb/device/usb_device_dci.c b/bsp/imxrt1052-evk/drivers/usb/device/usb_device_dci.c
new file mode 100644
index 0000000000..dd28bdcbe3
--- /dev/null
+++ b/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 */
diff --git a/bsp/imxrt1052-evk/drivers/usb/device/usb_device_dci.h b/bsp/imxrt1052-evk/drivers/usb/device/usb_device_dci.h
new file mode 100644
index 0000000000..fd4fdceb04
--- /dev/null
+++ b/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__ */
diff --git a/bsp/imxrt1052-evk/drivers/usb/device/usb_device_ehci.c b/bsp/imxrt1052-evk/drivers/usb/device/usb_device_ehci.c
new file mode 100644
index 0000000000..7bb202143d
--- /dev/null
+++ b/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 */
diff --git a/bsp/imxrt1052-evk/drivers/usb/device/usb_device_ehci.h b/bsp/imxrt1052-evk/drivers/usb/device/usb_device_ehci.h
new file mode 100644
index 0000000000..869e063263
--- /dev/null
+++ b/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__ */
diff --git a/bsp/imxrt1052-evk/drivers/usb/host/usb_host.h b/bsp/imxrt1052-evk/drivers/usb/host/usb_host.h
new file mode 100644
index 0000000000..53be402cd3
--- /dev/null
+++ b/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_ */
diff --git a/bsp/imxrt1052-evk/drivers/usb/host/usb_host_devices.c b/bsp/imxrt1052-evk/drivers/usb/host/usb_host_devices.c
new file mode 100644
index 0000000000..42b16e071e
--- /dev/null
+++ b/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;
+}
diff --git a/bsp/imxrt1052-evk/drivers/usb/host/usb_host_devices.h b/bsp/imxrt1052-evk/drivers/usb/host/usb_host_devices.h
new file mode 100644
index 0000000000..422e876a12
--- /dev/null
+++ b/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_ */
diff --git a/bsp/imxrt1052-evk/drivers/usb/host/usb_host_ehci.c b/bsp/imxrt1052-evk/drivers/usb/host/usb_host_ehci.c
new file mode 100644
index 0000000000..8a31514b3a
--- /dev/null
+++ b/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 */
diff --git a/bsp/imxrt1052-evk/drivers/usb/host/usb_host_ehci.h b/bsp/imxrt1052-evk/drivers/usb/host/usb_host_ehci.h
new file mode 100644
index 0000000000..162d6576cd
--- /dev/null
+++ b/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_ */
diff --git a/bsp/imxrt1052-evk/drivers/usb/host/usb_host_hci.c b/bsp/imxrt1052-evk/drivers/usb/host/usb_host_hci.c
new file mode 100644
index 0000000000..927bf8bd9c
--- /dev/null
+++ b/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
diff --git a/bsp/imxrt1052-evk/drivers/usb/host/usb_host_hci.h b/bsp/imxrt1052-evk/drivers/usb/host/usb_host_hci.h
new file mode 100644
index 0000000000..26b6d4a9c5
--- /dev/null
+++ b/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_ */
diff --git a/bsp/imxrt1052-evk/drivers/usb/include/usb.h b/bsp/imxrt1052-evk/drivers/usb/include/usb.h
new file mode 100644
index 0000000000..256896b472
--- /dev/null
+++ b/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__ */
diff --git a/bsp/imxrt1052-evk/drivers/usb/include/usb_device_config.h b/bsp/imxrt1052-evk/drivers/usb/include/usb_device_config.h
new file mode 100644
index 0000000000..551d92edc7
--- /dev/null
+++ b/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_ */
diff --git a/bsp/imxrt1052-evk/drivers/usb/include/usb_ehci.h b/bsp/imxrt1052-evk/drivers/usb/include/usb_ehci.h
new file mode 100644
index 0000000000..edc3496643
--- /dev/null
+++ b/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__ */
diff --git a/bsp/imxrt1052-evk/drivers/usb/include/usb_misc.h b/bsp/imxrt1052-evk/drivers/usb/include/usb_misc.h
new file mode 100644
index 0000000000..4e65cfa94b
--- /dev/null
+++ b/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__ */
diff --git a/bsp/imxrt1052-evk/drivers/usb/include/usb_spec.h b/bsp/imxrt1052-evk/drivers/usb/include/usb_spec.h
new file mode 100644
index 0000000000..d77b7d3598
--- /dev/null
+++ b/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__ */
diff --git a/bsp/imxrt1052-evk/drivers/usb/phy/usb_phy.c b/bsp/imxrt1052-evk/drivers/usb/phy/usb_phy.c
new file mode 100644
index 0000000000..85258c63af
--- /dev/null
+++ b/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
+}
diff --git a/bsp/imxrt1052-evk/drivers/usb/phy/usb_phy.h b/bsp/imxrt1052-evk/drivers/usb/phy/usb_phy.h
new file mode 100644
index 0000000000..0409f9c8b9
--- /dev/null
+++ b/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__ */
diff --git a/bsp/stm32f10x-HAL/drivers/drv_usb.c b/bsp/stm32f10x-HAL/drivers/drv_usb.c
index b77910c90a..bade24f086 100644
--- a/bsp/stm32f10x-HAL/drivers/drv_usb.c
+++ b/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;
diff --git a/bsp/v2m-mps2/rtconfig.py b/bsp/v2m-mps2/rtconfig.py
index b63ea11a91..fd76abcf42 100644
--- a/bsp/v2m-mps2/rtconfig.py
+++ b/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)
diff --git a/components/drivers/Kconfig b/components/drivers/Kconfig
index 90ad1c940f..fc02b0eaed 100755
--- a/components/drivers/Kconfig
+++ b/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
diff --git a/components/drivers/rtc/rtc.c b/components/drivers/rtc/rtc.c
index a33e1dfccf..f64a528ef0 100644
--- a/components/drivers/rtc/rtc.c
+++ b/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 */
diff --git a/components/drivers/usb/usbdevice/core/usbdevice.c b/components/drivers/usb/usbdevice/core/usbdevice.c
index 453084990b..da46425ec4 100644
--- a/components/drivers/usb/usbdevice/core/usbdevice.c
+++ b/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
diff --git a/components/libc/compilers/armlibc/sys/unistd.h b/components/libc/compilers/armlibc/sys/unistd.h
index 38ba8b5072..56979955ba 100644
--- a/components/libc/compilers/armlibc/sys/unistd.h
+++ b/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 */