diff --git a/Ubiquitous/XiUOS/arch/arm/cortex-m7/arch_interrupt.h b/Ubiquitous/XiUOS/arch/arm/cortex-m7/arch_interrupt.h index 589d49e28..f75920620 100644 --- a/Ubiquitous/XiUOS/arch/arm/cortex-m7/arch_interrupt.h +++ b/Ubiquitous/XiUOS/arch/arm/cortex-m7/arch_interrupt.h @@ -29,6 +29,9 @@ #define UART1_IRQn 20 #define UART2_IRQn 21 +#define USB1_IRQn 113 +#define USB2_IRQn 112 + int32 ArchEnableHwIrq(uint32 irq_num); int32 ArchDisableHwIrq(uint32 irq_num); diff --git a/Ubiquitous/XiUOS/board/aiit-arm32-board/.defconfig b/Ubiquitous/XiUOS/board/aiit-arm32-board/.defconfig index 028b6dbab..08045f21c 100644 --- a/Ubiquitous/XiUOS/board/aiit-arm32-board/.defconfig +++ b/Ubiquitous/XiUOS/board/aiit-arm32-board/.defconfig @@ -28,7 +28,7 @@ CONFIG_BSP_USING_UART=y # CONFIG_BSP_USING_UART4 is not set # CONFIG_BSP_USING_UART5 is not set # CONFIG_BSP_USING_USB is not set -# CONFIG_BSP_USING_USBH is not set +# CONFIG_BSP_USING_STM32_USBH is not set # # Hardware feature diff --git a/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/Kconfig b/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/Kconfig index 8dbc94076..a7978bc61 100755 --- a/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/Kconfig +++ b/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/Kconfig @@ -120,7 +120,7 @@ endif menuconfig BSP_USING_USB bool "Using USB device" default n -select BSP_USING_USBH +select BSP_USING_STM32_USBH select RESOURCES_USB select RESOURCES_USB_HOST select USBH_MSTORAGE diff --git a/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/usb/Kconfig b/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/usb/Kconfig index 75c6685ba..4fcd37871 100644 --- a/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/usb/Kconfig +++ b/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/usb/Kconfig @@ -1,7 +1,7 @@ -config BSP_USING_USBH +config BSP_USING_STM32_USBH bool "Using usb host" default y - if BSP_USING_USBH + if BSP_USING_STM32_USBH config USB_BUS_NAME string "usb bus name" default "usb" diff --git a/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/usb/usbh.c b/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/usb/usbh.c index c80645539..c28503494 100644 --- a/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/usb/usbh.c +++ b/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/usb/usbh.c @@ -31,7 +31,7 @@ Modification: *************************************************/ #include -#include +#include #include #include #include diff --git a/Ubiquitous/XiUOS/board/ok1052-c/link.lds b/Ubiquitous/XiUOS/board/ok1052-c/link.lds index 0d3ab2a58..41649a29f 100644 --- a/Ubiquitous/XiUOS/board/ok1052-c/link.lds +++ b/Ubiquitous/XiUOS/board/ok1052-c/link.lds @@ -241,9 +241,9 @@ SECTIONS stack_end = .; __StackTop = .; heap_start = .; - } > m_data2 + } > m_data - PROVIDE(heap_end = ORIGIN(m_data2) + LENGTH(m_data2)); + PROVIDE(heap_end = ORIGIN(m_data) + LENGTH(m_data)); .ARM.attributes 0 : { *(.ARM.attributes) } } diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/Kconfig b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/Kconfig index ef9867af5..91a0c2a5d 100644 --- a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/Kconfig +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/Kconfig @@ -25,3 +25,11 @@ menuconfig BSP_USING_SDIO if BSP_USING_SDIO source "$BSP_DIR/third_party_driver/sdio/Kconfig" endif + +menuconfig BSP_USING_USB + bool "Using USB device" + default n + select RESOURCES_USB + if BSP_USING_USB + source "$BSP_DIR/third_party_driver/usb/Kconfig" + endif diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/Makefile b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/Makefile index 4613b4f05..677573fef 100644 --- a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/Makefile +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/Makefile @@ -16,4 +16,8 @@ ifeq ($(CONFIG_BSP_USING_SDIO),y) SRC_DIR += sdio endif +ifeq ($(CONFIG_BSP_USING_USB),y) + SRC_DIR += usb +endif + include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/include/connect_usb.h b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/include/connect_usb.h new file mode 100644 index 000000000..2510702d7 --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/include/connect_usb.h @@ -0,0 +1,53 @@ +/* +* Copyright (c) 2020 AIIT XUOS Lab +* XiUOS is licensed under Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL v2. +* You may obtain a copy of Mulan PSL v2 at: +* http://license.coscl.org.cn/MulanPSL2 +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + +/** +* @file connect_usb.h +* @brief define ok1052-board usb function and struct +* @version 2.0 +* @author AIIT XUOS Lab +* @date 2022-02-09 +*/ + +#ifndef CONNECT_USB_H +#define CONNECT_USB_H + +#include +#include +#include +#include +#include +#include +#include + +#if defined(FS_VFS) +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define CONTROLLER_ID kUSB_ControllerEhci1 +#define USB_HOST_INTERRUPT_PRIORITY (3U) + +#define USB_HOST_STACK_SIZE 4096 + +#define USB_SINGLE_BLOCK_SIZE 512 + +int Imrt1052HwUsbHostInit(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/Kconfig b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/Kconfig new file mode 100644 index 000000000..a1f439ca9 --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/Kconfig @@ -0,0 +1,15 @@ +config BSP_USING_NXP_USBH + bool "Using usb host by NXP library" + default n + if BSP_USING_NXP_USBH + config USB_BUS_NAME + string "usb bus name" + default "usb" + config USB_DRIVER_NAME + string "usb bus driver name" + default "usb_drv" + config USB_DEVICE_NAME + string "usb bus device name" + default "usb_dev" + endif + diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/Makefile b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/Makefile new file mode 100644 index 000000000..01f068d18 --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/Makefile @@ -0,0 +1,5 @@ +SRC_DIR := nxp_usb_driver + +SRC_FILES := connect_usb.c + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/connect_usb.c b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/connect_usb.c new file mode 100644 index 000000000..dc530f79f --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/connect_usb.c @@ -0,0 +1,296 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/** +* @file connect_usb.c +* @brief support usb host function using bus driver framework on OK1052 board +* @version 2.0 +* @author AIIT XUOS Lab +* @date 2022-02-09 +*/ + +/************************************************* +File name: connect_usb.c +Description: support imxrt1052-board usb host configure and sdio bus register function +Others: take SDK_2.6.1_MIMXRT1052xxxxB/boards/evkbimxrt1050/usb_examples/usb_host_msd_command for references +History: +1. Date: 2022-02-09 +Author: AIIT XUOS Lab +Modification: +1. support imxrt1052-board usb host configure, write and read +2. support imxrt1052-board usb host bus device and driver register +*************************************************/ +#include +#include + +#define BSP_USING_NXP_USBH +#ifdef BSP_USING_NXP_USBH + +/*! @brief USB host msd command instance global variable */ +extern usb_host_msd_command_instance_t g_MsdCommandInstance; +usb_host_handle g_HostHandle; + +extern usb_status_t USB_HostMsdReadApi(usb_host_msd_command_instance_t *msdCommandInstance, uint8_t *buffer, uint32_t pos, uint32_t block_size, uint32_t block_num); +extern usb_status_t USB_HostMsdWriteApi(usb_host_msd_command_instance_t *msdCommandInstance, uint8_t *buffer, uint32_t pos, uint32_t block_size, uint32_t block_num); + +//USB HOST ISR +void UsbOtg2IrqHandler(int irqn, void *arg) +{ + x_base lock = 0; + lock = DISABLE_INTERRUPT(); + + USB_HostEhciIsrFunction(g_HostHandle); + + ENABLE_INTERRUPT(lock); +} +DECLARE_HW_IRQ(USB2_IRQn, UsbOtg2IrqHandler, NONE); + +void UsbHostClockInit(void) +{ + usb_phy_config_struct_t phyConfig = { + BOARD_USB_PHY_D_CAL, + BOARD_USB_PHY_TXCAL45DP, + BOARD_USB_PHY_TXCAL45DM, + }; + + if (CONTROLLER_ID == 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(CONTROLLER_ID, BOARD_XTAL0_CLK_HZ, &phyConfig); +} + +void UsbHostIsrEnable(void) +{ + uint8_t irqNumber; + + uint8_t usbHOSTEhciIrq[] = USBHS_IRQS; + irqNumber = usbHOSTEhciIrq[CONTROLLER_ID - kUSB_ControllerEhci0]; +/* USB_HOST_CONFIG_EHCI */ + +/* Install isr, set priority, and enable IRQ. */ + NVIC_SetPriority((IRQn_Type)irqNumber, USB_HOST_INTERRUPT_PRIORITY); + EnableIRQ((IRQn_Type)irqNumber); +} + +void UsbHostTaskFn(void *param) +{ + USB_HostEhciTaskFunction(param); +} + +/*! + * @brief USB isr function. + */ +static usb_status_t UsbHostEvent(usb_device_handle deviceHandle, + usb_host_configuration_handle configurationHandle, + uint32_t eventCode) +{ + usb_status_t status = kStatus_USB_Success; + switch (eventCode) + { + case kUSB_HostEventAttach: + KPrintf("usb device attached\n"); + status = USB_HostMsdEvent(deviceHandle, configurationHandle, eventCode); + break; + + case kUSB_HostEventNotSupported: + KPrintf("device not supported.\r\n"); + break; + + case kUSB_HostEventEnumerationDone: + status = USB_HostMsdEvent(deviceHandle, configurationHandle, eventCode); + break; + + case kUSB_HostEventDetach: + KPrintf("usb device detached\n"); + status = USB_HostMsdEvent(deviceHandle, configurationHandle, eventCode); + break; + + default: + break; + } + return status; +} + +static void UsbHostApplicationInit(void) +{ + usb_status_t status = kStatus_USB_Success; + + UsbHostClockInit(); + + status = USB_HostInit(CONTROLLER_ID, &g_HostHandle, UsbHostEvent); + if (status != kStatus_USB_Success) { + KPrintf("host init error\r\n"); + return; + } + UsbHostIsrEnable(); + + KPrintf("host init done\r\n"); +} + +#if defined(FS_VFS) +void UsbMountFileSystem() +{ + if (MountFilesystem(USB_BUS_NAME, USB_DEVICE_NAME, USB_DRIVER_NAME, FSTYPE_FATFS, UDISK_MOUNTPOINT) == 0) + KPrintf("Mount FAT on Udisk successful.\n"); + else + KPrintf("Mount FAT on Udisk failed.\n"); +} + +void UsbUnmountFileSystem() +{ + UnmountFileSystem(UDISK_MOUNTPOINT); +} +#endif + +static uint32 UsbHostOpen(void *dev) +{ + return EOK; +} + +static uint32 UsbHostClose(void *dev) +{ + return EOK; +} + +static uint32 UsbHostRead(void *dev, struct BusBlockReadParam *read_param) +{ + usb_status_t status; + + status = USB_HostMsdReadApi(&g_MsdCommandInstance, (uint8 *)read_param->buffer, read_param->pos, USB_SINGLE_BLOCK_SIZE, read_param->size); + if (kStatus_USB_Success == status) { + return read_param->size; + } + + return 0; +} + +static uint32 UsbHostWrite(void *dev, struct BusBlockWriteParam *write_param) +{ + usb_status_t status; + + status = USB_HostMsdWriteApi(&g_MsdCommandInstance, (uint8 *)write_param->buffer, write_param->pos, USB_SINGLE_BLOCK_SIZE, write_param->size); + if (kStatus_USB_Success == status) { + return write_param->size; + } + + return 0; +} + +/*manage the usb device operations*/ +static const struct UsbDevDone dev_done = +{ + .open = UsbHostOpen, + .close = UsbHostClose, + .write = UsbHostWrite, + .read = UsbHostRead, +}; + +static void UsbHostTask(void* parameter) +{ + while (1) { + UsbHostTaskFn(g_HostHandle); + USB_HostMsdTask(&g_MsdCommandInstance); + } +} + +/*Init usb host bus、driver*/ +static int BoardUsbBusInit(struct UsbBus *usb_bus, struct UsbDriver *usb_driver) +{ + x_err_t ret = EOK; + + /*Init the usb bus */ + ret = UsbBusInit(usb_bus, USB_BUS_NAME); + if (EOK != ret) { + KPrintf("board_usb_init UsbBusInit error %d\n", ret); + return ERROR; + } + + /*Init the usb driver*/ + ret = UsbDriverInit(usb_driver, USB_DRIVER_NAME); + if (EOK != ret){ + KPrintf("board_usb_init UsbDriverInit error %d\n", ret); + return ERROR; + } + + /*Attach the usb driver to the usb bus*/ + ret = UsbDriverAttachToBus(USB_DRIVER_NAME, USB_BUS_NAME); + if (EOK != ret) { + KPrintf("board_usb_init USEDriverAttachToBus error %d\n", ret); + return ERROR; + } + + return ret; +} + +/*Attach the usb device to the usb bus*/ +static int BoardUsbDevBend(void) +{ + x_err_t ret = EOK; + static struct UsbHardwareDevice usb_device; + memset(&usb_device, 0, sizeof(struct UsbHardwareDevice)); + + usb_device.dev_done = &dev_done; + + ret = USBDeviceRegister(&usb_device, NONE, USB_DEVICE_NAME); + if (EOK != ret) { + KPrintf("USBDeviceRegister device %s error %d\n", USB_DEVICE_NAME, ret); + return ERROR; + } + + ret = USBDeviceAttachToBus(USB_DEVICE_NAME, USB_BUS_NAME); + if (EOK != ret) { + KPrintf("USBDeviceAttachToBus device %s error %d\n", USB_DEVICE_NAME, ret); + return ERROR; + } + + return ret; +} + +/*RT1052 BOARD USB INIT*/ +int Imrt1052HwUsbHostInit(void) +{ + x_err_t ret = EOK; + int32 usb_host_task = 0; + + static struct UsbBus usb_bus; + memset(&usb_bus, 0, sizeof(struct UsbBus)); + + static struct UsbDriver usb_driver; + memset(&usb_driver, 0, sizeof(struct UsbDriver)); + + UsbHostApplicationInit(); + + ret = BoardUsbBusInit(&usb_bus, &usb_driver); + if (EOK != ret) { + KPrintf("BoardUsbBusInit error ret %u\n", ret); + return ERROR; + } + + ret = BoardUsbDevBend(); + if (EOK != ret) { + KPrintf("BoardUsbDevBend error ret %u\n", ret); + return ERROR; + } + + usb_host_task = KTaskCreate("usbh", UsbHostTask, NONE, + USB_HOST_STACK_SIZE, 8); + if(usb_host_task < 0) { + KPrintf("usb_host_task create failed ...%s %d.\n", __FUNCTION__,__LINE__); + return ERROR; + } + + StartupKTask(usb_host_task); + + return ret; +} + +#endif diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/Makefile b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/Makefile new file mode 100644 index 000000000..c1a2ffb13 --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/Makefile @@ -0,0 +1,5 @@ +SRC_DIR += host phy osa + +SRC_FILES := host_msd_command.c + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/Makefile b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/Makefile new file mode 100644 index 000000000..f871ce276 --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/Makefile @@ -0,0 +1,5 @@ +SRC_DIR += class + +SRC_FILES += usb_host_devices.c usb_host_framework.c usb_host_ehci.c usb_host_hci.c + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/class/Makefile b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/class/Makefile new file mode 100644 index 000000000..f52717f14 --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/class/Makefile @@ -0,0 +1,3 @@ +SRC_FILES += usb_host_msd_ufi.c usb_host_msd.c usb_host_hub.c usb_host_hub_app.c + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/class/usb_host_hub.c b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/class/usb_host_hub.c new file mode 100644 index 000000000..62b4e68ed --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/class/usb_host_hub.c @@ -0,0 +1,608 @@ +/* + * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "usb_host_config.h" +#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB)) +#include "usb_host.h" +#include "usb_host_hub.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/******************************************************************************* + * Prototypes + ******************************************************************************/ +/*! + * @brief hub control transfer callback. + * + * @param param callback parameter. + * @param transfer callback transfer. + * @param status transfer status. + */ +static void USB_HostHubControlCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status); + +/*! + * @brief hub interrupt in transfer callback. + * + * @param param callback parameter. + * @param transfer callback transfer. + * @param status transfer status. + */ +static void USB_HostHubInPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status); + +/*! + * @brief USB_HostHubSendPortReset's transfer callback. + * + * @param param callback parameter. + * @param transfer callback transfer. + * @param status transfer status. + */ +static void USB_HostHubResetCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status); + +/*! + * @brief hub control transfer common code. + * + * @param classHandle the class handle. + * @param requestType request type. + * @param request setup packet request field. + * @param wvalue setup packet wValue field. + * @param windex setup packet wIndex field. + * @param buffer the buffer pointer. + * @param bufferLength the buffer length. + * @param callbackFn this callback is called after this function completes. + * @param callbackParam the first parameter in the callback function. + * + * @return kStatus_USB_Success or error codes. + */ +static usb_status_t USB_HostHubClassRequestCommon(usb_host_class_handle classHandle, + uint8_t requestType, + uint8_t request, + uint16_t wvalue, + uint16_t windex, + uint8_t *buffer, + uint16_t bufferLength, + transfer_callback_t callbackFn, + void *callbackParam); + +/******************************************************************************* + * Variables + ******************************************************************************/ + +/******************************************************************************* + * Code + ******************************************************************************/ + +static void USB_HostHubControlCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status) +{ + usb_host_hub_instance_t *hubInstance = (usb_host_hub_instance_t *)param; + + hubInstance->controlTransfer = NULL; + if (hubInstance->controlCallbackFn) + { + /* callback to application, callback function is initialized in the USB_HostPrinterControl, + USB_HostPrinterSetInterface + or USB_HostHubClassRequestCommon, but is the same function */ + hubInstance->controlCallbackFn(hubInstance->controlCallbackParam, transfer->transferBuffer, + transfer->transferSofar, status); /* callback to application */ + } + USB_HostFreeTransfer(hubInstance->hostHandle, transfer); +} + +static void USB_HostHubInPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status) +{ + usb_host_hub_instance_t *hubInstance = (usb_host_hub_instance_t *)param; + + if (hubInstance->inCallbackFn) + { + /* callback to application, callback function is initialized in the USB_HostHubInterruptRecv */ + hubInstance->inCallbackFn(hubInstance->inCallbackParam, transfer->transferBuffer, transfer->transferSofar, + status); /* callback to application */ + } + USB_HostFreeTransfer(hubInstance->hostHandle, transfer); +} + +static void USB_HostHubResetCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status) +{ + usb_host_hub_instance_t *hubInstance = (usb_host_hub_instance_t *)param; + + /* note: there is not callback to application, the re-enumeration will start automatically after reset. */ + USB_HostFreeTransfer(hubInstance->hostHandle, transfer); +} + +static usb_status_t USB_HostHubClassRequestCommon(usb_host_class_handle classHandle, + uint8_t requestType, + uint8_t request, + uint16_t wvalue, + uint16_t windex, + uint8_t *buffer, + uint16_t bufferLength, + transfer_callback_t callbackFn, + void *callbackParam) +{ + usb_host_hub_instance_t *hubInstance = (usb_host_hub_instance_t *)classHandle; + usb_host_transfer_t *transfer; + + if (hubInstance->controlTransfer != NULL) + { + return kStatus_USB_Busy; + } + + /* get transfer */ + if (USB_HostMallocTransfer(hubInstance->hostHandle, &transfer) != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("error to get transfer\r\n"); +#endif + return kStatus_USB_Error; + } + + /* save hub application callback */ + hubInstance->controlCallbackFn = callbackFn; + hubInstance->controlCallbackParam = callbackParam; + + /* initialize transfer */ + transfer->transferBuffer = buffer; + transfer->transferLength = bufferLength; + transfer->callbackFn = USB_HostHubControlCallback; + transfer->callbackParam = hubInstance; + transfer->setupPacket->bmRequestType = requestType; + transfer->setupPacket->bRequest = request; + transfer->setupPacket->wValue = USB_SHORT_TO_LITTLE_ENDIAN(wvalue); + transfer->setupPacket->wIndex = USB_SHORT_TO_LITTLE_ENDIAN(windex); + transfer->setupPacket->wLength = USB_SHORT_TO_LITTLE_ENDIAN(bufferLength); + + /* send transfer */ + if (USB_HostSendSetup(hubInstance->hostHandle, hubInstance->controlPipe, transfer) != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("Error in hid get report descriptor\r\n"); +#endif + USB_HostFreeTransfer(hubInstance->hostHandle, transfer); + return kStatus_USB_Error; + } + hubInstance->controlTransfer = transfer; /* record the on-going setup transfer */ + return kStatus_USB_Success; +} + +usb_status_t USB_HostHubInit(usb_device_handle deviceHandle, usb_host_class_handle *classHandle) +{ + /* malloc the hub instance */ + usb_host_hub_instance_t *hubInstance = + (usb_host_hub_instance_t *)USB_OsaMemoryAllocate(sizeof(usb_host_hub_instance_t)); + + uint32_t infoValue; + + if (hubInstance == NULL) + { + return kStatus_USB_AllocFail; + } + +#if ((defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE)) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE > 0U)) + hubInstance->hubDescriptor = (uint8_t *)SDK_Malloc(7 + (USB_HOST_HUB_MAX_PORT >> 3) + 1, USB_CACHE_LINESIZE); + hubInstance->portStatusBuffer = (uint8_t *)SDK_Malloc(4, USB_CACHE_LINESIZE); + hubInstance->hubStatusBuffer = (uint8_t *)SDK_Malloc(4, USB_CACHE_LINESIZE); + hubInstance->hubBitmapBuffer = (uint8_t *)SDK_Malloc((USB_HOST_HUB_MAX_PORT >> 3) + 1, USB_CACHE_LINESIZE); +#endif + + /* initialize hub instance structure */ + hubInstance->deviceHandle = deviceHandle; + hubInstance->interfaceHandle = NULL; + USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetHostHandle, &infoValue); + hubInstance->hostHandle = (usb_host_handle)infoValue; + USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDeviceControlPipe, &infoValue); + hubInstance->controlPipe = (usb_host_pipe_handle)infoValue; + USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDeviceLevel, &infoValue); + hubInstance->hubLevel = infoValue; + + *classHandle = hubInstance; /* return the hub class handle */ + return kStatus_USB_Success; +} + +usb_status_t USB_HostHubSetInterface(usb_host_class_handle classHandle, + usb_host_interface_handle interfaceHandle, + uint8_t alternateSetting, + transfer_callback_t callbackFn, + void *callbackParam) +{ + usb_status_t status; + usb_host_hub_instance_t *hubInstance = (usb_host_hub_instance_t *)classHandle; + usb_host_interface_t *interface = (usb_host_interface_t *)interfaceHandle; + usb_descriptor_endpoint_t *epDesc = NULL; + usb_host_pipe_init_t pipeInit; + uint8_t epIndex; + + if (classHandle == NULL) + { + return kStatus_USB_InvalidHandle; + } + + hubInstance->interfaceHandle = interfaceHandle; /* save the interface handle */ + + /* notify the host driver that the interface is used by class */ + status = USB_HostOpenDeviceInterface(hubInstance->deviceHandle, interfaceHandle); + if (status != kStatus_USB_Success) + { + return status; + } + + /* close opened hub interrupt pipe */ + if (hubInstance->interruptPipe != NULL) + { + status = USB_HostCancelTransfer(hubInstance->hostHandle, hubInstance->interruptPipe, NULL); + status = USB_HostClosePipe(hubInstance->hostHandle, hubInstance->interruptPipe); + if (status != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("error when close pipe\r\n"); +#endif + } + hubInstance->interruptPipe = NULL; + } + + /* open hub interrupt pipe */ + for (epIndex = 0; epIndex < interface->epCount; ++epIndex) + { + epDesc = interface->epList[epIndex].epDesc; + if (((epDesc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) == + USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_IN) && + ((epDesc->bmAttributes & USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_TYPE_MASK) == USB_ENDPOINT_INTERRUPT)) + { + /* get pipe information from endpoint descriptor */ + pipeInit.devInstance = hubInstance->deviceHandle; + pipeInit.pipeType = USB_ENDPOINT_INTERRUPT; + pipeInit.direction = USB_IN; + pipeInit.endpointAddress = (epDesc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK); + pipeInit.interval = epDesc->bInterval; + pipeInit.maxPacketSize = (uint16_t)(USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(epDesc->wMaxPacketSize) & + USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_SIZE_MASK); + pipeInit.numberPerUframe = (USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(epDesc->wMaxPacketSize) & + USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_MASK); + pipeInit.nakCount = USB_HOST_CONFIG_MAX_NAK; + + /* open hub interrupt in pipe */ + status = USB_HostOpenPipe(hubInstance->hostHandle, &hubInstance->interruptPipe, &pipeInit); + if (status != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("usb_host_hid_set_interface fail to open pipe\r\n"); +#endif + return kStatus_USB_Error; + } + break; + } + } + + /* hub don't support alternatesetting that is not 0 */ + if (alternateSetting == 0) + { + if (callbackFn != NULL) + { + callbackFn(callbackParam, NULL, 0, kStatus_USB_Success); + } + } + else + { +#ifdef HOST_ECHO + usb_echo("host don't support alternate setting\r\n"); +#endif + return kStatus_USB_Error; + } + + return status; +} + +usb_status_t USB_HostHubDeinit(usb_device_handle deviceHandle, usb_host_class_handle classHandle) +{ + usb_host_hub_instance_t *hubInstance = (usb_host_hub_instance_t *)classHandle; + uint8_t status; + if (deviceHandle == NULL) + { + return kStatus_USB_InvalidHandle; + } + + if (classHandle != NULL) + { + /* close opened hub interrupt pipe */ + if (hubInstance->interruptPipe != NULL) + { + status = USB_HostCancelTransfer(hubInstance->hostHandle, hubInstance->interruptPipe, NULL); + status = USB_HostClosePipe(hubInstance->hostHandle, hubInstance->interruptPipe); + if (status != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("hub close interrupt pipe error\r\n"); +#endif + } + hubInstance->interruptPipe = NULL; + } + + /* cancel control transfer if exist */ + if ((hubInstance->controlPipe != NULL) && (hubInstance->controlTransfer != NULL)) + { + status = + USB_HostCancelTransfer(hubInstance->hostHandle, hubInstance->controlPipe, hubInstance->controlTransfer); + } + + /* notify host driver that the interface will not be used */ + USB_HostCloseDeviceInterface(deviceHandle, hubInstance->interfaceHandle); +#if ((defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE)) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE > 0U)) + SDK_Free(hubInstance->hubDescriptor); + SDK_Free(hubInstance->portStatusBuffer); + SDK_Free(hubInstance->hubStatusBuffer); + SDK_Free(hubInstance->hubBitmapBuffer); +#endif + USB_OsaMemoryFree(hubInstance); + } + else + { + /* notify host driver that the interface will not be used */ + USB_HostCloseDeviceInterface(deviceHandle, NULL); + } + + return kStatus_USB_Success; +} + +usb_status_t USB_HostHubInterruptRecv(usb_host_class_handle classHandle, + uint8_t *buffer, + uint16_t bufferLength, + transfer_callback_t callbackFn, + void *callbackParam) +{ + usb_host_hub_instance_t *hubInstance = (usb_host_hub_instance_t *)classHandle; + usb_host_transfer_t *transfer; + + if (classHandle == NULL) + { + return kStatus_USB_InvalidHandle; + } + + /* get transfer */ + if (USB_HostMallocTransfer(hubInstance->hostHandle, &transfer) != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("error to get transfer\r\n"); +#endif + return kStatus_USB_Error; + } + + /* save hub application callback */ + hubInstance->inCallbackFn = callbackFn; + hubInstance->inCallbackParam = callbackParam; + + /* initialize transfer */ + transfer->transferBuffer = buffer; + transfer->transferLength = bufferLength; + transfer->callbackFn = USB_HostHubInPipeCallback; + transfer->callbackParam = hubInstance; + + /* call host driver API to receive data */ + if (USB_HostRecv(hubInstance->hostHandle, hubInstance->interruptPipe, transfer) != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("failed to USB_HostRecv\r\n"); +#endif + USB_HostFreeTransfer(hubInstance->hostHandle, transfer); + return kStatus_USB_Error; + } + + return kStatus_USB_Success; +} + +usb_status_t USB_HostHubSendPortReset(usb_host_class_handle classHandle, uint8_t portNumber) +{ + usb_host_hub_instance_t *hubInstance = (usb_host_hub_instance_t *)classHandle; + usb_host_transfer_t *transfer; + + if (classHandle == NULL) + { + return kStatus_USB_InvalidHandle; + } + + /* get transfer */ + if (USB_HostMallocTransfer(hubInstance->hostHandle, &transfer) != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("error to get transfer\r\n"); +#endif + return kStatus_USB_Busy; + } + + /* initialize transfer */ + transfer->transferBuffer = NULL; + transfer->transferLength = 0; + transfer->callbackFn = USB_HostHubResetCallback; + transfer->callbackParam = hubInstance; + transfer->setupPacket->bmRequestType = + USB_REQUEST_TYPE_DIR_OUT | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_OTHER; + transfer->setupPacket->bRequest = USB_REQUEST_STANDARD_SET_FEATURE; + transfer->setupPacket->wValue = USB_SHORT_TO_LITTLE_ENDIAN(PORT_RESET); + transfer->setupPacket->wIndex = USB_SHORT_TO_LITTLE_ENDIAN(portNumber); + transfer->setupPacket->wLength = 0; + + /* send the transfer */ + if (USB_HostSendSetup(hubInstance->hostHandle, hubInstance->controlPipe, transfer) != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("Error in hid get report descriptor\r\n"); +#endif + USB_HostFreeTransfer(hubInstance->hostHandle, transfer); + return kStatus_USB_Error; + } + return kStatus_USB_Success; +} + +/*! + * @brief hub get descriptor. + * + * This function implements get hub descriptor specific request. + * + * @param classHandle the class handle. + * @param buffer the buffer pointer. + * @param bufferLength the buffer length. + * @param callbackFn this callback is called after this function completes. + * @param callbackParam the first parameter in the callback function. + * + * @retval kStatus_USB_Success send successfully. + * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer. + * @retval kStatus_USB_Busy There is no idle transfer. + * @retval kStatus_USB_Error pipe is not initialized. + * Or, send transfer fail, please reference to USB_HostSendSetup. + */ +usb_status_t USB_HostHubGetDescriptor(usb_host_class_handle classHandle, + uint8_t *buffer, + uint16_t bufferLength, + transfer_callback_t callbackFn, + void *callbackParam) +{ + return USB_HostHubClassRequestCommon( + classHandle, USB_REQUEST_TYPE_DIR_IN | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_DEVICE, + USB_REQUEST_STANDARD_GET_DESCRIPTOR, 0x00, 0, buffer, bufferLength, callbackFn, callbackParam); +} + +/*! + * @brief hub clear feature. + * + * This function implements clear hub feature specific request. + * + * @param classHandle the class handle. + * @param buffer the buffer pointer. + * @param bufferLength the buffer length. + * @param callbackFn this callback is called after this function completes. + * @param callbackParam the first parameter in the callback function. + * + * @retval kStatus_USB_Success send successfully. + * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer. + * @retval kStatus_USB_Busy There is no idle transfer. + * @retval kStatus_USB_Error pipe is not initialized. + * Or, send transfer fail, please reference to USB_HostSendSetup. + */ +usb_status_t USB_HostHubClearFeature(usb_host_class_handle classHandle, + uint8_t feature, + transfer_callback_t callbackFn, + void *callbackParam) +{ + return USB_HostHubClassRequestCommon(classHandle, USB_REQUEST_TYPE_DIR_OUT | USB_REQUEST_TYPE_TYPE_CLASS, + USB_REQUEST_STANDARD_CLEAR_FEATURE, feature, 0, NULL, 0, callbackFn, + callbackParam); +} + +/*! + * @brief hub get status. + * + * This function implements get hub status specific request. + * + * @param classHandle the class handle. + * @param buffer the buffer pointer. + * @param bufferLength the buffer length. + * @param callbackFn this callback is called after this function completes. + * @param callbackParam the first parameter in the callback function. + * + * @retval kStatus_USB_Success send successfully. + * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer. + * @retval kStatus_USB_Busy There is no idle transfer. + * @retval kStatus_USB_Error pipe is not initialized. + * Or, send transfer fail, please reference to USB_HostSendSetup. + */ +usb_status_t USB_HostHubGetStatus(usb_host_class_handle classHandle, + uint8_t *buffer, + uint16_t bufferLength, + transfer_callback_t callbackFn, + void *callbackParam) +{ + return USB_HostHubClassRequestCommon(classHandle, USB_REQUEST_TYPE_DIR_IN | USB_REQUEST_TYPE_TYPE_CLASS, + USB_REQUEST_STANDARD_GET_STATUS, 0, 0, buffer, bufferLength, callbackFn, + callbackParam); +} + +/*! + * @brief hub set feature. + * + * This function implements set hub feature specific request. + * + * @param classHandle the class handle. + * @param buffer the buffer pointer. + * @param bufferLength the buffer length. + * @param callbackFn this callback is called after this function completes. + * @param callbackParam the first parameter in the callback function. + * + * @retval kStatus_USB_Success send successfully. + * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer. + * @retval kStatus_USB_Busy There is no idle transfer. + * @retval kStatus_USB_Error pipe is not initialized. + * Or, send transfer fail, please reference to USB_HostSendSetup. + */ +usb_status_t USB_HostHubSetPortFeature(usb_host_class_handle classHandle, + uint8_t portNumber, + uint8_t feature, + transfer_callback_t callbackFn, + void *callbackParam) +{ + return USB_HostHubClassRequestCommon( + classHandle, USB_REQUEST_TYPE_DIR_OUT | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_OTHER, + USB_REQUEST_STANDARD_SET_FEATURE, feature, portNumber, NULL, 0, callbackFn, callbackParam); +} + +/*! + * @brief hub clear port feature. + * + * This function implements clear hub port feature specific request. + * + * @param classHandle the class handle. + * @param buffer the buffer pointer. + * @param bufferLength the buffer length. + * @param callbackFn this callback is called after this function completes. + * @param callbackParam the first parameter in the callback function. + * + * @retval kStatus_USB_Success send successfully. + * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer. + * @retval kStatus_USB_Busy There is no idle transfer. + * @retval kStatus_USB_Error pipe is not initialized. + * Or, send transfer fail, please reference to USB_HostSendSetup. + */ +usb_status_t USB_HostHubClearPortFeature(usb_host_class_handle classHandle, + uint8_t portNumber, + uint8_t feature, + transfer_callback_t callbackFn, + void *callbackParam) +{ + return USB_HostHubClassRequestCommon( + classHandle, USB_REQUEST_TYPE_DIR_OUT | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_OTHER, + USB_REQUEST_STANDARD_CLEAR_FEATURE, feature, portNumber, NULL, 0, callbackFn, callbackParam); +} + +/*! + * @brief hub port get status. + * + * This function implements get hub port status specific request. + * + * @param classHandle the class handle. + * @param buffer the buffer pointer. + * @param bufferLength the buffer length. + * @param callbackFn this callback is called after this function completes. + * @param callbackParam the first parameter in the callback function. + * + * @retval kStatus_USB_Success send successfully. + * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer. + * @retval kStatus_USB_Busy There is no idle transfer. + * @retval kStatus_USB_Error pipe is not initialized. + * Or, send transfer fail, please reference to USB_HostSendSetup. + */ +usb_status_t USB_HostHubGetPortStatus(usb_host_class_handle classHandle, + uint8_t portNumber, + uint8_t *buffer, + uint16_t bufferLength, + transfer_callback_t callbackFn, + void *callbackParam) +{ + return USB_HostHubClassRequestCommon( + classHandle, USB_REQUEST_TYPE_DIR_IN | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_OTHER, + USB_REQUEST_STANDARD_GET_STATUS, 0, portNumber, buffer, bufferLength, callbackFn, callbackParam); +} + +#endif /* USB_HOST_CONFIG_HUB */ diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/class/usb_host_hub.h b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/class/usb_host_hub.h new file mode 100644 index 000000000..d47af8637 --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/class/usb_host_hub.h @@ -0,0 +1,379 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _USB_HOST_HUB_H_ +#define _USB_HOST_HUB_H_ + +#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB)) + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/*! @brief USB host HUB maximum port count */ +#define USB_HOST_HUB_MAX_PORT (7U) + +/*! @brief HUB class code */ +#define USB_HOST_HUB_CLASS_CODE (9U) +/*! @brief HUB sub-class code */ +#define USB_HOST_HUB_SUBCLASS_CODE_NONE (0U) + +/* HUB and PORT status according to Table 11-17 in chapter 11.*/ +/*! @brief Local Power Status Change: This field indicates that a change has occurred in the HUB's Local Power Source */ +#define C_HUB_LOCAL_POWER (0U) +/*! @brief Over-Current Change: This field indicates if a change has occurred in the Over-Current field*/ +#define C_HUB_OVER_CURRENT (1U) +/*! @brief Current Connect Status: This field reflects whether or not a device is currently connected to this port*/ +#define PORT_CONNECTION (0U) +/*! @brief Port Enabled/Disabled: Ports can be enabled by the USB System Software only. Ports +can be disabled by either a fault condition (disconnect event or other fault condition) or by the USB System +Software*/ +#define PORT_ENABLE (1U) +/*! @brief Suspend: This field indicates whether or not the device on this port is suspended */ +#define PORT_SUSPEND (2U) +/*! @brief this field indicate that the current drain on the port exceeds the specified maximum. */ +#define PORT_OVER_CURRENT (3U) +/*! @brief This field is set when the host wishes to reset the attached device */ +#define PORT_RESET (4U) +/*! @brief This field reflects a port's logical, power control state */ +#define PORT_POWER (8U) +/*! @brief Low- Speed Device Attached: This is relevant only if a device is attached */ +#define PORT_LOW_SPEED (9U) +/*! @brief High-speed Device Attached: This is relevant only if a device is attached */ +#define PORT_HIGH_SPEED (10U) +/*! @brief Connect Status Change: Indicates a change has occurred in the port's Current Connect Status */ +#define C_PORT_CONNECTION (16U) +/*! @brief Port Enable/Disable Change: This field is set to one when a port is disabled because of a Port_Error + * condition */ +#define C_PORT_ENABLE (17U) +/*! @brief Suspend Change: This field indicates a change in the host-visible suspend state of the attached device */ +#define C_PORT_SUSPEND (18U) +/*! @brief Over-Current Indicator Change: This field applies only to HUBs that report over-current conditions on a + * per-port basis */ +#define C_PORT_OVER_CURRENT (19U) +/*! @brief Reset Change: This field is set when reset processing on this port is complete */ +#define C_PORT_RESET (20U) + +/*! @brief Get HUB think time value */ +#define USB_HOST_HUB_DESCRIPTOR_CHARACTERISTICS_THINK_TIME_MASK (0x60U) +/*! @brief Get HUB think time value */ +#define USB_HOST_HUB_DESCRIPTOR_CHARACTERISTICS_THINK_TIME_SHIFT (5U) + +/******************************************************************************* + * Prototypes + ******************************************************************************/ + +/*! @brief HUB descriptor structure */ +typedef struct _usb_host_hub_descriptor +{ + uint8_t blength; /*!< Number of bytes in this descriptor*/ + uint8_t bdescriptortype; /*!< Descriptor Type*/ + uint8_t bnrports; /*!< Number of downstream facing ports that this HUB supports*/ + uint8_t whubcharacteristics[2]; /*!< HUB characteristics please reference to Table 11-13 in usb2.0 specification*/ + uint8_t bpwron2pwrgood; /*!< Time (in 2 ms intervals) from the time the power-on sequence begins on a port until + power is good on that port.*/ + uint8_t bhubcontrcurrent; /*!< Maximum current requirements of the HUB Controller electronics in mA*/ + uint8_t deviceremovable; /*!< Indicates if a port has a removable device attached*/ +} usb_host_hub_descriptor_t; + +/*! @brief HUB port instance structure */ +typedef struct _usb_host_hub_port_instance +{ + usb_device_handle deviceHandle; /*!< Device handle*/ + uint8_t portStatus; /*!< Port running status*/ + uint8_t resetCount; /*!< Port reset time*/ + uint8_t speed; /*!< Port's device speed*/ +} usb_host_hub_port_instance_t; + +/*! @brief HUB instance structure */ +typedef struct _usb_host_hub_instance +{ + struct _usb_host_hub_instance *next; /*!< Next HUB instance*/ + usb_host_handle hostHandle; /*!< Host handle*/ + usb_device_handle deviceHandle; /*!< Device handle*/ + usb_host_interface_handle interfaceHandle; /*!< Interface handle*/ + usb_host_pipe_handle controlPipe; /*!< Control pipe handle*/ + usb_host_pipe_handle interruptPipe; /*!< HUB interrupt in pipe handle*/ + usb_host_hub_port_instance_t *portList; /*!< HUB's port instance list*/ + usb_host_transfer_t *controlTransfer; /*!< Control transfer in progress*/ + transfer_callback_t inCallbackFn; /*!< Interrupt in callback*/ + void *inCallbackParam; /*!< Interrupt in callback parameter*/ + transfer_callback_t controlCallbackFn; /*!< Control callback*/ + void *controlCallbackParam; /*!< Control callback parameter*/ + /* HUB property */ + uint16_t totalThinktime; /*!< HUB total think time*/ + uint8_t hubLevel; /*!< HUB level, the root HUB's level is 1*/ + + /* HUB application parameter */ +#if ((defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE)) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE > 0U)) + uint8_t *hubDescriptor; /*!< HUB descriptor buffer*/ + uint8_t *hubBitmapBuffer; /*!< HUB receiving bitmap data buffer*/ + uint8_t *hubStatusBuffer; /*!< HUB status buffer*/ + uint8_t *portStatusBuffer; /*!< Port status buffer*/ +#else + uint8_t hubDescriptor[7 + (USB_HOST_HUB_MAX_PORT >> 3) + 1]; /*!< HUB descriptor buffer*/ + uint8_t hubBitmapBuffer[(USB_HOST_HUB_MAX_PORT >> 3) + 1]; /*!< HUB receiving bitmap data buffer*/ + uint8_t hubStatusBuffer[4]; /*!< HUB status buffer*/ + uint8_t portStatusBuffer[4]; /*!< Port status buffer*/ +#endif + uint8_t hubStatus; /*!< HUB instance running status*/ + uint8_t portCount; /*!< HUB port count*/ + uint8_t portIndex; /*!< Record the index when processing ports in turn*/ + uint8_t portProcess; /*!< The port that is processing*/ + uint8_t primeStatus; /*!< Data prime transfer status*/ + uint8_t invalid; /*!< 0/1, when invalid, cannot send transfer to the class*/ +#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U)) + uint8_t supportRemoteWakeup; /*!< The HUB supports remote wakeup or not*/ + uint8_t controlRetry; /*!< Retry count for set remote wakeup feature*/ +#endif +} usb_host_hub_instance_t; + +/******************************************************************************* + * Variables + ******************************************************************************/ + +/******************************************************************************* + * Code + ******************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * @brief Initializes the HUB instance. + * + * This function allocates the resource for HUB instance. + * + * @param deviceHandle The device handle. + * @param classHandle Return class handle. + * + * @retval kStatus_USB_Success The device is initialized successfully. + * @retval kStatus_USB_AllocFail Allocate memory fail. + */ +extern usb_status_t USB_HostHubInit(usb_device_handle deviceHandle, usb_host_class_handle *classHandle); + +/*! + * @brief Sets interface. + * + * This function binds the interfaces with the HUB instance. + * + * @param classHandle The class handle. + * @param interfaceHandle The interface handle. + * @param alternateSetting The alternate setting value. + * @param callbackFn This callback is called after this function completes. + * @param callbackParam The first parameter in the callback function. + * + * @retval kStatus_USB_Success The device is initialized successfully. + * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer. + * @retval kStatus_USB_Busy There is no idle transfer. + * @retval kStatus_USB_Error Open pipe fail. See the USB_HostOpenPipe. + * Or send transfer fail. See the USB_HostSendSetup, + */ +extern usb_status_t USB_HostHubSetInterface(usb_host_class_handle classHandle, + usb_host_interface_handle interfaceHandle, + uint8_t alternateSetting, + transfer_callback_t callbackFn, + void *callbackParam); + +/*! + * @brief Deinitializes the HUB instance. + * + * This function releases the resource for HUB instance. + * + * @param deviceHandle The device handle. + * @param classHandle The class handle. + * + * @retval kStatus_USB_Success The device is deinitialized successfully. + */ +extern usb_status_t USB_HostHubDeinit(usb_device_handle deviceHandle, usb_host_class_handle classHandle); + +/*! + * @brief Receives data. + * + * This function implements the HUB receiving data. + * + * @param classHandle The class handle. + * @param buffer The buffer pointer. + * @param bufferLength The buffer length. + * @param callbackFn This callback is called after this function completes. + * @param callbackParam The first parameter in the callback function. + * + * @retval kStatus_USB_Success Receive request successfully. + * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer. + * @retval kStatus_USB_Busy There is no idle transfer. + * @retval kStatus_USB_Error Pipe is not initialized. + * Or, send transfer fail. See the USB_HostRecv. + */ +extern usb_status_t USB_HostHubInterruptRecv(usb_host_class_handle classHandle, + uint8_t *buffer, + uint16_t bufferLength, + transfer_callback_t callbackFn, + void *callbackParam); + +/*! + * @brief Port reset setup. + * + * This function sends the HUB port reset transfer. + * + * @param classHandle The class handle. + * @param portNumber Port number. + * + * @retval kStatus_USB_Success Send successfully. + * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer. + * @retval kStatus_USB_Busy There is no idle transfer. + * @retval kStatus_USB_Error Pipe is not initialized. + * Or, send transfer fail. See the USB_HostSendSetup. + */ +extern usb_status_t USB_HostHubSendPortReset(usb_host_class_handle classHandle, uint8_t portNumber); + +/*! + * @brief HUB get descriptor. + * + * This function implements get HUB descriptor-specific request. + * + * @param classHandle The class handle. + * @param buffer The buffer pointer. + * @param bufferLength The buffer length. + * @param callbackFn This callback is called after this function completes. + * @param callbackParam The first parameter in the callback function. + * + * @retval kStatus_USB_Success Send successfully. + * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer. + * @retval kStatus_USB_Busy There is no idle transfer. + * @retval kStatus_USB_Error Pipe is not initialized. + * Or, send transfer fail. See the USB_HostSendSetup. + */ +extern usb_status_t USB_HostHubGetDescriptor(usb_host_class_handle classHandle, + uint8_t *buffer, + uint16_t bufferLength, + transfer_callback_t callbackFn, + void *callbackParam); + +/*! + * @brief HUB clear feature. + * + * This function implements clear HUB feature specific request. + * + * @param classHandle the class handle. + * @param buffer the buffer pointer. + * @param bufferLength the buffer length. + * @param callbackFn this callback is called after this function completes. + * @param callbackParam the first parameter in the callback function. + * + * @retval kStatus_USB_Success send successfully. + * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer. + * @retval kStatus_USB_Busy There is no idle transfer. + * @retval kStatus_USB_Error pipe is not initialized. + * Or, send transfer fail, please reference to USB_HostSendSetup. + */ +extern usb_status_t USB_HostHubClearFeature(usb_host_class_handle classHandle, + uint8_t feature, + transfer_callback_t callbackFn, + void *callbackParam); + +/*! + * @brief HUB get status. + * + * This function implements the get HUB status-specific request. + * + * @param classHandle The class handle. + * @param buffer The buffer pointer. + * @param bufferLength The buffer length. + * @param callbackFn This callback is called after this function completes. + * @param callbackParam The first parameter in the callback function. + * + * @retval kStatus_USB_Success Send successfully. + * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer. + * @retval kStatus_USB_Busy There is no idle transfer. + * @retval kStatus_USB_Error Pipe is not initialized. + * Or, send transfer fail. See the USB_HostSendSetup. + */ +extern usb_status_t USB_HostHubGetStatus(usb_host_class_handle classHandle, + uint8_t *buffer, + uint16_t bufferLength, + transfer_callback_t callbackFn, + void *callbackParam); + +/*! + * @brief HUB set feature. + * + * This function implements the set HUB feature-specific request. + * + * @param classHandle The class handle. + * @param buffer The buffer pointer. + * @param bufferLength The buffer length. + * @param callbackFn This callback is called after this function completes. + * @param callbackParam The first parameter in the callback function. + * + * @retval kStatus_USB_Success Send successfully. + * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer. + * @retval kStatus_USB_Busy There is no idle transfer. + * @retval kStatus_USB_Error Pipe is not initialized. + * Or, send transfer fail. See the USB_HostSendSetup. + */ +extern usb_status_t USB_HostHubSetPortFeature(usb_host_class_handle classHandle, + uint8_t portNumber, + uint8_t feature, + transfer_callback_t callbackFn, + void *callbackParam); + +/*! + * @brief HUB clear port feature. + * + * This function implements the clear HUB port feature-specific request. + * + * @param classHandle The class handle. + * @param buffer The buffer pointer. + * @param bufferLength The buffer length. + * @param callbackFn This callback is called after this function completes. + * @param callbackParam The first parameter in the callback function. + * + * @retval kStatus_USB_Success Send successfully. + * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer. + * @retval kStatus_USB_Busy There is no idle transfer. + * @retval kStatus_USB_Error Pipe is not initialized. + * Or, send transfer fail. See the USB_HostSendSetup. + */ +extern usb_status_t USB_HostHubClearPortFeature(usb_host_class_handle classHandle, + uint8_t portNumber, + uint8_t feature, + transfer_callback_t callbackFn, + void *callbackParam); + +/*! + * @brief HUB port get status. + * + * This function implements the get HUB port status-specific request. + * + * @param classHandle The class handle. + * @param buffer The buffer pointer. + * @param bufferLength The buffer length. + * @param callbackFn This callback is called after this function completes. + * @param callbackParam The first parameter in the callback function. + * + * @retval kStatus_USB_Success Send successfully. + * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer. + * @retval kStatus_USB_Busy There is no idle transfer. + * @retval kStatus_USB_Error Pipe is not initialized. + * Or, send transfer fail. See the USB_HostSendSetup. + */ +extern usb_status_t USB_HostHubGetPortStatus(usb_host_class_handle classHandle, + uint8_t portNumber, + uint8_t *buffer, + uint16_t bufferLength, + transfer_callback_t callbackFn, + void *callbackParam); + +#ifdef __cplusplus +} +#endif + +#endif /* USB_HOST_CONFIG_HUB */ + +#endif /* _USB_HSOT_HUB_H_ */ diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/class/usb_host_hub_app.c b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/class/usb_host_hub_app.c new file mode 100644 index 000000000..89a24c122 --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/class/usb_host_hub_app.c @@ -0,0 +1,1631 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "usb_host_config.h" +#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB)) + +#include "usb_host.h" +#include "usb_host_hub.h" +#include "usb_host_hci.h" +#include "usb_host_hub_app.h" +#include "usb_host_devices.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/*! @brief HUB lock */ +#define USB_HostHubLock() USB_OsaMutexLock(hubGlobal->hubMutex) +/*! @brief HUB unlock */ +#define USB_HostHubUnlock() USB_OsaMutexUnlock(hubGlobal->hubMutex) + +/******************************************************************************* + * Prototypes + ******************************************************************************/ + +/*! + * @brief prime interrupt in data. + * + * @param hubInstance hub instance pointer. + */ +static void USB_HostHubGetInterruptStatus(usb_host_hub_instance_t *hubInstance); + +/*! + * @brief hub process state machine. hub is enable after the state machine. + * + * @param hubInstance hub instance pointer. + */ +static void USB_HostHubProcess(usb_host_hub_instance_t *hubInstance); + +/*! + * @brief hub port attach process state machine. one device is attached to the port after the state machine. + * + * @param hubInstance hub instance pointer. + */ +static void USB_HostHubProcessPortAttach(usb_host_hub_instance_t *hubInstance); + +/*! + * @brief hub port detach process state machine. one device is detached from the port after the state machine. + * + * @param hubInstance hub instance pointer. + */ +static void USB_HostHubProcessPortDetach(usb_host_hub_instance_t *hubInstance); + +/*! + * @brief hub port process. + * + * @param hubInstance hub instance pointer. + */ +static void USB_HostHubProcessPort(usb_host_hub_instance_t *hubInstance); + +/*! + * @brief hub interrupt in data process. + * + * @param hubInstance hub instance pointer. + */ +static void USB_HostHubProcessData(usb_host_hub_global_t *hubGlobal, usb_host_hub_instance_t *hubInstance); + +/*! + * @brief hub control pipe transfer callback. + * + * @param param callback parameter. + * @param transfer callback transfer. + * @param status transfer status. + */ +void USB_HostHubControlCallback(void *param, uint8_t *data, uint32_t data_len, usb_status_t status); + +/*! + * @brief hub interrupt pipe transfer callback. + * + * @param param callback parameter. + * @param transfer callback transfer. + * @param status transfer status. + */ +void USB_HostHubInterruptInCallback(void *param, uint8_t *data, uint32_t data_len, usb_status_t status); + +#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U)) + +static usb_host_hub_instance_t *USB_HostHubGetHubDeviceHandle(usb_host_handle hostHandle, uint8_t parentHubNo); + +static usb_status_t USB_HostSendHubRequest(usb_device_handle deviceHandle, + uint8_t requestType, + uint8_t request, + uint16_t wvalue, + uint16_t windex, + host_inner_transfer_callback_t callbackFn, + void *callbackParam); + +#endif +/******************************************************************************* + * Variables + ******************************************************************************/ + +static usb_device_handle s_HubDeviceHandle; +static usb_host_interface_handle s_HubInterfaceHandle; +static usb_host_hub_global_t s_HubGlobalArray[USB_HOST_CONFIG_MAX_HOST]; + +#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U)) +static usb_host_configuration_t *s_HubConfiguration; +#endif + +/******************************************************************************* + * Code + ******************************************************************************/ + +static usb_host_hub_global_t *USB_HostHubGetHubList(usb_host_handle hostHandle) +{ +#if (USB_HOST_CONFIG_MAX_HOST == 1U) + return &s_HubGlobalArray[0]; +#else + uint8_t index; + for (index = 0; index < USB_HOST_CONFIG_MAX_HOST; ++index) + { + if (s_HubGlobalArray[index].hostHandle == hostHandle) + { + return &s_HubGlobalArray[index]; + } + } + /* There is no used usb_host_hub_global_t instance */ + for (index = 0; index < USB_HOST_CONFIG_MAX_HOST; ++index) + { + if (s_HubGlobalArray[index].hostHandle == NULL) + { + s_HubGlobalArray[index].hostHandle = hostHandle; + return &s_HubGlobalArray[index]; + } + } + /* Look for the usb_host_hub_global_t instance that is not used any more */ + for (index = 0; index < USB_HOST_CONFIG_MAX_HOST; ++index) + { + if (s_HubGlobalArray[index].hubList == NULL) + { + s_HubGlobalArray[index].hostHandle = hostHandle; + return &s_HubGlobalArray[index]; + } + } + return NULL; +#endif +} + +static void USB_HostHubGetInterruptStatus(usb_host_hub_instance_t *hubInstance) +{ + if (hubInstance == NULL) + { + return; + } + + /* there is no prime for control or interrupt */ + if (hubInstance->primeStatus != kPrimeNone) + { + return; + } + + /* receive interrupt data */ + if (USB_HostHubInterruptRecv(hubInstance, hubInstance->hubBitmapBuffer, (hubInstance->portCount >> 3) + 1, + USB_HostHubInterruptInCallback, hubInstance) != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("error in hub interrupt recv\r\n"); +#endif + } + else + { + hubInstance->primeStatus = kPrimeInterrupt; + } +} + +static void USB_HostHubProcess(usb_host_hub_instance_t *hubInstance) +{ + uint8_t needPrimeInterrupt = 0; /* need to prime interrupt in transfer (0 - don't need; 1 - need) */ + uint8_t processSuccess = 0; /* the code execute successfully (0 - fail; 1 - success) */ + uint32_t tmp = 0; + usb_host_hub_descriptor_t *hubDescriptor; + + switch (hubInstance->hubStatus) + { + case kHubRunIdle: + case kHubRunInvalid: + break; + + case kHubRunWaitSetInterface: + hubInstance->hubStatus = kHubRunGetDescriptor7; /* update as next state */ + /* get hub descriptor */ + if (USB_HostHubGetDescriptor(hubInstance, hubInstance->hubDescriptor, 7, USB_HostHubControlCallback, + hubInstance) == kStatus_USB_Success) + { + hubInstance->primeStatus = kPrimeHubControl; /* control transfer is on-going */ + processSuccess = 1; +#ifdef HOST_ECHO + usb_echo("hub get descriptor 7\r\n"); +#endif + } + else + { +#ifdef HOST_ECHO + usb_echo("hub get descriptor 7 error\r\n"); +#endif + break; + } + break; + + case kHubRunGetDescriptor7: + hubDescriptor = (usb_host_hub_descriptor_t *)&hubInstance->hubDescriptor[0]; + + /* get the hub think time */ + USB_HostHelperGetPeripheralInformation(hubInstance->deviceHandle, kUSB_HostGetHubThinkTime, &tmp); + hubInstance->totalThinktime = tmp; + tmp = ((((uint32_t)hubDescriptor->whubcharacteristics[0] & + USB_HOST_HUB_DESCRIPTOR_CHARACTERISTICS_THINK_TIME_MASK) >> + USB_HOST_HUB_DESCRIPTOR_CHARACTERISTICS_THINK_TIME_SHIFT)); + /* + 00 - 8 FS bit times; + 01 - 16 FS bit times; + 10 - 24 FS bit times; + 11 - 32 FS bit times; + */ + tmp = (tmp + 1) << 3; + hubInstance->totalThinktime += tmp; + + /* get hub port number */ + hubInstance->portCount = hubDescriptor->bnrports; + if (hubInstance->portCount > USB_HOST_HUB_MAX_PORT) + { +#ifdef HOST_ECHO + usb_echo("port number is bigger than USB_HOST_HUB_MAX_PORT\r\n"); +#endif + return; + } + + hubInstance->hubStatus = kHubRunGetDescriptor; /* update as next state */ + /* get hub descriptor */ + if (USB_HostHubGetDescriptor(hubInstance, hubInstance->hubDescriptor, 7 + (hubInstance->portCount >> 3) + 1, + USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success) + { + hubInstance->primeStatus = kPrimeHubControl; /* control transfer is on-going */ + processSuccess = 1; +#ifdef HOST_ECHO + usb_echo("hub get descriptor\r\n"); +#endif + } + else + { +#ifdef HOST_ECHO + usb_echo("hub get descriptor error\r\n"); +#endif + break; + } + break; + + case kHubRunGetDescriptor: + /* malloc port instance for the hub's ports */ + hubInstance->portList = (usb_host_hub_port_instance_t *)USB_OsaMemoryAllocate( + hubInstance->portCount * sizeof(usb_host_hub_port_instance_t)); + if (hubInstance->portList == NULL) + { +#ifdef HOST_ECHO + usb_echo("port list allocate fail\r\n"); +#endif + hubInstance->hubStatus = kHubRunInvalid; + break; + } + /* TODO: port instance status -> can be removed. app_status */ + + hubInstance->hubStatus = kHubRunSetPortPower; /* update as next state */ + hubInstance->portIndex = 0; + + /* there is no significance, just for fixing misra error */ + if (hubInstance->hubStatus != kHubRunSetPortPower) + { + break; + } + + case kHubRunSetPortPower: + /* set PORT_POWER for all ports */ + if (hubInstance->portIndex < hubInstance->portCount) + { + hubInstance->portIndex++; + if (USB_HostHubSetPortFeature(hubInstance, hubInstance->portIndex, PORT_POWER, + USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success) + { + hubInstance->primeStatus = kPrimeHubControl; /* update as next state */ + processSuccess = 1; +#ifdef HOST_ECHO + usb_echo("set port feature PORT_POWER\r\n"); +#endif + } + else + { +#ifdef HOST_ECHO + usb_echo("set port feature PORT_POWER fail\r\n"); +#endif + needPrimeInterrupt = 1; + break; + } + break; + } + hubInstance->portProcess = 0; + /* reset port information as default */ + for (tmp = 0; tmp < hubInstance->portCount; ++tmp) + { + hubInstance->portList[tmp].deviceHandle = NULL; + hubInstance->portList[tmp].resetCount = USB_HOST_HUB_PORT_RESET_TIMES; + hubInstance->portList[tmp].portStatus = kPortRunWaitPortChange; + } + hubInstance->hubStatus = kHubRunIdle; + needPrimeInterrupt = 1; + break; + + case kHubRunGetStatusDone: /* process hub status change */ + tmp = USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS((&hubInstance->hubStatusBuffer[2])); + hubInstance->hubStatus = kHubRunIdle; + if ((1 << C_HUB_LOCAL_POWER) & tmp) /* C_HUB_LOCAL_POWER */ + { + if (USB_HostHubClearFeature(hubInstance, C_HUB_LOCAL_POWER, USB_HostHubControlCallback, hubInstance) == + kStatus_USB_Success) + { + hubInstance->primeStatus = kPrimeHubControl; + hubInstance->hubStatus = kHubRunClearDone; + processSuccess = 1; + } + else + { + needPrimeInterrupt = 1; + } + } + else if ((1 << C_HUB_OVER_CURRENT) & tmp) /* C_HUB_OVER_CURRENT */ + { + if (USB_HostHubClearFeature(hubInstance, C_HUB_OVER_CURRENT, USB_HostHubControlCallback, hubInstance) == + kStatus_USB_Success) + { + hubInstance->primeStatus = kPrimeHubControl; + processSuccess = 1; + hubInstance->hubStatus = kHubRunClearDone; + } + else + { + needPrimeInterrupt = 1; + } + } + else + { + needPrimeInterrupt = 1; + } + break; + + case kHubRunClearDone: + hubInstance->hubStatus = kHubRunIdle; + needPrimeInterrupt = 1; + break; + + default: + break; + } + + if (needPrimeInterrupt == 1) /* prime interrupt in transfer */ + { + hubInstance->hubStatus = kHubRunIdle; + USB_HostHubGetInterruptStatus(hubInstance); + } + else + { + if (processSuccess == 0) + { + hubInstance->hubStatus = kHubRunInvalid; + } + } +} + +static void USB_HostHubProcessPort(usb_host_hub_instance_t *hubInstance) +{ + usb_host_hub_port_instance_t *portInstance = &hubInstance->portList[hubInstance->portProcess - 1]; + + /* for device attach */ + if (portInstance->deviceHandle == NULL) + { + USB_HostHubProcessPortAttach(hubInstance); + } + else /* for device detach */ + { + USB_HostHubProcessPortDetach(hubInstance); + } +} + +static void USB_HostHubProcessPortAttach(usb_host_hub_instance_t *hubInstance) +{ + usb_host_hub_port_instance_t *portInstance = &hubInstance->portList[hubInstance->portProcess - 1]; + uint8_t processSuccess = 0; + uint32_t specStatus; + uint8_t feature; + uint32_t infoValue; + usb_host_hub_global_t *hubGlobal = USB_HostHubGetHubList(hubInstance->hostHandle); + if (hubGlobal == NULL) + { + return; + } + + switch (portInstance->portStatus) + { + case kPortRunIdle: + case kPortRunInvalid: + break; + case kPortRunWaitPortChange: /* (1) port is changed, and get port status */ + portInstance->portStatus = kPortRunCheckCPortConnection; /* update as next state */ + /* send class-specific request to get port status */ + if (USB_HostHubGetPortStatus(hubInstance, hubInstance->portProcess, hubInstance->portStatusBuffer, 4, + USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success) + { + hubInstance->primeStatus = kPrimePortControl; + processSuccess = 1; + } + break; + + case kPortRunCheckCPortConnection: /* (2) check port status, and clear the status bits */ + feature = 0; + specStatus = USB_LONG_FROM_LITTLE_ENDIAN_ADDRESS((hubInstance->portStatusBuffer)); + if ((1 << C_PORT_CONNECTION) & specStatus) + { + portInstance->portStatus = kPortRunGetPortConnection; /* update as next state */ + /* clear C_PORT_CONNECTION */ + if (USB_HostHubClearPortFeature(hubInstance, hubInstance->portProcess, C_PORT_CONNECTION, + USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success) + { + hubInstance->primeStatus = kPrimePortControl; + processSuccess = 1; + } + break; + } + else if ((1 << PORT_CONNECTION) & specStatus) + { + portInstance->portStatus = kPortRunWaitPortResetDone; /* update as next state */ + /* set PORT_RESET */ + if (USB_HostHubSetPortFeature(hubInstance, hubInstance->portProcess, PORT_RESET, + USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success) + { + hubInstance->primeStatus = kPrimePortControl; + processSuccess = 1; + if (portInstance->resetCount > 0) + { + portInstance->resetCount--; + } + } + break; + } + else if ((1 << C_PORT_RESET) & specStatus) + { + feature = C_PORT_RESET; /* clear C_PORT_RESET */ +#ifdef HOST_ECHO + usb_echo("hub: C_PORT_RESET when detached\r\n"); +#endif + } + else if ((1 << C_PORT_ENABLE) & specStatus) + { + feature = C_PORT_ENABLE; /* clear C_PORT_ENABLE */ +#ifdef HOST_ECHO + usb_echo("hub: C_PORT_ENABLE when detached\r\n"); +#endif + } + else if ((1 << C_PORT_OVER_CURRENT) & specStatus) + { + feature = C_PORT_OVER_CURRENT; /* clear C_PORT_OVER_CURRENT */ +#ifdef HOST_ECHO + usb_echo("hub: C_PORT_OVER_CURRENT when detached\r\n"); +#endif + } + else + { + } + + if (feature != 0) + { + portInstance->portStatus = kPortRunWaitPortChange; /* update as next state */ + /* clear feature */ + if (USB_HostHubClearPortFeature(hubInstance, hubInstance->portProcess, feature, + USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success) + { + hubInstance->primeStatus = kPrimePortControl; + processSuccess = 1; + } + } + break; + + case kPortRunGetPortConnection: /* (3) get port status */ + portInstance->portStatus = kPortRunCheckPortConnection; /* update as next state */ + /* get port status bits */ + if (USB_HostHubGetPortStatus(hubInstance, hubInstance->portProcess, hubInstance->portStatusBuffer, 4, + USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success) + { + hubInstance->primeStatus = kPrimePortControl; /* control transfer is on-going */ + processSuccess = 1; + } + break; + + case kPortRunCheckPortConnection: /* (4) check PORT_CONNECTION bit */ + specStatus = USB_LONG_FROM_LITTLE_ENDIAN_ADDRESS(hubInstance->portStatusBuffer); + if ((1 << PORT_CONNECTION) & specStatus) + { + portInstance->portStatus = kPortRunWaitPortResetDone; /* update as next state */ + /* set PORT_RESET */ + if (USB_HostHubSetPortFeature(hubInstance, hubInstance->portProcess, PORT_RESET, + USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success) + { + hubInstance->primeStatus = kPrimePortControl; + processSuccess = 1; + if (portInstance->resetCount > 0) + { + portInstance->resetCount--; + } + } + } + break; + + case kPortRunWaitPortResetDone: /* (5) wait port change */ + portInstance->portStatus = kPortRunWaitCPortReset; /* update as next state */ + processSuccess = 1; + /* must wait the enumeration done, then operate the next port */ + USB_HostHubGetInterruptStatus(hubInstance); + break; + + case kPortRunWaitCPortReset: /* (6) get port status for checking C_PORT_RESET */ + portInstance->portStatus = KPortRunCheckCPortReset; /* update as next state */ + /* get port status bits */ + if (USB_HostHubGetPortStatus(hubInstance, hubInstance->portProcess, hubInstance->portStatusBuffer, 4, + USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success) + { + hubInstance->primeStatus = kPrimePortControl; + processSuccess = 1; + } + break; + + case KPortRunCheckCPortReset: /* (7) check C_PORT_RESET and clear C_PORT_RESET */ + specStatus = USB_LONG_FROM_LITTLE_ENDIAN_ADDRESS(hubInstance->portStatusBuffer); + if ((1 << C_PORT_RESET) & specStatus) + { + if (portInstance->resetCount == 0) + { + portInstance->portStatus = kPortRunPortAttached; /* update as next state */ + /* get port's device speed */ + if (specStatus & (1 << PORT_HIGH_SPEED)) + { + portInstance->speed = USB_SPEED_HIGH; + } + else if (specStatus & (1 << PORT_LOW_SPEED)) + { + portInstance->speed = USB_SPEED_LOW; + } + else + { + portInstance->speed = USB_SPEED_FULL; + } + } + else + { + portInstance->portStatus = kPortRunResetAgain; /* update as next state */ + } + + /* clear C_PORT_RESET */ + if (USB_HostHubClearPortFeature(hubInstance, hubInstance->portProcess, C_PORT_RESET, + USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success) + { + hubInstance->primeStatus = kPrimePortControl; + processSuccess = 1; + } + } + break; + + case kPortRunResetAgain: /* (8) reset again */ + portInstance->portStatus = kPortRunCheckPortConnection; /* check connection then reset again */ + if (USB_HostHubGetPortStatus(hubInstance, hubInstance->portProcess, hubInstance->portStatusBuffer, 4, + USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success) + { + hubInstance->primeStatus = kPrimePortControl; + processSuccess = 1; + } + break; + + case kPortRunPortAttached: /* (9) the port have one device attached */ + USB_HostHelperGetPeripheralInformation(hubInstance->deviceHandle, kUSB_HostGetDeviceAddress, &infoValue); + USB_HostAttachDevice(hubInstance->hostHandle, portInstance->speed, infoValue, hubInstance->portProcess, + hubInstance->hubLevel + 1, &portInstance->deviceHandle); + processSuccess = 1; + hubInstance->portProcess = 0; + hubGlobal->hubProcess = NULL; + portInstance->resetCount = USB_HOST_HUB_PORT_RESET_TIMES; + USB_HostHubGetInterruptStatus(hubInstance); + break; + default: + break; + } + + if (processSuccess == 0) + { + portInstance->portStatus = kPortRunWaitPortChange; + hubInstance->portProcess = 0; + hubGlobal->hubProcess = NULL; + portInstance->resetCount = USB_HOST_HUB_PORT_RESET_TIMES; + + USB_HostHubGetInterruptStatus(hubInstance); + } +} + +static void USB_HostHubProcessPortDetach(usb_host_hub_instance_t *hubInstance) +{ + usb_host_hub_port_instance_t *portInstance = &hubInstance->portList[hubInstance->portProcess - 1]; +#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U)) + usb_host_instance_t *hostPointer = (usb_host_instance_t *)hubInstance->hostHandle; +#endif + uint8_t processSuccess = 0; + uint32_t specStatus; + usb_host_hub_global_t *hubGlobal = USB_HostHubGetHubList(hubInstance->hostHandle); + if (hubGlobal == NULL) + { + return; + } + + switch (portInstance->portStatus) + { + case kPortRunIdle: + case kPortRunInvalid: + break; +#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U)) + case kPortRunPortSuspended: +#endif + case kPortRunPortAttached: /* (1) port is changed, then get port status */ + portInstance->portStatus = kPortRunCheckPortDetach; + /* get port status */ + if (USB_HostHubGetPortStatus(hubInstance, hubInstance->portProcess, hubInstance->portStatusBuffer, 4, + USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success) + { + hubInstance->primeStatus = kPrimePortControl; + processSuccess = 1; + } + break; + + case kPortRunCheckPortDetach: /* (2) check port status bits */ + specStatus = USB_LONG_FROM_LITTLE_ENDIAN_ADDRESS(hubInstance->portStatusBuffer); + portInstance->portStatus = kPortRunGetConnectionBit; + if ((1 << C_PORT_CONNECTION) & specStatus) /* C_PORT_CONNECTION */ + { + if (USB_HostHubClearPortFeature(hubInstance, hubInstance->portProcess, C_PORT_CONNECTION, + USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success) + { + hubInstance->primeStatus = kPrimePortControl; + processSuccess = 1; + } + break; + } + else if ((1 << C_PORT_ENABLE) & specStatus) /* C_PORT_ENABLE */ + { + if (USB_HostHubClearPortFeature(hubInstance, hubInstance->portProcess, C_PORT_ENABLE, + USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success) + { + hubInstance->primeStatus = kPrimePortControl; + processSuccess = 1; + } + break; + } +#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U)) + else if ((1 << C_PORT_SUSPEND) & specStatus) + { + /* clear C_PORT_SUSPEND */ + if (USB_HostHubClearPortFeature(hubInstance, hubInstance->portProcess, C_PORT_SUSPEND, + USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success) + { + portInstance->portStatus = kPortRunClearCPortSuspend; /* update as next state */ + hubInstance->primeStatus = kPrimePortControl; + processSuccess = 1; + break; + } + } +#endif + else + { + /* don't break to check CONNECTION bit */ + } + case kPortRunGetConnectionBit: /* (3) get port status */ + portInstance->portStatus = kPortRunCheckConnectionBit; + if (USB_HostHubGetPortStatus(hubInstance, hubInstance->portProcess, hubInstance->portStatusBuffer, 4, + USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success) + { + hubInstance->primeStatus = kPrimePortControl; + processSuccess = 1; + } + break; + + case kPortRunCheckConnectionBit: /* (4) check port connection bit */ + specStatus = USB_LONG_FROM_LITTLE_ENDIAN_ADDRESS(hubInstance->portStatusBuffer); + if ((1 << PORT_CONNECTION) & specStatus) /* PORT_CONNECTION */ + { + portInstance->portStatus = kPortRunPortAttached; +#ifdef HOST_ECHO + usb_echo("PORT_CONNECTION in attach for detach\r\n"); +#endif + } + else + { + processSuccess = 1; + /* port's device is detached */ + portInstance->portStatus = kPortRunWaitPortChange; + USB_HostDetachDeviceInternal(hubInstance->hostHandle, portInstance->deviceHandle); + portInstance->deviceHandle = NULL; + hubGlobal->hubProcess = NULL; + hubInstance->portProcess = 0; + USB_HostHubGetInterruptStatus(hubInstance); + } + break; +#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U)) + case kPortRunClearCPortSuspend: + portInstance->portStatus = kPortRunCheckPortSuspend; /* update as next state */ + /* get port status bits */ + if (USB_HostHubGetPortStatus(hubInstance, hubInstance->portProcess, hubInstance->portStatusBuffer, 4, + USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success) + { + hubInstance->primeStatus = kPrimePortControl; + processSuccess = 1; + } + break; + case kPortRunCheckPortSuspend: + specStatus = USB_LONG_FROM_LITTLE_ENDIAN_ADDRESS(hubInstance->portStatusBuffer); + if ((1 << PORT_SUSPEND) & specStatus) + { + portInstance->portStatus = kPortRunPortSuspended; /* update as next state */ + /* call host callback function, function is initialized in USB_HostInit */ + hostPointer->deviceCallback(hostPointer->suspendedDevice, NULL, + kUSB_HostEventSuspended); /* call host callback function */ + } + else + { + portInstance->portStatus = kPortRunPortAttached; /* update as next state */ + /* call host callback function, function is initialized in USB_HostInit */ + hostPointer->deviceCallback(hostPointer->suspendedDevice, NULL, + kUSB_HostEventResumed); /* call host callback function */ + hostPointer->suspendedDevice = NULL; + } + break; +#endif + default: + break; + } + + if (processSuccess == 0) + { + portInstance->portStatus = kPortRunPortAttached; + hubGlobal->hubProcess = NULL; + hubInstance->portProcess = 0; + USB_HostHubGetInterruptStatus(hubInstance); + } +} + +static void USB_HostHubProcessData(usb_host_hub_global_t *hubGlobal, usb_host_hub_instance_t *hubInstance) +{ + uint8_t needPrimeInterrupt = 1; + uint8_t portIndex; + + /* process the port which status change */ + for (portIndex = 0; portIndex <= hubInstance->portCount; ++portIndex) + { + if ((0x01u << (portIndex & 0x07u)) & (hubInstance->hubBitmapBuffer[portIndex >> 3])) + { + if (portIndex == 0) /* hub status change */ + { + if ((hubGlobal->hubProcess == NULL) || + ((hubGlobal->hubProcess == hubInstance) && (hubInstance->portProcess == 0))) + { + hubInstance->hubStatus = kHubRunGetStatusDone; + if (USB_HostHubGetStatus(hubInstance, hubInstance->hubStatusBuffer, 4, USB_HostHubControlCallback, + hubInstance) != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("error in usb_class_hub_get_status\r\n"); +#endif + hubInstance->hubStatus = kHubRunIdle; + } + else + { + hubInstance->primeStatus = kPrimeHubControl; + needPrimeInterrupt = 0; + return; /* return replace break because the misra */ + } + } + } + else /* port's status change */ + { + /* process the on-going port or process one new port */ + if ((hubGlobal->hubProcess == NULL) || + ((hubGlobal->hubProcess == hubInstance) && (hubInstance->portProcess == 0)) || + ((hubGlobal->hubProcess == hubInstance) && (hubInstance->portProcess == portIndex))) + { + if (hubInstance->controlTransfer == NULL) + { + hubGlobal->hubProcess = hubInstance; + hubInstance->portProcess = portIndex; + needPrimeInterrupt = 0; + USB_HostHubProcessPort(hubInstance); + } + break; /* process the port change in turn */ + } + } + } + } + + if (needPrimeInterrupt == 1) + { + USB_HostHubGetInterruptStatus(hubInstance); + } +} + +void USB_HostHubControlCallback(void *param, uint8_t *data, uint32_t data_len, usb_status_t status) +{ + usb_host_hub_instance_t *hubInstance = (usb_host_hub_instance_t *)param; + usb_host_hub_global_t *hubGlobal = USB_HostHubGetHubList(hubInstance->hostHandle); + if (hubGlobal == NULL) + { + return; + } + + if (hubInstance->invalid == 1) + { + return; + } + if (status != kStatus_USB_Success) + { + /* if transfer fail, prime a new interrupt in transfer */ + hubInstance->primeStatus = kPrimeNone; + hubGlobal->hubProcess = NULL; + hubInstance->portProcess = 0; + USB_HostHubGetInterruptStatus(hubInstance); + return; + } + + if (hubInstance->primeStatus == kPrimeHubControl) /* hub related control transfer */ + { + hubInstance->primeStatus = kPrimeNone; + USB_HostHubProcess(hubInstance); + } + else if (hubInstance->primeStatus == kPrimePortControl) /* hub's port related control transfer */ + { + hubInstance->primeStatus = kPrimeNone; + USB_HostHubProcessPort(hubInstance); + } + else + { + } +} + +#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U)) +/*! + * @brief get device's hub device instance. + * + * @param parent_hub_no device's parent hub instance. + * + * @return think time value. + */ +static usb_host_hub_instance_t *USB_HostHubGetHubDeviceHandle(usb_host_handle hostHandle, uint8_t parentHubNo) +{ + usb_host_hub_instance_t *hubInstance; + uint32_t deviceAddress; + usb_host_hub_global_t *hubGlobal = USB_HostHubGetHubList(hostHandle); + if (hubGlobal == NULL) + { + return NULL; + } + hubInstance = hubGlobal->hubList; + + /* get parentHubNo's hub instance handle */ + while (hubInstance != NULL) + { + USB_HostHelperGetPeripheralInformation(hubInstance->deviceHandle, kUSB_HostGetDeviceAddress, &deviceAddress); + if (parentHubNo == deviceAddress) + { + break; + } + hubInstance = hubInstance->next; + } + if (hubInstance != NULL) + { + return hubInstance; + } + return (usb_host_hub_instance_t *)NULL; +} + +static void USB_HostSetHubRequestCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status) +{ + usb_host_instance_t *hostInstance = (usb_host_instance_t *)param; + USB_HostFreeTransfer(param, transfer); + + if (kStatus_USB_Success == status) + { + /* call host callback function, function is initialized in USB_HostInit */ + hostInstance->deviceCallback(hostInstance->suspendedDevice, NULL, + kUSB_HostEventSuspended); /* call host callback function */ + } + else + { + /* call host callback function, function is initialized in USB_HostInit */ + hostInstance->deviceCallback(hostInstance->suspendedDevice, NULL, + kUSB_HostEventNotSuspended); /* call host callback function */ + } +} + +static void USB_HostClearHubRequestCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status) +{ + USB_HostFreeTransfer(param, transfer); + + if (kStatus_USB_Success == status) + { + } +} + +static void USB_HostHubRemoteWakeupCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status) +{ + usb_host_hub_instance_t *hubInstance; + usb_host_instance_t *hostInstance; + usb_host_device_instance_t *deviceInstance; + if (NULL == param) + { + return; + } + + hubInstance = (usb_host_hub_instance_t *)param; + + hostInstance = (usb_host_instance_t *)hubInstance->hostHandle; + if (NULL == hostInstance) + { + return; + } + + USB_HostFreeTransfer(hostInstance, transfer); + + if (kStatus_USB_Success != status) + { + usb_echo("Transfer failed to set remote wakeup request to HUB.\r\n"); + } + + if (kStatus_USB_Success == status) + { + hubInstance->controlRetry = USB_HOST_HUB_REMOTE_WAKEUP_TIMES; + hubInstance = hubInstance->next; + while (hubInstance) + { + hubInstance->controlRetry = USB_HOST_HUB_REMOTE_WAKEUP_TIMES; + if (hubInstance->supportRemoteWakeup) + { + usb_echo("Set HUB remote wakeup feature: level %d, address %d.\r\n", + ((usb_host_device_instance_t *)hubInstance->deviceHandle)->level, + ((usb_host_device_instance_t *)hubInstance->deviceHandle)->setAddress); + status = USB_HostSendHubRequest( + hubInstance->deviceHandle, + USB_REQUEST_TYPE_RECIPIENT_DEVICE | USB_REQUEST_TYPE_DIR_OUT | USB_REQUEST_TYPE_TYPE_STANDARD, + USB_REQUEST_STANDARD_SET_FEATURE, USB_REQUEST_STANDARD_FEATURE_SELECTOR_DEVICE_REMOTE_WAKEUP, 0, + USB_HostHubRemoteWakeupCallback, hubInstance); + if (kStatus_USB_Success != status) + { + usb_echo("Send set remote wakeup request to HUB failed.\r\n"); + } + break; + } + hubInstance = hubInstance->next; + } + } + else + { + if (hubInstance->controlRetry) + { + hubInstance->controlRetry--; + usb_echo("Retry...\r\n", ((usb_host_device_instance_t *)hubInstance->deviceHandle)->level, + ((usb_host_device_instance_t *)hubInstance->deviceHandle)->setAddress); + status = USB_HostSendHubRequest( + hubInstance->deviceHandle, + USB_REQUEST_TYPE_RECIPIENT_DEVICE | USB_REQUEST_TYPE_DIR_OUT | USB_REQUEST_TYPE_TYPE_STANDARD, + USB_REQUEST_STANDARD_SET_FEATURE, USB_REQUEST_STANDARD_FEATURE_SELECTOR_DEVICE_REMOTE_WAKEUP, 0, + USB_HostHubRemoteWakeupCallback, hubInstance); + if (kStatus_USB_Success != status) + { + usb_echo("Send set remote wakeup request to HUB failed.\r\n"); + } + } + else + { + usb_echo("Transfer failed to set remote wakeup request to HUB.\r\n"); + } + } + if (kStatus_USB_Success != status) + { + /* call host callback function, function is initialized in USB_HostInit */ + hostInstance->deviceCallback(hostInstance->suspendedDevice, NULL, kUSB_HostEventNotSuspended); + return; + } + if (NULL == hubInstance) + { + status = kStatus_USB_Error; + deviceInstance = (usb_host_device_instance_t *)hostInstance->suspendedDevice; + if (NULL == deviceInstance) + { + usb_host_bus_control_t type = kUSB_HostBusSuspend; + /* the callbackFn is initialized in USB_HostGetControllerInterface */ + status = hostInstance->controllerTable->controllerIoctl(hostInstance->controllerHandle, kUSB_HostBusControl, + &type); + if (kStatus_USB_Success != status) + { + usb_echo("Suspend USB BUS failed.\r\n"); + } + } + else + { + usb_host_hub_instance_t *hubInstance4Device = + USB_HostHubGetHubDeviceHandle(hostInstance, deviceInstance->hubNumber); + if (NULL != hubInstance4Device) + { + status = USB_HostSendHubRequest( + hubInstance4Device->deviceHandle, + USB_REQUEST_TYPE_DIR_OUT | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_OTHER, + USB_REQUEST_STANDARD_SET_FEATURE, PORT_SUSPEND, deviceInstance->portNumber, + USB_HostSetHubRequestCallback, hostInstance); + if (kStatus_USB_Success != status) + { + usb_echo("Send suspend request to HUB is failed.\r\n"); + } + } + else + { + usb_echo("Invalid HUB instance of device.\r\n"); + } + } + if (kStatus_USB_Success != status) + { + /* call host callback function, function is initialized in USB_HostInit */ + hostInstance->deviceCallback(hostInstance->suspendedDevice, NULL, kUSB_HostEventNotSuspended); + return; + } + } +} + +static usb_status_t USB_HostSendHubRequest(usb_device_handle deviceHandle, + uint8_t requestType, + uint8_t request, + uint16_t wvalue, + uint16_t windex, + host_inner_transfer_callback_t callbackFn, + void *callbackParam) +{ + usb_host_device_instance_t *deviceInstance = (usb_host_device_instance_t *)deviceHandle; + usb_host_transfer_t *transfer; + + /* get transfer */ + 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; + } + + /* initialize transfer */ + transfer->transferBuffer = NULL; + transfer->transferLength = 0U; + transfer->callbackFn = callbackFn; + transfer->callbackParam = callbackParam; + transfer->setupPacket->bmRequestType = requestType; + transfer->setupPacket->bRequest = request; + transfer->setupPacket->wValue = USB_SHORT_TO_LITTLE_ENDIAN(wvalue); + transfer->setupPacket->wIndex = USB_SHORT_TO_LITTLE_ENDIAN(windex); + transfer->setupPacket->wLength = USB_SHORT_TO_LITTLE_ENDIAN(0U); + + /* send transfer */ + if (USB_HostSendSetup(deviceInstance->hostHandle, deviceInstance->controlPipe, transfer) != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("Error in sending hub set report!\r\n"); +#endif + USB_HostFreeTransfer(deviceInstance->hostHandle, transfer); + return kStatus_USB_Error; + } + return kStatus_USB_Success; +} +#endif + +void USB_HostHubInterruptInCallback(void *param, uint8_t *data, uint32_t data_len, usb_status_t status) +{ + usb_host_hub_instance_t *hubInstance = (usb_host_hub_instance_t *)param; + usb_host_hub_global_t *hubGlobal = USB_HostHubGetHubList(hubInstance->hostHandle); + if (hubGlobal == NULL) + { + return; + } + + if (hubInstance->invalid == 1) + { + return; + } + /* interrupt data received */ + hubInstance->primeStatus = kPrimeNone; + if (status != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("hub interrupt in data callback error\r\n"); +#endif + /* prime nexe interrupt transfer */ + if (hubInstance->controlTransfer == NULL) + { + hubGlobal->hubProcess = NULL; + hubInstance->portProcess = 0; + USB_HostHubGetInterruptStatus(hubInstance); + } + } + else + { + USB_HostHubProcessData(hubGlobal, hubInstance); /* process the interrupt data */ + } +} + +/*! + * @brief host hub callback function. + * + * This function should be called in the host callback function. + * + * @param hostHandle host handle. + * @param deviceHandle device handle. + * @param configurationHandle attached device's configuration descriptor information. + * @param event_code callback event code, please reference to enumeration host_event_t. + * + * @retval kStatus_USB_Success The host is initialized successfully. + * @retval kStatus_USB_NotSupported The configuration don't contain hub interface. + */ +usb_status_t USB_HostHubDeviceEvent(usb_host_handle hostHandle, + usb_device_handle deviceHandle, + usb_host_configuration_handle configurationHandle, + uint32_t eventCode) +{ + usb_host_configuration_t *configuration; + usb_host_interface_t *interface; + uint8_t interfaceIndex; + uint8_t id; + usb_status_t status = kStatus_USB_Success; + usb_host_class_handle hubClassHandle; + usb_host_hub_instance_t *hubInstance; + usb_host_hub_instance_t *prevInstance; + uint32_t infoValue; + usb_osa_status_t osaStatus; + usb_host_hub_global_t *hubGlobal = USB_HostHubGetHubList(hostHandle); + if (hubGlobal == NULL) + { + return kStatus_USB_Error; + } + + switch (eventCode) + { + case kUSB_HostEventAttach: + /* judge whether is configurationHandle supported */ + configuration = (usb_host_configuration_t *)configurationHandle; + for (interfaceIndex = 0; interfaceIndex < configuration->interfaceCount; ++interfaceIndex) + { + interface = &configuration->interfaceList[interfaceIndex]; + id = interface->interfaceDesc->bInterfaceClass; + if (id != USB_HOST_HUB_CLASS_CODE) + { + continue; + } + id = interface->interfaceDesc->bInterfaceSubClass; + if (id != USB_HOST_HUB_SUBCLASS_CODE_NONE) + { + continue; + } + else + { + USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDeviceLevel, &infoValue); + if (infoValue > 5) + { +#ifdef HOST_ECHO + usb_echo("Host can support max 5 level hubs\r\n"); +#endif + continue; + } + /* the interface is hub */ + s_HubDeviceHandle = deviceHandle; + s_HubInterfaceHandle = interface; +#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U)) + s_HubConfiguration = configuration; +#endif + return kStatus_USB_Success; + } + } + status = kStatus_USB_NotSupported; + break; + + case kUSB_HostEventEnumerationDone: + /* the device enumeration is done */ + if ((s_HubDeviceHandle != NULL) && (s_HubInterfaceHandle != NULL)) + { + /* print hub information */ + USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDeviceLevel, &infoValue); + usb_echo("hub attached:level=%d ", infoValue); + USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDeviceAddress, &infoValue); + usb_echo("address=%d\r\n", infoValue); + + /* initialize hub mutex */ + if (hubGlobal->hubMutex == (usb_osa_mutex_handle)NULL) + { + osaStatus = USB_OsaMutexCreate(&hubGlobal->hubMutex); + if (osaStatus != kStatus_USB_OSA_Success) + { + hubGlobal->hubMutex = NULL; +#ifdef HOST_ECHO + usb_echo("hub mutex error\r\n"); +#endif + } + } + + /* initialize hub class instance */ + status = USB_HostHubInit(s_HubDeviceHandle, &hubClassHandle); + hubInstance = (usb_host_hub_instance_t *)hubClassHandle; + + /* link hub instance to list */ + USB_HostHubLock(); + hubInstance->next = hubGlobal->hubList; + hubGlobal->hubList = hubInstance; + USB_HostHubUnlock(); +#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U)) + hubInstance->supportRemoteWakeup = 0U; + hubInstance->controlRetry = USB_HOST_HUB_REMOTE_WAKEUP_TIMES; + if (s_HubConfiguration->configurationDesc->bmAttributes & + USB_DESCRIPTOR_CONFIGURE_ATTRIBUTE_REMOTE_WAKEUP_MASK) + { + hubInstance->supportRemoteWakeup = 1U; + } +#endif + /* set hub instance's interface */ + if (status == kStatus_USB_Success) + { + hubInstance->primeStatus = kPrimeHubControl; + hubInstance->hubStatus = kHubRunWaitSetInterface; + if (USB_HostHubSetInterface(hubClassHandle, s_HubInterfaceHandle, 0, USB_HostHubControlCallback, + hubInstance) != kStatus_USB_Success) + { + hubInstance->hubStatus = kHubRunInvalid; + } + } + } + break; + + case kUSB_HostEventDetach: + /* the device is detached */ + hubInstance = NULL; + + /* get device's hub instance handle */ + USB_HostHubLock(); + prevInstance = hubGlobal->hubList; + if (prevInstance->deviceHandle == deviceHandle) + { + hubInstance = prevInstance; + hubGlobal->hubList = prevInstance->next; + } + else + { + hubInstance = prevInstance->next; + while (hubInstance != NULL) + { + if (hubInstance->deviceHandle == deviceHandle) + { + prevInstance->next = hubInstance->next; + break; + } + prevInstance = hubInstance; + hubInstance = hubInstance->next; + } + } + USB_HostHubUnlock(); + + if (hubInstance != NULL) + { + if (hubInstance == hubGlobal->hubProcess) + { + hubGlobal->hubProcess = NULL; + } + /* print hub information */ + USB_HostHelperGetPeripheralInformation(hubInstance->deviceHandle, kUSB_HostGetDeviceLevel, &infoValue); + usb_echo("hub detached:level=%d ", infoValue); + USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDeviceAddress, &infoValue); + usb_echo("address=%d\r\n", infoValue); + hubInstance->invalid = 1; + /* detach hub ports' devices */ + for (uint8_t portIndex = 0; portIndex < hubInstance->portCount; ++portIndex) + { + if ((hubInstance->portList != NULL) && (hubInstance->portList[portIndex].deviceHandle != NULL)) + { + USB_HostDetachDeviceInternal(hubInstance->hostHandle, + hubInstance->portList[portIndex].deviceHandle); + hubInstance->portList[portIndex].deviceHandle = NULL; + } + } + if (hubInstance->portList != NULL) + { + USB_OsaMemoryFree(hubInstance->portList); + } + USB_HostHubDeinit(deviceHandle, hubInstance); /* de-initialize hub instance */ + } + + /* destroy hub mutex if there is no hub instance */ + if (hubGlobal->hubList == NULL) + { + if (hubGlobal->hubMutex != NULL) + { + USB_OsaMutexDestroy(hubGlobal->hubMutex); + hubGlobal->hubMutex = NULL; + } + } + break; + + default: + break; + } + + return status; +} + +/*! + * @brief remove attached device. called by USB_HostRemoveDevice. + * + * @param hubNumber the device attached hub. + * @param portNumber the device attached port. + * + * @return kStatus_USB_Success or error codes. + */ +usb_status_t USB_HostHubRemovePort(usb_host_handle hostHandle, uint8_t hubNumber, uint8_t portNumber) +{ + usb_host_hub_instance_t *hubInstance; + uint32_t infoValue; + usb_host_hub_global_t *hubGlobal = USB_HostHubGetHubList(hostHandle); + if (hubGlobal == NULL) + { + return kStatus_USB_Error; + } + + /* get hub number's hub instance handle */ + hubInstance = (usb_host_hub_instance_t *)hubGlobal->hubList; + while (hubInstance != NULL) + { + USB_HostHelperGetPeripheralInformation(hubInstance->deviceHandle, kUSB_HostGetDeviceAddress, &infoValue); + if (infoValue == hubNumber) + { + break; + } + hubInstance = hubInstance->next; + } + + /* set port's status as default, and reset port */ + if (hubInstance != NULL) + { + hubInstance->portList[portNumber - 1].deviceHandle = NULL; + hubInstance->portList[portNumber - 1].portStatus = kPortRunInvalid; + if (hubInstance->portProcess == portNumber) + { + hubInstance->portProcess = 0; + } + USB_HostHubSendPortReset(hubInstance, portNumber); + } + return kStatus_USB_Error; +} + +/*! + * @brief get device's high-speed hub's address. + * + * @param parent_hub_no device's parent hub's address. + * + * @return hub number. + */ +uint32_t USB_HostHubGetHsHubNumber(usb_host_handle hostHandle, uint8_t parentHubNo) +{ + usb_host_hub_instance_t *hubInstance; + uint32_t deviceInfo; + uint32_t hubNumber; + usb_host_hub_global_t *hubGlobal = USB_HostHubGetHubList(hostHandle); + if (hubGlobal == NULL) + { + return kStatus_USB_Error; + } + hubInstance = hubGlobal->hubList; + + /* get parentHubNo's hub instance handle */ + while (hubInstance != NULL) + { + USB_HostHelperGetPeripheralInformation(hubInstance->deviceHandle, kUSB_HostGetDeviceAddress, &deviceInfo); + if (parentHubNo == deviceInfo) + { + break; + } + hubInstance = hubInstance->next; + } + if (hubInstance != NULL) + { + USB_HostHelperGetPeripheralInformation(hubInstance->deviceHandle, kUSB_HostGetDeviceSpeed, &deviceInfo); + if (deviceInfo == USB_SPEED_HIGH) /* parent hub is HS */ + { + hubNumber = parentHubNo; + } + else /* parent hub is not HS */ + { + USB_HostHelperGetPeripheralInformation(hubInstance->deviceHandle, kUSB_HostGetDeviceHSHubNumber, + &hubNumber); + } + return hubNumber; + } + return 0; +} + +/*! + * @brief get device's high-speed hub's port number. + * + * @param parent_hub_no device's parent hub's address. + * @param parent_port_no device's parent port no. + * + * @return port number. + */ +uint32_t USB_HostHubGetHsHubPort(usb_host_handle hostHandle, uint8_t parentHubNo, uint8_t parentPortNo) +{ + usb_host_hub_instance_t *hubInstance; + uint32_t deviceInfo; + uint32_t hubPort; + usb_host_hub_global_t *hubGlobal = USB_HostHubGetHubList(hostHandle); + if (hubGlobal == NULL) + { + return kStatus_USB_Error; + } + hubInstance = hubGlobal->hubList; + + /* get parentHubNo's hub instance handle */ + while (hubInstance != NULL) + { + USB_HostHelperGetPeripheralInformation(hubInstance->deviceHandle, kUSB_HostGetDeviceAddress, &deviceInfo); + if (parentHubNo == deviceInfo) + { + break; + } + hubInstance = hubInstance->next; + } + if (hubInstance != NULL) + { + USB_HostHelperGetPeripheralInformation(hubInstance->deviceHandle, kUSB_HostGetDeviceSpeed, &deviceInfo); + if (deviceInfo == USB_SPEED_HIGH) /* parent hub is HS */ + { + hubPort = parentPortNo; + } + else /* parent hub is not HS */ + { + USB_HostHelperGetPeripheralInformation(hubInstance->deviceHandle, kUSB_HostGetDeviceHSHubNumber, &hubPort); + } + return hubPort; + } + return 0; +} + +/*! + * @brief get device's hub total think time. + * + * @param parent_hub_no device's parent hub's address. + * + * @return think time value. + */ +uint32_t USB_HostHubGetTotalThinkTime(usb_host_handle hostHandle, uint8_t parentHubNo) +{ + usb_host_hub_instance_t *hubInstance; + uint32_t deviceAddress; + usb_host_hub_global_t *hubGlobal = USB_HostHubGetHubList(hostHandle); + if (hubGlobal == NULL) + { + return kStatus_USB_Error; + } + hubInstance = hubGlobal->hubList; + + /* get parentHubNo's hub instance handle */ + while (hubInstance != NULL) + { + USB_HostHelperGetPeripheralInformation(hubInstance->deviceHandle, kUSB_HostGetDeviceAddress, &deviceAddress); + if (parentHubNo == deviceAddress) + { + break; + } + hubInstance = hubInstance->next; + } + if (hubInstance != NULL) + { + return hubInstance->totalThinktime; + } + return 0; +} + +#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U)) +/*! + * @brief Suspend the device. + * + * @param hostHandle Host instance. + * + * @return kStatus_USB_Success or error codes. + * + */ +usb_status_t USB_HostHubSuspendDevice(usb_host_handle hostHandle) +{ + usb_host_instance_t *hostInstance; + usb_host_hub_instance_t *hubInstance; + usb_status_t status = kStatus_USB_Error; + usb_host_hub_global_t *hubGlobal = USB_HostHubGetHubList(hostHandle); + if (hubGlobal == NULL) + { + return kStatus_USB_Error; + } + hubInstance = hubGlobal->hubList; + + if (NULL == hostHandle) + { + return kStatus_USB_InvalidHandle; + } + hostInstance = (usb_host_instance_t *)hostHandle; + if (NULL == hubInstance) + { + usb_host_bus_control_t type = kUSB_HostBusSuspend; + /* the callbackFn is initialized in USB_HostGetControllerInterface */ + status = + hostInstance->controllerTable->controllerIoctl(hostInstance->controllerHandle, kUSB_HostBusControl, &type); + if (kStatus_USB_Success != status) + { + usb_echo("Suspend USB BUS failed.\r\n"); + } + return status; + } + /* Scan HUB instance handle */ + while (hubInstance != NULL) + { + hubInstance->controlRetry = USB_HOST_HUB_REMOTE_WAKEUP_TIMES; + if (hubInstance->supportRemoteWakeup) + { + usb_echo("Set HUB remote wakeup feature: level %d, address %d.\r\n", + ((usb_host_device_instance_t *)hubInstance->deviceHandle)->level, + ((usb_host_device_instance_t *)hubInstance->deviceHandle)->setAddress); + status = USB_HostSendHubRequest( + hubInstance->deviceHandle, + USB_REQUEST_TYPE_RECIPIENT_DEVICE | USB_REQUEST_TYPE_DIR_OUT | USB_REQUEST_TYPE_TYPE_STANDARD, + USB_REQUEST_STANDARD_SET_FEATURE, USB_REQUEST_STANDARD_FEATURE_SELECTOR_DEVICE_REMOTE_WAKEUP, 0, + USB_HostHubRemoteWakeupCallback, hubInstance); + break; + } + hubInstance = hubInstance->next; + } + if (NULL == hubInstance) + { + usb_host_device_instance_t *deviceInstance = (usb_host_device_instance_t *)hostInstance->suspendedDevice; + if (NULL == deviceInstance) + { + usb_host_bus_control_t type = kUSB_HostBusSuspend; + /* the callbackFn is initialized in USB_HostGetControllerInterface */ + status = hostInstance->controllerTable->controllerIoctl(hostInstance->controllerHandle, kUSB_HostBusControl, + &type); + if (kStatus_USB_Success != status) + { + usb_echo("Suspend USB BUS failed.\r\n"); + } + } + else + { + usb_host_hub_instance_t *hubInstance4Device = + USB_HostHubGetHubDeviceHandle(hostHandle, deviceInstance->hubNumber); + if (NULL != hubInstance4Device) + { + status = USB_HostSendHubRequest( + hubInstance4Device->deviceHandle, + USB_REQUEST_TYPE_DIR_OUT | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_OTHER, + USB_REQUEST_STANDARD_SET_FEATURE, PORT_SUSPEND, deviceInstance->portNumber, + USB_HostSetHubRequestCallback, hostInstance); + if (kStatus_USB_Success != status) + { + usb_echo("Send suspend request to HUB is failed.\r\n"); + } + } + else + { + usb_echo("Invalid HUB instance of device.\r\n"); + } + } + } + return status; +} + +/*! + * @brief Resume the device. + * + * @param hostHandle Host instance. + * + * @return kStatus_USB_Success or error codes. + * + */ +usb_status_t USB_HostHubResumeDevice(usb_host_handle hostHandle) +{ + usb_host_instance_t *hostInstance; + usb_host_device_instance_t *deviceInstance; + usb_status_t status = kStatus_USB_Error; + + if (NULL == hostHandle) + { + return kStatus_USB_InvalidHandle; + } + hostInstance = (usb_host_instance_t *)hostHandle; + + deviceInstance = (usb_host_device_instance_t *)hostInstance->suspendedDevice; + if (NULL == deviceInstance) + { + return kStatus_USB_InvalidHandle; + } + + status = USB_HostSendHubRequest( + USB_HostHubGetHubDeviceHandle(hostHandle, deviceInstance->hubNumber)->deviceHandle, + USB_REQUEST_TYPE_DIR_OUT | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_OTHER, + USB_REQUEST_STANDARD_CLEAR_FEATURE, PORT_SUSPEND, deviceInstance->portNumber, USB_HostClearHubRequestCallback, + hostInstance); + + return status; +} +#endif + +#endif /* USB_HOST_CONFIG_HUB */ diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/class/usb_host_hub_app.h b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/class/usb_host_hub_app.h new file mode 100644 index 000000000..4727d0a19 --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/class/usb_host_hub_app.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _USB_HOST_HUB_APP_H_ +#define _USB_HOST_HUB_APP_H_ + +#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB)) + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/*! @brief HUB reset times*/ +#define USB_HOST_HUB_PORT_RESET_TIMES (1) + +#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U)) +/*! @brief HUB Control tansaction retry times for remote wakeup*/ +#define USB_HOST_HUB_REMOTE_WAKEUP_TIMES (3U) +#endif + +/*! @brief HUB application global structure */ +typedef struct _usb_host_hub_global +{ + usb_host_handle hostHandle; /*!< This HUB list belong to this host*/ + usb_host_hub_instance_t *hubProcess; /*!< HUB in processing*/ + usb_host_hub_instance_t *hubList; /*!< host's HUB list*/ + usb_osa_mutex_handle hubMutex; /*!< HUB mutex*/ +} usb_host_hub_global_t; + +/*! @brief HUB application status */ +typedef enum _usb_host_hub_app_status +{ + kHubRunIdle = 0, /*!< Idle */ + kHubRunInvalid, /*!< Invalid state */ + kHubRunWaitSetInterface, /*!< Wait callback of set interface */ + kHubRunGetDescriptor7, /*!< Get 7 bytes HUB descriptor */ + kHubRunGetDescriptor, /*!< Get all HUB descriptor */ + kHubRunSetPortPower, /*!< Set HUB's port power */ + kHubRunGetStatusDone, /*!< HUB status changed */ + kHubRunClearDone, /*!< clear HUB feature callback */ +} usb_host_hub_app_status_t; + +/*! @brief HUB port application status */ +typedef enum _usb_host_port_app_status +{ + kPortRunIdle = 0, /*!< Idle */ + kPortRunInvalid, /*!< Invalid state */ + kPortRunWaitPortChange, /*!< Wait port status change */ + kPortRunCheckCPortConnection, /*!< Check C_PORT_CONNECTION */ + kPortRunGetPortConnection, /*!< Get port status data */ + kPortRunCheckPortConnection, /*!< Check PORT_CONNECTION */ + kPortRunWaitPortResetDone, /*!< Wait port reset transfer done */ + kPortRunWaitCPortReset, /*!< Wait C_PORT_RESET */ + KPortRunCheckCPortReset, /*!< Check C_PORT_RESET */ + kPortRunResetAgain, /*!< Reset port again */ + kPortRunPortAttached, /*!< Device is attached on the port */ + kPortRunCheckPortDetach, /*!< Check port is detached */ + kPortRunGetConnectionBit, /*!< Get the port status data */ + kPortRunCheckConnectionBit, /*!< Check PORT_CONNECTION */ +#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U)) + kPortRunClearCPortSuspend, /*!< Clear C_PORT_SUSPEND */ + kPortRunCheckPortSuspend, /*!< Check PORT_SUSPEND */ + kPortRunPortSuspended, /*!< Port is suspended */ +#endif +} usb_host_port_app_status_t; + +/*! @brief HUB data prime status */ +typedef enum _usb_host_hub_prime_status +{ + kPrimeNone = 0, /*!< Don't prime data*/ + kPrimeHubControl, /*!< Prime HUB control transfer*/ + kPrimePortControl, /*!< Prime port control transfer*/ + kPrimeInterrupt, /*!< Prime interrupt transfer*/ +} usb_host_hub_prime_status_t; + +/******************************************************************************* + * API + ******************************************************************************/ + +#endif /* USB_HOST_CONFIG_HUB */ + +#endif /* _USB_HOST_HUB_APP_H_ */ diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/class/usb_host_msd.c b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/class/usb_host_msd.c new file mode 100644 index 000000000..bd34ed7c9 --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/class/usb_host_msd.c @@ -0,0 +1,1137 @@ +/* + * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc. + * Copyright 2016, 2019 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "usb_host_config.h" +#if ((defined USB_HOST_CONFIG_MSD) && (USB_HOST_CONFIG_MSD)) +#include "usb_host.h" +#include "usb_host_msd.h" +#include "usb_host_hci.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/******************************************************************************* + * Prototypes + ******************************************************************************/ + +/*! + * @brief clear stall transfer callback. + * + * @param param callback parameter. + * @param transfer transfer. + * @param status transfer result status. + */ +static void USB_HostMsdClearHaltCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status); + +/*! + * @brief send clear stall transfer. + * + * @param msdInstance msd instance pointer. + * @param callbackFn callback function. + * @param endpoint endpoint address. + * + * @return An error code or kStatus_USB_Success. + */ +static usb_status_t USB_HostMsdClearHalt(usb_host_msd_instance_t *msdInstance, + host_inner_transfer_callback_t callbackFn, + uint8_t endpoint); + +/*! + * @brief mass storage reset three step processes are done. + * + * @param msdInstance msd instance pointer. + * @param status result status. + */ +static void USB_HostMsdResetDone(usb_host_msd_instance_t *msdInstance, usb_status_t status); + +/*! + * @brief mass storage reset process step 3 callback. + * + * @param msdInstance msd instance pointer. + * @param transfer transfer + * @param status result status. + */ +static void USB_HostMsdMassResetClearOutCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status); + +/*! + * @brief mass storage reset process step 2 callback. + * + * @param msdInstance msd instance pointer. + * @transfer transfer + * @param status result status. + */ +static void USB_HostMsdMassResetClearInCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status); + +/*! + * @brief mass storage reset process step 1 callback. + * + * @param msdInstance msd instance pointer. + * @param transfer transfer + * @param status result status. + */ +static void USB_HostMsdMassResetCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status); + +/*! + * @brief mass storage control transfer callback function. + * + * @param msdInstance msd instance pointer. + * @param transfer transfer + * @param status result status. + */ +static void USB_HostMsdControlCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status); + +/*! + * @brief this function is called when ufi command is done. + * + * @param msdInstance msd instance pointer. + */ +static void USB_HostMsdCommandDone(usb_host_msd_instance_t *msdInstance, usb_status_t status); + +/*! + * @brief csw transfer callback. + * + * @param msdInstance msd instance pointer. + * @param transfer transfer + * @param status result status. + */ +static void USB_HostMsdCswCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status); + +/*! + * @brief cbw transfer callback. + * + * @param msdInstance msd instance pointer. + * @param transfer transfer + * @param status result status. + */ +static void USB_HostMsdCbwCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status); + +/*! + * @brief data transfer callback. + * + * @param msdInstance sd instance pointer. + * @param transfer transfer + * @param status result status. + */ +static void USB_HostMsdDataCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status); + +/*! + * @brief msd open interface. + * + * @param msdInstance msd instance pointer. + * + * @return kStatus_USB_Success or error codes. + */ +static usb_status_t USB_HostMsdOpenInterface(usb_host_msd_instance_t *msdInstance); + +/*! + * @brief msd set interface callback, open pipes. + * + * @param param callback parameter. + * @param transfer callback transfer. + * @param status transfer status. + */ +static void USB_HostMsdSetInterfaceCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status); + +/*! + * @brief msd control transfer common code. + * + * This function allocate the resource for msd instance. + * + * @param msdInstance the msd class instance. + * @param pipeCallbackFn inner callback function. + * @param callbackFn callback function. + * @param callbackParam callback parameter. + * @param buffer buffer pointer. + * @param bufferLength buffer length. + * @param requestType request type. + * @param requestValue request value. + * + * @return An error code or kStatus_USB_Success. + */ +static usb_status_t USB_HostMsdControl(usb_host_msd_instance_t *msdInstance, + host_inner_transfer_callback_t pipeCallbackFn, + transfer_callback_t callbackFn, + void *callbackParam, + uint8_t *buffer, + uint16_t bufferLength, + uint8_t requestType, + uint8_t requestValue); + +/*! + * @brief command process function, this function is called many time for one command's different state. + * + * @param msdInstance the msd class instance. + * + * @return An error code or kStatus_USB_Success. + */ +static usb_status_t USB_HostMsdProcessCommand(usb_host_msd_instance_t *msdInstance); + +/******************************************************************************* + * Variables + ******************************************************************************/ + +/******************************************************************************* + * Code + ******************************************************************************/ + +static void USB_HostMsdClearHaltCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status) +{ + usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)param; + + if (status != kStatus_USB_Success) + { + USB_HostMsdCommandDone(msdInstance, kStatus_USB_TransferCancel); + } + + if (msdInstance->commandStatus == kMSD_CommandErrorDone) + { + USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error); /* command fail */ + } + else + { + USB_HostMsdProcessCommand(msdInstance); /* continue to process ufi command */ + } +} + +static usb_status_t USB_HostMsdClearHalt(usb_host_msd_instance_t *msdInstance, + host_inner_transfer_callback_t callbackFn, + uint8_t endpoint) +{ + usb_status_t status; + usb_host_transfer_t *transfer; + + /* malloc one transfer */ + status = USB_HostMallocTransfer(msdInstance->hostHandle, &transfer); + if (status != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("allocate transfer error\r\n"); +#endif + return status; + } + + /* initialize transfer */ + transfer->callbackFn = callbackFn; + transfer->callbackParam = msdInstance; + transfer->transferBuffer = NULL; + transfer->transferLength = 0; + transfer->setupPacket->bRequest = USB_REQUEST_STANDARD_CLEAR_FEATURE; + transfer->setupPacket->bmRequestType = USB_REQUEST_TYPE_RECIPIENT_ENDPOINT; + transfer->setupPacket->wValue = USB_SHORT_TO_LITTLE_ENDIAN(USB_REQUEST_STANDARD_FEATURE_SELECTOR_ENDPOINT_HALT); + transfer->setupPacket->wIndex = USB_SHORT_TO_LITTLE_ENDIAN(endpoint); + transfer->setupPacket->wLength = 0; + status = USB_HostSendSetup(msdInstance->hostHandle, msdInstance->controlPipe, transfer); + + if (status != kStatus_USB_Success) + { + USB_HostFreeTransfer(msdInstance->hostHandle, transfer); + } + msdInstance->controlTransfer = transfer; + + return status; +} + +static void USB_HostMsdResetDone(usb_host_msd_instance_t *msdInstance, usb_status_t status) +{ + if (msdInstance->internalResetRecovery == 1) /* internal mass reset recovery */ + { + msdInstance->internalResetRecovery = 0; + + if ((status != kStatus_USB_Success) || (msdInstance->commandStatus == kMSD_CommandErrorDone)) + { + USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error); /* command fail */ + } + else + { + USB_HostMsdProcessCommand(msdInstance); /* continue to process ufi command */ + } + } + else /* user call mass storage reset recovery */ + { + if (msdInstance->controlCallbackFn != NULL) + { + /* callback to application, callback function is initialized in the USB_HostMsdControl, + or USB_HostMsdSetInterface, but is the same function */ + msdInstance->controlCallbackFn(msdInstance->controlCallbackParam, NULL, 0, + status); /* callback to application */ + } + } +} + +static void USB_HostMsdMassResetClearOutCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status) +{ + usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)param; + + msdInstance->controlTransfer = NULL; + USB_HostFreeTransfer(msdInstance->hostHandle, transfer); + USB_HostMsdResetDone(msdInstance, status); /* mass storage reset done */ +} + +static void USB_HostMsdMassResetClearInCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status) +{ + usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)param; + + msdInstance->controlTransfer = NULL; + USB_HostFreeTransfer(msdInstance->hostHandle, transfer); + + if (status == kStatus_USB_Success) + { + if (msdInstance->outPipe != NULL) + { + /* continue to process mass storage reset */ + USB_HostMsdClearHalt( + msdInstance, USB_HostMsdMassResetClearOutCallback, + (USB_REQUEST_TYPE_DIR_OUT | ((usb_host_pipe_t *)msdInstance->outPipe)->endpointAddress)); + } + } + else + { + USB_HostMsdResetDone(msdInstance, status); /* mass storage reset done */ + } +} + +static void USB_HostMsdMassResetCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status) +{ + usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)param; + + msdInstance->controlTransfer = NULL; + USB_HostFreeTransfer(msdInstance->hostHandle, transfer); + if (status == kStatus_USB_Success) + { + if (msdInstance->inPipe != NULL) + { + /* continue to process mass storage reset */ + USB_HostMsdClearHalt(msdInstance, USB_HostMsdMassResetClearInCallback, + (USB_REQUEST_TYPE_DIR_IN | ((usb_host_pipe_t *)msdInstance->inPipe)->endpointAddress)); + } + } + else + { + USB_HostMsdResetDone(msdInstance, status); /* mass storage reset done */ + } +} + +static void USB_HostMsdControlCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status) +{ + usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)param; + + msdInstance->controlTransfer = NULL; + if (msdInstance->controlCallbackFn != NULL) + { + /* callback to application, callback function is initialized in the USB_HostMsdControl, + or USB_HostMsdSetInterface, but is the same function */ + msdInstance->controlCallbackFn(msdInstance->controlCallbackParam, transfer->transferBuffer, + transfer->transferSofar, status); /* callback to application */ + } + USB_HostFreeTransfer(msdInstance->hostHandle, transfer); +} + +static void USB_HostMsdCommandDone(usb_host_msd_instance_t *msdInstance, usb_status_t status) +{ + if (msdInstance->commandCallbackFn != NULL) + { + /* callback to application, the callback function is initialized in USB_HostMsdCommand */ + msdInstance->commandCallbackFn(msdInstance->commandCallbackParam, msdInstance->msdCommand.dataBuffer, + msdInstance->msdCommand.dataSofar, status); + } + msdInstance->commandStatus = kMSD_CommandIdle; +} + +static void USB_HostMsdCswCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status) +{ + usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)param; + + if (status == kStatus_USB_Success) + { + /* kStatus_USB_Success */ + if ((transfer->transferSofar == USB_HOST_UFI_CSW_LENGTH) && + (msdInstance->msdCommand.cswBlock.CSWSignature == USB_LONG_TO_LITTLE_ENDIAN(USB_HOST_MSD_CSW_SIGNATURE))) + { + switch (msdInstance->msdCommand.cswBlock.CSWStatus) + { + case 0: + USB_HostMsdCommandDone(msdInstance, kStatus_USB_Success); + break; + + case 1: + USB_HostMsdCommandDone(msdInstance, kStatus_USB_MSDStatusFail); + break; + + case 2: + msdInstance->internalResetRecovery = 1; + msdInstance->commandStatus = kMSD_CommandErrorDone; + if (USB_HostMsdMassStorageReset(msdInstance, NULL, NULL) != kStatus_USB_Success) + { + USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error); + } + break; + + default: + USB_HostMsdCommandDone(msdInstance, kStatus_USB_MSDStatusFail); + break; + } + } + else + { + /* mass reset recovery to end ufi command */ + msdInstance->internalResetRecovery = 1; + msdInstance->commandStatus = kMSD_CommandErrorDone; + if (USB_HostMsdMassStorageReset(msdInstance, NULL, NULL) != kStatus_USB_Success) + { + USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error); + } + } + } + else + { + if (status == kStatus_USB_TransferStall) /* case 1: stall */ + { + if (msdInstance->msdCommand.retryTime > 0) + { + msdInstance->msdCommand.retryTime--; /* retry reduce when error */ + } + if (msdInstance->msdCommand.retryTime > 0) + { + /* clear stall to continue the ufi command */ + if (USB_HostMsdClearHalt( + msdInstance, USB_HostMsdClearHaltCallback, + (USB_REQUEST_TYPE_DIR_IN | ((usb_host_pipe_t *)msdInstance->inPipe)->endpointAddress)) != + kStatus_USB_Success) + { + USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error); + } + } + else + { + /* mass reset recovery to continue ufi command */ + msdInstance->internalResetRecovery = 1; + msdInstance->commandStatus = kMSD_CommandErrorDone; + if (USB_HostMsdMassStorageReset(msdInstance, NULL, NULL) != kStatus_USB_Success) + { + USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error); + } + } + } + else if (status == kStatus_USB_TransferCancel) /* case 2: cancel */ + { + USB_HostMsdCommandDone(msdInstance, status); /* command cancel */ + } + else /* case 3: error */ + { + if (msdInstance->msdCommand.retryTime > 0) + { + msdInstance->msdCommand.retryTime--; /* retry reduce when error */ + } + if (msdInstance->msdCommand.retryTime > 0) + { + USB_HostMsdProcessCommand(msdInstance); /* retry the last step transaction */ + } + else + { + /* mass reset recovery to continue ufi command */ + msdInstance->internalResetRecovery = 1; + msdInstance->commandStatus = kMSD_CommandErrorDone; + if (USB_HostMsdMassStorageReset(msdInstance, NULL, NULL) != kStatus_USB_Success) + { + USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error); + } + } + } + } +} + +static void USB_HostMsdCbwCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status) +{ + usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)param; + + if (status == kStatus_USB_Success) + { + /* kStatus_USB_Success */ + if (transfer->transferSofar == USB_HOST_UFI_CBW_LENGTH) + { + msdInstance->commandStatus = kMSD_CommandTransferData; + USB_HostMsdProcessCommand(msdInstance); /* continue to process ufi command */ + } + else + { + if (msdInstance->msdCommand.retryTime > 0) + { + msdInstance->msdCommand.retryTime--; + } + if (msdInstance->msdCommand.retryTime > 0) + { + USB_HostMsdProcessCommand(msdInstance); /* retry the last step transaction */ + } + else + { + /* mass reset recovery to continue ufi command */ + msdInstance->internalResetRecovery = 1; + msdInstance->commandStatus = kMSD_CommandErrorDone; + if (USB_HostMsdMassStorageReset(msdInstance, NULL, NULL) != kStatus_USB_Success) + { + USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error); + } + } + } + } + else + { + if (status == kStatus_USB_TransferStall) /* case 1: stall */ + { + if (msdInstance->msdCommand.retryTime > 0) + { + msdInstance->msdCommand.retryTime--; /* retry reduce when error */ + } + if (msdInstance->msdCommand.retryTime > 0) + { + /* clear stall to continue the ufi command */ + if (USB_HostMsdClearHalt( + msdInstance, USB_HostMsdClearHaltCallback, + (USB_REQUEST_TYPE_DIR_OUT | ((usb_host_pipe_t *)msdInstance->inPipe)->endpointAddress)) != + kStatus_USB_Success) + { + USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error); + } + } + else + { + /* mass reset recovery to continue ufi command */ + msdInstance->internalResetRecovery = 1; + msdInstance->commandStatus = kMSD_CommandErrorDone; + if (USB_HostMsdMassStorageReset(msdInstance, NULL, NULL) != kStatus_USB_Success) + { + USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error); + } + } + } + else if (status == kStatus_USB_TransferCancel) /* case 2: cancel */ + { + USB_HostMsdCommandDone(msdInstance, status); /* command cancel */ + } + else /* case 3: error */ + { + if (msdInstance->msdCommand.retryTime > 0) + { + msdInstance->msdCommand.retryTime--; + } + if (msdInstance->msdCommand.retryTime > 0) + { + USB_HostMsdProcessCommand(msdInstance); /* retry the last step transaction */ + } + else + { + /* mass reset recovery to continue ufi command */ + msdInstance->internalResetRecovery = 1; + msdInstance->commandStatus = kMSD_CommandErrorDone; + if (USB_HostMsdMassStorageReset(msdInstance, NULL, NULL) != kStatus_USB_Success) + { + USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error); + } + } + } + return; + } +} + +static void USB_HostMsdDataCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status) +{ + usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)param; + uint8_t direction; + + if (status == kStatus_USB_Success) + { + /* kStatus_USB_Success */ + msdInstance->msdCommand.dataSofar += transfer->transferSofar; + USB_HostMsdProcessCommand(msdInstance); /* continue to process ufi command */ + } + else + { + if (status == kStatus_USB_TransferStall) /* case 1: stall */ + { + if (msdInstance->msdCommand.retryTime > 0) + { + msdInstance->msdCommand.retryTime--; /* retry reduce when error */ + } + if (transfer->direction == USB_IN) + { + direction = USB_REQUEST_TYPE_DIR_IN; + } + else + { + direction = USB_REQUEST_TYPE_DIR_OUT; + } + + if (msdInstance->msdCommand.retryTime == 0) + { + msdInstance->commandStatus = kMSD_CommandTransferCSW; /* next step */ + } + /* clear stall to continue the ufi command */ + if (USB_HostMsdClearHalt(msdInstance, USB_HostMsdClearHaltCallback, + (direction | ((usb_host_pipe_t *)msdInstance->inPipe)->endpointAddress)) != + kStatus_USB_Success) + { + USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error); + } + } + else if (status == kStatus_USB_TransferCancel) /* case 2: cancel */ + { + USB_HostMsdCommandDone(msdInstance, status); /* command cancel */ + } + else /* case 3: error */ + { + /* mass reset recovery to finish ufi command */ + msdInstance->internalResetRecovery = 1; + msdInstance->commandStatus = kMSD_CommandErrorDone; + if (USB_HostMsdMassStorageReset(msdInstance, NULL, NULL) != kStatus_USB_Success) + { + USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error); + } + } + } +} + +static usb_status_t USB_HostMsdProcessCommand(usb_host_msd_instance_t *msdInstance) +{ + usb_status_t status = kStatus_USB_Success; + usb_host_transfer_t *transfer; + + if (msdInstance->msdCommand.transfer == NULL) + { + /* malloc one transfer */ + status = USB_HostMallocTransfer(msdInstance->hostHandle, &(msdInstance->msdCommand.transfer)); + if (status != kStatus_USB_Success) + { + msdInstance->msdCommand.transfer = NULL; +#ifdef HOST_ECHO + usb_echo("allocate transfer error\r\n"); +#endif + return kStatus_USB_Busy; + } + } + transfer = msdInstance->msdCommand.transfer; + switch (msdInstance->commandStatus) + { + case kMSD_CommandTransferCBW: /* ufi CBW phase */ + transfer->direction = USB_OUT; + transfer->transferBuffer = (uint8_t *)(&(msdInstance->msdCommand.cbwBlock)); + transfer->transferLength = USB_HOST_UFI_CBW_LENGTH; + transfer->callbackFn = USB_HostMsdCbwCallback; + transfer->callbackParam = msdInstance; + status = USB_HostSend(msdInstance->hostHandle, msdInstance->outPipe, transfer); + if (status != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("host send error\r\n"); +#endif + } + break; + + case kMSD_CommandTransferData: /* ufi DATA phase */ + if (msdInstance->msdCommand.dataBuffer != NULL) + { + transfer->direction = msdInstance->msdCommand.dataDirection; + transfer->transferBuffer = (msdInstance->msdCommand.dataBuffer + msdInstance->msdCommand.dataSofar); + transfer->transferLength = (msdInstance->msdCommand.dataLength - msdInstance->msdCommand.dataSofar); + transfer->callbackParam = msdInstance; + if (msdInstance->msdCommand.dataSofar != msdInstance->msdCommand.dataLength) + { + if (transfer->direction == USB_OUT) + { + transfer->callbackFn = USB_HostMsdDataCallback; + status = USB_HostSend(msdInstance->hostHandle, msdInstance->outPipe, transfer); + if (status != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("host send error\r\n"); +#endif + } + } + else + { + transfer->callbackFn = USB_HostMsdDataCallback; + status = USB_HostRecv(msdInstance->hostHandle, msdInstance->inPipe, transfer); + if (status != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("host recv error\r\n"); +#endif + } + } + break; + } + else + { + /* don't break */ + } + } + else + { + /* don't break */ + } + case kMSD_CommandTransferCSW: /* ufi CSW phase */ + transfer->direction = USB_IN; + transfer->transferBuffer = (uint8_t *)&msdInstance->msdCommand.cswBlock; + transfer->transferLength = USB_HOST_UFI_CSW_LENGTH; + transfer->callbackFn = USB_HostMsdCswCallback; + transfer->callbackParam = msdInstance; + status = USB_HostRecv(msdInstance->hostHandle, msdInstance->inPipe, transfer); + if (status != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("host recv error\r\n"); +#endif + } + break; + + case kMSD_CommandDone: + USB_HostMsdCommandDone(msdInstance, kStatus_USB_Success); + break; + + default: + break; + } + return status; +} + +/*! + * @brief all ufi function calls this api. + * + * This function implements the common ufi commands. + * + * @param classHandle the class msd handle. + * @param buffer buffer pointer. + * @param bufferLength buffer length. + * @param callbackFn callback function. + * @param callbackParam callback parameter. + * @param direction command direction. + * @param byteValues ufi command fields value. + * + * @return An error code or kStatus_USB_Success. + */ +usb_status_t USB_HostMsdCommand(usb_host_class_handle classHandle, + uint8_t *buffer, + uint32_t bufferLength, + transfer_callback_t callbackFn, + void *callbackParam, + uint8_t direction, + uint8_t byteValues[10]) +{ + usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)classHandle; + usb_host_cbw_t *cbwPointer = &(msdInstance->msdCommand.cbwBlock); + uint8_t index = 0; + + if (classHandle == NULL) + { + return kStatus_USB_InvalidHandle; + } + + if (msdInstance->commandStatus != kMSD_CommandIdle) + { + return kStatus_USB_Busy; + } + + /* save the application callback function */ + msdInstance->commandCallbackFn = callbackFn; + msdInstance->commandCallbackParam = callbackParam; + + /* initialize CBWCB fields */ + for (index = 0; index < USB_HOST_UFI_BLOCK_DATA_VALID_LENGTH; ++index) + { + cbwPointer->CBWCB[index] = byteValues[index]; + } + + /* initialize CBW fields */ + cbwPointer->CBWDataTransferLength = USB_LONG_TO_LITTLE_ENDIAN(bufferLength); + cbwPointer->CBWFlags = direction; + cbwPointer->CBWLun = (byteValues[1] >> USB_HOST_UFI_LOGICAL_UNIT_POSITION); + cbwPointer->CBWCBLength = USB_HOST_UFI_BLOCK_DATA_VALID_LENGTH; + + msdInstance->commandStatus = kMSD_CommandTransferCBW; + if (direction == USB_HOST_MSD_CBW_FLAGS_DIRECTION_IN) + { + msdInstance->msdCommand.dataDirection = USB_IN; + } + else + { + msdInstance->msdCommand.dataDirection = USB_OUT; + } + msdInstance->msdCommand.dataBuffer = buffer; + + msdInstance->msdCommand.dataLength = bufferLength; + msdInstance->msdCommand.dataSofar = 0; + msdInstance->msdCommand.retryTime = USB_HOST_MSD_RETRY_MAX_TIME; + + return USB_HostMsdProcessCommand(msdInstance); /* start to process ufi command */ +} + +static usb_status_t USB_HostMsdOpenInterface(usb_host_msd_instance_t *msdInstance) +{ + usb_status_t status; + uint8_t epIndex = 0; + usb_host_pipe_init_t pipeInit; + usb_descriptor_endpoint_t *epDesc = NULL; + usb_host_interface_t *interfacePointer; + + if (msdInstance->inPipe != NULL) /* close bulk in pipe if the pipe is open */ + { + status = USB_HostClosePipe(msdInstance->hostHandle, msdInstance->inPipe); + if (status != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("error when close pipe\r\n"); +#endif + } + msdInstance->inPipe = NULL; + } + if (msdInstance->outPipe != NULL) /* close bulk out pipe if the pipe is open */ + { + status = USB_HostClosePipe(msdInstance->hostHandle, msdInstance->outPipe); + if (status != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("error when close pipe\r\n"); +#endif + } + msdInstance->outPipe = NULL; + } + + /* open interface pipes */ + interfacePointer = (usb_host_interface_t *)msdInstance->interfaceHandle; + for (epIndex = 0; epIndex < interfacePointer->epCount; ++epIndex) + { + epDesc = interfacePointer->epList[epIndex].epDesc; + if (((epDesc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) == + USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_IN) && + ((epDesc->bmAttributes & USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_TYPE_MASK) == USB_ENDPOINT_BULK)) + { + pipeInit.devInstance = msdInstance->deviceHandle; + pipeInit.pipeType = USB_ENDPOINT_BULK; + pipeInit.direction = USB_IN; + pipeInit.endpointAddress = (epDesc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK); + pipeInit.interval = epDesc->bInterval; + pipeInit.maxPacketSize = (uint16_t)(USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(epDesc->wMaxPacketSize) & + USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_SIZE_MASK); + pipeInit.numberPerUframe = (USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(epDesc->wMaxPacketSize) & + USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_MASK); + pipeInit.nakCount = USB_HOST_CONFIG_MAX_NAK; + + status = USB_HostOpenPipe(msdInstance->hostHandle, &msdInstance->inPipe, &pipeInit); + if (status != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("usb_host_hid_set_interface fail to open pipe\r\n"); +#endif + return status; + } + } + else if (((epDesc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) == + USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_OUT) && + ((epDesc->bmAttributes & USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_TYPE_MASK) == USB_ENDPOINT_BULK)) + { + pipeInit.devInstance = msdInstance->deviceHandle; + pipeInit.pipeType = USB_ENDPOINT_BULK; + pipeInit.direction = USB_OUT; + pipeInit.endpointAddress = (epDesc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK); + pipeInit.interval = epDesc->bInterval; + pipeInit.maxPacketSize = (uint16_t)(USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(epDesc->wMaxPacketSize) & + USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_SIZE_MASK); + pipeInit.numberPerUframe = (USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(epDesc->wMaxPacketSize) & + USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_MASK); + pipeInit.nakCount = USB_HOST_CONFIG_MAX_NAK; + + status = USB_HostOpenPipe(msdInstance->hostHandle, &msdInstance->outPipe, &pipeInit); + if (status != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("usb_host_hid_set_interface fail to open pipe\r\n"); +#endif + return status; + } + } + else + { + } + } + + return kStatus_USB_Success; +} + +static void USB_HostMsdSetInterfaceCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status) +{ + usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)param; + + msdInstance->controlTransfer = NULL; + if (status == kStatus_USB_Success) + { + status = USB_HostMsdOpenInterface(msdInstance); /* msd open interface */ + } + + if (msdInstance->controlCallbackFn != NULL) + { + /* callback to application, callback function is initialized in the USB_HostMsdControl, + or USB_HostMsdSetInterface, but is the same function */ + msdInstance->controlCallbackFn(msdInstance->controlCallbackParam, NULL, 0, + status); /* callback to application */ + } + USB_HostFreeTransfer(msdInstance->hostHandle, transfer); +} + +usb_status_t USB_HostMsdInit(usb_device_handle deviceHandle, usb_host_class_handle *classHandle) +{ + uint32_t infoValue; + usb_status_t status; + usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)USB_OsaMemoryAllocate( + sizeof(usb_host_msd_instance_t)); /* malloc msd class instance */ + + if (msdInstance == NULL) + { + return kStatus_USB_AllocFail; + } + + /* initialize msd instance */ + msdInstance->deviceHandle = deviceHandle; + msdInstance->interfaceHandle = NULL; + USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetHostHandle, &infoValue); + msdInstance->hostHandle = (usb_host_handle)infoValue; + USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDeviceControlPipe, &infoValue); + msdInstance->controlPipe = (usb_host_pipe_handle)infoValue; + + msdInstance->msdCommand.cbwBlock.CBWSignature = USB_LONG_TO_LITTLE_ENDIAN(USB_HOST_MSD_CBW_SIGNATURE); + status = USB_HostMallocTransfer(msdInstance->hostHandle, &(msdInstance->msdCommand.transfer)); + if (status != kStatus_USB_Success) + { + msdInstance->msdCommand.transfer = NULL; +#ifdef HOST_ECHO + usb_echo("allocate transfer error\r\n"); +#endif + } + + *classHandle = msdInstance; + return kStatus_USB_Success; +} + +usb_status_t USB_HostMsdSetInterface(usb_host_class_handle classHandle, + usb_host_interface_handle interfaceHandle, + uint8_t alternateSetting, + transfer_callback_t callbackFn, + void *callbackParam) +{ + usb_status_t status = kStatus_USB_Error; + usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)classHandle; + usb_host_transfer_t *transfer; + + if (classHandle == NULL) + { + return kStatus_USB_InvalidHandle; + } + + status = USB_HostOpenDeviceInterface(msdInstance->deviceHandle, + interfaceHandle); /* notify host driver the interface is open */ + if (status != kStatus_USB_Success) + { + return status; + } + msdInstance->interfaceHandle = interfaceHandle; + + /* cancel transfers */ + if (msdInstance->inPipe != NULL) + { + status = USB_HostCancelTransfer(msdInstance->hostHandle, msdInstance->inPipe, NULL); + if (status != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("error when cancel pipe\r\n"); +#endif + } + } + if (msdInstance->outPipe != NULL) + { + status = USB_HostCancelTransfer(msdInstance->hostHandle, msdInstance->outPipe, NULL); + if (status != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("error when cancel pipe\r\n"); +#endif + } + } + + if (alternateSetting == 0) /* open interface directly */ + { + if (callbackFn != NULL) + { + status = USB_HostMsdOpenInterface(msdInstance); + callbackFn(callbackParam, NULL, 0, status); + } + } + else /* send setup transfer */ + { + /* malloc one transfer */ + if (USB_HostMallocTransfer(msdInstance->hostHandle, &transfer) != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("error to get transfer\r\n"); +#endif + return kStatus_USB_Busy; + } + /* save the application callback function */ + msdInstance->controlCallbackFn = callbackFn; + msdInstance->controlCallbackParam = callbackParam; + /* initialize transfer */ + transfer->callbackFn = USB_HostMsdSetInterfaceCallback; + transfer->callbackParam = msdInstance; + transfer->setupPacket->bRequest = USB_REQUEST_STANDARD_SET_INTERFACE; + transfer->setupPacket->bmRequestType = USB_REQUEST_TYPE_RECIPIENT_INTERFACE; + transfer->setupPacket->wIndex = USB_SHORT_TO_LITTLE_ENDIAN( + ((usb_host_interface_t *)msdInstance->interfaceHandle)->interfaceDesc->bInterfaceNumber); + transfer->setupPacket->wValue = USB_SHORT_TO_LITTLE_ENDIAN(alternateSetting); + transfer->setupPacket->wLength = 0; + transfer->transferBuffer = NULL; + transfer->transferLength = 0; + status = USB_HostSendSetup(msdInstance->hostHandle, msdInstance->controlPipe, transfer); + + if (status == kStatus_USB_Success) + { + msdInstance->controlTransfer = transfer; + } + else + { + USB_HostFreeTransfer(msdInstance->hostHandle, transfer); + } + } + + return status; +} + +usb_status_t USB_HostMsdDeinit(usb_device_handle deviceHandle, usb_host_class_handle classHandle) +{ + usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)classHandle; + usb_status_t status; + + if (classHandle != NULL) + { + if (msdInstance->inPipe != NULL) + { + status = USB_HostCancelTransfer(msdInstance->hostHandle, msdInstance->inPipe, NULL); /* cancel pipe */ + status = USB_HostClosePipe(msdInstance->hostHandle, msdInstance->inPipe); /* close pipe */ + if (status != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("error when close pipe\r\n"); +#endif + } + } + if (msdInstance->outPipe != NULL) + { + status = USB_HostCancelTransfer(msdInstance->hostHandle, msdInstance->outPipe, NULL); /* cancel pipe */ + status = USB_HostClosePipe(msdInstance->hostHandle, msdInstance->outPipe); /* close pipe */ + if (status != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("error when close pipe\r\n"); +#endif + } + } + if ((msdInstance->controlPipe != NULL) && + (msdInstance->controlTransfer != NULL)) /* cancel control transfer if there is on-going control transfer */ + { + status = + USB_HostCancelTransfer(msdInstance->hostHandle, msdInstance->controlPipe, msdInstance->controlTransfer); + } + if (msdInstance->msdCommand.transfer) + { + USB_HostFreeTransfer(msdInstance->hostHandle, msdInstance->msdCommand.transfer); + } + USB_HostCloseDeviceInterface(deviceHandle, + msdInstance->interfaceHandle); /* notify host driver the interface is closed */ + USB_OsaMemoryFree(msdInstance); + } + else + { + USB_HostCloseDeviceInterface(deviceHandle, NULL); + } + + return kStatus_USB_Success; +} + +static usb_status_t USB_HostMsdControl(usb_host_msd_instance_t *msdInstance, + host_inner_transfer_callback_t pipeCallbackFn, + transfer_callback_t callbackFn, + void *callbackParam, + uint8_t *buffer, + uint16_t bufferLength, + uint8_t requestType, + uint8_t requestValue) +{ + usb_host_transfer_t *transfer; + + if (msdInstance == NULL) + { + return kStatus_USB_InvalidHandle; + } + + /* malloc one transfer */ + if (USB_HostMallocTransfer(msdInstance->hostHandle, &transfer) != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("allocate transfer error\r\n"); +#endif + return kStatus_USB_Busy; + } + /* save the application callback function */ + msdInstance->controlCallbackFn = callbackFn; + msdInstance->controlCallbackParam = callbackParam; + /* initialize transfer */ + transfer->transferBuffer = buffer; + transfer->transferLength = bufferLength; + transfer->callbackFn = pipeCallbackFn; + transfer->callbackParam = msdInstance; + + transfer->setupPacket->bmRequestType = requestType; + transfer->setupPacket->bRequest = requestValue; + transfer->setupPacket->wValue = 0x0000; + transfer->setupPacket->wIndex = + ((usb_host_interface_t *)msdInstance->interfaceHandle)->interfaceDesc->bInterfaceNumber; + transfer->setupPacket->wLength = bufferLength; + + if (USB_HostSendSetup(msdInstance->hostHandle, msdInstance->controlPipe, transfer) != + kStatus_USB_Success) /* call host driver api */ + { + USB_HostFreeTransfer(msdInstance->hostHandle, transfer); + return kStatus_USB_Error; + } + msdInstance->controlTransfer = transfer; + + return kStatus_USB_Success; +} + +usb_status_t USB_HostMsdMassStorageReset(usb_host_class_handle classHandle, + transfer_callback_t callbackFn, + void *callbackParam) +{ + usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)classHandle; + + return USB_HostMsdControl(msdInstance, USB_HostMsdMassResetCallback, callbackFn, callbackParam, NULL, 0, + (USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE), + USB_HOST_HID_MASS_STORAGE_RESET); +} + +usb_status_t USB_HostMsdGetMaxLun(usb_host_class_handle classHandle, + uint8_t *logicalUnitNumber, + transfer_callback_t callbackFn, + void *callbackParam) +{ + usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)classHandle; + + return USB_HostMsdControl( + msdInstance, USB_HostMsdControlCallback, callbackFn, callbackParam, logicalUnitNumber, 1, + (USB_REQUEST_TYPE_DIR_IN | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE), + USB_HOST_HID_GET_MAX_LUN); +} + +#endif /* USB_HOST_CONFIG_MSD */ diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/class/usb_host_msd.h b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/class/usb_host_msd.h new file mode 100644 index 000000000..e7fce910d --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/class/usb_host_msd.h @@ -0,0 +1,851 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _USB_HOST_MSD_H_ +#define _USB_HOST_MSD_H_ + +/******************************************************************************* + * MSD class private structure, enumeration, macro + ******************************************************************************/ + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/* CBW and CSW Macros */ +#define USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT (0x00U) +#define USB_HOST_MSD_CBW_FLAGS_DIRECTION_IN (0x80U) +#define USB_HOST_MSD_CBW_SIGNATURE (0x43425355U) +#define USB_HOST_MSD_CSW_SIGNATURE (0x53425355U) + +/* UFI data bit macro */ +#define USB_HOST_UFI_BLOCK_DATA_VALID_LENGTH (10U) +#define USB_HOST_UFI_LOGICAL_UNIT_POSITION (5U) +#define USB_HOST_UFI_CBW_LENGTH (31U) +#define USB_HOST_UFI_CSW_LENGTH (13U) +#define USB_HOST_UFI_MODE_SENSE_PAGE_CONTROL_SHIFT (6U) +#define USB_HOST_UFI_MODE_SENSE_PAGE_CODE_SHIFT (0U) +#define USB_HOST_UFI_START_STOP_UNIT_LOEJ_SHIFT (1U) +#define USB_HOST_UFI_START_STOP_UNIT_START_SHIFT (0U) +#define USB_HOST_UFI_SEND_DIAGNOSTIC_SELF_TEST_SHIFT (2U) + +/******************************************************************************* + * MSD class public structure, enumeration, macro, function + ******************************************************************************/ +/*! + * @addtogroup usb_host_msc_drv + * @{ + */ + +/*! @brief retry time when transfer fail, when all the retries fail the transfer callback with error status */ +#define USB_HOST_MSD_RETRY_MAX_TIME (1U) +/*! @brief mass storage block size */ +#define USB_HOST_MSD_BLOCK_SIZE (512U) + +/*! @brief MSD class code */ +#define USB_HOST_MSD_CLASS_CODE (8U) +/*! @brief MSD sub-class code */ +#define USB_HOST_MSD_SUBCLASS_CODE_UFI (4U) +/*! @brief MSD sub-class code */ +#define USB_HOST_MSD_SUBCLASS_CODE_SCSI (6U) +/*! @brief MSD protocol code */ +#define USB_HOST_MSD_PROTOCOL_BULK (0x50U) + +/*! @brief MSD class-specific request (mass storage reset) */ +#define USB_HOST_HID_MASS_STORAGE_RESET (0xFFU) +/*! @brief MSD class-specific request (get maximum logical unit number) */ +#define USB_HOST_HID_GET_MAX_LUN (0xFEU) + +/*! @brief UFI command process status */ +typedef enum _usb_host_msd_command_status +{ + kMSD_CommandIdle = 0, + kMSD_CommandTransferCBW, + kMSD_CommandTransferData, + kMSD_CommandTransferCSW, + kMSD_CommandDone, + kMSD_CommandCancel, + kMSD_CommandErrorDone, +} usb_host_msd_command_status_t; + +/*! @brief MSC Bulk-Only command block wrapper (CBW) */ +typedef struct _usb_host_cbw +{ + uint32_t CBWSignature; /*!< Signature that helps identify this data packet as a CBW. The signature field shall + contain the value 43425355h (little endian), indicating a CBW */ + uint32_t + CBWTag; /*!< A Command Block Tag sent by the host. The device shall echo the contents of this field back to the + host in the dCSWTag field of the associated CSW */ + uint32_t CBWDataTransferLength; /*!< The number of bytes of data that the host expects to transfer on the Bulk-In or + Bulk-Out endpoint during the execution of this command */ + uint8_t CBWFlags; /*!< + Bit 7 Direction - the device shall ignore this bit if the dCBWDataTransferLength field is + zero, otherwise: + 0 = Data-Out from host to the device, + 1 = Data-In from the device to the host. + Bit 6 Obsolete. The host shall set this bit to zero. + Bits 5..0 Reserved - the host shall set these bits to zero. + */ + uint8_t CBWLun; /*!< The device Logical Unit Number (LUN) to which the command block is being sent */ + uint8_t CBWCBLength; /*!< The valid length of the CBWCB in bytes. This defines the valid length of the command + block. The only legal values are 1 through 16 (01h through 10h).*/ + uint8_t CBWCB[16]; /*!< The command block to be executed by the device*/ +} usb_host_cbw_t; + +/*! @brief MSC Bulk-Only command status wrapper (CSW) */ +typedef struct _usb_host_csw +{ + uint32_t CSWSignature; /*!< Signature that helps identify this data packet as a CSW. The signature field shall + contain the value 53425355h (little endian), indicating CSW.*/ + uint32_t CSWTag; /*!< The device shall set this field to the value received in the dCBWTag of the associated CBW*/ + uint32_t CSWDataResidue; /*!< the difference between the amount of data expected as stated in the + dCBWDataTransferLength and the actual amount of relevant data processed by the device.*/ + uint8_t CSWStatus; /*!< + bCSWStatus indicates the success or failure of the command. + 00h - Command passed. + 01h - Command Failed. + 02h - Phase error. + others - Reserved. + */ +} usb_host_csw_t; + +/*! @brief MSC UFI command information structure */ +typedef struct _usb_host_msd_command +{ + usb_host_cbw_t cbwBlock; /*!< CBW data block*/ + usb_host_csw_t cswBlock; /*!< CSW data block*/ + uint8_t *dataBuffer; /*!< Data buffer pointer*/ + uint32_t dataLength; /*!< Data buffer length*/ + uint32_t dataSofar; /*!< Successful transfer data length*/ + usb_host_transfer_t *transfer; /*!< The transfer is used for processing the UFI command*/ + uint8_t retryTime; /*!< The UFI command residual retry time, when it reduce to zero the UFI command fail */ + uint8_t dataDirection; /*!< The data direction, its value is USB_OUT or USB_IN*/ +} usb_host_msd_command_t; + +/*! @brief MSD instance structure, MSD usb_host_class_handle pointer to this structure */ +typedef struct _usb_host_msd_instance +{ + usb_host_handle hostHandle; /*!< This instance's related host handle*/ + usb_device_handle deviceHandle; /*!< This instance's related device handle*/ + usb_host_interface_handle interfaceHandle; /*!< This instance's related interface handle*/ + usb_host_pipe_handle controlPipe; /*!< This instance's related device control pipe*/ + usb_host_pipe_handle outPipe; /*!< MSD bulk out pipe*/ + usb_host_pipe_handle inPipe; /*!< MSD bulk in pipe*/ + transfer_callback_t commandCallbackFn; /*!< MSD UFI command callback function pointer*/ + void *commandCallbackParam; /*!< MSD UFI command callback parameter*/ + transfer_callback_t controlCallbackFn; /*!< MSD control transfer callback function pointer*/ + void *controlCallbackParam; /*!< MSD control transfer callback parameter*/ + usb_host_transfer_t *controlTransfer; /*!< Ongoing control transfer*/ + usb_host_msd_command_t msdCommand; /*!< Ongoing MSD UFI command information*/ + uint8_t commandStatus; /*!< UFI command process status, see command_status_t*/ + uint8_t internalResetRecovery; /*!< 1 - class driver internal mass storage reset recovery is on-going; 0 - + application call USB_HostMsdMassStorageReset to reset or there is no reset*/ +} usb_host_msd_instance_t; + +/*! @brief UFI standard sense data structure */ +typedef struct _usb_host_ufi_sense_data +{ + uint8_t errorCode; /*!< This field shall contain a value of 70h to indicate current errors*/ + uint8_t reserved1; /*!< Reserved field*/ + uint8_t senseKey; /*!< Provide a hierarchy of error or command result information*/ + uint8_t information[4]; /*!< This field is command-specific; it is typically used by some commands to return a + logical block address denoting where an error occurred*/ + uint8_t additionalSenseLength; /*!< The UFI device sets the value of this field to ten, to indicate that ten more + bytes of sense data follow this field*/ + uint8_t reserved2[4]; /*!< Reserved field*/ + uint8_t additionalSenseCode; /*!< Provide a hierarchy of error or command result information*/ + uint8_t additionalSenseCodeQualifier; /*!< Provide a hierarchy of error or command result information*/ + uint8_t reserved3[4]; /*!< Reserved field*/ +} usb_host_ufi_sense_data_t; + +/*! @brief UFI standard inquiry data structure */ +typedef struct _usb_host_ufi_inquiry_data +{ + uint8_t peripheralDeviceType; /*!< Identifies the device currently connected to the requested logical unit*/ + uint8_t removableMediaBit; /*!< This shall be set to one to indicate removable media*/ + uint8_t version; /*!< Version*/ + uint8_t responseDataFormat; /*!< A value of 01h shall be used for UFI device*/ + uint8_t additionalLength; /*!< Specify the length in bytes of the parameters*/ + uint8_t reserved1[3]; /*!< Reserved field*/ + uint8_t vendorInformation[8]; /*!< Contains 8 bytes of ASCII data identifying the vendor of the product*/ + uint8_t productIdentification[16]; /*!< Contains 16 bytes of ASCII data as defined by the vendor*/ + uint8_t productRevisionLevel[4]; /*!< Contains 4 bytes of ASCII data as defined by the vendor*/ +} usb_host_ufi_inquiry_data_t; + +/*! @brief UFI read capacity data structure */ +typedef struct _usb_host_ufi_read_capacity +{ + uint8_t lastLogicalBlockAddress[4]; /*!< The logical block number*/ + uint8_t blockLengthInBytes[4]; /*!< Block size*/ +} usb_host_ufi_read_capacity_t; + +#ifdef __cplusplus +extern "C" { +#endif + +/******************************************************************************* + * API + ******************************************************************************/ + +/*! + * @name USB host MSD class APIs + * @{ + */ + +/*! + * @brief Initializes the MSD instance. + * + * This function allocates the resources for the MSD instance. + * + * @param[in] deviceHandle The device handle. + * @param[out] classHandle Return class handle. + * + * @retval kStatus_USB_Success The device is initialized successfully. + * @retval kStatus_USB_AllocFail Allocate memory fail. + */ +extern usb_status_t USB_HostMsdInit(usb_device_handle deviceHandle, usb_host_class_handle *classHandle); + +/*! + * @brief Sets the interface. + * + * This function binds the interface with the MSD instance. + * + * @param[in] classHandle The class handle. + * @param[in] interfaceHandle The interface handle. + * @param[in] alternateSetting The alternate setting value. + * @param[in] callbackFn This callback is called after this function completes. + * @param[in] callbackParam The first parameter in the callback function. + * + * @retval kStatus_USB_Success The device is initialized successfully. + * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer. + * @retval kStatus_USB_Busy There is no idle transfer. + * @retval kStatus_USB_Error Send transfer fail. See the USB_HostSendSetup. + * @retval kStatus_USB_Success Callback return status, the command succeeded. + * @retval kStatus_USB_Busy Callback return status, there is no idle pipe. + * @retval kStatus_USB_TransferStall Callback return status, the transfer is stalled by the device. + * @retval kStatus_USB_Error Callback return status, open pipe fail. See the USB_HostOpenPipe. + */ +extern usb_status_t USB_HostMsdSetInterface(usb_host_class_handle classHandle, + usb_host_interface_handle interfaceHandle, + uint8_t alternateSetting, + transfer_callback_t callbackFn, + void *callbackParam); + +/*! + * @brief Deinitializes the MSD instance. + * + * This function frees the resource for the MSD instance. + * + * @param[in] deviceHandle The device handle. + * @param[in] classHandle The class handle. + * + * @retval kStatus_USB_Success The device is de-initialized successfully. + */ +extern usb_status_t USB_HostMsdDeinit(usb_device_handle deviceHandle, usb_host_class_handle classHandle); + +/*! + * @brief Mass storage reset. + * + * This function implements the mass storage reset request. + * + * @param[in] classHandle The class handle. + * @param[in] callbackFn This callback is called after this function completes. + * @param[in] callbackParam The first parameter in the callback function. + * + * @retval kStatus_USB_Success The device is initialized successfully. + * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer. + * @retval kStatus_USB_Busy There is no idle transfer. + * @retval kStatus_USB_Error Send transfer fail. See the USB_HostSendSetup. + */ +extern usb_status_t USB_HostMsdMassStorageReset(usb_host_class_handle classHandle, + transfer_callback_t callbackFn, + void *callbackParam); + +/*! + * @brief Gets the maximum logical unit number. + * + * This function implements the get maximum LUN request. + * + * @param[in] classHandle The class handle. + * @param[out] logicalUnitNumber Return logical unit number value. + * @param[in] callbackFn This callback is called after this function completes. + * @param[in] callbackParam The first parameter in the callback function. + * + * @retval kStatus_USB_Success The device is initialized successfully. + * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer. + * @retval kStatus_USB_Busy There is no idle transfer. + * @retval kStatus_USB_Error Send transfer fail. See the USB_HostSendSetup. + * @retval kStatus_USB_Success Callback return status, the command succeed. + * @retval kStatus_USB_MSDStatusFail Callback return status, the CSW status indicate this command fail. + * @retval kStatus_USB_Error Callback return status, the command fail. + */ +extern usb_status_t USB_HostMsdGetMaxLun(usb_host_class_handle classHandle, + uint8_t *logicalUnitNumber, + transfer_callback_t callbackFn, + void *callbackParam); + +/*! + * @brief Mass storage read (10). + * + * This function implements the UFI READ(10) command. This command requests that the UFI + * device transfer data to the host. + * + * @param[in] classHandle The class MSD handle. + * @param[in] logicalUnit Logical unit number. + * @param[in] blockAddress The start block address. + * @param[out] buffer Buffer pointer. + * @param[in] bufferLength The buffer length. + * @param[in] blockNumber Read block number. + * @param[in] callbackFn This callback is called after this command completes. + * @param[in] callbackParam The first parameter in the callback function. + * + * @retval kStatus_USB_Success The device is initialized successfully. + * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer. + * @retval kStatus_USB_Busy The previous command is executing or there is no idle transfer. + * @retval kStatus_USB_Error Send transfer fail. See the USB_HostSend/USB_HostRecv. + * @retval kStatus_USB_Success Callback return status, the command succeed. + * @retval kStatus_USB_MSDStatusFail Callback return status, the CSW status indicate this command fail. + * @retval kStatus_USB_Error Callback return status, the command fail. + */ +extern usb_status_t USB_HostMsdRead10(usb_host_class_handle classHandle, + uint8_t logicalUnit, + uint32_t blockAddress, + uint8_t *buffer, + uint32_t bufferLength, + uint32_t blockNumber, + transfer_callback_t callbackFn, + void *callbackParam); + +/*! + * @brief Mass storage read (12). + * + * This function implements the UFI READ(12) command and requests that the UFI + * device transfer data to the host. + * + * @param[in] classHandle The class MSD handle. + * @param[in] logicalUnit Logical unit number. + * @param[in] blockAddress The start block address. + * @param[out] buffer Buffer pointer. + * @param[in] bufferLength The buffer length. + * @param[in] blockNumber Read block number. + * @param[in] callbackFn This callback is called after this command completes. + * @param[in] callbackParam The first parameter in the callback function. + * + * @retval kStatus_USB_Success The device is initialized successfully. + * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer. + * @retval kStatus_USB_Busy The previous command is executing or there is no idle transfer. + * @retval kStatus_USB_Error Send transfer fail. See the USB_HostSend/USB_HostRecv. + * @retval kStatus_USB_Success Callback return status, the command succeed. + * @retval kStatus_USB_MSDStatusFail Callback return status, the CSW status indicate this command fail. + * @retval kStatus_USB_Error Callback return status, the command fail. + */ +extern usb_status_t USB_HostMsdRead12(usb_host_class_handle classHandle, + uint8_t logicalUnit, + uint32_t blockAddress, + uint8_t *buffer, + uint32_t bufferLength, + uint32_t blockNumber, + transfer_callback_t callbackFn, + void *callbackParam); + +/*! + * @brief Mass storage write (10). + * + * This function implements the UFI WRITE(10) command and requests that the UFI device + * write the data transferred by the host to the medium. + * + * @param[in] classHandle The class MSD handle. + * @param[in] logicalUnit Logical unit number. + * @param[in] blockAddress The start block address. + * @param[in] buffer Buffer pointer. + * @param[in] bufferLength The buffer length. + * @param[in] blockNumber Write block number. + * @param[in] callbackFn This callback is called after this command completes. + * @param[in] callbackParam The first parameter in the callback function. + * + * @retval kStatus_USB_Success The device is initialized successfully. + * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer. + * @retval kStatus_USB_Busy The previous command is executing or there is no idle transfer. + * @retval kStatus_USB_Error Send transfer fail. See the USB_HostSend/USB_HostRecv. + * @retval kStatus_USB_Success Callback return status, the command succeed. + * @retval kStatus_USB_MSDStatusFail Callback return status, the CSW status indicate this command fail. + * @retval kStatus_USB_Error Callback return status, the command fail. + */ +extern usb_status_t USB_HostMsdWrite10(usb_host_class_handle classHandle, + uint8_t logicalUnit, + uint32_t blockAddress, + uint8_t *buffer, + uint32_t bufferLength, + uint32_t blockNumber, + transfer_callback_t callbackFn, + void *callbackParam); + +/*! + * @brief Mass storage write (12). + * + * This function implements the UFI WRITE(12) command and requests that the UFI device + * write the data transferred by the host to the medium. + * + * @param[in] classHandle The class MSD handle. + * @param[in] logicalUnit Logical unit number. + * @param[in] blockAddress The start block address. + * @param[in] buffer Buffer pointer. + * @param[in] bufferLength The buffer length. + * @param[in] blockNumber Write block number. + * @param[in] callbackFn This callback is called after this command completes. + * @param[in] callbackParam The first parameter in the callback function. + * + * @retval kStatus_USB_Success The device is initialized successfully. + * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer. + * @retval kStatus_USB_Busy The previous command is executing or there is no idle transfer. + * @retval kStatus_USB_Error Send transfer fail. See the USB_HostSend/USB_HostRecv. + * @retval kStatus_USB_Success Callback return status, the command succeed. + * @retval kStatus_USB_MSDStatusFail Callback return status, the CSW status indicate this command fail. + * @retval kStatus_USB_Error Callback return status, the command fail. + */ +extern usb_status_t USB_HostMsdWrite12(usb_host_class_handle classHandle, + uint8_t logicalUnit, + uint32_t blockAddress, + uint8_t *buffer, + uint32_t bufferLength, + uint32_t blockNumber, + transfer_callback_t callbackFn, + void *callbackParam); + +/*! + * @brief Mass storage read capacity. + * + * This function implements the UFI READ CAPACITY command and allows the host to request + * capacities of the currently installed medium. + * + * @param[in] classHandle The class MSD handle. + * @param[in] logicalUnit Logical unit number. + * @param[out] buffer Buffer pointer. + * @param[in] bufferLength The buffer length. + * @param[in] callbackFn This callback is called after this command completes. + * @param[in] callbackParam The first parameter in the callback function. + * + * @retval kStatus_USB_Success The device is initialized successfully. + * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer. + * @retval kStatus_USB_Busy The previous command is executing or there is no idle transfer. + * @retval kStatus_USB_Error Send transfer fail. See the USB_HostSend/USB_HostRecv. + * @retval kStatus_USB_Success Callback return status, the command succeed. + * @retval kStatus_USB_MSDStatusFail Callback return status, the CSW status indicate this command fail. + * @retval kStatus_USB_Error Callback return status, the command fail. + */ +extern usb_status_t USB_HostMsdReadCapacity(usb_host_class_handle classHandle, + uint8_t logicalUnit, + uint8_t *buffer, + uint32_t bufferLength, + transfer_callback_t callbackFn, + void *callbackParam); + +/*! + * @brief Mass storage test unit ready. + * + * This function implements the UFI TEST UNIT READY command and + * checks if the UFI device is ready. + * + * @param[in] classHandle The class MSD handle. + * @param[in] logicalUnit Logical unit number. + * @param[in] callbackFn This callback is called after this command completes. + * @param[in] callbackParam The first parameter in the callback function. + * + * @retval kStatus_USB_Success The device is initialized successfully. + * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer. + * @retval kStatus_USB_Busy The previous command is executing or there is no idle transfer. + * @retval kStatus_USB_Error Send transfer fail. See the USB_HostSend/USB_HostRecv. + * @retval kStatus_USB_Success Callback return status, the command succeed. + * @retval kStatus_USB_MSDStatusFail Callback return status, the CSW status indicate this command fail. + * @retval kStatus_USB_Error Callback return status, the command fail. + */ +extern usb_status_t USB_HostMsdTestUnitReady(usb_host_class_handle classHandle, + uint8_t logicalUnit, + transfer_callback_t callbackFn, + void *callbackParam); + +/*! + * @brief mass storage request sense. + * + * This function implements the UFI REQUEST SENSE command, this command instructs + * the UFI device to transfer sense data to the host for the specified logical unit. + * + * @param[in] classHandle The class MSD handle. + * @param[in] logicalUnit Logical unit number. + * @param[out] buffer Buffer pointer. + * @param[in] bufferLength The buffer length. + * @param[in] callbackFn This callback is called after this command completes. + * @param[in] callbackParam The first parameter in the callback function. + * + * @retval kStatus_USB_Success The device is initialized successfully. + * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer. + * @retval kStatus_USB_Busy The previous command is executing or there is no idle transfer. + * @retval kStatus_USB_Error Send transfer fail. See the USB_HostSend/USB_HostRecv. + * @retval kStatus_USB_Success Callback return status, the command succeed. + * @retval kStatus_USB_MSDStatusFail Callback return status, the CSW status indicate this command fail. + * @retval kStatus_USB_Error Callback return status, the command fail. + */ +extern usb_status_t USB_HostMsdRequestSense(usb_host_class_handle classHandle, + uint8_t logicalUnit, + uint8_t *buffer, + uint32_t bufferLength, + transfer_callback_t callbackFn, + void *callbackParam); + +/*! + * @brief Mass storage mode select. + * + * This function implements the UFI MODE SELECT command and allows the host + * to specify medium or device parameters to the UFI device. + * + * @param[in] classHandle The class MSD handle. + * @param[in] logicalUnit Logical unit number. + * @param[in] buffer Buffer pointer. + * @param[in] bufferLength The buffer length. + * @param[in] callbackFn This callback is called after this command completes. + * @param[in] callbackParam The first parameter in the callback function. + * + * @retval kStatus_USB_Success The device is initialized successfully. + * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer. + * @retval kStatus_USB_Busy The previous command is executing or there is no idle transfer. + * @retval kStatus_USB_Error Send transfer fail. See the USB_HostSend/USB_HostRecv. + * @retval kStatus_USB_Success Callback return status, the command succeed. + * @retval kStatus_USB_MSDStatusFail Callback return status, the CSW status indicate this command fail. + * @retval kStatus_USB_Error Callback return status, the command fail. + */ +extern usb_status_t USB_HostMsdModeSelect(usb_host_class_handle classHandle, + uint8_t logicalUnit, + uint8_t *buffer, + uint32_t bufferLength, + transfer_callback_t callbackFn, + void *callbackParam); + +/*! + * @brief Mass storage mode sense. + * + * This function implements the UFI MODE SENSE command and allows the UFI + * device to report medium or device parameters to the host. + * + * @param[in] classHandle The class MSD handle. + * @param[in] logicalUnit Logical unit number. + * @param[in] pageControl The page control field specifies the type of mode parameters to return. + * @param[in] pageCode Buffer pointer. + * @param[out] buffer Buffer pointer. + * @param[in] bufferLength The buffer length. + * @param[in] callbackFn This callback is called after this command completes. + * @param[in] callbackParam The first parameter in the callback function. + * + * @retval kStatus_USB_Success The device is initialized successfully. + * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer. + * @retval kStatus_USB_Busy The previous command is executing or there is no idle transfer. + * @retval kStatus_USB_Error Send transfer fail. See the USB_HostSend/USB_HostRecv. + * @retval kStatus_USB_Success Callback return status, the command succeed. + * @retval kStatus_USB_MSDStatusFail Callback return status, the CSW status indicate this command fail. + * @retval kStatus_USB_Error Callback return status, the command fail. + */ +extern usb_status_t USB_HostMsdModeSense(usb_host_class_handle classHandle, + uint8_t logicalUnit, + uint8_t pageControl, + uint8_t pageCode, + uint8_t *buffer, + uint32_t bufferLength, + transfer_callback_t callbackFn, + void *callbackParam); + +/*! + * @brief Mass storage inquiry. + * + * This function implements the UFI INQUIRY command and requests that information regarding + * parameters of the UFI device itself be sent to the host. + * + * @param[in] classHandle The class MSD handle. + * @param[in] logicalUnit Logical unit number. + * @param[out] buffer Buffer pointer. + * @param[in] bufferLength The buffer length. + * @param[in] callbackFn This callback is called after this command completes. + * @param[in] callbackParam The first parameter in the callback function. + * + * @retval kStatus_USB_Success The device is initialized successfully. + * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer. + * @retval kStatus_USB_Busy The previous command is executing or there is no idle transfer. + * @retval kStatus_USB_Error Send transfer fail. See the USB_HostSend/USB_HostRecv. + * @retval kStatus_USB_Success Callback return status, the command succeed. + * @retval kStatus_USB_MSDStatusFail Callback return status, the CSW status indicate this command fail. + * @retval kStatus_USB_Error Callback return status, the command fail. + */ +extern usb_status_t USB_HostMsdInquiry(usb_host_class_handle classHandle, + uint8_t logicalUnit, + uint8_t *buffer, + uint32_t bufferLength, + transfer_callback_t callbackFn, + void *callbackParam); + +/*! + * @brief Mass storage read format capacities. + * + * This function implements the UFI READ FORMAT CAPACITIES command and allows the host to request + * a list of the possible capacities that can be formatted on the currently installed medium. + * + * @param[in] classHandle The class MSD handle. + * @param[in] logicalUnit Logical unit number. + * @param[out] buffer Buffer pointer. + * @param[in] bufferLength The buffer length. + * @param[in] callbackFn This callback is called after this command completes. + * @param[in] callbackParam The first parameter in the callback function. + * + * @retval kStatus_USB_Success The device is initialized successfully. + * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer. + * @retval kStatus_USB_Busy The previous command is executing or there is no idle transfer. + * @retval kStatus_USB_Error Send transfer fail. See the USB_HostSend/USB_HostRecv. + * @retval kStatus_USB_Success Callback return status, the command succeed. + * @retval kStatus_USB_MSDStatusFail Callback return status, the CSW status indicate this command fail. + * @retval kStatus_USB_Error Callback return status, the command fail. + */ +extern usb_status_t USB_HostMsdReadFormatCapacities(usb_host_class_handle classHandle, + uint8_t logicalUnit, + uint8_t *buffer, + uint32_t bufferLength, + transfer_callback_t callbackFn, + void *callbackParam); + +/*! + * @brief Mass storage format unit. + * + * This function implements the UFI FORMAT UNIT command and the host sends this command to physically format one + * track of a diskette according to the selected options. + * + * @param[in] classHandle The class MSD handle. + * @param[in] logicalUnit Logical unit number. + * @param[in] trackNumber This specifies which track is to be formatted. + * @param[in] interLeave This specifies the interleave that shall be used for formatting. + * @param[in] buffer Buffer pointer. + * @param[in] bufferLength The buffer length. + * @param[in] callbackFn This callback is called after this command completes. + * @param[in] callbackParam The first parameter in the callback function. + * + * @retval kStatus_USB_Success The device is initialized successfully. + * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer. + * @retval kStatus_USB_Busy The previous command is executing or there is no idle transfer. + * @retval kStatus_USB_Error Send transfer fail. See the USB_HostSend/USB_HostRecv. + * @retval kStatus_USB_Success Callback return status, the command succeed. + * @retval kStatus_USB_MSDStatusFail Callback return status, the CSW status indicate this command fail. + * @retval kStatus_USB_Error Callback return status, the command fail. + */ +extern usb_status_t USB_HostMsdFormatUnit(usb_host_class_handle classHandle, + uint8_t logicalUnit, + uint8_t trackNumber, + uint16_t interLeave, + uint8_t *buffer, + uint32_t bufferLength, + transfer_callback_t callbackFn, + void *callbackParam); + +/*! + * @brief Mass storage prevents/allows a medium removal. + * + * This function implements the UFI PREVENT-ALLOW MEDIUM REMOVAL command and notifies the FUI device + * to enable or disable the removal of the medium in the logical unit. + * + * @param[in] classHandle The class MSD handle. + * @param[in] logicalUnit Logical unit number. + * @param[in] prevent Prevent or allow + * - 0: enable (allow) the removal of the medium + * - 1: disable (prevent) removal of the medium + * @param[in] callbackFn This callback is called after this command completes. + * @param[in] callbackParam The first parameter in the callback function. + * + * @retval kStatus_USB_Success The device is initialized successfully. + * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer. + * @retval kStatus_USB_Busy The previous command is executing or there is no idle transfer. + * @retval kStatus_USB_Error Send transfer fail. See the USB_HostSend/USB_HostRecv. + * @retval kStatus_USB_Success Callback return status, the command succeed. + * @retval kStatus_USB_MSDStatusFail Callback return status, the CSW status indicate this command fail. + * @retval kStatus_USB_Error Callback return status, the command fail. + */ +extern usb_status_t USB_HostMsdPreventAllowRemoval(usb_host_class_handle classHandle, + uint8_t logicalUnit, + uint8_t prevent, + transfer_callback_t callbackFn, + void *callbackParam); + +/*! + * @brief Mass storage write and verify. + * + * This function implements the UFI WRITE AND VERIFY command and requests that the UFI device + * writes the data transferred by the host to the medium, then verifies the data on the medium. + * + * @param[in] classHandle The class MSD handle. + * @param[in] logicalUnit Logical unit number. + * @param[in] blockAddress The start block address. + * @param[in] buffer Buffer pointer. + * @param[in] bufferLength The buffer length. + * @param[in] blockNumber Write and verify block number. + * @param[in] callbackFn This callback is called after this command completes. + * @param[in] callbackParam The first parameter in the callback function. + * + * @retval kStatus_USB_Success The device is initialized successfully. + * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer. + * @retval kStatus_USB_Busy The previous command is executing or there is no idle transfer. + * @retval kStatus_USB_Error Send transfer fail. See the USB_HostSend/USB_HostRecv. + * @retval kStatus_USB_Success Callback return status, the command succeed. + * @retval kStatus_USB_MSDStatusFail Callback return status, the CSW status indicate this command fail. + * @retval kStatus_USB_Error Callback return status, the command fail. + */ +extern usb_status_t USB_HostMsdWriteAndVerify(usb_host_class_handle classHandle, + uint8_t logicalUnit, + uint32_t blockAddress, + uint8_t *buffer, + uint32_t bufferLength, + uint32_t blockNumber, + transfer_callback_t callbackFn, + void *callbackParam); + +/*! + * @brief Mass storage start stop unit. + * + * This function implements the UFI START-STOP UNIT command and instructs the UFI device + * to enable or disable media access operations . + * + * @param[in] classHandle The class MSD handle. + * @param[in] logicalUnit Logical unit number. + * @param[in] loadEject A Load Eject (LoEj) bit of zero requests that no eject action be performed. A LoEj bit of + * one, with the + * Start bit cleared to zero, which instructs the UFI device to eject the media. + * @param[in] start A Start bit of one instructs the UFI device to enable media access operations. A Start bit + * of zero instructs the UFI device to disable media access operations. + * @param[in] callbackFn This callback is called after this command completes. + * @param[in] callbackParam The first parameter in the callback function. + * + * @retval kStatus_USB_Success The device is initialized successfully. + * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer. + * @retval kStatus_USB_Busy The previous command is executing or there is no idle transfer. + * @retval kStatus_USB_Error Send transfer fail. See the USB_HostSend/USB_HostRecv. + * @retval kStatus_USB_Success Callback return status, the command succeed. + * @retval kStatus_USB_MSDStatusFail Callback return status, the CSW status indicate this command fail. + * @retval kStatus_USB_Error Callback return status, the command fail. + */ +extern usb_status_t USB_HostMsdStartStopUnit(usb_host_class_handle classHandle, + uint8_t logicalUnit, + uint8_t loadEject, + uint8_t start, + transfer_callback_t callbackFn, + void *callbackParam); + +/*! + * @brief Mass storage verify. + * + * This function implements the UFI VERIFY command and requests that the UFI device + * verify the data on the medium. + * + * @param[in] classHandle The class MSD handle. + * @param[in] logicalUnit Logical unit number. + * @param[in] blockAddress The start block address. + * @param[in] verificationLength The data length that need to be verified. + * @param[in] callbackFn This callback is called after this command completes. + * @param[in] callbackParam The first parameter in the callback function. + * + * @retval kStatus_USB_Success The device is initialized successfully. + * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer. + * @retval kStatus_USB_Busy The previous command is executing or there is no idle transfer. + * @retval kStatus_USB_Error Send transfer fail. See the USB_HostSend/USB_HostRecv. + * @retval kStatus_USB_Success Callback return status, the command succeed. + * @retval kStatus_USB_MSDStatusFail Callback return status, the CSW status indicate this command fail. + * @retval kStatus_USB_Error Callback return status, the command fail. + */ +extern usb_status_t USB_HostMsdVerify(usb_host_class_handle classHandle, + uint8_t logicalUnit, + uint32_t blockAddress, + uint16_t verificationLength, + transfer_callback_t callbackFn, + void *callbackParam); + +/*! + * @brief Mass storage rezero. + * + * This function implements the UFI REZERO UNIT command. This command positions the head of + * the drive to the cylinder 0. + * + * @param[in] classHandle The class MSD handle. + * @param[in] logicalUnit Logical unit number. + * @param[in] callbackFn This callback is called after this command completes. + * @param[in] callbackParam The first parameter in the callback function. + * + * @retval kStatus_USB_Success The device is initialized successfully. + * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer. + * @retval kStatus_USB_Busy The previous command is executing or there is no idle transfer. + * @retval kStatus_USB_Error Send transfer fail. See the USB_HostSend/USB_HostRecv. + * @retval kStatus_USB_Success Callback return status, the command succeed. + * @retval kStatus_USB_MSDStatusFail Callback return status, the CSW status indicate this command fail. + * @retval kStatus_USB_Error Callback return status, the command fail. + */ +extern usb_status_t USB_HostMsdRezeroUnit(usb_host_class_handle classHandle, + uint8_t logicalUnit, + transfer_callback_t callbackFn, + void *callbackParam); + +/*! + * @brief Mass storage seek(10). + * + * This function implements the UFI SEEK(10) command and requests that the UFI device + * seek to the specified Logical Block Address. + * + * @param[in] classHandle The class MSD handle. + * @param[in] logicalUnit Logical unit number. + * @param[in] blockAddress The start block address. + * @param[in] callbackFn This callback is called after this command completes. + * @param[in] callbackParam The first parameter in the callback function. + * + * @retval kStatus_USB_Success The device is initialized successfully. + * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer. + * @retval kStatus_USB_Busy The previous command is executing or there is no idle transfer. + * @retval kStatus_USB_Error Send transfer fail. See the USB_HostSend/USB_HostRecv. + * @retval kStatus_USB_Success Callback return status, the command succeed. + * @retval kStatus_USB_MSDStatusFail Callback return status, the CSW status indicate this command fail. + * @retval kStatus_USB_Error Callback return status, the command fail. + */ +extern usb_status_t USB_HostMsdSeek10(usb_host_class_handle classHandle, + uint8_t logicalUnit, + uint32_t blockAddress, + transfer_callback_t callbackFn, + void *callbackParam); + +/*! + * @brief Mass storage send diagnostic. + * + * This function implements the UFI SEND DIAGNOSTIC command. This command requests the UFI device + * to do a reset or perform a self-test. + * + * @param[in] classHandle The class MSD handle. + * @param[in] logicalUnit Logical unit number. + * @param[in] selfTest 0 = perform special diagnostic test; 1 = perform default self-test. + * @param[in] callbackFn This callback is called after this command completes. + * @param[in] callbackParam The first parameter in the callback function. + * + * @retval kStatus_USB_Success The device is initialized successfully. + * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer. + * @retval kStatus_USB_Busy The previous command is executing or there is no idle transfer. + * @retval kStatus_USB_Error Send transfer fail. See the USB_HostSend/USB_HostRecv. + * @retval kStatus_USB_Success Callback return status, the command succeed. + * @retval kStatus_USB_MSDStatusFail Callback return status, the CSW status indicate this command fail. + * @retval kStatus_USB_Error Callback return status, the command fail. + */ +extern usb_status_t USB_HostMsdSendDiagnostic(usb_host_class_handle classHandle, + uint8_t logicalUnit, + uint8_t selfTest, + transfer_callback_t callbackFn, + void *callbackParam); + +/*! @}*/ + +#ifdef __cplusplus +} +#endif + +/*! @}*/ + +#endif /* _USB_HOST_MSD_H_ */ diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/class/usb_host_msd_ufi.c b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/class/usb_host_msd_ufi.c new file mode 100644 index 000000000..9c65b2fb3 --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/class/usb_host_msd_ufi.c @@ -0,0 +1,451 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "usb_host_config.h" +#if ((defined USB_HOST_CONFIG_MSD) && (USB_HOST_CONFIG_MSD)) +#include "usb_host.h" +#include "usb_host_msd.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/* UFI command code */ +#define UFI_FORMAT_UNIT (0x04U) +#define UFI_INQUIRY (0x12U) +#define UFI_START_STOP (0x1BU) +#define UFI_MODE_SELECT (0x55U) +#define UFI_MODE_SENSE (0x5AU) +#define UFI_MEDIUM_REMOVAL (0x1EU) +#define UFI_READ10 (0x28U) +#define UFI_READ12 (0xA8U) +#define UFI_READ_CAPACITY (0x25U) +#define UFI_READ_FORMAT_CAPACITY (0x23U) +#define UFI_REQUEST_SENSE (0x03U) +#define UFI_REZERO_UINT (0x01U) +#define UFI_SEEK (0x2BU) +#define UFI_SEND_DIAGNOSTIC (0x1DU) +#define UFI_TEST_UNIT_READY (0x00U) +#define UFI_VERIFY (0x2FU) +#define UFI_WRITE10 (0x2AU) +#define UFI_WRITE12 (0xAAU) +#define UFI_WRITE_VERIFY (0x2EU) + +#define GET_BYTE_FROM_LE_LONG(b, n) \ + ((uint8_t)((USB_LONG_TO_LITTLE_ENDIAN(b)) >> (n * 8))) /* get the byte from the long value */ + +/******************************************************************************* + * Prototypes + ******************************************************************************/ + +extern usb_status_t USB_HostMsdCommand(usb_host_class_handle classHandle, + uint8_t *buffer, + uint32_t bufferLength, + transfer_callback_t callbackFn, + void *callbackParam, + uint8_t direction, + uint8_t byteValues[10]); + +/******************************************************************************* + * Variables + ******************************************************************************/ + +/******************************************************************************* + * Code + ******************************************************************************/ + +usb_status_t USB_HostMsdRead10(usb_host_class_handle classHandle, + uint8_t logicalUnit, + uint32_t blockAddress, + uint8_t *buffer, + uint32_t bufferLength, + uint32_t blockNumber, + transfer_callback_t callbackFn, + void *callbackParam) +{ + uint8_t ufiBytes[] = {UFI_READ10, + (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION), + GET_BYTE_FROM_LE_LONG(blockAddress, 3), + GET_BYTE_FROM_LE_LONG(blockAddress, 2), + GET_BYTE_FROM_LE_LONG(blockAddress, 1), + GET_BYTE_FROM_LE_LONG(blockAddress, 0), + 0x00, + GET_BYTE_FROM_LE_LONG(blockNumber, 1), + GET_BYTE_FROM_LE_LONG(blockNumber, 0), + 0x00}; + return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam, + USB_HOST_MSD_CBW_FLAGS_DIRECTION_IN, ufiBytes); +} + +usb_status_t USB_HostMsdRead12(usb_host_class_handle classHandle, + uint8_t logicalUnit, + uint32_t blockAddress, + uint8_t *buffer, + uint32_t bufferLength, + uint32_t blockNumber, + transfer_callback_t callbackFn, + void *callbackParam) +{ + uint8_t ufiBytes[] = {UFI_READ12, + (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION), + GET_BYTE_FROM_LE_LONG(blockAddress, 3), + GET_BYTE_FROM_LE_LONG(blockAddress, 2), + GET_BYTE_FROM_LE_LONG(blockAddress, 1), + GET_BYTE_FROM_LE_LONG(blockAddress, 0), + GET_BYTE_FROM_LE_LONG(blockNumber, 3), + GET_BYTE_FROM_LE_LONG(blockNumber, 2), + GET_BYTE_FROM_LE_LONG(blockNumber, 1), + GET_BYTE_FROM_LE_LONG(blockNumber, 0)}; + return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam, + USB_HOST_MSD_CBW_FLAGS_DIRECTION_IN, ufiBytes); +} + +usb_status_t USB_HostMsdWrite10(usb_host_class_handle classHandle, + uint8_t logicalUnit, + uint32_t blockAddress, + uint8_t *buffer, + uint32_t bufferLength, + uint32_t blockNumber, + transfer_callback_t callbackFn, + void *callbackParam) +{ + uint8_t ufiBytes[] = {UFI_WRITE10, + (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION), + GET_BYTE_FROM_LE_LONG(blockAddress, 3), + GET_BYTE_FROM_LE_LONG(blockAddress, 2), + GET_BYTE_FROM_LE_LONG(blockAddress, 1), + GET_BYTE_FROM_LE_LONG(blockAddress, 0), + 0x00, + GET_BYTE_FROM_LE_LONG(blockNumber, 1), + GET_BYTE_FROM_LE_LONG(blockNumber, 0), + 0x00}; + return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam, + USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT, ufiBytes); +} + +usb_status_t USB_HostMsdWrite12(usb_host_class_handle classHandle, + uint8_t logicalUnit, + uint32_t blockAddress, + uint8_t *buffer, + uint32_t bufferLength, + uint32_t blockNumber, + transfer_callback_t callbackFn, + void *callbackParam) +{ + uint8_t ufiBytes[] = {UFI_WRITE12, + (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION), + GET_BYTE_FROM_LE_LONG(blockAddress, 3), + GET_BYTE_FROM_LE_LONG(blockAddress, 2), + GET_BYTE_FROM_LE_LONG(blockAddress, 1), + GET_BYTE_FROM_LE_LONG(blockAddress, 0), + GET_BYTE_FROM_LE_LONG(blockNumber, 3), + GET_BYTE_FROM_LE_LONG(blockNumber, 2), + GET_BYTE_FROM_LE_LONG(blockNumber, 1), + GET_BYTE_FROM_LE_LONG(blockNumber, 0)}; + return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam, + USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT, ufiBytes); +} + +usb_status_t USB_HostMsdReadCapacity(usb_host_class_handle classHandle, + uint8_t logicalUnit, + uint8_t *buffer, + uint32_t bufferLength, + transfer_callback_t callbackFn, + void *callbackParam) +{ + uint8_t ufiBytes[] = {UFI_READ_CAPACITY, + (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION), + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00}; + return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam, + USB_HOST_MSD_CBW_FLAGS_DIRECTION_IN, ufiBytes); +} + +usb_status_t USB_HostMsdTestUnitReady(usb_host_class_handle classHandle, + uint8_t logicalUnit, + transfer_callback_t callbackFn, + void *callbackParam) +{ + uint8_t ufiBytes[] = {UFI_TEST_UNIT_READY, + (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION), + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00}; + return USB_HostMsdCommand(classHandle, NULL, 0, callbackFn, callbackParam, USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT, + ufiBytes); +} + +usb_status_t USB_HostMsdRequestSense(usb_host_class_handle classHandle, + uint8_t logicalUnit, + uint8_t *buffer, + uint32_t bufferLength, + transfer_callback_t callbackFn, + void *callbackParam) +{ + uint8_t ufiBytes[] = {UFI_REQUEST_SENSE, + (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION), + 0x00, + 0x00, + (uint8_t)bufferLength, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00}; + return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam, + USB_HOST_MSD_CBW_FLAGS_DIRECTION_IN, ufiBytes); +} + +usb_status_t USB_HostMsdModeSelect(usb_host_class_handle classHandle, + uint8_t logicalUnit, + uint8_t *buffer, + uint32_t bufferLength, + transfer_callback_t callbackFn, + void *callbackParam) +{ + uint8_t ufiBytes[] = {UFI_MODE_SELECT, + (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION), + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + GET_BYTE_FROM_LE_LONG(bufferLength, 1), + GET_BYTE_FROM_LE_LONG(bufferLength, 0), + 0x00}; + return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam, + USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT, ufiBytes); +} + +usb_status_t USB_HostMsdModeSense(usb_host_class_handle classHandle, + uint8_t logicalUnit, + uint8_t pageControl, + uint8_t pageCode, + uint8_t *buffer, + uint32_t bufferLength, + transfer_callback_t callbackFn, + void *callbackParam) +{ + uint8_t ufiBytes[] = {UFI_MODE_SENSE, (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION), + (uint8_t)(((uint32_t)pageCode << USB_HOST_UFI_MODE_SENSE_PAGE_CONTROL_SHIFT) | + ((uint32_t)pageCode << USB_HOST_UFI_MODE_SENSE_PAGE_CODE_SHIFT)), + 0x00, 0x00, 0x00, 0x00, GET_BYTE_FROM_LE_LONG(bufferLength, 1), + GET_BYTE_FROM_LE_LONG(bufferLength, 0), 0x00}; + return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam, + USB_HOST_MSD_CBW_FLAGS_DIRECTION_IN, ufiBytes); +} + +usb_status_t USB_HostMsdInquiry(usb_host_class_handle classHandle, + uint8_t logicalUnit, + uint8_t *buffer, + uint32_t bufferLength, + transfer_callback_t callbackFn, + void *callbackParam) +{ + uint8_t ufiBytes[] = {UFI_INQUIRY, + (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION), + 0x00, + 0x00, + (uint8_t)bufferLength, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00}; + return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam, + USB_HOST_MSD_CBW_FLAGS_DIRECTION_IN, ufiBytes); +} + +usb_status_t USB_HostMsdReadFormatCapacities(usb_host_class_handle classHandle, + uint8_t logicalUnit, + uint8_t *buffer, + uint32_t bufferLength, + transfer_callback_t callbackFn, + void *callbackParam) +{ + uint8_t ufiBytes[] = {UFI_READ_FORMAT_CAPACITY, + (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION), + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + GET_BYTE_FROM_LE_LONG(bufferLength, 1), + GET_BYTE_FROM_LE_LONG(bufferLength, 0), + 0x00}; + return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam, + USB_HOST_MSD_CBW_FLAGS_DIRECTION_IN, ufiBytes); +} + +usb_status_t USB_HostMsdFormatUnit(usb_host_class_handle classHandle, + uint8_t logicalUnit, + uint8_t trackNumber, + uint16_t interLeave, + uint8_t *buffer, + uint32_t bufferLength, + transfer_callback_t callbackFn, + void *callbackParam) +{ + uint8_t ufiBytes[] = {UFI_FORMAT_UNIT, + (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION), + trackNumber, + GET_BYTE_FROM_LE_LONG(interLeave, 1), + GET_BYTE_FROM_LE_LONG(interLeave, 0), + 0x00, + 0x00, + GET_BYTE_FROM_LE_LONG(bufferLength, 1), + GET_BYTE_FROM_LE_LONG(bufferLength, 0), + 0x00}; + return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam, + USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT, ufiBytes); +} + +usb_status_t USB_HostMsdPreventAllowRemoval(usb_host_class_handle classHandle, + uint8_t logicalUnit, + uint8_t prevent, + transfer_callback_t callbackFn, + void *callbackParam) +{ + uint8_t ufiBytes[] = {UFI_MEDIUM_REMOVAL, + (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION), + 0x00, + 0x00, + prevent, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00}; + return USB_HostMsdCommand(classHandle, NULL, 0, callbackFn, callbackParam, USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT, + ufiBytes); +} + +usb_status_t USB_HostMsdWriteAndVerify(usb_host_class_handle classHandle, + uint8_t logicalUnit, + uint32_t blockAddress, + uint8_t *buffer, + uint32_t bufferLength, + uint32_t blockNumber, + transfer_callback_t callbackFn, + void *callbackParam) +{ + uint8_t ufiBytes[] = {UFI_WRITE_VERIFY, + (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION), + GET_BYTE_FROM_LE_LONG(blockAddress, 3), + GET_BYTE_FROM_LE_LONG(blockAddress, 2), + GET_BYTE_FROM_LE_LONG(blockAddress, 1), + GET_BYTE_FROM_LE_LONG(blockAddress, 0), + 0x00, + GET_BYTE_FROM_LE_LONG(blockNumber, 1), + GET_BYTE_FROM_LE_LONG(blockNumber, 0), + 0x00}; + return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam, + USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT, ufiBytes); +} + +usb_status_t USB_HostMsdStartStopUnit(usb_host_class_handle classHandle, + uint8_t logicalUnit, + uint8_t loadEject, + uint8_t start, + transfer_callback_t callbackFn, + void *callbackParam) +{ + uint8_t ufiBytes[] = {UFI_START_STOP, (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION), 0x00, 0x00, + (uint8_t)(((uint32_t)loadEject << USB_HOST_UFI_START_STOP_UNIT_LOEJ_SHIFT) | + ((uint32_t)start << USB_HOST_UFI_START_STOP_UNIT_START_SHIFT)), + 0x00, 0x00, 0x00, 0x00, 0x00}; + return USB_HostMsdCommand(classHandle, NULL, 0, callbackFn, callbackParam, USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT, + ufiBytes); +} + +usb_status_t USB_HostMsdVerify(usb_host_class_handle classHandle, + uint8_t logicalUnit, + uint32_t blockAddress, + uint16_t verificationLength, + transfer_callback_t callbackFn, + void *callbackParam) +{ + uint8_t ufiBytes[] = {UFI_VERIFY, + (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION), + GET_BYTE_FROM_LE_LONG(blockAddress, 3), + GET_BYTE_FROM_LE_LONG(blockAddress, 2), + GET_BYTE_FROM_LE_LONG(blockAddress, 1), + GET_BYTE_FROM_LE_LONG(blockAddress, 0), + 0x00, + GET_BYTE_FROM_LE_LONG(verificationLength, 1), + GET_BYTE_FROM_LE_LONG(verificationLength, 0), + 0x00}; + return USB_HostMsdCommand(classHandle, NULL, 0, callbackFn, callbackParam, USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT, + ufiBytes); +} + +usb_status_t USB_HostMsdRezeroUnit(usb_host_class_handle classHandle, + uint8_t logicalUnit, + transfer_callback_t callbackFn, + void *callbackParam) +{ + uint8_t ufiBytes[] = {UFI_REZERO_UINT, + (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION), + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00}; + return USB_HostMsdCommand(classHandle, NULL, 0, callbackFn, callbackParam, USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT, + ufiBytes); +} + +usb_status_t USB_HostMsdSeek10(usb_host_class_handle classHandle, + uint8_t logicalUnit, + uint32_t blockAddress, + transfer_callback_t callbackFn, + void *callbackParam) +{ + uint8_t ufiBytes[] = {UFI_SEEK, + (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION), + GET_BYTE_FROM_LE_LONG(blockAddress, 3), + GET_BYTE_FROM_LE_LONG(blockAddress, 2), + GET_BYTE_FROM_LE_LONG(blockAddress, 1), + GET_BYTE_FROM_LE_LONG(blockAddress, 0), + 0x00, + 0x00, + 0x00, + 0x00}; + return USB_HostMsdCommand(classHandle, NULL, 0, callbackFn, callbackParam, USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT, + ufiBytes); +} + +usb_status_t USB_HostMsdSendDiagnostic(usb_host_class_handle classHandle, + uint8_t logicalUnit, + uint8_t selfTest, + transfer_callback_t callbackFn, + void *callbackParam) +{ + uint8_t ufiBytes[] = {UFI_REZERO_UINT, + (uint8_t)(((uint32_t)logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION) | + ((uint32_t)selfTest << USB_HOST_UFI_SEND_DIAGNOSTIC_SELF_TEST_SHIFT)), + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + return USB_HostMsdCommand(classHandle, NULL, 0, callbackFn, callbackParam, USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT, + ufiBytes); +} + +#endif /* USB_HOST_CONFIG_MSD */ diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/usb_host.h b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/usb_host.h new file mode 100644 index 000000000..d5cb2d471 --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/usb_host.h @@ -0,0 +1,705 @@ +/* + * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _USB_HOST_H_ +#define _USB_HOST_H_ + +#include "usb.h" +#include "usb_misc.h" +#include "usb_spec.h" +#include "usb_host_framework.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; /*! 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 configure the lpm token. + * + * @param[in] hostHandle The host handle. + * @param[in] lpmParam HIRD value 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/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/usb_host_devices.c b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/usb_host_devices.c new file mode 100644 index 000000000..b994c7cec --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/usb_host_devices.c @@ -0,0 +1,1393 @@ +/* + * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "usb_host_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 */ +#define HOST_ECHO +/******************************************************************************* + * 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; + /* the callbackFn is initialized in USB_HostGetControllerInterface */ + hostInstance->controllerTable->controllerIoctl( + hostInstance->controllerHandle, kUSB_HostUpdateControlPacketSize, deviceInstance->controlPipe); + break; + + case kStatus_DEV_SetAddress: /* process set address result */ + deviceInstance->setAddress = deviceInstance->allocatedAddress; + /* the callbackFn is initialized in USB_HostGetControllerInterface */ + 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 & 0xFFFCu) + 4, USB_CACHE_LINESIZE); +#else + deviceInstance->configurationDesc = + (uint8_t *)USB_OsaMemoryAllocate((deviceInstance->configurationLen & 0xFFFCu) + 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 configuration 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)) + { + /* call host callback function, function is initialized in USB_HostInit */ + status1 = hostInstance->deviceCallback(deviceInstance, &deviceInstance->configuration, eventCode); + } + 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) + { + /* call host callback function, function is initialized in USB_HostInit */ + status1 = hostInstance->deviceCallback(deviceInstance, &deviceInstance->configuration, eventCode); + } +#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 position 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) + { +#if (((defined USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST)) || defined(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 notified 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; + } + /* the callbackFn is initialized in USB_HostGetControllerInterface */ + 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) /* enumeration 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/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/usb_host_devices.h b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/usb_host_devices.h new file mode 100644 index 000000000..9d06ba26e --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/usb_host_devices.h @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#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/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/usb_host_ehci.c b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/usb_host_ehci.c new file mode 100644 index 000000000..efbe042c5 --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/usb_host_ehci.c @@ -0,0 +1,4796 @@ +/* + * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "usb_host_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]; + +static uint8_t usbHostEhciFramListStatus[1] = {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]; +static uint8_t usbHostEhciFramListStatus[2] = {0, 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}; +static uint8_t s_SlotMaxBandwidthHs[8] = {100, 100, 100, 100, 100, 100, 100, 100}; + +/******************************************************************************* + * 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; + } + +#if 0 + for (index = 0; index < 7; ++index) /* */ + { + if (frameBandwidths[index] > s_SlotMaxBandwidthHs[index]) + { + frameBandwidths[index + 1] += (frameBandwidths[index] - s_SlotMaxBandwidthHs[index]); + frameBandwidths[index] = s_SlotMaxBandwidthHs[index]; + } + } +#endif +} + +/*! + * @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_SlotMaxBandwidthHs[(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_SlotMaxBandwidthHs[index]) + { + allocateOk = 0; + break; + } + } + } + else /* ISO IN */ + { + index = uframeIntervalIndex; + if (frameTimes[index] + timeStartSplit > s_SlotMaxBandwidthHs[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_SlotMaxBandwidthHs[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_SlotMaxBandwidthHs[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_SlotMaxBandwidthHs[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); + /* callback function is different from the current condition */ + 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); + /* callback function is different from the current condition */ + 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); + /* callback function is different from the current condition */ + 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 * 3))) && (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) & + (~((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) & + (~((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 *itdHead = 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; + } + itdHead = ehciInstance->ehciItdList; + 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 */ + + itdPointer = itdHead; + /* link itd to frame list (note: initialize frameEntryIndex)*/ + while (itdPointer) + { + itdPointer->frameEntryIndex = linkUframe >> 3; + /* add to frame head */ + itdPointer->nextLinkPointer = ((uint32_t *)ehciInstance->ehciFrameList)[linkUframe >> 3]; + ((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; + /* callback function is different from the current condition */ + 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 + 7) / 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 + 7) / 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 = (100 * 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) + { + /* callback function is different from the current condition */ + transfer->callbackFn(transfer->callbackParam, transfer, + kStatus_USB_TransferFailed); /* transfer fail */ + } + else + { + /* callback function is different from the current condition */ + transfer->callbackFn(transfer->callbackParam, transfer, kStatus_USB_TransferStall); + } + } + 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); + } + } + + /* callback function is different from the current condition */ + 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) + { + /* callback function is different from the current condition */ + transfer->callbackFn(transfer->callbackParam, transfer, + kStatus_USB_TransferFailed); /* transfer fail */ + } + else + { + /* callback function is different from the current condition */ + 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; + /* callback function is different from the current condition */ + 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; + /* callback function is different from the current condition */ + 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; + /* callback function is different from the current condition */ + 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 + +void *USB_EhciGetValidFrameList(usb_host_ehci_instance_t *ehciInstance, uint8_t *instanceIndex) +{ + if (ehciInstance->controllerId < kUSB_ControllerEhci0) + { + return NULL; + } + +#if (USB_HOST_CONFIG_EHCI == 1U) + if (!usbHostEhciFramListStatus[0]) + { + usbHostEhciFramListStatus[0] = 1; + *instanceIndex = 0; + return &s_UsbHostEhciFrameList1[0]; + } +#elif (USB_HOST_CONFIG_EHCI == 2U) + if (!usbHostEhciFramListStatus[0]) + { + usbHostEhciFramListStatus[0] = 1; + *instanceIndex = 0; + return &s_UsbHostEhciFrameList1[0]; + } + else if (!usbHostEhciFramListStatus[1]) + { + usbHostEhciFramListStatus[1] = 1; + *instanceIndex = 1; + return &s_UsbHostEhciFrameList2[0]; + } + else + { + } +#endif + + return NULL; +} + +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; + uint32_t *framePointer; + uint8_t instanceIndex; + + 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 = USB_EhciGetValidFrameList(ehciInstance, &instanceIndex); + if (ehciInstance->ehciFrameList == NULL) + { + return kStatus_USB_Error; + } + + /* initialize ehci units */ + ehciInstance->ehciUnitBase = (uint32_t *)(usbHostEhciData[instanceIndex]); + /* 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 */ +#if (USB_HOST_CONFIG_EHCI == 1U) + if (ehciInstance->ehciFrameList == &s_UsbHostEhciFrameList1[0]) + { + usbHostEhciFramListStatus[0] = 0; + } +#elif (USB_HOST_CONFIG_EHCI == 2U) + if (ehciInstance->ehciFrameList == &s_UsbHostEhciFrameList1[0]) + { + usbHostEhciFramListStatus[0] = 0; + } + else if (ehciInstance->ehciFrameList == &s_UsbHostEhciFrameList2[0]) + { + usbHostEhciFramListStatus[1] = 0; + } + else + { + } +#endif + 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; + USB_HostEhciDelay(ehciInstance->ehciIpBase, 2U); + 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/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/usb_host_ehci.h b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/usb_host_ehci.h new file mode 100644 index 000000000..b16c668d1 --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/usb_host_ehci.h @@ -0,0 +1,477 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#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 (50U) + +#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/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/usb_host_framework.c b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/usb_host_framework.c new file mode 100644 index 000000000..7a351d3e3 --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/usb_host_framework.c @@ -0,0 +1,361 @@ +/* + * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "usb_host_config.h" +#include "usb_host.h" +#include "usb_host_hci.h" +#include "usb_host_devices.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/*! + * @brief standard control transfer common code. + * + * @param deviceInstance device instance handle. + * @param transfer transfer. + * @param buffer data buffer pointer. + * @param bufferLen data length. + * + * @return kStatus_USB_Success or error codes. + */ +usb_status_t USB_HostCh9RequestCommon(usb_host_device_instance_t *deviceInstance, + usb_host_transfer_t *transfer, + uint8_t *buffer, + uint32_t bufferLen); + +/*! + * @brief standard get status implementation. + * + * @param deviceInstance device instance handle. + * @param transfer transfer. + * @param param parameter. + * + * @return kStatus_USB_Success or error codes. + */ +usb_status_t USB_HostStandardGetStatus(usb_host_device_instance_t *deviceInstance, + usb_host_transfer_t *transfer, + void *param); + +/*! + * @brief standard set/clear feature implementation. + * + * @param deviceInstance device instance handle. + * @param transfer transfer. + * @param param parameter. + * + * @return kStatus_USB_Success or error codes. + */ +usb_status_t USB_HostStandardSetClearFeature(usb_host_device_instance_t *deviceInstance, + usb_host_transfer_t *transfer, + void *param); + +/*! + * @brief standard set address implementation. + * + * @param deviceInstance device instance handle. + * @param transfer transfer. + * @param param parameter. + * + * @return kStatus_USB_Success or error codes. + */ +usb_status_t USB_HostStandardSetAddress(usb_host_device_instance_t *deviceInstance, + usb_host_transfer_t *transfer, + void *param); + +/*! + * @brief standard set/get descriptor implementation. + * + * @param deviceInstance device instance handle. + * @param transfer transfer. + * @param param parameter. + * + * @return kStatus_USB_Success or error codes. + */ +usb_status_t USB_HostStandardSetGetDescriptor(usb_host_device_instance_t *deviceInstance, + usb_host_transfer_t *transfer, + void *param); + +/*! + * @brief standard get interface implementation. + * + * @param deviceInstance device instance handle. + * @param transfer transfer. + * @param param parameter. + * + * @return kStatus_USB_Success or error codes. + */ +usb_status_t USB_HostStandardGetInterface(usb_host_device_instance_t *deviceInstance, + usb_host_transfer_t *transfer, + void *param); + +/*! + * @brief standard set interface implementation. + * + * @param deviceInstance device instance handle. + * @param transfer transfer. + * @param param parameter. + * + * @return kStatus_USB_Success or error codes. + */ +usb_status_t USB_HostStandardSetInterface(usb_host_device_instance_t *deviceInstance, + usb_host_transfer_t *transfer, + void *param); + +/*! + * @brief standard sync frame implementation. + * + * @param deviceInstance device instance handle. + * @param transfer transfer. + * @param param parameter. + * + * @return kStatus_USB_Success or error codes. + */ +usb_status_t USB_HostStandardSyncFrame(usb_host_device_instance_t *deviceInstance, + usb_host_transfer_t *transfer, + void *param); + +/******************************************************************************* + * Prototypes + ******************************************************************************/ + +/******************************************************************************* + * Variables + ******************************************************************************/ + +/******************************************************************************* + * Code + ******************************************************************************/ + +usb_status_t USB_HostCh9RequestCommon(usb_host_device_instance_t *deviceInstance, + usb_host_transfer_t *transfer, + uint8_t *buffer, + uint32_t bufferLen) +{ + /* initialize transfer */ + transfer->setupPacket->wLength = USB_SHORT_TO_LITTLE_ENDIAN(bufferLen); + transfer->transferBuffer = buffer; + transfer->transferLength = bufferLen; + + if (USB_HostSendSetup(deviceInstance->hostHandle, deviceInstance->controlPipe, transfer) != + kStatus_USB_Success) /* send setup transfer */ + { +#ifdef HOST_ECHO + usb_echo("failed for USB_HostSendSetup\r\n"); +#endif + USB_HostFreeTransfer(deviceInstance->hostHandle, transfer); + return kStatus_USB_Error; + } + return kStatus_USB_Success; +} + +usb_status_t USB_HostStandardGetStatus(usb_host_device_instance_t *deviceInstance, + usb_host_transfer_t *transfer, + void *param) +{ + usb_host_get_status_param_t *statusParam; + uint8_t length; + + /* initialize transfer */ + statusParam = (usb_host_get_status_param_t *)param; + transfer->setupPacket->bmRequestType = USB_REQUEST_TYPE_DIR_IN | USB_REQUEST_TYPE_TYPE_STANDARD; + if (statusParam->requestType == kRequestDevice) + { + transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_RECIPIENT_DEVICE; + } + else if (statusParam->requestType == kRequestInterface) + { + transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_RECIPIENT_INTERFACE; + } + else + { + transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_RECIPIENT_ENDPOINT; + } + transfer->setupPacket->wIndex = USB_SHORT_TO_LITTLE_ENDIAN(statusParam->statusSelector); + + length = 2; + if (statusParam->statusSelector == USB_REQUEST_STANDARD_GET_STATUS_OTG_STATUS_SELECTOR) + { + length = 1; + } + return USB_HostCh9RequestCommon(deviceInstance, transfer, statusParam->statusBuffer, length); +} + +usb_status_t USB_HostStandardSetClearFeature(usb_host_device_instance_t *deviceInstance, + usb_host_transfer_t *transfer, + void *param) +{ + usb_host_process_feature_param_t *featureParam; + + /* initialize transfer */ + featureParam = (usb_host_process_feature_param_t *)param; + if (featureParam->requestType == kRequestDevice) + { + transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_RECIPIENT_DEVICE; + } + else if (featureParam->requestType == kRequestInterface) + { + transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_RECIPIENT_INTERFACE; + } + else + { + transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_RECIPIENT_ENDPOINT; + } + transfer->setupPacket->wValue = USB_SHORT_TO_LITTLE_ENDIAN(featureParam->featureSelector); + transfer->setupPacket->wIndex = USB_SHORT_TO_LITTLE_ENDIAN(featureParam->interfaceOrEndpoint); + + return USB_HostCh9RequestCommon(deviceInstance, transfer, NULL, 0); +} + +usb_status_t USB_HostStandardSetAddress(usb_host_device_instance_t *deviceInstance, + usb_host_transfer_t *transfer, + void *param) +{ + uint8_t address; + + /* initialize transfer */ + address = *(uint8_t *)param; + transfer->setupPacket->wValue = USB_SHORT_TO_LITTLE_ENDIAN(address); + + return USB_HostCh9RequestCommon(deviceInstance, transfer, NULL, 0); +} + +usb_status_t USB_HostStandardSetGetDescriptor(usb_host_device_instance_t *deviceInstance, + usb_host_transfer_t *transfer, + void *param) +{ + usb_host_process_descriptor_param_t *descriptorParam; + + /* initialize transfer */ + descriptorParam = (usb_host_process_descriptor_param_t *)param; + transfer->setupPacket->wValue = USB_SHORT_TO_LITTLE_ENDIAN( + (uint16_t)((uint16_t)descriptorParam->descriptorType << 8) | descriptorParam->descriptorIndex); + transfer->setupPacket->wIndex = USB_SHORT_TO_LITTLE_ENDIAN(descriptorParam->languageId); + return USB_HostCh9RequestCommon(deviceInstance, transfer, descriptorParam->descriptorBuffer, + descriptorParam->descriptorLength); +} + +usb_status_t USB_HostStandardGetInterface(usb_host_device_instance_t *deviceInstance, + usb_host_transfer_t *transfer, + void *param) +{ + usb_host_get_interface_param_t *interfaceParam; + + /* initialize transfer */ + interfaceParam = (usb_host_get_interface_param_t *)param; + transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_DIR_IN; + transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_RECIPIENT_INTERFACE; + transfer->setupPacket->wIndex = USB_SHORT_TO_LITTLE_ENDIAN(interfaceParam->interface); + + return USB_HostCh9RequestCommon(deviceInstance, transfer, interfaceParam->alternateInterfaceBuffer, 1); +} + +usb_status_t USB_HostStandardSetInterface(usb_host_device_instance_t *deviceInstance, + usb_host_transfer_t *transfer, + void *param) +{ + usb_host_set_interface_param_t *setParam; + + /* initialize transfer */ + setParam = (usb_host_set_interface_param_t *)param; + transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_RECIPIENT_INTERFACE; + transfer->setupPacket->wIndex = USB_SHORT_TO_LITTLE_ENDIAN(setParam->interface); + transfer->setupPacket->wValue = USB_SHORT_TO_LITTLE_ENDIAN(setParam->alternateSetting); + + return USB_HostCh9RequestCommon(deviceInstance, transfer, NULL, 0); +} + +usb_status_t USB_HostStandardSyncFrame(usb_host_device_instance_t *deviceInstance, + usb_host_transfer_t *transfer, + void *param) +{ + usb_host_synch_frame_param_t *frameParam; + + /* initialize transfer */ + frameParam = (usb_host_synch_frame_param_t *)param; + transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_DIR_IN; + transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_RECIPIENT_ENDPOINT; + transfer->setupPacket->wIndex = USB_SHORT_TO_LITTLE_ENDIAN(frameParam->endpoint); + + return USB_HostCh9RequestCommon(deviceInstance, transfer, frameParam->frameNumberBuffer, 2); +} + +usb_status_t USB_HostRequestControl(usb_device_handle deviceHandle, + uint8_t usbRequest, + usb_host_transfer_t *transfer, + void *param) +{ + usb_host_device_instance_t *deviceInstance = (usb_host_device_instance_t *)deviceHandle; + usb_status_t status = kStatus_USB_Error; + + if (deviceHandle == NULL) + { + return kStatus_USB_InvalidHandle; + } + + /* reset transfer fields */ + transfer->setupPacket->bmRequestType = 0x00; + transfer->setupPacket->bRequest = usbRequest; + transfer->setupPacket->wIndex = 0; + transfer->setupPacket->wLength = 0; + transfer->setupPacket->wValue = 0; + + switch (usbRequest) + { + case USB_REQUEST_STANDARD_GET_STATUS: /* standard get status request */ + status = USB_HostStandardGetStatus(deviceInstance, transfer, param); + break; + + case USB_REQUEST_STANDARD_CLEAR_FEATURE: /* standard clear status request */ + case USB_REQUEST_STANDARD_SET_FEATURE: /* standard set feature request */ + status = USB_HostStandardSetClearFeature(deviceInstance, transfer, param); + break; + + case USB_REQUEST_STANDARD_SET_ADDRESS: /* standard set address request */ + status = USB_HostStandardSetAddress(deviceInstance, transfer, param); + break; + + case USB_REQUEST_STANDARD_GET_DESCRIPTOR: /* standard get descriptor request */ + case USB_REQUEST_STANDARD_SET_DESCRIPTOR: /* standard set descriptor request */ + if (usbRequest == USB_REQUEST_STANDARD_GET_DESCRIPTOR) + { + transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_DIR_IN; + } + status = USB_HostStandardSetGetDescriptor(deviceInstance, transfer, param); + break; + + case USB_REQUEST_STANDARD_GET_CONFIGURATION: /* standard get configuration descriptor request */ + transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_DIR_IN; + status = + USB_HostCh9RequestCommon((usb_host_device_instance_t *)deviceHandle, transfer, (uint8_t *)param, 1); + break; + + case USB_REQUEST_STANDARD_SET_CONFIGURATION: /* standard set configuration request */ + transfer->setupPacket->wValue = USB_SHORT_TO_LITTLE_ENDIAN(*((uint8_t *)param)); + status = USB_HostCh9RequestCommon((usb_host_device_instance_t *)deviceHandle, transfer, NULL, 0); + break; + + case USB_REQUEST_STANDARD_GET_INTERFACE: /* standard get interface request */ + status = USB_HostStandardGetInterface(deviceInstance, transfer, param); + break; + + case USB_REQUEST_STANDARD_SET_INTERFACE: /* standard set interface request */ + status = USB_HostStandardSetInterface(deviceInstance, transfer, param); + break; + + case USB_REQUEST_STANDARD_SYNCH_FRAME: /* standard synch frame request */ + status = USB_HostStandardSyncFrame(deviceInstance, transfer, param); + break; + + default: + break; + } + + return status; +} diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/usb_host_framework.h b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/usb_host_framework.h new file mode 100644 index 000000000..fd84fc714 --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/usb_host_framework.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _USB_HOST_CH9_H_ +#define _USB_HOST_CH9_H_ + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/*! + * @addtogroup usb_host_drv + * @{ + */ + +/*! @brief Request type */ +typedef enum _usb_host_request_type +{ + kRequestDevice = 1U, /*!< Control request object is device */ + kRequestInterface, /*!< Control request object is interface */ + kRequestEndpoint, /*!< Control request object is endpoint */ +} usb_host_request_type_t; + +/*! @brief For USB_REQUEST_STANDARD_CLEAR_FEATURE and USB_REQUEST_STANDARD_SET_FEATURE */ +typedef struct _usb_host_process_feature_param +{ + uint8_t requestType; /*!< See the #usb_host_request_type_t */ + uint8_t featureSelector; /*!< Set/cleared feature */ + uint8_t interfaceOrEndpoint; /*!< Interface or end pointer */ +} usb_host_process_feature_param_t; + +/*! @brief For USB_REQUEST_STANDARD_GET_DESCRIPTOR and USB_REQUEST_STANDARD_SET_DESCRIPTOR */ +typedef struct _usb_host_process_descriptor_param +{ + uint8_t descriptorType; /*!< See the usb_spec.h, such as the USB_DESCRIPTOR_TYPE_DEVICE */ + uint8_t descriptorIndex; /*!< The descriptor index is used to select a specific descriptor (only for configuration + and string descriptors) when several descriptors of the same type are implemented in a + device */ + uint8_t languageId; /*!< It specifies the language ID for string descriptors or is reset to zero for other + descriptors */ + uint8_t *descriptorBuffer; /*!< Buffer pointer */ + uint16_t descriptorLength; /*!< Buffer data length */ +} usb_host_process_descriptor_param_t; + +/*! @brief For USB_REQUEST_STANDARD_GET_INTERFACE */ +typedef struct _usb_host_get_interface_param +{ + uint8_t interface; /*!< Interface number */ + uint8_t *alternateInterfaceBuffer; /*!< Save the transfer result */ +} usb_host_get_interface_param_t; + +/*! @brief For USB_REQUEST_STANDARD_GET_STATUS */ +typedef struct _usb_host_get_status_param +{ + uint16_t statusSelector; /*!< Interface number, the end pointer number or OTG status selector */ + uint8_t requestType; /*!< See the #usb_host_request_type_t */ + uint8_t *statusBuffer; /*!< Save the transfer result */ +} usb_host_get_status_param_t; + +/*! @brief For USB_REQUEST_STANDARD_SET_INTERFACE */ +typedef struct _usb_host_set_interface_param +{ + uint8_t alternateSetting; /*!< Alternate setting value */ + uint8_t interface; /*!< Interface number */ +} usb_host_set_interface_param_t; + +/*! @brief For USB_REQUEST_STANDARD_SYNCH_FRAME */ +typedef struct _usb_host_synch_frame_param +{ + uint8_t endpoint; /*!< Endpoint number */ + uint8_t *frameNumberBuffer; /*!< Frame number data buffer */ +} usb_host_synch_frame_param_t; + +/*! @}*/ + +/******************************************************************************* + * API + ******************************************************************************/ + +#endif /* _USB_HOST_CH9_H_ */ diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/usb_host_hci.c b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/usb_host_hci.c new file mode 100644 index 000000000..cce9f3729 --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/usb_host_hci.c @@ -0,0 +1,1047 @@ +/* + * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "usb_host_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 + ******************************************************************************/ + +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "middleware.usb.host_stack" +#endif + +/******************************************************************************* + * 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, the callbackFn is initialized in USB_HostGetControllerInterface */ + 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 destroy, the callbackFn is initialized in USB_HostGetControllerInterface */ + status = hostInstance->controllerTable->controllerDestory(hostInstance->controllerHandle); + hostInstance->controllerHandle = NULL; + if (status != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("host controller destroy 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, the callbackFn is initialized in USB_HostGetControllerInterface */ + 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, the callbackFn is initialized in USB_HostGetControllerInterface */ + 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 + /* the callbackFn is initialized in USB_HostGetControllerInterface */ + 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 + /* the callbackFn is initialized in USB_HostGetControllerInterface */ + 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 + /* the callbackFn is initialized in USB_HostGetControllerInterface */ + 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 */ + /* the callbackFn is initialized in USB_HostGetControllerInterface */ + 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 descriptor */ + 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 suspend 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 + /* the callbackFn is initialized in USB_HostGetControllerInterface */ + 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) + { + /* the callbackFn is initialized in USB_HostGetControllerInterface */ + 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) + { + /* the callbackFn is initialized in USB_HostGetControllerInterface */ + 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) + { + /* the callbackFn is initialized in USB_HostGetControllerInterface */ + 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 suspend 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, incomplete hub L1 suspend device*/ + /*#else*/ + /* the callbackFn is initialized in USB_HostGetControllerInterface */ + 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) + { + /* the callbackFn is initialized in USB_HostGetControllerInterface */ + status = hostInstance->controllerTable->controllerIoctl(hostInstance->controllerHandle, kUSB_HostBusControl, + &type); + } + } + if (kStatus_USB_Error == status) + { + hostInstance->suspendedDevice = NULL; + } + return status; +} +/* Send BUS or specific device suspend 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; + /* the callbackFn is initialized in USB_HostGetControllerInterface */ + 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) + { + /* the callbackFn is initialized in USB_HostGetControllerInterface */ + 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) + { + /* the callbackFn is initialized in USB_HostGetControllerInterface */ + 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/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/usb_host_hci.h b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/usb_host_hci.h new file mode 100644 index 000000000..3cdd83df3 --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host/usb_host_hci.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#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/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host_msd_command.c b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host_msd_command.c new file mode 100644 index 000000000..176d08bfd --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/host_msd_command.c @@ -0,0 +1,699 @@ +/* + * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc. + * Copyright 2016, 2018 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/** +* @file host_msd_command.c +* @brief modify usb msd command test function +* @version 2.0 +* @author AIIT XUOS Lab +* @date 2022-02-10 +*/ + +/************************************************* +File name: usb_misc.h +Description: modify usb_echo to KPrintf +Others: take SDK_2.6.1_MIMXRT1052xxxxB/boards/evkbimxrt1050/usb_examples/usb_host_msd_command for references +History: +1. Date: 2022-02-10 +Author: AIIT XUOS Lab +Modification: +1. modify USB_HostMsdCommandTest, delete read10 and write10 test +2. add USB_HostMsdReadApi and USB_HostMsdWriteApi +3. add UsbMountFileSystem() and UsbUnmountFileSystem() +*************************************************/ + +#include "usb_host_config.h" +#include "usb_host.h" +#include "usb_host_msd.h" +#include "host_msd_command.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +#if MSD_THROUGHPUT_TEST_ENABLE +#include "fsl_device_registers.h" +#define THROUGHPUT_BUFFER_SIZE (64 * 1024) /* throughput test buffer */ +#define MCU_CORE_CLOCK (120000000) /* mcu core clock, user need to configure it. */ +#endif /* MSD_THROUGHPUT_TEST_ENABLE */ + +/******************************************************************************* + * Prototypes + ******************************************************************************/ +extern void UsbMountFileSystem(); +extern void UsbUnmountFileSystem(); + +/*! + * @brief host msd ufi command callback. + * + * This function is used as callback function for ufi command. + * + * @param param the host msd command instance pointer. + * @param data data buffer pointer. + * @param dataLength data length. + * @status transfer result status. + */ +static void USB_HostMsdUfiCallback(void *param, uint8_t *data, uint32_t dataLength, usb_status_t status); + +/*! + * @brief host msd control transfer callback. + * + * This function is used as callback function for control transfer . + * + * @param param the host msd command instance pointer. + * @param data data buffer pointer. + * @param dataLength data length. + * @status transfer result status. + */ +static void USB_HostMsdControlCallback(void *param, uint8_t *data, uint32_t dataLength, usb_status_t status); + +/*! + * @brief host msd command test done. + * + * @param msdCommandInstance the host command instance pointer. + */ +static void msd_command_test_done(usb_host_msd_command_instance_t *msdCommandInstance); + +/*! + * @brief host msd command test. + * + * This function implements msd command test. + * + * @param msdCommandInstance the host command instance pointer. + */ +static void USB_HostMsdCommandTest(usb_host_msd_command_instance_t *msdCommandInstance); + +/******************************************************************************* + * Variables + ******************************************************************************/ +extern usb_host_handle g_HostHandle; /* global host handle */ +usb_host_msd_command_instance_t g_MsdCommandInstance = {0}; /* global msd command instance */ +/* command on-going state. It should set to 1 when start command, it is set to 0 in the callback */ +volatile uint8_t ufiIng; +/* command callback status */ +volatile usb_status_t ufiStatus; + +USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE) static uint8_t s_TestUfiBuffer[512]; /*!< test buffer */ + +#if MSD_THROUGHPUT_TEST_ENABLE +USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE) static uint32_t testThroughputBuffer[THROUGHPUT_BUFFER_SIZE / 4]; /* the buffer for throughput test */ +uint32_t testSizeArray[] = {50 * 1024, 50 * 1024}; /* test time and test size (uint: K) */ +#endif /* MSD_THROUGHPUT_TEST_ENABLE */ + +/******************************************************************************* + * Code + ******************************************************************************/ + +static void USB_HostMsdUfiCallback(void *param, uint8_t *data, uint32_t dataLength, usb_status_t status) +{ + ufiIng = 0; + ufiStatus = status; +} + +static void USB_HostMsdControlCallback(void *param, uint8_t *data, uint32_t dataLength, usb_status_t status) +{ + usb_host_msd_command_instance_t *msdCommandInstance = (usb_host_msd_command_instance_t *)param; + + if (msdCommandInstance->runWaitState == kUSB_HostMsdRunWaitSetInterface) /* set interface finish */ + { + msdCommandInstance->runWaitState = kUSB_HostMsdRunIdle; + msdCommandInstance->runState = kUSB_HostMsdRunMassStorageTest; + } +} + +static void msd_command_test_done(usb_host_msd_command_instance_t *msdCommandInstance) +{ + usb_echo("........................check USB device done....................\r\n"); +} + +static inline void USB_HostControllerTaskFunction(usb_host_handle hostHandle) +{ +#if ((defined USB_HOST_CONFIG_KHCI) && (USB_HOST_CONFIG_KHCI)) + USB_HostKhciTaskFunction(hostHandle); +#endif /* USB_HOST_CONFIG_KHCI */ +#if ((defined USB_HOST_CONFIG_EHCI) && (USB_HOST_CONFIG_EHCI)) + USB_HostEhciTaskFunction(hostHandle); +#endif /* USB_HOST_CONFIG_EHCI */ +#if ((defined USB_HOST_CONFIG_OHCI) && (USB_HOST_CONFIG_OHCI > 0U)) + USB_HostOhciTaskFunction(g_HostHandle); +#endif /* USB_HOST_CONFIG_OHCI */ +#if ((defined USB_HOST_CONFIG_IP3516HS) && (USB_HOST_CONFIG_IP3516HS > 0U)) + USB_HostIp3516HsTaskFunction(g_HostHandle); +#endif /* USB_HOST_CONFIG_IP3516HS */ +} + +static void USB_HostMsdCommandTest(usb_host_msd_command_instance_t *msdCommandInstance) +{ + usb_status_t status; + uint32_t blockSize = 512; + uint32_t address; + + usb_echo("........................check USB device start....................\r\n"); + + usb_echo("get max logical units...."); + ufiIng = 1; + status = USB_HostMsdGetMaxLun(msdCommandInstance->classHandle, msdCommandInstance->testUfiBuffer, + USB_HostMsdUfiCallback, msdCommandInstance); + if (status != kStatus_USB_Success) + { + usb_echo("error\r\n"); + msd_command_test_done(msdCommandInstance); + return; + } + while (ufiIng) /* wait the command */ + { + USB_HostControllerTaskFunction(g_HostHandle); + } + if (ufiStatus == kStatus_USB_Success) /* print the command result */ + { + usb_echo("success, logical units: %d\r\n", msdCommandInstance->testUfiBuffer[0]); + } + else + { + usb_echo("fail\r\n"); + msd_command_test_done(msdCommandInstance); + return; + } + + if (msdCommandInstance->deviceState != kStatus_DEV_Attached) + { + msd_command_test_done(msdCommandInstance); + return; + } + usb_echo("test unit ready...."); + ufiIng = 1; + status = USB_HostMsdTestUnitReady(msdCommandInstance->classHandle, 0, USB_HostMsdUfiCallback, msdCommandInstance); + if (status != kStatus_USB_Success) + { + usb_echo("error\r\n"); + msd_command_test_done(msdCommandInstance); + return; + } + while (ufiIng) /* wait the command */ + { + USB_HostControllerTaskFunction(g_HostHandle); + } + if ((ufiStatus == kStatus_USB_Success) || (ufiStatus == kStatus_USB_MSDStatusFail)) /* print the command result */ + { + usb_echo("success, unit status: %s\r\n", ufiStatus == kStatus_USB_MSDStatusFail ? "not ready" : "ready"); + } + else + { + usb_echo("fail\r\n"); + msd_command_test_done(msdCommandInstance); + return; + } + + if (msdCommandInstance->deviceState != kStatus_DEV_Attached) + { + msd_command_test_done(msdCommandInstance); + return; + } + usb_echo("request sense...."); + ufiIng = 1; + status = USB_HostMsdRequestSense(msdCommandInstance->classHandle, 0, msdCommandInstance->testUfiBuffer, + sizeof(usb_host_ufi_sense_data_t), USB_HostMsdUfiCallback, msdCommandInstance); + if (status != kStatus_USB_Success) + { + usb_echo("error\r\n"); + msd_command_test_done(msdCommandInstance); + return; + } + while (ufiIng) /* wait the command */ + { + USB_HostControllerTaskFunction(g_HostHandle); + } + if (ufiStatus == kStatus_USB_Success) /* print the command result */ + { + usb_echo("success\r\n"); + } + else + { + usb_echo("fail\r\n"); + msd_command_test_done(msdCommandInstance); + return; + } + + if (msdCommandInstance->deviceState != kStatus_DEV_Attached) + { + msd_command_test_done(msdCommandInstance); + return; + } + usb_echo("inquiry..."); + ufiIng = 1; + status = USB_HostMsdInquiry(msdCommandInstance->classHandle, 0, msdCommandInstance->testUfiBuffer, + sizeof(usb_host_ufi_inquiry_data_t), USB_HostMsdUfiCallback, msdCommandInstance); + if (status != kStatus_USB_Success) + { + usb_echo("error\r\n"); + msd_command_test_done(msdCommandInstance); + return; + } + while (ufiIng) /* wait the command */ + { + USB_HostControllerTaskFunction(g_HostHandle); + } + if (ufiStatus == kStatus_USB_Success) /* print the command result */ + { + usb_echo("success\r\n"); + } + else + { + usb_echo("fail\r\n"); + msd_command_test_done(msdCommandInstance); + return; + } + + if (msdCommandInstance->deviceState != kStatus_DEV_Attached) + { + msd_command_test_done(msdCommandInstance); + return; + } + usb_echo("read capacity..."); + ufiIng = 1; + status = USB_HostMsdReadCapacity(msdCommandInstance->classHandle, 0, msdCommandInstance->testUfiBuffer, + sizeof(usb_host_ufi_read_capacity_t), USB_HostMsdUfiCallback, msdCommandInstance); + if (status != kStatus_USB_Success) + { + usb_echo("error\r\n"); + msd_command_test_done(msdCommandInstance); + return; + } + while (ufiIng) /* wait the command */ + { + USB_HostControllerTaskFunction(g_HostHandle); + } + if (ufiStatus == kStatus_USB_Success) /* print the command result */ + { + address = (uint32_t) & (msdCommandInstance->testUfiBuffer[0]); + address = (uint32_t)((usb_host_ufi_read_capacity_t *)(address))->blockLengthInBytes; + blockSize = USB_LONG_FROM_BIG_ENDIAN_ADDRESS(((uint8_t *)address)); + address = (uint32_t) & (msdCommandInstance->testUfiBuffer[0]); + address = (uint32_t)((usb_host_ufi_read_capacity_t *)(address))->lastLogicalBlockAddress; + usb_echo("success, last logical block:%d block length:%d\r\n", + USB_LONG_FROM_BIG_ENDIAN_ADDRESS(((uint8_t *)address)), blockSize); + } + else + { + usb_echo("fail\r\n"); + msd_command_test_done(msdCommandInstance); + return; + } + + if (msdCommandInstance->deviceState != kStatus_DEV_Attached) + { + msd_command_test_done(msdCommandInstance); + return; + } +#if 1 + if (blockSize == 0) + { + blockSize = 512; + } + usb_echo("read(10)..."); + ufiIng = 1; + status = USB_HostMsdRead10(msdCommandInstance->classHandle, 0, 0, msdCommandInstance->testUfiBuffer, blockSize, 1, + USB_HostMsdUfiCallback, msdCommandInstance); + if (status != kStatus_USB_Success) + { + usb_echo("error\r\n"); + msd_command_test_done(msdCommandInstance); + return; + } + while (ufiIng) /* wait the command */ + { + USB_HostControllerTaskFunction(g_HostHandle); + } + if (ufiStatus == kStatus_USB_Success) /* print the command result */ + { + usb_echo("success\r\n"); + } + else + { + usb_echo("fail\r\n"); + msd_command_test_done(msdCommandInstance); + return; + } + + if (msdCommandInstance->deviceState != kStatus_DEV_Attached) + { + msd_command_test_done(msdCommandInstance); + return; + } + usb_echo("write(10)..."); + ufiIng = 1; + status = USB_HostMsdWrite10(msdCommandInstance->classHandle, 0, 0, msdCommandInstance->testUfiBuffer, blockSize, 1, + USB_HostMsdUfiCallback, msdCommandInstance); + if (status != kStatus_USB_Success) + { + usb_echo("error\r\n"); + msd_command_test_done(msdCommandInstance); + return; + } + while (ufiIng) /* wait the command */ + { + USB_HostControllerTaskFunction(g_HostHandle); + } + if (ufiStatus == kStatus_USB_Success) /* print the command result */ + { + usb_echo("success\r\n"); + } + else + { + usb_echo("fail\r\n"); + msd_command_test_done(msdCommandInstance); + return; + } +#endif + +#if MSD_THROUGHPUT_TEST_ENABLE + uint64_t totalTime; + uint32_t testSize; + uint32_t blockAddress; + uint8_t testIndex; + + /* time delay (~100ms) */ + for (testSize = 0; testSize < 400000; ++testSize) + { + __ASM("nop"); + } + + CoreDebug->DEMCR |= (1 << CoreDebug_DEMCR_TRCENA_Pos); + + for (testSize = 0; testSize < (THROUGHPUT_BUFFER_SIZE / 4); ++testSize) + { + testThroughputBuffer[testSize] = testSize; + } + + usb_echo("throughput test:\r\n"); + for (testIndex = 0; testIndex < (sizeof(testSizeArray) / 4); ++testIndex) + { + totalTime = 0; + blockAddress = 0; + testSize = testSizeArray[testIndex] * 1024; + while (testSize) + { + if (msdCommandInstance->deviceState != kStatus_DEV_Attached) + { + msd_command_test_done(msdCommandInstance); + return; + } + ufiIng = 1; + DWT->CYCCNT = 0; + DWT->CTRL |= (1 << DWT_CTRL_CYCCNTENA_Pos); + status = + USB_HostMsdWrite10(msdCommandInstance->classHandle, 0, blockAddress, + (uint8_t *)&testThroughputBuffer[0], THROUGHPUT_BUFFER_SIZE, + (THROUGHPUT_BUFFER_SIZE / blockSize), USB_HostMsdUfiCallback, msdCommandInstance); + if (status != kStatus_USB_Success) + { + usb_echo(" error\r\n"); + msd_command_test_done(msdCommandInstance); + return; + } + while (ufiIng) /* wait the command */ + { + USB_HostControllerTaskFunction(g_HostHandle); + } + totalTime += DWT->CYCCNT; + DWT->CTRL &= ~(1U << DWT_CTRL_CYCCNTENA_Pos); + if (ufiStatus != kStatus_USB_Success) + { + usb_echo("fail\r\n"); + msd_command_test_done(msdCommandInstance); + return; + } + testSize -= THROUGHPUT_BUFFER_SIZE; + blockAddress += (THROUGHPUT_BUFFER_SIZE / blockSize); + } + testSize = testSizeArray[testIndex]; + usb_echo(" write %dKB data the speed is %d KB/s\r\n", testSize, + (uint32_t)((uint64_t)testSize * (uint64_t)MCU_CORE_CLOCK / (uint64_t)totalTime)); + + totalTime = 0; + blockAddress = 0; + testSize = testSizeArray[testIndex] * 1024; + while (testSize) + { + if (msdCommandInstance->deviceState != kStatus_DEV_Attached) + { + msd_command_test_done(msdCommandInstance); + return; + } + ufiIng = 1; + DWT->CYCCNT = 0; + DWT->CTRL |= (1 << DWT_CTRL_CYCCNTENA_Pos); + status = + USB_HostMsdRead10(msdCommandInstance->classHandle, 0, blockAddress, (uint8_t *)&testThroughputBuffer[0], + THROUGHPUT_BUFFER_SIZE, (THROUGHPUT_BUFFER_SIZE / blockSize), USB_HostMsdUfiCallback, + msdCommandInstance); + if (status != kStatus_USB_Success) + { + usb_echo(" error\r\n"); + msd_command_test_done(msdCommandInstance); + return; + } + while (ufiIng) /* wait the command */ + { + USB_HostControllerTaskFunction(g_HostHandle); + } + totalTime += DWT->CYCCNT; + DWT->CTRL &= ~(1U << DWT_CTRL_CYCCNTENA_Pos); + if (ufiStatus != kStatus_USB_Success) + { + usb_echo("fail\r\n"); + msd_command_test_done(msdCommandInstance); + return; + } + testSize -= THROUGHPUT_BUFFER_SIZE; + blockAddress += (THROUGHPUT_BUFFER_SIZE / blockSize); + } + testSize = testSizeArray[testIndex]; + usb_echo(" read %dKB data the speed is %d KB/s\r\n", testSize, + (uint32_t)((uint64_t)testSize * (uint64_t)MCU_CORE_CLOCK / (uint64_t)totalTime)); + } +#endif /* MSD_THROUGHPUT_TEST_ENABLE */ + + UsbMountFileSystem(); + msd_command_test_done(msdCommandInstance); /* all test are done */ +} + +usb_status_t USB_HostMsdReadApi(usb_host_msd_command_instance_t *msdCommandInstance, uint8_t *buffer, uint32_t pos, uint32_t block_size, uint32_t block_num) +{ + if (msdCommandInstance->deviceState == kStatus_DEV_Attached) { + usb_status_t status; + ufiIng = 1; + status = USB_HostMsdRead10(msdCommandInstance->classHandle, 0, pos, buffer, block_size, block_num, USB_HostMsdUfiCallback, msdCommandInstance); + if (status != kStatus_USB_Success) { + usb_echo("UsbHostRead error\r\n"); + return kStatus_USB_Error; + } + + while (ufiIng) { + USB_HostControllerTaskFunction(g_HostHandle); + } + + if (ufiStatus == kStatus_USB_Success){ + return kStatus_USB_Success; + } + } + + return kStatus_USB_Error; +} + +usb_status_t USB_HostMsdWriteApi(usb_host_msd_command_instance_t *msdCommandInstance, uint8_t *buffer, uint32_t pos, uint32_t block_size, uint32_t block_num) +{ + if (msdCommandInstance->deviceState == kStatus_DEV_Attached) { + usb_status_t status; + ufiIng = 1; + status = USB_HostMsdWrite10(msdCommandInstance->classHandle, 0, pos, buffer, block_size, block_num, USB_HostMsdUfiCallback, msdCommandInstance); + if (status != kStatus_USB_Success) { + usb_echo("UsbHostWrite error\r\n"); + return kStatus_USB_Error; + } + + while (ufiIng) { + USB_HostControllerTaskFunction(g_HostHandle); + } + + if (ufiStatus == kStatus_USB_Success) { + return kStatus_USB_Success; + } + } + + return kStatus_USB_Error; +} + + +void USB_HostMsdTask(void *arg) +{ + usb_status_t status; + usb_host_msd_command_instance_t *msdCommandInstance = (usb_host_msd_command_instance_t *)arg; + + if (msdCommandInstance->deviceState != msdCommandInstance->prevDeviceState) + { + msdCommandInstance->prevDeviceState = msdCommandInstance->deviceState; + switch (msdCommandInstance->deviceState) + { + case kStatus_DEV_Idle: + break; + + case kStatus_DEV_Attached: /* deivce is attached and numeration is done */ + status = USB_HostMsdInit(msdCommandInstance->deviceHandle, + &msdCommandInstance->classHandle); /* msd class initialization */ + if (status != kStatus_USB_Success) + { + usb_echo("usb host msd init fail\r\n"); + return; + } + msdCommandInstance->runState = kUSB_HostMsdRunSetInterface; + break; + + case kStatus_DEV_Detached: /* device is detached */ + UsbUnmountFileSystem(); + msdCommandInstance->deviceState = kStatus_DEV_Idle; + msdCommandInstance->runState = kUSB_HostMsdRunIdle; + USB_HostMsdDeinit(msdCommandInstance->deviceHandle, + msdCommandInstance->classHandle); /* msd class de-initialization */ + msdCommandInstance->classHandle = NULL; + + usb_echo("mass storage device detached\r\n"); + break; + + default: + break; + } + } + + /* run state */ + switch (msdCommandInstance->runState) + { + case kUSB_HostMsdRunIdle: + break; + + case kUSB_HostMsdRunSetInterface: /* set msd interface */ + msdCommandInstance->runState = kUSB_HostMsdRunIdle; + msdCommandInstance->runWaitState = kUSB_HostMsdRunWaitSetInterface; + status = USB_HostMsdSetInterface(msdCommandInstance->classHandle, msdCommandInstance->interfaceHandle, 0, + USB_HostMsdControlCallback, msdCommandInstance); + if (status != kStatus_USB_Success) + { + usb_echo("set interface fail\r\n"); + } + break; + + case kUSB_HostMsdRunMassStorageTest: /* set interface succeed */ + USB_HostMsdCommandTest(msdCommandInstance); /* test msd device */ + msdCommandInstance->runState = kUSB_HostMsdRunIdle; + break; + + default: + break; + } +} + +usb_status_t USB_HostMsdEvent(usb_device_handle deviceHandle, + usb_host_configuration_handle configurationHandle, + uint32_t eventCode) +{ + usb_status_t status = kStatus_USB_Success; + uint8_t id; + usb_host_configuration_t *configuration; + uint8_t interfaceIndex; + usb_host_interface_t *interface; + uint32_t infoValue; + + switch (eventCode) + { + case kUSB_HostEventAttach: + /* judge whether is configurationHandle supported */ + configuration = (usb_host_configuration_t *)configurationHandle; + for (interfaceIndex = 0; interfaceIndex < configuration->interfaceCount; ++interfaceIndex) + { + interface = &configuration->interfaceList[interfaceIndex]; + id = interface->interfaceDesc->bInterfaceClass; + if (id != USB_HOST_MSD_CLASS_CODE) + { + continue; + } + id = interface->interfaceDesc->bInterfaceSubClass; + if ((id != USB_HOST_MSD_SUBCLASS_CODE_UFI) && (id != USB_HOST_MSD_SUBCLASS_CODE_SCSI)) + { + continue; + } + id = interface->interfaceDesc->bInterfaceProtocol; + if (id != USB_HOST_MSD_PROTOCOL_BULK) + { + continue; + } + else + { + if (g_MsdCommandInstance.deviceState == kStatus_DEV_Idle) + { + /* the interface is supported by the application */ + g_MsdCommandInstance.testUfiBuffer = s_TestUfiBuffer; + g_MsdCommandInstance.deviceHandle = deviceHandle; + g_MsdCommandInstance.interfaceHandle = interface; + g_MsdCommandInstance.configHandle = configurationHandle; + return kStatus_USB_Success; + } + else + { + continue; + } + } + } + status = kStatus_USB_NotSupported; + break; + + case kUSB_HostEventNotSupported: + break; + + case kUSB_HostEventEnumerationDone: + if (g_MsdCommandInstance.configHandle == configurationHandle) + { + if ((g_MsdCommandInstance.deviceHandle != NULL) && (g_MsdCommandInstance.interfaceHandle != NULL)) + { + /* the device enumeration is done */ + if (g_MsdCommandInstance.deviceState == kStatus_DEV_Idle) + { + g_MsdCommandInstance.deviceState = kStatus_DEV_Attached; + + USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDevicePID, &infoValue); + usb_echo("mass storage device attached:pid=0x%x", infoValue); + USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDeviceVID, &infoValue); + usb_echo("vid=0x%x ", infoValue); + USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDeviceAddress, &infoValue); + usb_echo("address=%d\r\n", infoValue); + } + else + { + usb_echo("not idle msd instance\r\n"); + status = kStatus_USB_Error; + } + } + } + break; + + case kUSB_HostEventDetach: + if (g_MsdCommandInstance.configHandle == configurationHandle) + { + /* the device is detached */ + g_MsdCommandInstance.configHandle = NULL; + if (g_MsdCommandInstance.deviceState != kStatus_DEV_Idle) + { + g_MsdCommandInstance.deviceState = kStatus_DEV_Detached; + } + } + break; + + default: + break; + } + return status; +} diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/include/host_msd_command.h b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/include/host_msd_command.h new file mode 100644 index 000000000..18763ce50 --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/include/host_msd_command.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016, 2018 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _HOST_MSD_COMMAND_H_ +#define _HOST_MSD_COMMAND_H_ + +#include "usb_host.h" +#include "usb_host_msd.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/*! @brief 1 - execute throughput test; 0 - don't execute throughput test */ +#define MSD_THROUGHPUT_TEST_ENABLE (0U) + +/*! @brief host app device attach/detach status */ +typedef enum _usb_host_app_state +{ + kStatus_DEV_Idle = 0, /*!< there is no device attach/detach */ + kStatus_DEV_Attached, /*!< device is attached */ + kStatus_DEV_Detached, /*!< device is detached */ +} usb_host_app_state_t; + +/*! @brief host app run status */ +typedef enum _usb_host_msd_run_state +{ + kUSB_HostMsdRunIdle = 0, /*!< idle */ + kUSB_HostMsdRunSetInterface, /*!< execute set interface code */ + kUSB_HostMsdRunWaitSetInterface, /*!< wait set interface done */ + kUSB_HostMsdRunMassStorageTest /*!< execute mass storage test code */ +} usb_host_msd_run_state_t; + +/*! @brief USB host msd command instance structure */ +typedef struct _usb_host_msd_command_instance +{ + usb_host_configuration_handle configHandle; /*!< configuration handle */ + usb_device_handle deviceHandle; /*!< device handle */ + usb_host_class_handle classHandle; /*!< class handle */ + usb_host_interface_handle interfaceHandle; /*!< interface handle */ + uint8_t *testUfiBuffer; /*!< test buffer */ + uint8_t prevDeviceState; /*!< device attach/detach previous status */ + uint8_t deviceState; /*!< device attach/detach status */ + uint8_t runWaitState; /*!< application wait status, go to next run status when the wait status success */ + uint8_t runState; /*!< application run status */ +} usb_host_msd_command_instance_t; + +/******************************************************************************* + * API + ******************************************************************************/ + +/*! + * @brief host msd callback function. + * + * This function should be called in the host callback function. + * + * @param deviceHandle device handle. + * @param configurationHandle attached device's configuration descriptor information. + * @param eventCode callback event code, please reference to enumeration host_event_t. + * + * @retval kStatus_USB_Success The host is initialized successfully. + * @retval kStatus_USB_NotSupported The configuration don't contain msd interface. + * @retval kStatus_USB_Error There is no idle msd instance. + */ +extern usb_status_t USB_HostMsdEvent(usb_device_handle deviceHandle, + usb_host_configuration_handle configurationHandle, + uint32_t eventCode); + +/*! +* @brief host msd command task function. +* +* This function implements the host msd command action, it is used to create task. +* +* @param arg the host msd command instance pointer. +*/ +extern void USB_HostMsdTask(void *arg); + +#endif /* _HOST_MSD_COMMAND_H_ */ diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/include/usb.h b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/include/usb.h new file mode 100644 index 000000000..701c5469d --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/include/usb.h @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __USB_H__ +#define __USB_H__ + +#include +#include +#include "fsl_common.h" +#include "usb_osa.h" +#include "usb_misc.h" +#include "usb_spec.h" + + + +/*! + * @addtogroup usb_drv + * @{ + */ + +/******************************************************************************* + * Definitions + ******************************************************************************/ +/*! @brief Defines USB stack major version */ +#define USB_STACK_VERSION_MAJOR (2U) +/*! @brief Defines USB stack minor version */ +#define USB_STACK_VERSION_MINOR (2U) +/*! @brief Defines USB stack bugfix version */ +#define USB_STACK_VERSION_BUGFIX (0U) + +/*! @brief USB stack version definition */ +#define USB_MAKE_VERSION(major, minor, bugfix) (((major) << 16) | ((minor) << 8) | (bugfix)) + +#define MAKE_VERSION(major, minor, bugfix) (((major) << 16) | ((minor) << 8) | (bugfix)) + +/*! @brief USB stack component version definition, changed with component in yaml together */ +#define USB_STACK_COMPONENT_VERSION MAKE_VERSION(2, 2, 0) + +/* + * Component ID used by tools + * + * FSL_COMPONENT_ID "middleware.usb.stack_common" + */ + +/*! @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. */ + kUSB_ControllerDwc30 = 12U, /*!< DWC3 0U */ + kUSB_ControllerDwc31 = + 13U, /*!< DWC3 1U Currently, there are no platforms which have two Dwc 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/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/include/usb_host_config.h b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/include/usb_host_config.h new file mode 100644 index 000000000..b3636302e --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/include/usb_host_config.h @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _USB_HOST_CONFIG_H_ +#define _USB_HOST_CONFIG_H_ + +/* Host Controller Enable */ +/*! + * @brief host khci instance count, meantime it indicates khci enable or disable. + * - if 0, host khci driver is disable. + * - if greater than 0, host khci driver is enable. + */ +#define USB_HOST_CONFIG_KHCI (0U) + +/*! + * @brief host ehci instance count, meantime it indicates ehci enable or disable. + * - if 0, host ehci driver is disable. + * - if greater than 0, host ehci driver is enable. + */ +#define USB_HOST_CONFIG_EHCI (2U) + +/*! + * @brief host ohci instance count, meantime it indicates ohci enable or disable. + * - if 0, host ohci driver is disable. + * - if greater than 0, host ohci driver is enable. + */ +#define USB_HOST_CONFIG_OHCI (0U) + +/*! + * @brief host ip3516hs instance count, meantime it indicates ohci enable or disable. + * - if 0, host ip3516hs driver is disable. + * - if greater than 0, host ip3516hs driver is enable. + */ +#define USB_HOST_CONFIG_IP3516HS (0U) + +/* Common configuration macros for all controllers */ + +/*! + * @brief host driver instance max count. + * for example: 2 - one for khci, one for ehci. + */ +#define USB_HOST_CONFIG_MAX_HOST \ + (USB_HOST_CONFIG_KHCI + USB_HOST_CONFIG_EHCI + USB_HOST_CONFIG_OHCI + USB_HOST_CONFIG_IP3516HS) + +/*! + * @brief host pipe max count. + * pipe is the host driver resource for device endpoint, one endpoint need one pipe. + */ +#define USB_HOST_CONFIG_MAX_PIPES (16U) + +/*! + * @brief host transfer max count. + * transfer is the host driver resource for data transmission mission, one transmission mission need one transfer. + */ +#define USB_HOST_CONFIG_MAX_TRANSFERS (16U) + +/*! + * @brief the max endpoint for one interface. + * the max endpoint descriptor number that one interface descriptor contain. + */ +#define USB_HOST_CONFIG_INTERFACE_MAX_EP (4U) + +/*! + * @brief the max interface for one configuration. + * the max interface descriptor number that one configuration descriptor can contain. + */ +#define USB_HOST_CONFIG_CONFIGURATION_MAX_INTERFACE (5U) + +/*! + * @brief the max power for one device. + * the max power the host can provide for one device. + */ +#define USB_HOST_CONFIG_MAX_POWER (250U) + +/*! + * @brief the max retries for enumeration. + * retry time when enumeration fail. + */ +#define USB_HOST_CONFIG_ENUMERATION_MAX_RETRIES (3U) + +/*! + * @brief the max retries for enumeration setup stall. + * the max times for one transfer can stall. + */ +#define USB_HOST_CONFIG_ENUMERATION_MAX_STALL_RETRIES (1U) + +/*! + * @brief the max NAK count for one transaction. + * when nak count reach to the value, the transaction fail. + */ +#define USB_HOST_CONFIG_MAX_NAK (3000U) + +/*! @brief Whether the transfer buffer is cache-enabled or not. */ +#ifndef USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE +#define USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE (0U) +#endif +/*! @brief if 1, enable usb compliance test codes; if 0, disable usb compliance test codes. */ +#define USB_HOST_CONFIG_COMPLIANCE_TEST (0U) + +/*! @brief if 1, class driver clear stall automatically; if 0, class driver don't clear stall. */ +#define USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL (0U) + +/* KHCI configuration */ +#if ((defined USB_HOST_CONFIG_KHCI) && (USB_HOST_CONFIG_KHCI)) + +/*! + * @brief khci dma align fix buffer size. + */ +#define USB_HOST_CONFIG_KHCI_DMA_ALIGN_BUFFER (64U) + +#endif + +/* EHCI configuration */ +#if ((defined USB_HOST_CONFIG_EHCI) && (USB_HOST_CONFIG_EHCI)) + +/*! + * @brief ehci periodic frame list size. + * the value can be 1024, 512, 256, 128, 64, 32, 16 or 8. + */ +#define USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE (1024U) + +/*! + * @brief ehci QH max count. + */ +#define USB_HOST_CONFIG_EHCI_MAX_QH (8U) + +/*! + * @brief ehci QTD max count. + */ +#define USB_HOST_CONFIG_EHCI_MAX_QTD (8U) + +/*! + * @brief ehci ITD max count. + */ +#define USB_HOST_CONFIG_EHCI_MAX_ITD (0U) + +/*! + * @brief ehci SITD max count. + */ +#define USB_HOST_CONFIG_EHCI_MAX_SITD (0U) + +#endif + +/* OHCI configuration */ +#if ((defined USB_HOST_CONFIG_OHCI) && (USB_HOST_CONFIG_OHCI)) + +/*! + * @brief ohci ED max count. + */ +#define USB_HOST_CONFIG_OHCI_MAX_ED (16U) + +/*! + * @brief ohci GTD max count. + */ +#define USB_HOST_CONFIG_OHCI_MAX_GTD (16U) + +/*! + * @brief ohci ITD max count. + */ +#define USB_HOST_CONFIG_OHCI_MAX_ITD (8U) + +#endif + +/* OHCI configuration */ +#if ((defined USB_HOST_CONFIG_IP3516HS) && (USB_HOST_CONFIG_IP3516HS)) + +#define USB_HOST_CONFIG_IP3516HS_MAX_PIPE (32U) + +/*! + * @brief ohci ED max count. + */ +#define USB_HOST_CONFIG_IP3516HS_MAX_ATL (32U) + +/*! + * @brief ohci GTD max count. + */ +#define USB_HOST_CONFIG_IP3516HS_MAX_INT (32U) + +/*! + * @brief ohci ITD max count. + */ +#define USB_HOST_CONFIG_IP3516HS_MAX_ISO (0U) + +#endif + +/*! + * @brief host HUB class instance count, meantime it indicates HUB class enable or disable. + * - if 0, host HUB class driver is disable. + * - if greater than 0, host HUB class driver is enable. + */ +#define USB_HOST_CONFIG_HUB (1U) + +/*! + * @brief host HID class instance count, meantime it indicates HID class enable or disable. + * - if 0, host HID class driver is disable. + * - if greater than 0, host HID class driver is enable. + */ +#define USB_HOST_CONFIG_HID (1U) + +/*! + * @brief host MSD class instance count, meantime it indicates MSD class enable or disable. + * - if 0, host MSD class driver is disable. + * - if greater than 0, host MSD class driver is enable. + */ +#define USB_HOST_CONFIG_MSD (1U) + +/*! + * @brief host CDC class instance count, meantime it indicates CDC class enable or disable. + * - if 0, host CDC class driver is disable. + * - if greater than 0, host CDC class driver is enable. + */ +#define USB_HOST_CONFIG_CDC (1U) + +/*! + * @brief host AUDIO class instance count, meantime it indicates AUDIO class enable or disable. + * - if 0, host AUDIO class driver is disable. + * - if greater than 0, host AUDIO class driver is enable. + */ +#define USB_HOST_CONFIG_AUDIO (1U) + +/*! + * @brief host PHDC class instance count, meantime it indicates PHDC class enable or disable. + * - if 0, host PHDC class driver is disable. + * - if greater than 0, host PHDC class driver is enable. + */ +#define USB_HOST_CONFIG_PHDC (1U) + +/*! + * @brief host printer class instance count, meantime it indicates printer class enable or disable. + * - if 0, host printer class driver is disable. + * - if greater than 0, host printer class driver is enable. + */ +#define USB_HOST_CONFIG_PRINTER (1U) + +#endif /* _USB_HOST_CONFIG_H_ */ diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/include/usb_misc.h b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/include/usb_misc.h new file mode 100644 index 000000000..f76a376bc --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/include/usb_misc.h @@ -0,0 +1,452 @@ +/* + * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc. + * Copyright 2016, 2019 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/** +* @file usb_misc.h +* @brief modify usb_echo to KPrintf +* @version 2.0 +* @author AIIT XUOS Lab +* @date 2022-02-10 +*/ + +/************************************************* +File name: usb_misc.h +Description: modify usb_echo to KPrintf +Others: take SDK_2.6.1_MIMXRT1052xxxxB/middleware/usb/include/usb_misc.h for references +History: +1. Date: 2022-02-10 +Author: AIIT XUOS Lab +Modification: +1. add xiuos.h +2. modify usb_echo to KPrintf +*************************************************/ + +#ifndef __USB_MISC_H__ +#define __USB_MISC_H__ + +#include + +#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 KPrintf +#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) || (defined(__ARMCC_VERSION)) + +#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] = ((((uint32_t)(n)) >> 24U) & 0xFFU); \ + m[2] = ((((uint32_t)(n)) >> 16U) & 0xFFU); \ + m[1] = ((((uint32_t)(n)) >> 8U) & 0xFFU); \ + m[0] = (((uint32_t)(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] = ((((uint32_t)(n)) >> 24U) & 0xFFU); \ + m[1] = ((((uint32_t)(n)) >> 16U) & 0xFFU); \ + m[2] = ((((uint32_t)(n)) >> 8U) & 0xFFU); \ + m[3] = (((uint32_t)(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] = ((((uint16_t)(n)) >> 8U) & 0xFFU); \ + m[0] = (((uint16_t)(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] = ((((uint16_t)(n)) >> 8U) & 0xFFU); \ + m[1] = (((uint16_t)(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) = ((((uint32_t)(n)) >> 24U) & 0xFFU); \ + *((uint8_t *)&(m) + 2) = ((((uint32_t)(n)) >> 16U) & 0xFFU); \ + *((uint8_t *)&(m) + 1) = ((((uint32_t)(n)) >> 8U) & 0xFFU); \ + *((uint8_t *)&(m) + 0) = (((uint32_t)(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) = ((((uint16_t)(n)) >> 8U) & 0xFFU); \ + *((uint8_t *)&(m)) = ((((uint16_t)(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] = ((((uint32_t)(n)) >> 24U) & 0xFFU); \ + m[2] = ((((uint32_t)(n)) >> 16U) & 0xFFU); \ + m[1] = ((((uint32_t)(n)) >> 8U) & 0xFFU); \ + m[0] = (((uint32_t)(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] = ((((uint32_t)(n)) >> 24U) & 0xFFU); \ + m[1] = ((((uint32_t)(n)) >> 16U) & 0xFFU); \ + m[2] = ((((uint32_t)(n)) >> 8U) & 0xFFU); \ + m[3] = (((uint32_t)(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] = ((((uint16_t)(n)) >> 8U) & 0xFFU); \ + m[0] = (((uint16_t)(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] = ((((uint16_t)(n)) >> 8U) & 0xFFU); \ + m[1] = (((uint16_t)(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) = ((((uint32_t)(n)) >> 24U) & 0xFFU); \ + *((uint8_t *)&(m) + 2) = ((((uint32_t)(n)) >> 16U) & 0xFFU); \ + *((uint8_t *)&(m) + 1) = ((((uint32_t)(n)) >> 8U) & 0xFFU); \ + *((uint8_t *)&(m) + 0) = (((uint32_t)(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) = ((((uint16_t)(n)) >> 8U) & 0xFFU); \ + *((uint8_t *)&(m)) = ((((uint16_t)(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 macro 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_DMA_INIT_DATA(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) || (defined(__ARMCC_VERSION)) + +#define USB_WEAK_VAR __attribute__((weak)) +#define USB_WEAK_FUN __attribute__((weak)) +#define USB_RAM_ADDRESS_ALIGNMENT(n) __attribute__((aligned(n))) +#define USB_LINK_DMA_INIT_DATA(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_DMA_INIT_DATA(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 - 1U) & (~(USB_DATA_ALIGN_SIZE - 1U))) + +#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_DMA_INIT_DATA(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_DMA_INIT_DATA(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_DMA_INIT_DATA(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/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/include/usb_spec.h b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/include/usb_spec.h new file mode 100644 index 000000000..650ba1cb3 --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/include/usb_spec.h @@ -0,0 +1,300 @@ +/* + * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#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) +#define USB_SPEED_SUPER (0x04U) + +/* 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_ENDPOINT_COMPANION (0x06U) +#define USB_DESCRIPTOR_LENGTH_DEVICE_QUALITIER (0x0AU) +#define USB_DESCRIPTOR_LENGTH_OTG_DESCRIPTOR (5U) +#define USB_DESCRIPTOR_LENGTH_BOS_DESCRIPTOR (5U) +#define USB_DESCRIPTOR_LENGTH_DEVICE_CAPABILITY_USB20_EXTENSION (0x07U) +#define USB_DESCRIPTOR_LENGTH_DEVICE_CAPABILITY_SUPERSPEED (0x0AU) + +/* 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) + +#define USB_DESCRIPTOR_TYPE_ENDPOINT_COMPANION (0x30U) + +/* 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_endpoint_companion +{ + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bMaxBurst; + uint8_t bmAttributes; + uint8_t wBytesPerInterval[2]; +} usb_descriptor_endpoint_companion_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 struct _usb_descriptor_super_speed_device_capability +{ + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDevCapabilityType; + uint8_t bmAttributes; + uint8_t wSpeedsSupported[2]; + uint8_t bFunctionalitySupport; + uint8_t bU1DevExitLat; + uint8_t wU2DevExitLat[2]; +} usb_bos_device_capability_susperspeed_desc_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_endpoint_companion_t endpointCompanion; /* Endpoint companion descriptor */ +} usb_descriptor_union_t; + +#endif /* __USB_SPEC_H__ */ diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/osa/Makefile b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/osa/Makefile new file mode 100644 index 000000000..8b4cc292c --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/osa/Makefile @@ -0,0 +1,3 @@ +SRC_FILES += usb_osa_bm.c + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/osa/usb_osa.h b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/osa/usb_osa.h new file mode 100644 index 000000000..a54e4f8d4 --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/osa/usb_osa.h @@ -0,0 +1,577 @@ +/* + * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __USB_OSA_H__ +#define __USB_OSA_H__ + +/*! + * @addtogroup usb_os_abstraction + * @{ + */ + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/*! @brief Define big endian */ +#define USB_BIG_ENDIAN (0U) +/*! @brief Define little endian */ +#define USB_LITTLE_ENDIAN (1U) + +/*! @brief Define current endian */ +#define ENDIANNESS USB_LITTLE_ENDIAN + +/*! @brief Define USB OSA event handle */ +typedef void *usb_osa_event_handle; + +/*! @brief Define USB OSA semaphore handle */ +typedef void *usb_osa_sem_handle; + +/*! @brief Define USB OSA mutex handle */ +typedef void *usb_osa_mutex_handle; + +/*! @brief Define USB OSA message queue handle */ +typedef void *usb_osa_msgq_handle; + +/*! @brief USB OSA error code */ +typedef enum _usb_osa_status +{ + kStatus_USB_OSA_Success = 0x00U, /*!< Success */ + kStatus_USB_OSA_Error, /*!< Failed */ + kStatus_USB_OSA_TimeOut, /*!< Timeout occurs while waiting */ +} usb_osa_status_t; + +/*! @brief The event flags are cleared automatically or manually.*/ +typedef enum _usb_osa_event_mode +{ + kUSB_OsaEventManualClear = 0U, /*!< The flags of the event is cleared manually. */ + kUSB_OsaEventAutoClear = 1U, /*!< The flags of the event is cleared automatically. */ +} usb_osa_event_mode_t; + +#define USB_STACK_BM +/* Include required header file based on RTOS selection */ +#if defined(USB_STACK_BM) + +#include "usb_osa_bm.h" + +#elif defined(USB_STACK_FREERTOS) + +#include "usb_osa_freertos.h" + +#elif defined(USB_STACK_UCOSII) + +#include "usb_osa_ucosii.h" + +#elif defined(USB_STACK_UCOSIII) + +#include "usb_osa_ucosiii.h" + +#else +#if defined(SDK_OS_BAREMETAL) + +#define USB_STACK_BM +#include "usb_osa_bm.h" + +#elif defined(SDK_OS_FREE_RTOS) + +#define USB_STACK_FREERTOS +#include "usb_osa_freertos.h" + +#elif defined(SDK_OS_UCOSII) + +#define USB_STACK_UCOSII +#include "usb_osa_ucosii.h" + +#elif defined(SDK_OS_UCOSIII) + +#define USB_STACK_UCOSIII +#include "usb_osa_ucosiii.h" + +#else + +#error Not define RTOS in file "usb_osa.h". +#endif +#endif + +/******************************************************************************* + * API + ******************************************************************************/ + +#if defined(__cplusplus) +extern "C" { +#endif + +/*! + * @name USB OSA Memory Management + * @{ + */ + +/*! + * @brief Reserves the requested amount of memory in bytes. + * + * The function is used to reserve the requested amount of memory in bytes and initializes it to 0. + * + * @param length Amount of bytes to reserve. + * + * @return Pointer to the reserved memory. NULL if memory can't be allocated. + */ +void *USB_OsaMemoryAllocate(uint32_t length); + +/*! + * @brief Frees the memory previously reserved. + * + * The function is used to free the memory block previously reserved. + * + * @param p Pointer to the start of the memory block previously reserved. + * + */ +extern void USB_OsaMemoryFree(void *p); + +/* @} */ + +/*! + * @name USB OSA Event + * @{ + */ + +/*! + * @brief Creates an event object with all flags cleared. + * + * This function creates an event object and sets its clear mode. If the clear mode + * is kUSB_OsaEventAutoClear, when a task gets the event flags, these flags are + * cleared automatically. If the clear mode is kUSB_OsaEventManualClear, the flags must + * be cleared manually. + * + * @param handle It is an out parameter, which is used to return the pointer of the event object. + * @param flag The event is auto-clear or manual-clear. See the enumeration #usb_osa_event_mode_t. + * + * @return A USB OSA error code or kStatus_OSA_Success. + * + * Example: + @code + usb_osa_event_handle eventHandle; + usb_osa_status_t usbOsaStatus; + usbOsaStatus = USB_OsaEventCreate(&eventHandle, kUSB_OsaEventManualClear); + @endcode + * + */ +extern usb_osa_status_t USB_OsaEventCreate(usb_osa_event_handle *handle, uint32_t flag); + +/*! + * @brief Destroys a created event object. + * + * @param handle Pointer to the event object. + * + * @return A USB OSA error code or kStatus_OSA_Success. + * + * Example: + @code + usb_osa_status_t usbOsaStatus; + ... + usbOsaStatus = USB_OsaEventDestroy(eventHandle); + @endcode + * + */ +extern usb_osa_status_t USB_OsaEventDestroy(usb_osa_event_handle handle); + +/*! + * @brief Sets an event flag. + * + * Sets specified flags for an event object. + * + * @param handle Pointer to the event object. + * @param bitMask Event flags to be set. + * + * @return A USB OSA error code or kStatus_OSA_Success. + * + * Example: + @code + usb_osa_status_t usbOsaStatus; + ... + usbOsaStatus = USB_OsaEventSet(eventHandle, 0x01U); + @endcode + * + */ +extern usb_osa_status_t USB_OsaEventSet(usb_osa_event_handle handle, uint32_t bitMask); + +/*! + * @brief Waits for an event flag. + * + * This function waits for a combination of flags to be set in an event object. + * An applications can wait for any/all bits to be set. This function can + * get the flags that wake up the waiting task. + * + * @param handle Pointer to the event object. + * @param bitMask Event flags to wait. + * @param flag Wait all flags or any flag to be set. 0U - wait any flag, others, wait all flags. + * @param timeout The maximum number of milliseconds to wait for the event. + * If the wait condition is not met, passing 0U + * waits indefinitely when the environment is an RTOS and returns the kStatus_OSA_Timeout + * immediately. Pass any value for the bare metal. + * @param bitSet Flags that wake up the waiting task are obtained by this parameter. + * + * @return An USB OSA error code or kStatus_OSA_Success. + * + * Example: + @code + usb_osa_status_t usbOsaStatus; + uint32_t bitSet; + ... + usbOsaStatus = USB_OsaEventWait(eventHandle, 0x01U, 0U, 0U, &bitSet); + @endcode + * + */ +extern usb_osa_status_t USB_OsaEventWait( + usb_osa_event_handle handle, uint32_t bitMask, uint32_t flag, uint32_t timeout, uint32_t *bitSet); + +/*! + * @brief Checks an event flag. + * + * This function checks for a combination of flags to be set in an event object. + * + * @param handle Pointer to the event object. + * @param bitMask Event flags to check. + * @param bitSet Flags have been set. + * + * @return An USB OSA error code or kStatus_OSA_Success. + * + * Example: + @code + usb_osa_status_t usbOsaStatus; + uint32_t bitSet; + ... + usbOsaStatus = USB_OsaEventCheck(eventHandle, 0x01U, &bitSet); + @endcode + * + */ +extern usb_osa_status_t USB_OsaEventCheck(usb_osa_event_handle handle, uint32_t bitMask, uint32_t *bitSet); + +/*! + * @brief Clears an event flag. + * + * This function clears flags of an event object. + * + * @param handle Pointer to the event object + * @param bitMask Event flags to be cleared. + * + * @return An USB OSA error code or kStatus_OSA_Success. + * + * Example: + @code + usb_osa_status_t usbOsaStatus; + ... + usbOsaStatus = USB_OsaEventClear(eventHandle, 0x01U); + @endcode + */ +extern usb_osa_status_t USB_OsaEventClear(usb_osa_event_handle handle, uint32_t bitMask); +/* @} */ + +/*! + * @name USB OSA Semaphore + * @{ + */ + +/*! + * @brief Creates a semaphore with a given value. + * + * This function creates a semaphore and sets the default count. + * + * @param handle It is an out parameter, which is used to return pointer of the semaphore object. + * @param count Initializes a value of the semaphore. + * + * @return An USB OSA error code or kStatus_OSA_Success. + * + * Example: + @code + usb_osa_sem_handle semHandle; + usb_osa_status_t usbOsaStatus; + usbOsaStatus = USB_OsaSemCreate(&semHandle, 1U); + @endcode + * + */ +extern usb_osa_status_t USB_OsaSemCreate(usb_osa_sem_handle *handle, uint32_t count); + +/*! + * @brief Destroys a semaphore object. + * + * This function destroys a semaphore object. + * + * @param handle Pointer to the semaphore. + * + * @return An USB OSA error code or kStatus_OSA_Success. + * + * Example: + @code + usb_osa_sem_handle semHandle; + usb_osa_status_t usbOsaStatus; + ... + usbOsaStatus = USB_OsaSemDestroy(semHandle); + @endcode + * + */ +extern usb_osa_status_t USB_OsaSemDestroy(usb_osa_sem_handle handle); + +/*! + * @brief Posts a semaphore. + * + * This function wakes up a task waiting on the semaphore. If a task is not pending, increases the semaphore's + value. + * + * @param handle Pointer to the semaphore. + * + * @return A USB OSA error code or kStatus_OSA_Success. + * + * Example: + @code + usb_osa_sem_handle semHandle; + usb_osa_status_t usbOsaStatus; + ... + usbOsaStatus = USB_OsaSemPost(semHandle); + @endcode + * + */ +extern usb_osa_status_t USB_OsaSemPost(usb_osa_sem_handle handle); + +/*! + * @brief Waits on a semaphore. + * + * This function checks the semaphore's value. If it is positive, it decreases the semaphore's value and return + kStatus_OSA_Success. + * + * @param handle Pointer to the semaphore. + * @param timeout The maximum number of milliseconds to wait for the semaphore. + * If the wait condition is not met, passing 0U + * waits indefinitely when environment is RTOS. And return kStatus_OSA_Timeout + * immediately for bare metal no matter what value has been passed. + * + * @return A USB OSA error code or kStatus_OSA_Success. + * + * Example: + @code + usb_osa_sem_handle semHandle; + usb_osa_status_t usbOsaStatus; + ... + usbOsaStatus = USB_OsaSemWait(semHandle, 0U); + @endcode + * + */ +extern usb_osa_status_t USB_OsaSemWait(usb_osa_sem_handle handle, uint32_t timeout); +/* @} */ + +/*! + * @name USB OSA Mutex + * @{ + */ + +/*! + * @brief Creates a mutex. + * + * This function creates a mutex and sets it to an unlocked status. + * + * @param handle It is out parameter, which is used to return the pointer of the mutex object. + * + * @return A USB OSA error code or kStatus_OSA_Success. + * + * Example: + @code + usb_osa_mutex_handle mutexHandle; + usb_osa_status_t usbOsaStatus; + usbOsaStatus = USB_OsaMutexCreate(&mutexHandle); + @endcode + * + */ +extern usb_osa_status_t USB_OsaMutexCreate(usb_osa_mutex_handle *handle); + +/*! + * @brief Destroys a mutex. + * + * This function destroys a mutex and sets it to an unlocked status. + * + * @param handle Pointer to the mutex. + * + * @return A USB OSA error code or kStatus_OSA_Success. + * + * Example: + @code + usb_osa_mutex_handle mutexHandle; + usb_osa_status_t usbOsaStatus; + ... + usbOsaStatus = USB_OsaMutexDestroy(mutexHandle); + @endcode + * + */ +extern usb_osa_status_t USB_OsaMutexDestroy(usb_osa_mutex_handle handle); + +/*! + * @brief Waits for a mutex and locks it. + * + * This function checks the mutex status. If it is unlocked, it locks it and returns the + * kStatus_OSA_Success. Otherwise, it waits forever to lock in RTOS and returns the + * kStatus_OSA_Success immediately for bare metal. + * + * @param handle Pointer to the mutex. + * + * @return A USB OSA error code or kStatus_OSA_Success. + * + * Example: + @code + usb_osa_mutex_handle mutexHandle; + usb_osa_status_t usbOsaStatus; + ... + usbOsaStatus = USB_OsaMutexLock(mutexHandle); + @endcode + * + */ +extern usb_osa_status_t USB_OsaMutexLock(usb_osa_mutex_handle handle); + +/*! + * @brief Unlocks a mutex. + * + * This function unlocks a mutex. + * + * @param handle Pointer to the mutex. + * + * @return A USB OSA error code or kStatus_OSA_Success. + * + * Example: + @code + usb_osa_mutex_handle mutexHandle; + usb_osa_status_t usbOsaStatus; + ... + usbOsaStatus = USB_OsaMutexUnlock(mutexHandle); + @endcode + * + */ +extern usb_osa_status_t USB_OsaMutexUnlock(usb_osa_mutex_handle handle); +/* @} */ + +/*! + * @name USB OSA Message Queue + * @{ + */ + +/*! + * @brief Creates a message queue. + * + * This function creates a message queue. + * + * @param handle It is an out parameter, which is used to return a pointer of the message queue object. + * @param count The count of elements in the queue. + * @param size Size of every elements in words. + * + * @return A USB OSA error code or kStatus_OSA_Success. + * + * Example: + @code + usb_osa_msgq_handle msgqHandle; + usb_osa_status_t usbOsaStatus; + usbOsaStatus = USB_OsaMsgqCreate(msgqHandle, 8U, 4U); + @endcode + * + */ +extern usb_osa_status_t USB_OsaMsgqCreate(usb_osa_msgq_handle *handle, uint32_t count, uint32_t size); + +/*! + * @brief Destroys a message queue. + * + * This function destroys a message queue. + * + * @param handle Pointer to a message queue. + * + * @return A USB OSA error code or kStatus_OSA_Success. + * + * Example: + @code + usb_osa_msgq_handle msgqHandle; + usb_osa_status_t usbOsaStatus; + ... + usbOsaStatus = USB_OsaMsgqDestroy(msgqHandle); + @endcode + * + */ +extern usb_osa_status_t USB_OsaMsgqDestroy(usb_osa_msgq_handle handle); + +/*! + * @brief Sends a message. + * + * This function sends a message to the tail of the message queue. + * + * @param handle Pointer to a message queue. + * @param msg The pointer to a message to be put into the queue. + * + * @return A USB OSA error code or kStatus_OSA_Success. + * + * Example: + @code + usb_osa_msgq_handle msgqHandle; + message_struct_t message; + usb_osa_status_t usbOsaStatus; + ... + usbOsaStatus = USB_OsaMsgqSend(msgqHandle, &message); + @endcode + * + */ +extern usb_osa_status_t USB_OsaMsgqSend(usb_osa_msgq_handle handle, void *msg); + +/*! + * @brief Receives a message. + * + * This function receives a message from the head of the message queue. + * + * @param handle Pointer to a message queue. + * @param msg The pointer to save a received message. + * @param timeout The maximum number of milliseconds to wait for a message. + * If the wait condition is not met, passing 0U + * waits indefinitely when an environment is RTOS and returns the kStatus_OSA_Timeout + * immediately for bare metal. + * + * @return A USB OSA error code or kStatus_OSA_Success. + * + * Example: + @code + usb_osa_msgq_handle msgqHandle; + message_struct_t message; + usb_osa_status_t usbOsaStatus; + ... + usbOsaStatus = USB_OsaMsgqRecv(msgqHandle, &message, 0U); + @endcode + * + */ +extern usb_osa_status_t USB_OsaMsgqRecv(usb_osa_msgq_handle handle, void *msg, uint32_t timeout); + +/*! + * @brief Checks a message queue and receives a message if the queue is not empty. + * + * This function checks a message queue and receives a message if the queue is not empty. + * + * @param handle Pointer to a message queue. + * @param msg The pointer to save a received message. + * + * @return A USB OSA error code or kStatus_OSA_Success. + * + * Example: + @code + usb_osa_msgq_handle msgqHandle; + message_struct_t message; + usb_osa_status_t usbOsaStatus; + ... + usbOsaStatus = USB_OsaMsgqCheck(msgqHandle, &message); + @endcode + * + */ +extern usb_osa_status_t USB_OsaMsgqCheck(usb_osa_msgq_handle handle, void *msg); + +/* @} */ + +#if defined(__cplusplus) +} +#endif + +/* @} */ + +#endif /* __USB_OSA_H__ */ diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/osa/usb_osa_bm.c b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/osa/usb_osa_bm.c new file mode 100644 index 000000000..9512fb699 --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/osa/usb_osa_bm.c @@ -0,0 +1,522 @@ +/* + * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include "stdint.h" +#include "usb.h" +#include "usb_osa.h" +#include "stdlib.h" +#include "fsl_device_registers.h" +#include "fsl_common.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ +#define USB_OSA_BM_EVENT_COUNT (4U) +#define USB_OSA_BM_SEM_COUNT (1U) +#define USB_OSA_BM_MSGQ_COUNT (1U) +#define USB_OSA_BM_MSG_COUNT (8U) +#define USB_OSA_BM_MSG_SIZE (4U) + +/* BM Event status structure */ +typedef struct _usb_osa_event_struct +{ + uint32_t value; /* Event mask */ + uint32_t flag; /* Event flags, includes auto clear flag */ + uint8_t isUsed; /* Is used */ +} usb_osa_event_struct_t; + +/* BM semaphore status structure */ +typedef struct _usb_osa_sem_struct +{ + uint32_t value; /* Semaphore count */ + uint8_t isUsed; /* Is used */ +} usb_osa_sem_struct_t; + +/* BM msg status structure */ +typedef struct _usb_osa_msg_struct +{ + uint32_t msg[USB_OSA_BM_MSG_SIZE]; /* Message entity pointer */ +} usb_osa_msg_struct_t; + +/* BM msgq status structure */ +typedef struct _usb_osa_msgq_struct +{ + usb_osa_msg_struct_t msgs[USB_OSA_BM_MSG_COUNT]; /* Message entity list */ + uint32_t count; /* Max message entity count */ + uint32_t msgSize; /* Size of each message */ + uint32_t msgCount; /* Valid messages */ + uint32_t index; /* The first empty message entity index */ + uint32_t current; /* The vaild message index */ + uint8_t isUsed; /* Is used */ +} usb_osa_msgq_struct_t; + +/******************************************************************************* + * Prototypes + ******************************************************************************/ + +/******************************************************************************* + * Variables + ******************************************************************************/ + +USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static usb_osa_sem_struct_t + s_UsbBmSemStruct[USB_OSA_BM_SEM_COUNT]; +USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static usb_osa_event_struct_t + s_UsbBmEventStruct[USB_OSA_BM_EVENT_COUNT]; +USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static usb_osa_msgq_struct_t + s_UsbBmMsgqStruct[USB_OSA_BM_MSGQ_COUNT]; + +/******************************************************************************* + * Code + ******************************************************************************/ + +void *USB_OsaMemoryAllocate(uint32_t length) +{ + void *p = (void *)malloc(length); + uint8_t *temp = (uint8_t *)p; + if (p) + { + for (uint32_t count = 0U; count < length; count++) + { + temp[count] = 0U; + } + } + return p; +} + +void USB_OsaMemoryFree(void *p) +{ + free(p); +} + +void USB_OsaEnterCritical(uint32_t *sr) +{ + *sr = DisableGlobalIRQ(); + + + __ASM("CPSID i"); +} + +void USB_OsaExitCritical(uint32_t sr) +{ + EnableGlobalIRQ(sr); +} + +usb_osa_status_t USB_OsaEventCreate(usb_osa_event_handle *handle, uint32_t flag) +{ + usb_osa_event_struct_t *event = NULL; + USB_OSA_SR_ALLOC(); + + if (!handle) + { + return kStatus_USB_OSA_Error; + } + + USB_OSA_ENTER_CRITICAL(); + for (uint32_t i = 0; i < USB_OSA_BM_EVENT_COUNT; i++) + { + if (0 == s_UsbBmEventStruct[i].isUsed) + { + event = &s_UsbBmEventStruct[i]; + break; + } + } + + if (NULL == event) + { + USB_OSA_EXIT_CRITICAL(); + return kStatus_USB_OSA_Error; + } + + event->value = 0U; + event->flag = flag; + event->isUsed = 1; + *handle = event; + USB_OSA_EXIT_CRITICAL(); + return kStatus_USB_OSA_Success; +} + +usb_osa_status_t USB_OsaEventDestroy(usb_osa_event_handle handle) +{ + usb_osa_event_struct_t *event = (usb_osa_event_struct_t *)handle; + USB_OSA_SR_ALLOC(); + + if (handle) + { + USB_OSA_ENTER_CRITICAL(); + event->isUsed = 0; + USB_OSA_EXIT_CRITICAL(); + return kStatus_USB_OSA_Success; + } + return kStatus_USB_OSA_Error; +} + +usb_osa_status_t USB_OsaEventSet(usb_osa_event_handle handle, uint32_t bitMask) +{ + usb_osa_event_struct_t *event = (usb_osa_event_struct_t *)handle; + USB_OSA_SR_ALLOC(); + + if (handle) + { + USB_OSA_ENTER_CRITICAL(); + event->value |= bitMask; + USB_OSA_EXIT_CRITICAL(); + return kStatus_USB_OSA_Success; + } + return kStatus_USB_OSA_Error; +} + +usb_osa_status_t USB_OsaEventWait( + usb_osa_event_handle handle, uint32_t bitMask, uint32_t flag, uint32_t timeout, uint32_t *bitSet) +{ + usb_osa_event_struct_t *event = (usb_osa_event_struct_t *)handle; + uint32_t bits; + USB_OSA_SR_ALLOC(); + + if (handle) + { + USB_OSA_ENTER_CRITICAL(); + bits = event->value & bitMask; + if (flag) + { + if (bits != bitMask) + { + USB_OSA_EXIT_CRITICAL(); + return kStatus_USB_OSA_TimeOut; + } + } + else + { + if (!bits) + { + USB_OSA_EXIT_CRITICAL(); + return kStatus_USB_OSA_TimeOut; + } + } + if (bitSet) + { + *bitSet = bits; + } + if (event->flag) + { + event->value &= ~bits; + } + USB_OSA_EXIT_CRITICAL(); + return kStatus_USB_OSA_Success; + } + return kStatus_USB_OSA_Error; +} + +usb_osa_status_t USB_OsaEventCheck(usb_osa_event_handle handle, uint32_t bitMask, uint32_t *bitSet) +{ + usb_osa_event_struct_t *event = (usb_osa_event_struct_t *)handle; + uint32_t bits; + USB_OSA_SR_ALLOC(); + + if (handle) + { + USB_OSA_ENTER_CRITICAL(); + bits = event->value & bitMask; + + if (!bits) + { + USB_OSA_EXIT_CRITICAL(); + return kStatus_USB_OSA_Error; + } + + if (bitSet) + { + *bitSet = bits; + } + USB_OSA_EXIT_CRITICAL(); + return kStatus_USB_OSA_Success; + } + return kStatus_USB_OSA_Error; +} + +usb_osa_status_t USB_OsaEventClear(usb_osa_event_handle handle, uint32_t bitMask) +{ + usb_osa_event_struct_t *event = (usb_osa_event_struct_t *)handle; + uint32_t bits; + USB_OSA_SR_ALLOC(); + + if (handle) + { + USB_OSA_ENTER_CRITICAL(); + bits = event->value & bitMask; + event->value &= ~bits; + USB_OSA_EXIT_CRITICAL(); + return kStatus_USB_OSA_Success; + } + return kStatus_USB_OSA_Error; +} + +usb_osa_status_t USB_OsaSemCreate(usb_osa_sem_handle *handle, uint32_t count) +{ + usb_osa_sem_struct_t *sem = NULL; + USB_OSA_SR_ALLOC(); + + if (!handle) + { + return kStatus_USB_OSA_Error; + } + + USB_OSA_ENTER_CRITICAL(); + for (uint32_t i = 0; i < USB_OSA_BM_SEM_COUNT; i++) + { + if (0 == s_UsbBmSemStruct[i].isUsed) + { + sem = &s_UsbBmSemStruct[i]; + break; + } + } + if (NULL == sem) + { + USB_OSA_EXIT_CRITICAL(); + return kStatus_USB_OSA_Error; + } + + sem->value = count; + sem->isUsed = 1; + *handle = sem; + USB_OSA_EXIT_CRITICAL(); + return kStatus_USB_OSA_Success; +} + +usb_osa_status_t USB_OsaSemDestroy(usb_osa_sem_handle handle) +{ + usb_osa_sem_struct_t *sem = (usb_osa_sem_struct_t *)handle; + USB_OSA_SR_ALLOC(); + + if (handle) + { + USB_OSA_ENTER_CRITICAL(); + sem->isUsed = 0; + USB_OSA_EXIT_CRITICAL(); + return kStatus_USB_OSA_Success; + } + return kStatus_USB_OSA_Error; +} + +usb_osa_status_t USB_OsaSemPost(usb_osa_sem_handle handle) +{ + usb_osa_sem_struct_t *sem = (usb_osa_sem_struct_t *)handle; + USB_OSA_SR_ALLOC(); + + if (!handle) + { + return kStatus_USB_OSA_Error; + } + + USB_OSA_ENTER_CRITICAL(); + sem->value++; + USB_OSA_EXIT_CRITICAL(); + return kStatus_USB_OSA_Success; +} + +usb_osa_status_t USB_OsaSemWait(usb_osa_sem_handle handle, uint32_t timeout) +{ + usb_osa_sem_struct_t *sem = (usb_osa_sem_struct_t *)handle; + USB_OSA_SR_ALLOC(); + + if (!handle) + { + return kStatus_USB_OSA_Error; + } + + USB_OSA_ENTER_CRITICAL(); + if (sem->value) + { + sem->value--; + } + else + { + USB_OSA_EXIT_CRITICAL(); + return kStatus_USB_OSA_TimeOut; + } + USB_OSA_EXIT_CRITICAL(); + return kStatus_USB_OSA_Success; +} + +usb_osa_status_t USB_OsaMutexCreate(usb_osa_mutex_handle *handle) +{ + if (!handle) + { + return kStatus_USB_OSA_Error; + } + *handle = (usb_osa_mutex_handle)0xFFFF0000U; + return kStatus_USB_OSA_Success; +} + +usb_osa_status_t USB_OsaMutexDestroy(usb_osa_mutex_handle handle) +{ + return kStatus_USB_OSA_Success; +} +usb_osa_status_t USB_OsaMutexLock(usb_osa_mutex_handle handle) +{ + return kStatus_USB_OSA_Success; +} +usb_osa_status_t USB_OsaMutexUnlock(usb_osa_mutex_handle handle) +{ + return kStatus_USB_OSA_Success; +} + +usb_osa_status_t USB_OsaMsgqCreate(usb_osa_msgq_handle *handle, uint32_t count, uint32_t size) +{ + usb_osa_msgq_struct_t *msgq = NULL; + USB_OSA_SR_ALLOC(); + + if (!handle) + { + return kStatus_USB_OSA_Error; + } + USB_OSA_ENTER_CRITICAL(); + + for (uint32_t i = 0; i < USB_OSA_BM_MSGQ_COUNT; i++) + { + if (0 == s_UsbBmMsgqStruct[i].isUsed) + { + msgq = &s_UsbBmMsgqStruct[i]; + break; + } + } + if ((NULL == msgq) || (count > USB_OSA_BM_MSG_COUNT) || (size > USB_OSA_BM_MSG_SIZE)) + { + USB_OSA_EXIT_CRITICAL(); + return kStatus_USB_OSA_Error; + } + msgq->count = count; + msgq->msgSize = size; + msgq->msgCount = 0U; + msgq->index = 0U; + msgq->current = 0U; + msgq->isUsed = 1; + *handle = msgq; + USB_OSA_EXIT_CRITICAL(); + return kStatus_USB_OSA_Success; +} + +usb_osa_status_t USB_OsaMsgqDestroy(usb_osa_msgq_handle handle) +{ + usb_osa_msgq_struct_t *msgq = (usb_osa_msgq_struct_t *)handle; + USB_OSA_SR_ALLOC(); + + if (!handle) + { + return kStatus_USB_OSA_Error; + } + USB_OSA_ENTER_CRITICAL(); + msgq->isUsed = 0; + USB_OSA_EXIT_CRITICAL(); + return kStatus_USB_OSA_Success; +} + +usb_osa_status_t USB_OsaMsgqSend(usb_osa_msgq_handle handle, void *msg) +{ + usb_osa_msgq_struct_t *msgq = (usb_osa_msgq_struct_t *)handle; + usb_osa_msg_struct_t *msgEntity; + uint32_t *p; + uint32_t *q; + uint32_t count; + USB_OSA_SR_ALLOC(); + + if (!handle) + { + return kStatus_USB_OSA_Error; + } + USB_OSA_ENTER_CRITICAL(); + if (msgq->msgCount >= msgq->count) + { + USB_OSA_EXIT_CRITICAL(); + return kStatus_USB_OSA_Error; + } + + msgEntity = &msgq->msgs[msgq->index]; + p = (uint32_t *)&msgEntity->msg[0]; + q = (uint32_t *)msg; + + for (count = 0U; count < msgq->msgSize; count++) + { + p[count] = q[count]; + } + + if (0U == msgq->msgCount) + { + msgq->current = msgq->index; + } + + msgq->msgCount++; + msgq->index++; + msgq->index = msgq->index % msgq->count; + + USB_OSA_EXIT_CRITICAL(); + + return kStatus_USB_OSA_Success; +} + +usb_osa_status_t USB_OsaMsgqRecv(usb_osa_msgq_handle handle, void *msg, uint32_t timeout) +{ + usb_osa_msgq_struct_t *msgq = (usb_osa_msgq_struct_t *)handle; + usb_osa_msg_struct_t *msgEntity; + uint32_t *p; + uint32_t *q; + uint32_t count; + USB_OSA_SR_ALLOC(); + + if (!handle) + { + return kStatus_USB_OSA_Error; + } + USB_OSA_ENTER_CRITICAL(); + if (msgq->msgCount < 1U) + { + USB_OSA_EXIT_CRITICAL(); + return kStatus_USB_OSA_TimeOut; + } + + msgEntity = &msgq->msgs[msgq->current]; + q = (uint32_t *)&msgEntity->msg[0]; + p = (uint32_t *)msg; + + for (count = 0U; count < msgq->msgSize; count++) + { + p[count] = q[count]; + } + + msgq->msgCount--; + msgq->current++; + msgq->current = msgq->current % msgq->count; + + USB_OSA_EXIT_CRITICAL(); + + return kStatus_USB_OSA_Success; +} + +usb_osa_status_t USB_OsaMsgqCheck(usb_osa_msgq_handle handle, void *msg) +{ + usb_osa_msgq_struct_t *msgq = (usb_osa_msgq_struct_t *)handle; + uint32_t msgCount; + USB_OSA_SR_ALLOC(); + + if (!handle) + { + return kStatus_USB_OSA_Error; + } + + USB_OSA_ENTER_CRITICAL(); + msgCount = msgq->msgCount; + USB_OSA_EXIT_CRITICAL(); + + if (msgCount) + { + if (kStatus_USB_OSA_Success == USB_OsaMsgqRecv(msgq, msg, 0U)) + { + return kStatus_USB_OSA_Success; + } + } + + return kStatus_USB_OSA_Error; +} diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/osa/usb_osa_bm.h b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/osa/usb_osa_bm.h new file mode 100644 index 000000000..ad0612141 --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/osa/usb_osa_bm.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __USB_OSA_BM_H__ +#define __USB_OSA_BM_H__ + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +#define USB_OSA_SR_ALLOC() uint32_t usbOsaCurrentSr; +#define USB_OSA_ENTER_CRITICAL() USB_OsaEnterCritical(&usbOsaCurrentSr) +#define USB_OSA_EXIT_CRITICAL() USB_OsaExitCritical(usbOsaCurrentSr) + +/******************************************************************************* + * API + ******************************************************************************/ + +#if defined(__cplusplus) +extern "C" { +#endif + +extern void USB_OsaEnterCritical(uint32_t *sr); +extern void USB_OsaExitCritical(uint32_t sr); + +#if defined(__cplusplus) +} +#endif + +#endif /* __USB_OSA_BM_H__ */ diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/phy/Makefile b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/phy/Makefile new file mode 100644 index 000000000..a18326f77 --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/phy/Makefile @@ -0,0 +1,3 @@ +SRC_FILES += usb_phy.c + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/phy/usb_phy.c b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/phy/usb_phy.c new file mode 100644 index 000000000..ab472c214 --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/phy/usb_phy.c @@ -0,0 +1,243 @@ +/* + * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc. + * Copyright 2016 - 2017 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "usb.h" +#include "fsl_device_registers.h" + +#include "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; + } + + if ((controllerId == kUSB_ControllerEhci0) || (controllerId == kUSB_ControllerEhci1)) + { + controllerId = controllerId - kUSB_ControllerEhci0; + } + else if ((controllerId == kUSB_ControllerLpcIp3511Hs0) || (controllerId == kUSB_ControllerLpcIp3511Hs1)) + { + controllerId = controllerId - kUSB_ControllerLpcIp3511Hs0; + } + else if ((controllerId == kUSB_ControllerIp3516Hs0) || (controllerId == kUSB_ControllerIp3516Hs1)) + { + controllerId = controllerId - kUSB_ControllerIp3516Hs0; + } + else + { + } + + 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; + if ((kUSB_ControllerIp3516Hs0 == controllerId) || (kUSB_ControllerIp3516Hs1 == controllerId) || + (kUSB_ControllerLpcIp3511Hs0 == controllerId) || (kUSB_ControllerLpcIp3511Hs0 == controllerId)) + { + usbPhyBase->CTRL_SET = USBPHY_CTRL_SET_ENAUTOCLR_CLKGATE_MASK; + usbPhyBase->CTRL_SET = USBPHY_CTRL_SET_ENAUTOCLR_PHY_PWD_MASK; + } + if (NULL != phyConfig) + { + /* 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)) && (!(defined FSL_FEATURE_USBHSD_USB_RAM))) + /* 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 + if (NULL != phyConfig) + { + /* 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/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/phy/usb_phy.h b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/phy/usb_phy.h new file mode 100644 index 000000000..752df48ea --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/usb/nxp_usb_driver/phy/usb_phy.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016 - 2017 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#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/Ubiquitous/XiUOS/board/stm32f103-nano/.defconfig b/Ubiquitous/XiUOS/board/stm32f103-nano/.defconfig index cfc19af53..bc0280cc8 100644 --- a/Ubiquitous/XiUOS/board/stm32f103-nano/.defconfig +++ b/Ubiquitous/XiUOS/board/stm32f103-nano/.defconfig @@ -26,7 +26,7 @@ CONFIG_BSP_USING_UART1=y # CONFIG_BSP_USING_UART4 is not set # CONFIG_BSP_USING_UART5 is not set # CONFIG_BSP_USING_USB is not set -# CONFIG_BSP_USING_USBH is not set +# CONFIG_BSP_USING_STM32_USBH is not set # # Hardware feature diff --git a/Ubiquitous/XiUOS/board/stm32f407-st-discovery/.defconfig b/Ubiquitous/XiUOS/board/stm32f407-st-discovery/.defconfig index d5f673277..4ecb3a27b 100644 --- a/Ubiquitous/XiUOS/board/stm32f407-st-discovery/.defconfig +++ b/Ubiquitous/XiUOS/board/stm32f407-st-discovery/.defconfig @@ -26,7 +26,7 @@ CONFIG_BSP_USING_UART3=y # CONFIG_BSP_USING_UART4 is not set # CONFIG_BSP_USING_UART5 is not set #CONFIG_BSP_USING_USB is not set -#CONFIG_BSP_USING_USBH is not set +#CONFIG_BSP_USING_STM32_USBH is not set # # Hardware feature diff --git a/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/Kconfig b/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/Kconfig index 4bbfcb82c..283313b3b 100755 --- a/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/Kconfig +++ b/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/Kconfig @@ -98,7 +98,7 @@ endif menuconfig BSP_USING_USB bool "Using USB device" default n -select BSP_USING_USBH +select BSP_USING_STM32_USBH select RESOURCES_USB select RESOURCES_USB_HOST select USBH_MSTORAGE diff --git a/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/usb/Kconfig b/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/usb/Kconfig index 1aeabc314..69d2536d9 100644 --- a/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/usb/Kconfig +++ b/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/usb/Kconfig @@ -1,4 +1,4 @@ -config BSP_USING_USBH +config BSP_USING_STM32_USBH bool "Using usb host" default y config USB_BUS_NAME diff --git a/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/usb/usbh.c b/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/usb/usbh.c index 6363fd221..98f45734e 100644 --- a/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/usb/usbh.c +++ b/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/usb/usbh.c @@ -31,7 +31,7 @@ Modification: *************************************************/ #include -#include +#include #include #include #include diff --git a/Ubiquitous/XiUOS/board/stm32f407zgt6/.defconfig b/Ubiquitous/XiUOS/board/stm32f407zgt6/.defconfig index c9163eae2..ac3157109 100644 --- a/Ubiquitous/XiUOS/board/stm32f407zgt6/.defconfig +++ b/Ubiquitous/XiUOS/board/stm32f407zgt6/.defconfig @@ -26,7 +26,7 @@ CONFIG_BSP_USING_UART3=y # CONFIG_BSP_USING_UART4 is not set # CONFIG_BSP_USING_UART5 is not set #CONFIG_BSP_USING_USB is not set -#CONFIG_BSP_USING_USBH is not set +#CONFIG_BSP_USING_STM32_USBH is not set # # Hardware feature diff --git a/Ubiquitous/XiUOS/kernel/thread/init.c b/Ubiquitous/XiUOS/kernel/thread/init.c index 94a3d1881..6fa7a56ab 100644 --- a/Ubiquitous/XiUOS/kernel/thread/init.c +++ b/Ubiquitous/XiUOS/kernel/thread/init.c @@ -27,7 +27,7 @@ #include #include -#ifdef BSP_USING_USBH +#ifdef BSP_USING_USB #include "connect_usb.h" #endif @@ -123,9 +123,12 @@ struct InitSequenceDesc env_init[] = }; struct InitSequenceDesc communication_init[] = { -#ifdef BSP_USING_USBH +#ifdef BSP_USING_STM32_USBH { "STM32USBHostRegister", STM32USBHostRegister }, { "hw usb", Stm32HwUsbInit }, +#endif +#ifdef BSP_USING_NXP_USBH + { "nxp hw usb", Imrt1052HwUsbHostInit }, #endif { " NONE ", NONE }, }; diff --git a/Ubiquitous/XiUOS/path_kernel.mk b/Ubiquitous/XiUOS/path_kernel.mk index 58dc83c47..ace806d36 100755 --- a/Ubiquitous/XiUOS/path_kernel.mk +++ b/Ubiquitous/XiUOS/path_kernel.mk @@ -176,6 +176,11 @@ KERNELPATHS :=-I$(BSP_ROOT) \ -I$(BSP_ROOT)/third_party_driver/include \ -I$(BSP_ROOT)/third_party_driver/sdio/sdmmc/inc \ -I$(BSP_ROOT)/third_party_driver/sdio/sdmmc/port \ + -I$(BSP_ROOT)/third_party_driver/usb/nxp_usb_driver/host \ + -I$(BSP_ROOT)/third_party_driver/usb/nxp_usb_driver/host/class \ + -I$(BSP_ROOT)/third_party_driver/usb/nxp_usb_driver/include \ + -I$(BSP_ROOT)/third_party_driver/usb/nxp_usb_driver/osa \ + -I$(BSP_ROOT)/third_party_driver/usb/nxp_usb_driver/phy \ -I$(BSP_ROOT)/third_party_driver/ethernet \ -I$(BSP_ROOT)/third_party_driver/ethernet/ksz8081 \ -I$(BSP_ROOT)/third_party_driver/MIMXRT1052 \ diff --git a/Ubiquitous/XiUOS/resources/include/device.h b/Ubiquitous/XiUOS/resources/include/device.h index db9799b2a..48280f3a4 100644 --- a/Ubiquitous/XiUOS/resources/include/device.h +++ b/Ubiquitous/XiUOS/resources/include/device.h @@ -53,7 +53,7 @@ #include #include #ifdef RESOURCES_USB_HOST -#include +#include #endif #endif diff --git a/Ubiquitous/XiUOS/resources/include/usb_common.h b/Ubiquitous/XiUOS/resources/include/stm32_usb_common.h similarity index 99% rename from Ubiquitous/XiUOS/resources/include/usb_common.h rename to Ubiquitous/XiUOS/resources/include/stm32_usb_common.h index 45ebd6f4d..a7e3a0229 100644 --- a/Ubiquitous/XiUOS/resources/include/usb_common.h +++ b/Ubiquitous/XiUOS/resources/include/stm32_usb_common.h @@ -11,7 +11,7 @@ */ /** -* @file usb_common.h +* @file stm32_usb_common.h * @brief define usb function and struct * @version 1.0 * @author AIIT XUOS Lab @@ -19,7 +19,7 @@ */ /************************************************* -File name: usb_common.h +File name: stm32_usb_common.h Description: define usb function and common struct Others: take RT-Thread v4.0.2/components/drivers/include/drivers/usb_common.h for references https://github.com/RT-Thread/rt-thread/tree/v4.0.2 diff --git a/Ubiquitous/XiUOS/resources/include/usb_host.h b/Ubiquitous/XiUOS/resources/include/stm32_usb_host.h similarity index 98% rename from Ubiquitous/XiUOS/resources/include/usb_host.h rename to Ubiquitous/XiUOS/resources/include/stm32_usb_host.h index 473b647fb..c79ba3086 100644 --- a/Ubiquitous/XiUOS/resources/include/usb_host.h +++ b/Ubiquitous/XiUOS/resources/include/stm32_usb_host.h @@ -9,7 +9,7 @@ */ /** -* @file usb_host.h +* @file stm32_usb_host.h * @brief define usb host function and struct * @version 1.0 * @author AIIT XUOS Lab @@ -17,7 +17,7 @@ */ /************************************************* -File name: usb_host.h +File name: stm32_usb_host.h Description: define usb host function and struct Others: take RT-Thread v4.0.2/components/drivers/include/drivers/usb_host.h for references https://github.com/RT-Thread/rt-thread/tree/v4.0.2 @@ -34,7 +34,7 @@ Modification: #include -#include +#include #ifdef __cplusplus extern "C" { diff --git a/Ubiquitous/XiUOS/resources/usb/third_party_usb/Makefile b/Ubiquitous/XiUOS/resources/usb/third_party_usb/Makefile index 06f346bbc..97642cfd3 100644 --- a/Ubiquitous/XiUOS/resources/usb/third_party_usb/Makefile +++ b/Ubiquitous/XiUOS/resources/usb/third_party_usb/Makefile @@ -1,3 +1,5 @@ -SRC_DIR := usbhost +ifeq ($(CONFIG_BSP_USING_STM32_USBH),y) + SRC_DIR := usbhost +endif include $(KERNEL_ROOT)/compiler.mk \ No newline at end of file diff --git a/Ubiquitous/XiUOS/resources/usb/third_party_usb/usbhost/class/mass.c b/Ubiquitous/XiUOS/resources/usb/third_party_usb/usbhost/class/mass.c index ad543b51f..23403252b 100644 --- a/Ubiquitous/XiUOS/resources/usb/third_party_usb/usbhost/class/mass.c +++ b/Ubiquitous/XiUOS/resources/usb/third_party_usb/usbhost/class/mass.c @@ -30,7 +30,7 @@ Modification: *************************************************/ #include -#include +#include #include "mass.h" #ifdef USBH_MSTORAGE diff --git a/Ubiquitous/XiUOS/resources/usb/third_party_usb/usbhost/class/udisk.c b/Ubiquitous/XiUOS/resources/usb/third_party_usb/usbhost/class/udisk.c index 4b02e1394..200b6e0b3 100644 --- a/Ubiquitous/XiUOS/resources/usb/third_party_usb/usbhost/class/udisk.c +++ b/Ubiquitous/XiUOS/resources/usb/third_party_usb/usbhost/class/udisk.c @@ -31,7 +31,7 @@ Modification: #include -#include +#include #include "mass.h" #if defined(FS_VFS) diff --git a/Ubiquitous/XiUOS/resources/usb/third_party_usb/usbhost/core/core.c b/Ubiquitous/XiUOS/resources/usb/third_party_usb/usbhost/core/core.c index 26c594327..2ad722538 100644 --- a/Ubiquitous/XiUOS/resources/usb/third_party_usb/usbhost/core/core.c +++ b/Ubiquitous/XiUOS/resources/usb/third_party_usb/usbhost/core/core.c @@ -30,7 +30,7 @@ Modification: *************************************************/ #include -#include +#include static struct uinstance dev[USB_MAX_DEVICE]; diff --git a/Ubiquitous/XiUOS/resources/usb/third_party_usb/usbhost/core/driver.c b/Ubiquitous/XiUOS/resources/usb/third_party_usb/usbhost/core/driver.c index 56260f9b2..16e636788 100644 --- a/Ubiquitous/XiUOS/resources/usb/third_party_usb/usbhost/core/driver.c +++ b/Ubiquitous/XiUOS/resources/usb/third_party_usb/usbhost/core/driver.c @@ -31,7 +31,7 @@ Modification: #include #include -#include +#include static DoubleLinklistType DriverList; diff --git a/Ubiquitous/XiUOS/resources/usb/third_party_usb/usbhost/core/hub.c b/Ubiquitous/XiUOS/resources/usb/third_party_usb/usbhost/core/hub.c index 52d2c8121..edf4480cb 100644 --- a/Ubiquitous/XiUOS/resources/usb/third_party_usb/usbhost/core/hub.c +++ b/Ubiquitous/XiUOS/resources/usb/third_party_usb/usbhost/core/hub.c @@ -30,7 +30,7 @@ Modification: *************************************************/ #include -#include +#include #define USB_THREAD_STACK_SIZE 4096 diff --git a/Ubiquitous/XiUOS/resources/usb/third_party_usb/usbhost/core/usbhost.c b/Ubiquitous/XiUOS/resources/usb/third_party_usb/usbhost/core/usbhost.c index f257a4ff5..1026ae308 100644 --- a/Ubiquitous/XiUOS/resources/usb/third_party_usb/usbhost/core/usbhost.c +++ b/Ubiquitous/XiUOS/resources/usb/third_party_usb/usbhost/core/usbhost.c @@ -30,7 +30,7 @@ Modification: *************************************************/ #include -#include +#include #define USB_HOST_CONTROLLER_NAME "usbh"