feat add third_party_driver/usb for hc32f4a0 board, compile OK

This commit is contained in:
Liu_Weichao 2022-11-08 14:15:23 +08:00
parent 636f803b7b
commit 9a818b1ef4
42 changed files with 6765 additions and 1 deletions

View File

@ -42,6 +42,10 @@ Modification:
#include <connect_spi.h> #include <connect_spi.h>
#endif #endif
#ifdef BSP_USING_USB
#include <connect_usb.h>
#endif
extern void entry(void); extern void entry(void);
extern int HwUsartInit(); extern int HwUsartInit();
@ -132,6 +136,9 @@ struct InitSequenceDesc _board_init[] =
#endif #endif
#ifdef BSP_USING_SPI #ifdef BSP_USING_SPI
{ "spi", HwSpiInit }, { "spi", HwSpiInit },
#endif
#ifdef BSP_USING_USB
{ "usb", HwUsbHostInit },
#endif #endif
{ " NONE ", NONE }, { " NONE ", NONE },
}; };

View File

@ -21,3 +21,11 @@ menuconfig BSP_USING_SDIO
if BSP_USING_SDIO if BSP_USING_SDIO
source "$BSP_DIR/third_party_driver/sdio/Kconfig" source "$BSP_DIR/third_party_driver/sdio/Kconfig"
endif 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

View File

@ -12,4 +12,8 @@ ifeq ($(CONFIG_BSP_USING_SDIO),y)
SRC_DIR += sdio SRC_DIR += sdio
endif endif
ifeq ($(CONFIG_BSP_USING_USB),y)
SRC_DIR += usb
endif
include $(KERNEL_ROOT)/compiler.mk include $(KERNEL_ROOT)/compiler.mk

View File

@ -101,7 +101,7 @@ extern "C"
#define LL_TMRA_ENABLE (DDL_ON) #define LL_TMRA_ENABLE (DDL_ON)
#define LL_TRNG_ENABLE (DDL_ON) #define LL_TRNG_ENABLE (DDL_ON)
#define LL_USART_ENABLE (DDL_ON) #define LL_USART_ENABLE (DDL_ON)
#define LL_USB_ENABLE (DDL_OFF) #define LL_USB_ENABLE (DDL_ON)
#define LL_VREF_ENABLE (DDL_OFF) #define LL_VREF_ENABLE (DDL_OFF)
#define LL_WDT_ENABLE (DDL_ON) #define LL_WDT_ENABLE (DDL_ON)

View File

@ -12,4 +12,8 @@ ifeq ($(CONFIG_BSP_USING_SPI),y)
SRC_FILES += hc32_ll_spi.c SRC_FILES += hc32_ll_spi.c
endif endif
ifeq ($(CONFIG_BSP_USING_USB),y)
SRC_FILES += hc32_ll_usb.c
endif
include $(KERNEL_ROOT)/compiler.mk include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,54 @@
/*
* 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 hc32f4a0-board usb function and struct
* @version 2.0
* @author AIIT XUOS Lab
* @date 2022-11-07
*/
#ifndef CONNECT_USB_H
#define CONNECT_USB_H
#include <device.h>
#include <hc32_ll_utility.h>
#include <hc32_ll_gpio.h>
#include <usb_lib.h>
#include <usb_host_user.h>
#include <usb_host_driver.h>
#include <usb_host_core.h>
#include <usb_host_msc_class.h>
#include <usb_host_msc_scsi.h>
#include <usb_host_msc_bot.h>
#include <usb_host_int.h>
#if defined(FS_VFS)
#include <iot-vfs.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
#define USB_HOST_STACK_SIZE 4096
#define USB_SINGLE_BLOCK_SIZE 512
int HwUsbHostInit(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,15 @@
config BSP_USING_HC32_USBH
bool "Using usb host by HC32 library"
default y
if BSP_USING_HC32_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

View File

@ -0,0 +1,5 @@
SRC_DIR := hc32_usb_driver
SRC_FILES := connect_usb.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,227 @@
/*
* 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.c
* @brief support hc32f4a0-board usb function and register to bus framework
* @version 2.0
* @author AIIT XUOS Lab
* @date 2022-11-07
*/
/*************************************************
File name: connect_usb.c
Description: support hc32f4a0-board usb function and register to bus framework
Others:
History:
1. Date: 2022-11-07
Author: AIIT XUOS Lab
Modification:
1. support hc32f4a0-board usb configure, write and read
2. support hc32f4a0-board usb bus device and driver register
*************************************************/
#include <connect_usb.h>
usb_core_instance usb_app_instance;
USBH_HOST usb_app_host;
#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_HOST_MSC_STATUS status = USB_HOST_MSC_OK;
if (host_driver_ifdevconnected(&usb_app_instance) != 0UL) {
do {
status = usb_host_msc_Read10(&usb_app_instance, (uint8 *)read_param->buffer, read_param->pos, USB_SINGLE_BLOCK_SIZE * (uint32_t)read_param->size);
usb_host_msc_botxferprocess(&usb_app_instance, &usb_app_host);
if (host_driver_ifdevconnected(&usb_app_instance) == 0UL) {
return 0;
}
} while (USB_HOST_MSC_BUSY == status);
}
if (USB_HOST_MSC_OK == status) {
return read_param->size;
}
return 0;
}
static uint32 UsbHostWrite(void *dev, struct BusBlockWriteParam *write_param)
{
USB_HOST_MSC_STATUS status = USB_HOST_MSC_OK;
if (host_driver_ifdevconnected(&usb_app_instance) != 0UL) {
do {
status = usb_host_msc_Write10(&usb_app_instance, (uint8 *)write_param->buffer, write_param->pos, USB_SINGLE_BLOCK_SIZE * (uint32_t)write_param->size);
usb_host_msc_botxferprocess(&usb_app_instance, &usb_app_host);
if (host_driver_ifdevconnected(&usb_app_instance) == 0UL) {
return 0;
}
} while (USB_HOST_MSC_BUSY == status);
}
if (USB_HOST_MSC_OK == status) {
return write_param->size;
}
return 0;
}
static int UsbControl(struct HardwareDev *dev, struct HalDevBlockParam *block_param)
{
NULL_PARAM_CHECK(dev);
if (OPER_BLK_GETGEOME == block_param->cmd) {
block_param->dev_block.size_perbank = USB_SINGLE_BLOCK_SIZE;
block_param->dev_block.block_size = USB_SINGLE_BLOCK_SIZE;
block_param->dev_block.bank_num = USB_HOST_MSC_Param.MSC_Capacity;
}
return EOK;
}
/*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) {
usb_host_mainprocess(&usb_app_instance, &usb_app_host);
}
}
/*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;
usb_device.haldev.dev_block_control = UsbControl;
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;
}
int HwUsbHostInit(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));
usb_host_init(&usb_app_instance, &usb_app_host, &USBH_MSC_cb, &USR_cb);
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;
}

View File

@ -0,0 +1,5 @@
SRC_FILES := usb_host_user.c usb_bsp.c
SRC_DIR := usb_host_lib
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,104 @@
/**
*******************************************************************************
* @file usb/usb_host_msc/source/usb_app_conf.h
* @brief low level driver configuration
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
@endverbatim
*******************************************************************************
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
#ifndef __USB_APP_CONF_H__
#define __USB_APP_CONF_H__
/* C binding of definitions if building with C++ compiler */
#ifdef __cplusplus
extern "C"
{
#endif
/*******************************************************************************
* Include files
******************************************************************************/
/* USB MODE CONFIGURATION */
/*
USB_FS_MODE, USB_HS_MODE, USB_HS_EXTERNAL_PHY defined comment
(1) If only defined USB_FS_MODE:
MCU USBFS core work in full speed using internal PHY.
(2) If only defined USB_HS_MODE:
MCU USBHS core work in full speed using internal PHY.
(3) If both defined USB_HS_MODE && USB_HS_EXTERNAL_PHY
MCU USBHS core work in high speed using external PHY.
(4) Other combination:
Not support, forbid!!
*/
//#define USB_HS_MODE
#define USB_FS_MODE
#define USE_HOST_MODE
#ifdef USB_HS_MODE
#define USB_HS_EXTERNAL_PHY
#endif
#ifndef USB_HS_MODE
#ifndef USB_FS_MODE
#error "USB_HS_MODE or USB_FS_MODE should be defined"
#endif
#endif
#ifndef USE_DEVICE_MODE
#ifndef USE_HOST_MODE
#error "USE_DEVICE_MODE or USE_HOST_MODE should be defined"
#endif
#endif
/* USB FIFO CONFIGURATION */
#ifdef USB_FS_MODE
#define RX_FIFO_FS_SIZE (128U)
#define TXH_NP_FS_FIFOSIZ (32U)
#define TXH_P_FS_FIFOSIZ (64U)
#if ((RX_FIFO_FS_SIZE + TXH_NP_FS_FIFOSIZ + TXH_P_FS_FIFOSIZ) > 640U)
#error "The USB max FIFO size is 640 x 4 Bytes!"
#endif
#endif
#ifdef USB_HS_MODE
#define RX_FIFO_HS_SIZE (512U)
#define TXH_NP_HS_FIFOSIZ (128U)
#define TXH_P_HS_FIFOSIZ (256U)
#if ((RX_FIFO_FS_SIZE + TXH_NP_FS_FIFOSIZ + TXH_P_FS_FIFOSIZ) > 2048U)
#error "The USB max FIFO size is 2048 x 4 Bytes!"
#endif
#endif
/* FUNCTION CONFIGURATION */
#define USBH_MAX_NUM_INTERFACES (3U)
#define USBH_MAX_NUM_ENDPOINTS (2U)
/* CONFIGURATION FOR MSC */
#define USBH_MSC_MPS_SIZE (0x40U)
//#define USB_MSC_FAT_VALID
#ifdef __cplusplus
}
#endif
#endif /* __USB_APP_CONF_H__ */
/*******************************************************************************
* EOF (not truncated)
******************************************************************************/

View File

@ -0,0 +1,156 @@
/**
*******************************************************************************
* @file usb/usb_host_msc/source/usb_bsp.c
* @brief BSP function for USB example
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
@endverbatim
*******************************************************************************
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
/**
* @file usb_bsp.c
* @brief support hc32f4a0-board usb bsp function
* @version 2.0
* @author AIIT XUOS Lab
* @date 2022-11-08
*/
/*************************************************
File name: usb_bsp.c
Description: support hc32f4a0-board usb bsp function
Others:
History:
1. Date: 2022-11-08
Author: AIIT XUOS Lab
Modification:
1. support hc32f4a0-board usb IO configure
2. support hc32f4a0-board usb irq define
*************************************************/
#include <device.h>
#include "usb_bsp.h"
#include <usb_host_int.h>
extern usb_core_instance usb_app_instance;
/* USBFS Core*/
#define USB_DP_PORT (GPIO_PORT_A)
#define USB_DP_PIN (GPIO_PIN_12)
#define USB_DM_PORT (GPIO_PORT_A)
#define USB_DM_PIN (GPIO_PIN_11)
#define USB_DRVVBUS_PORT (GPIO_PORT_C)
#define USB_DRVVBUS_PIN (GPIO_PIN_09)
#define USB_VBUSDET_PORT (GPIO_PORT_A)
#define USB_VBUSDET_PIN (GPIO_PIN_09)
#define USB_OC_PORT (GPIO_PORT_D)
#define USB_OC_PIN (GPIO_PIN_15)
//USB HOST ISR
static void USB_IRQ_Handler(void)
{
x_base lock = 0;
lock = DISABLE_INTERRUPT();
usb_host_isr(&usb_app_instance);
ENABLE_INTERRUPT(lock);
}
void usb_bsp_init(usb_core_instance *pdev)
{
stc_gpio_init_t stcGpioCfg;
/* SysTick configuration */
(void)SysTick_Init(1000U);
NVIC_SetPriority(SysTick_IRQn, DDL_IRQ_PRIO_14);
/* USB clock source configurate */
CLK_SetUSBClockSrc(CLK_USBCLK_SYSCLK_DIV5);
(void)GPIO_StructInit(&stcGpioCfg);
#ifdef USB_FS_MODE
stcGpioCfg.u16PinAttr = PIN_ATTR_ANALOG;
(void)GPIO_Init(USB_DM_PORT, USB_DM_PIN, &stcGpioCfg);
(void)GPIO_Init(USB_DP_PORT, USB_DP_PIN, &stcGpioCfg);
// stcGpioInit.u16PinState = PIN_STAT_RST;
// stcGpioInit.u16PinDir = PIN_DIR_OUT;
// (void)GPIO_Init(USB_DRVVBUS_PORT, USB_DRVVBUS_PIN, &stcGpioInit);
// GPIO_SetPins(USB_DRVVBUS_PORT, USB_DRVVBUS_PIN);
GPIO_SetFunc(USB_DRVVBUS_PORT, USB_DRVVBUS_PIN, GPIO_FUNC_10); /* VBUS */
FCG_Fcg1PeriphClockCmd(FCG1_PERIPH_USBFS, ENABLE);
#endif
}
void usb_bsp_nvicconfig(void)
{
stc_irq_signin_config_t stcIrqRegiConf;
/* Register INT_SRC_USBFS_GLB Int to Vect.No.030 */
stcIrqRegiConf.enIRQn = INT030_IRQn;
/* Select interrupt function */
#ifdef USB_FS_MODE
stcIrqRegiConf.enIntSrc = INT_SRC_USBFS_GLB;
#else
stcIrqRegiConf.enIntSrc = INT_SRC_USBHS_GLB;
#endif
/* Callback function */
stcIrqRegiConf.pfnCallback = &USB_IRQ_Handler;
/* Registration IRQ */
(void)INTC_IrqSignIn(&stcIrqRegiConf);
/* Clear Pending */
NVIC_ClearPendingIRQ(stcIrqRegiConf.enIRQn);
/* Set priority */
NVIC_SetPriority(stcIrqRegiConf.enIRQn, DDL_IRQ_PRIO_15);
/* Enable NVIC */
NVIC_EnableIRQ(stcIrqRegiConf.enIRQn);
}
void usb_udelay(const uint32_t usec)
{
__IO uint32_t i;
uint32_t j;
j = (HCLK_VALUE + 1000000UL - 1UL) / 1000000UL * usec;
for (i = 0UL; i < j; i++) {
}
}
void usb_mdelay(const uint32_t msec)
{
SysTick_Delay(msec);
}
/**
* @brief Configures the IO for the Vbus and OverCurrent
* @param [in] pdev device instance
* @retval None
*/
void usb_bsp_cfgvbus(LL_USB_TypeDef *USBx)
{
}
/**
* @brief Drive vbus
* @param [in] pdev device instance
* @param [in] state the vbus state it would be.
* @retval None
*/
void usb_bsp_drivevbus(LL_USB_TypeDef *USBx, uint8_t state)
{
}

View File

@ -0,0 +1,104 @@
/**
*******************************************************************************
* @file usb/usb_host_msc/source/usb_bsp.h
* @brief Head file for usb_bsp.c
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
@endverbatim
*******************************************************************************
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
/**
* @file usb_bsp.h
* @brief support hc32f4a0-board usb bsp function
* @version 2.0
* @author AIIT XUOS Lab
* @date 2022-11-08
*/
/*************************************************
File name: usb_bsp.h
Description: support hc32f4a0-board usb bsp function
Others:
History:
1. Date: 2022-11-08
Author: AIIT XUOS Lab
Modification:
*************************************************/
#ifndef USB_BSP_H
#define USB_BSP_H
/* C binding of definitions if building with C++ compiler */
#ifdef __cplusplus
extern "C"
{
#endif
/*******************************************************************************
* Include files
******************************************************************************/
#include <usb_lib.h>
/**
* @addtogroup HC32F4A0_DDL_Applications
* @{
*/
/**
* @addtogroup USB_Host_Msc
* @{
*/
/*******************************************************************************
* Global type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Global pre-processor symbols/macros ('#define')
******************************************************************************/
/*******************************************************************************
* Global variable definitions ('extern')
******************************************************************************/
/*******************************************************************************
Global function prototypes (definition in C source)
******************************************************************************/
extern void usb_bsp_init(usb_core_instance *pdev);
extern void usb_udelay(const uint32_t usec);
extern void usb_mdelay(const uint32_t msec);
extern void usb_bsp_nvicconfig(void);
#ifdef USE_HOST_MODE
extern void usb_bsp_cfgvbus(LL_USB_TypeDef *USBx);
extern void usb_bsp_drivevbus(LL_USB_TypeDef *USBx, uint8_t state);
#endif
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USB_BSP_H__ */
/*******************************************************************************
* EOF (not truncated)
******************************************************************************/

View File

@ -0,0 +1,3 @@
SRC_DIR := host_class host_core
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,3 @@
SRC_DIR := msc
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,3 @@
SRC_FILES := usb_host_msc_bot.c usb_host_msc_class.c usb_host_msc_scsi.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,449 @@
/**
*******************************************************************************
* @file usb_host_msc_bot.c
* @brief mass storage related functions
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
@endverbatim
*******************************************************************************
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
/*******************************************************************************
* Include files
******************************************************************************/
#include "usb_host_msc_class.h"
#include "usb_host_msc_scsi.h"
#include "usb_host_msc_bot.h"
#include "usb_host_ctrltrans.h"
#include "usb_host_def.h"
#include "usb_host_int.h"
#include "usb_host_driver.h"
/**
* @addtogroup LL_USB_LIB
* @{
*/
/**
* @addtogroup LL_USB_HOST_CLASS
* @{
*/
/**
* @addtogroup LL_USB_HOST_MSC USB Host MSC
* @{
*/
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
#ifdef USB_INTERNAL_DMA_ENABLED
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
#pragma data_alignment=4
#endif
#endif /* USB_INTERNAL_DMA_ENABLED */
__USB_ALIGN_BEGIN HOST_CSW_PACKET_TypeDef USBH_MSC_CSWData;
USB_HOST_BOTXFER_TypeDef USBH_MSC_BOTXferParam;
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
#ifdef USB_INTERNAL_DMA_ENABLED
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
#pragma data_alignment=4
#endif
#endif /* USB_INTERNAL_DMA_ENABLED */
__USB_ALIGN_BEGIN HostCBWPkt_TypeDef USBH_MSC_CBWData;
static uint32_t BOTStallErrorCount; /* Keeps count of STALL Error Cases*/
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/**
* @brief initializes original state of the mass storage parameters
* @param [in] pdev device instance
* @retval None
*/
void usb_host_msc_init(usb_core_instance *pdev)
{
if (host_driver_ifdevconnected(pdev) != 0UL) {
USBH_MSC_CBWData.field.CBWSignature = HOST_MSC_BOT_CBW_SIGNATURE;
USBH_MSC_CBWData.field.CBWTag = HOST_MSC_BOT_CBW_TAG;
USBH_MSC_CBWData.field.CBWLUN = 0U;
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_SEND;
}
BOTStallErrorCount = 0UL;
MSCErrorCount = 0U;
}
/**
* @brief manages the different states of BOT transfer and updates the
* status for the upper layer.
* @param [in] pdev device instance
* @param [in] phost host state set
* @retval None
*/
void usb_host_msc_botxferprocess(usb_core_instance *pdev, USBH_HOST *phost)
{
uint8_t xferDirection, index;
static uint32_t remainingDataLength;
static uint8_t *datapointer, *datapointer_prev;
static uint8_t error_direction;
HOST_STATUS status;
HOST_CH_XFER_STATE URB_Status;
if (host_driver_ifdevconnected(pdev) != 0UL) {
switch (USBH_MSC_BOTXferParam.BOTState) {
case HOST_MSC_SEND_CBW:
/* send a CBW */
usb_host_sendbulkdata(pdev,
&USBH_MSC_CBWData.CBWArray[0],
HOST_MSC_BOT_CBW_PACKET_LENGTH,
MSC_Machine.hc_num_out);
USBH_MSC_BOTXferParam.BOTStateBkp = HOST_MSC_SEND_CBW;
USBH_MSC_BOTXferParam.BOTState = HOST_MSC_SENT_CBW;
break;
case HOST_MSC_SENT_CBW:
URB_Status = host_driver_getxferstate(pdev, MSC_Machine.hc_num_out);
switch (URB_Status) {
case HOST_CH_XFER_DONE:
BOTStallErrorCount = 0U;
USBH_MSC_BOTXferParam.BOTStateBkp = HOST_MSC_SENT_CBW;
/* If the CBW packet is sent successful, then update the state */
xferDirection = (USBH_MSC_CBWData.field.CBWFlags & USB_REQ_DIR_MASK);
if (USBH_MSC_CBWData.field.CBWTransferLength != 0UL) {
remainingDataLength = USBH_MSC_CBWData.field.CBWTransferLength ;
datapointer = USBH_MSC_BOTXferParam.pRxTxBuff;
datapointer_prev = datapointer;
/* If there has data transfer stage, update the direction whether it is D2H or H2D */
if (xferDirection == USB_D2H) {
USBH_MSC_BOTXferParam.BOTState = HOST_MSC_BOT_DATAIN_STATE;
} else {
USBH_MSC_BOTXferParam.BOTState = HOST_MSC_BOT_DATAOUT_STATE;
}
} else {
/* If there has not data transfer stage also update the state */
USBH_MSC_BOTXferParam.BOTState = HOST_MSC_RECEIVE_CSW_STATE;
}
break;
case HOST_CH_XFER_UNREADY:
USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOTXferParam.BOTStateBkp;
break;
case HOST_CH_XFER_STALL:
error_direction = HOST_MSC_DIR_OUT;
USBH_MSC_BOTXferParam.BOTState = HOST_MSC_BOT_ERROR_OUT;
break;
default:
break;
}
break;
case HOST_MSC_BOT_DATAIN_STATE:
URB_Status = host_driver_getxferstate(pdev, MSC_Machine.hc_num_in);
if ((URB_Status == HOST_CH_XFER_DONE) \
|| (USBH_MSC_BOTXferParam.BOTStateBkp != HOST_MSC_BOT_DATAIN_STATE)) {
BOTStallErrorCount = 0U;
USBH_MSC_BOTXferParam.BOTStateBkp = HOST_MSC_BOT_DATAIN_STATE;
if (remainingDataLength > MSC_Machine.MSC_BulkInEpSize) {
usb_host_recvbulkdata(pdev,
datapointer,
MSC_Machine.MSC_BulkInEpSize,
MSC_Machine.hc_num_in);
remainingDataLength -= MSC_Machine.MSC_BulkInEpSize;
datapointer = datapointer + MSC_Machine.MSC_BulkInEpSize;
} else if (remainingDataLength == 0UL) {
/* If value was 0, and successful transfer, then change the state */
USBH_MSC_BOTXferParam.BOTState = HOST_MSC_RECEIVE_CSW_STATE;
} else {
usb_host_recvbulkdata(pdev,
datapointer,
(uint16_t)remainingDataLength,
MSC_Machine.hc_num_in);
remainingDataLength = 0UL;
}
} else if (URB_Status == HOST_CH_XFER_STALL) {
error_direction = HOST_MSC_DIR_IN;
USBH_MSC_BOTXferParam.BOTState = HOST_MSC_BOT_ERROR_IN;
USBH_MSC_BOTXferParam.BOTStateBkp = HOST_MSC_RECEIVE_CSW_STATE;
} else {
;
}
break;
case HOST_MSC_BOT_DATAOUT_STATE:
URB_Status = host_driver_getxferstate(pdev, MSC_Machine.hc_num_out);
if (URB_Status == HOST_CH_XFER_DONE) {
BOTStallErrorCount = 0UL;
USBH_MSC_BOTXferParam.BOTStateBkp = HOST_MSC_BOT_DATAOUT_STATE;
if (remainingDataLength > MSC_Machine.MSC_BulkOutEpSize) {
usb_host_sendbulkdata(pdev,
datapointer,
MSC_Machine.MSC_BulkOutEpSize,
MSC_Machine.hc_num_out);
datapointer_prev = datapointer;
datapointer = datapointer + MSC_Machine.MSC_BulkOutEpSize;
remainingDataLength = remainingDataLength - MSC_Machine.MSC_BulkOutEpSize;
} else if (remainingDataLength == 0UL) {
USBH_MSC_BOTXferParam.BOTState = HOST_MSC_RECEIVE_CSW_STATE;
} else {
usb_host_sendbulkdata(pdev,
datapointer,
(uint16_t)remainingDataLength,
MSC_Machine.hc_num_out);
remainingDataLength = 0UL;
}
} else if (URB_Status == HOST_CH_XFER_UNREADY) {
if (datapointer != datapointer_prev) {
usb_host_sendbulkdata(pdev,
(datapointer - MSC_Machine.MSC_BulkOutEpSize),
MSC_Machine.MSC_BulkOutEpSize,
MSC_Machine.hc_num_out);
} else {
usb_host_sendbulkdata(pdev,
datapointer,
MSC_Machine.MSC_BulkOutEpSize,
MSC_Machine.hc_num_out);
}
} else if (URB_Status == HOST_CH_XFER_STALL) {
error_direction = HOST_MSC_DIR_OUT;
USBH_MSC_BOTXferParam.BOTState = HOST_MSC_BOT_ERROR_OUT;
USBH_MSC_BOTXferParam.BOTStateBkp = HOST_MSC_RECEIVE_CSW_STATE;
} else {
;
}
break;
case HOST_MSC_RECEIVE_CSW_STATE:
USBH_MSC_BOTXferParam.BOTStateBkp = HOST_MSC_RECEIVE_CSW_STATE;
USBH_MSC_BOTXferParam.pRxTxBuff = USBH_MSC_CSWData.CSWArray;
USBH_MSC_BOTXferParam.DataLength = HOST_MSC_CSW_MAX_LENGTH;
for (index = 0U; index < HOST_MSC_CSW_LENGTH; index++) {
USBH_MSC_CSWData.CSWArray[index] = 0U;
}
USBH_MSC_CSWData.CSWArray[0] = 0U;
usb_host_recvbulkdata(pdev,
USBH_MSC_BOTXferParam.pRxTxBuff,
HOST_MSC_CSW_MAX_LENGTH,
MSC_Machine.hc_num_in);
USBH_MSC_BOTXferParam.BOTState = HOST_MSC_DECODE_CSW;
break;
case HOST_MSC_DECODE_CSW:
URB_Status = host_driver_getxferstate(pdev, MSC_Machine.hc_num_in);
if (URB_Status == HOST_CH_XFER_DONE) {
BOTStallErrorCount = 0UL;
USBH_MSC_BOTXferParam.BOTStateBkp = HOST_MSC_RECEIVE_CSW_STATE;
USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOTXferParam.MSCStateCurrent ;
USBH_MSC_BOTXferParam.BOTXferStatus = usb_host_msc_cswdecode(pdev, phost);
} else if (URB_Status == HOST_CH_XFER_STALL) {
error_direction = HOST_MSC_DIR_IN;
USBH_MSC_BOTXferParam.BOTState = HOST_MSC_BOT_ERROR_IN;
} else {
;
}
break;
case HOST_MSC_BOT_ERROR_IN:
status = usb_host_msc_botabort(pdev, phost, HOST_MSC_DIR_IN);
if (status == HSTATUS_OK) {
if (error_direction == HOST_MSC_BOTH_DIR) {
USBH_MSC_BOTXferParam.BOTState = HOST_MSC_BOT_ERROR_OUT;
} else {
/* switch back to the original state */
USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOTXferParam.BOTStateBkp;
}
} else if (status == HSTATUS_UNRECOVERED_ERROR) {
/* This means that there is a STALL Error limit, Do Reset Recovery */
USBH_MSC_BOTXferParam.BOTXferStatus = (uint8_t)USB_HOST_MSC_PHASE_ERROR;
} else {
;
}
break;
case HOST_MSC_BOT_ERROR_OUT:
status = usb_host_msc_botabort(pdev, phost, HOST_MSC_DIR_OUT);
if (status == HSTATUS_OK) {
/* switch back to the original state */
USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOTXferParam.BOTStateBkp;
} else if (status == HSTATUS_UNRECOVERED_ERROR) {
/* This means that there is a STALL Error limit, Do Reset Recovery */
USBH_MSC_BOTXferParam.BOTXferStatus = (uint8_t)USB_HOST_MSC_PHASE_ERROR;
} else {
;
}
break;
default:
break;
}
}
}
/**
* @brief manages the different Error handling for STALL
* @param [in] pdev device instance
* @param [in] phost host state set
* @param [in] direction IN / OUT
* @retval None
*/
HOST_STATUS usb_host_msc_botabort(usb_core_instance *pdev, USBH_HOST *phost, uint8_t direction)
{
HOST_STATUS status;
status = HSTATUS_BUSY;
switch (direction) {
case HOST_MSC_DIR_IN:
/* send ClrFeture on Bulk IN endpoint */
status = usb_host_clrfeature(pdev,
phost,
MSC_Machine.MSC_BulkInEp,
MSC_Machine.hc_num_in);
break;
case HOST_MSC_DIR_OUT:
/* send ClrFeature on Bulk OUT endpoint */
status = usb_host_clrfeature(pdev,
phost,
MSC_Machine.MSC_BulkOutEp,
MSC_Machine.hc_num_out);
break;
default:
break;
}
BOTStallErrorCount++;
if (BOTStallErrorCount > 4UL) {
status = HSTATUS_UNRECOVERED_ERROR;
}
return status;
}
/**
* @brief Decodes the CSW received by the device and updates the same to upper layer
* @param [in] pdev device instance
* @param [in] phost host state set
* @retval On success USB_HOST_MSC_OK, on failure USB_HOST_MSC_FAIL
*/
uint8_t usb_host_msc_cswdecode(usb_core_instance *pdev, USBH_HOST *phost)
{
USB_HOST_MSC_STATUS status;
uint32_t dataXferCount;
status = USB_HOST_MSC_FAIL;
if (host_driver_ifdevconnected(pdev) != 0UL) {
dataXferCount = host_driver_getxfercnt(pdev, MSC_Machine.hc_num_in);
if (dataXferCount != HOST_MSC_CSW_LENGTH) {
/*(4) Hi > Dn (Host expects to receive data from the device,
Device intends to transfer no data)
(5) Hi > Di (Host expects to receive data from the device,
Device intends to send data to the host)
(9) Ho > Dn (Host expects to send data to the device,
Device intends to transfer no data)
(11) Ho > Do (Host expects to send data to the device,
Device intends to receive data from the host)*/
status = USB_HOST_MSC_PHASE_ERROR;
} else {
/* CSW length is Correct */
/* Check validity of the CSW Signature and CSWStatus */
if (USBH_MSC_CSWData.field.dCSWSignature == HOST_MSC_BOT_CSW_SIGNATURE) {
/* Check Condition 1. dCSWSignature is equal to 53425355h */
if (USBH_MSC_CSWData.field.dCSWTag == USBH_MSC_CBWData.field.CBWTag) {
/* Check Condition 3. dCSWTag matches the dCBWTag from the
corresponding CBW */
if (USBH_MSC_CSWData.field.dCSWStatus == (uint8_t)USB_HOST_MSC_OK) {
/* Refer to USB Mass-Storage Class : BOT (www.usb.org)
Hn Host expects no data transfers
Hi Host expects to receive data from the device
Ho Host expects to send data to the device
Dn Device intends to transfer no data
Di Device intends to send data to the host
Do Device intends to receive data from the host
Section 6.7
(1) Hn = Dn (Host expects no data transfers,
Device intends to transfer no data)
(6) Hi = Di (Host expects to receive data from the device,
Device intends to send data to the host)
(12) Ho = Do (Host expects to send data to the device,
Device intends to receive data from the host)
*/
status = USB_HOST_MSC_OK;
} else if (USBH_MSC_CSWData.field.dCSWStatus == (uint8_t)USB_HOST_MSC_FAIL) {
status = USB_HOST_MSC_FAIL;
} else if (USBH_MSC_CSWData.field.dCSWStatus == (uint8_t)USB_HOST_MSC_PHASE_ERROR) {
/* Refer to USB Mass-Storage Class : BOT (www.usb.org)
Section 6.7
(2) Hn < Di ( Host expects no data transfers,
Device intends to send data to the host)
(3) Hn < Do ( Host expects no data transfers,
Device intends to receive data from the host)
(7) Hi < Di ( Host expects to receive data from the device,
Device intends to send data to the host)
(8) Hi <> Do ( Host expects to receive data from the device,
Device intends to receive data from the host)
(10) Ho <> Di (Host expects to send data to the device,
Di Device intends to send data to the host)
(13) Ho < Do (Host expects to send data to the device,
Device intends to receive data from the host)
*/
status = USB_HOST_MSC_PHASE_ERROR;
} else {
;
}
}
} else {
status = USB_HOST_MSC_PHASE_ERROR;
}
}
}
USBH_MSC_BOTXferParam.BOTXferStatus = (uint8_t)status;
return (uint8_t)status;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/*******************************************************************************
* EOF (not truncated)
******************************************************************************/

View File

@ -0,0 +1,162 @@
/**
*******************************************************************************
* @file usb_host_msc_bot.h
* @brief Head file for usb_host_msc_bot.c
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
@endverbatim
*******************************************************************************
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
#ifndef __USB_HOST_MSC_BOT_H__
#define __USB_HOST_MSC_BOT_H__
/* C binding of definitions if building with C++ compiler */
#ifdef __cplusplus
extern "C"
{
#endif
/*******************************************************************************
* Include files
******************************************************************************/
#include "usb_host_stdreq.h"
/**
* @addtogroup LL_USB_LIB
* @{
*/
/**
* @addtogroup LL_USB_HOST_CLASS
* @{
*/
/**
* @addtogroup LL_USB_HOST_MSC
* @{
*/
/*******************************************************************************
* Global type definitions ('typedef')
******************************************************************************/
typedef union _USBH_CBW_Block {
struct __CBW {
uint32_t CBWSignature;
uint32_t CBWTag;
uint32_t CBWTransferLength;
uint8_t CBWFlags;
uint8_t CBWLUN;
uint8_t CBWLength;
uint8_t CBWCB[16];
} field;
uint8_t CBWArray[31];
} HostCBWPkt_TypeDef;
typedef struct {
uint8_t MSCState;
uint8_t MSCStateBkp;
uint8_t MSCStateCurrent;
uint8_t CmdStateMachine;
uint8_t BOTState;
uint8_t BOTStateBkp;
uint8_t *pRxTxBuff;
uint16_t DataLength;
uint8_t BOTXferStatus;
} USB_HOST_BOTXFER_TypeDef;
typedef union {
struct {
uint32_t dCSWSignature;
uint32_t dCSWTag;
uint32_t dCSWDataResidue;
uint8_t dCSWStatus;
} field;
uint8_t CSWArray[13];
} HOST_CSW_PACKET_TypeDef;
/*******************************************************************************
* Global pre-processor symbols/macros ('#define')
******************************************************************************/
#define HOST_MSC_BOT_INIT_STATE (0U)
#define HOST_MSC_BOT_RESET (1U)
#define HOST_MSC_GET_MAX_LUN (2U)
#define HOST_MSC_TEST_UNIT_READY (3U)
#define HOST_MSC_READ_CAPACITY10 (4U)
#define HOST_MSC_MODE_SENSE6 (5U)
#define HOST_MSC_REQUEST_SENSE (6U)
#define HOST_MSC_BOT_USB_TRANSFERS (7U)
#define HOST_MSC_DEFAULT_APPLI_STATE (8U)
#define HOST_MSC_CTRL_ERROR_STATE (9U)
#define HOST_MSC_UNRECOVERED_STATE (10U)
#define HOST_MSC_SEND_CBW (1U)
#define HOST_MSC_SENT_CBW (2U)
#define HOST_MSC_BOT_DATAIN_STATE (3U)
#define HOST_MSC_BOT_DATAOUT_STATE (4U)
#define HOST_MSC_RECEIVE_CSW_STATE (5U)
#define HOST_MSC_DECODE_CSW (6U)
#define HOST_MSC_BOT_ERROR_IN (7U)
#define HOST_MSC_BOT_ERROR_OUT (8U)
#define HOST_MSC_BOT_CBW_SIGNATURE (0x43425355UL)
#define HOST_MSC_BOT_CBW_TAG (0x20304050UL)
#define HOST_MSC_BOT_CSW_SIGNATURE (0x53425355UL)
#define HOST_MSC_CSW_DATA_LENGTH (13U)
#define HOST_MSC_BOT_CBW_PACKET_LENGTH (31U)
#define HOST_MSC_CSW_LENGTH (13U)
#define HOST_MSC_CSW_MAX_LENGTH (63U)
#define HOST_MSC_DIR_IN (0U)
#define HOST_MSC_DIR_OUT (1U)
#define HOST_MSC_BOTH_DIR (2U)
#define HOST_MSC_PAGE_LENGTH (512UL)
#define CBW_CB_LENGTH (16U)
#define CBW_LENGTH (10U)
#define CBW_LENGTH_TEST_UNIT_READY (6U)
/*******************************************************************************
* Global variable definitions ('extern')
******************************************************************************/
extern USB_HOST_BOTXFER_TypeDef USBH_MSC_BOTXferParam;
extern HostCBWPkt_TypeDef USBH_MSC_CBWData;
extern HOST_CSW_PACKET_TypeDef USBH_MSC_CSWData;
/*******************************************************************************
Global function prototypes (definition in C source)
******************************************************************************/
extern void usb_host_msc_init(usb_core_instance *pdev);
extern void usb_host_msc_botxferprocess(usb_core_instance *pdev, USBH_HOST *phost);
extern uint8_t usb_host_msc_cswdecode(usb_core_instance *pdev, USBH_HOST *phost);
extern HOST_STATUS usb_host_msc_botabort(usb_core_instance *pdev, USBH_HOST *phost, uint8_t direction);
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USB_HOST_MSC_BOT_H__ */
/*******************************************************************************
* EOF (not truncated)
******************************************************************************/

View File

@ -0,0 +1,395 @@
/**
*******************************************************************************
* @file usb_host_msc_class.c
* @brief The MSC class driver functions
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
@endverbatim
*******************************************************************************
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
/*******************************************************************************
* Include files
******************************************************************************/
#include "usb_host_msc_class.h"
#include "usb_host_msc_scsi.h"
#include "usb_host_msc_bot.h"
#include "usb_host_core.h"
#include "usb_host_driver.h"
/**
* @addtogroup LL_USB_LIB
* @{
*/
/**
* @addtogroup LL_USB_HOST_CLASS
* @{
*/
/**
* @addtogroup LL_USB_HOST_MSC
* @{
*/
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
#define USBH_MSC_ERROR_RETRY_LIMIT (10U)
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
HOST_STATUS usb_host_msc_itfinit(usb_core_instance *pdev, void *phost);
void usb_host_msc_itfdeinit(usb_core_instance *pdev);
HOST_STATUS usb_host_msc_process(usb_core_instance *pdev, void *phost);
HOST_STATUS usb_host_msc_classreq(usb_core_instance *pdev, void *phost);
HOST_STATUS usb_host_msc_bot_reset(usb_core_instance *pdev, USBH_HOST *phost);
HOST_STATUS usb_host_msc_maxlun_get(usb_core_instance *pdev, USBH_HOST *phost);
void usb_host_msc_error_process(USB_HOST_MSC_STATUS status);
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
#ifdef USB_INTERNAL_DMA_ENABLED
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
#pragma data_alignment=4
#endif
#endif /* USB_INTERNAL_DMA_ENABLED */
__USB_ALIGN_BEGIN MSC_Machine_TypeDef MSC_Machine;
#ifdef USB_INTERNAL_DMA_ENABLED
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
#pragma data_alignment=4
#endif
#endif /* USB_INTERNAL_DMA_ENABLED */
uint8_t MSCErrorCount = 0U;
usb_host_class_callback_func USBH_MSC_cb = {
&usb_host_msc_itfinit,
&usb_host_msc_itfdeinit,
&usb_host_msc_classreq,
&usb_host_msc_process,
};
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/**
* @brief This request is used to issue a request to reset the msc device and
* its related interface. This class-specific request shall prepare the
* device for the next CBW from the host.
* @param [in] pdev device instance
* @param [in] phost host state set
* @retval status define by HOST_STATUS
*/
HOST_STATUS usb_host_msc_bot_reset(usb_core_instance *pdev, USBH_HOST *phost)
{
phost->ctrlparam.setup.b.bmRequestType = USB_H2D | USB_REQ_TYPE_CLASS | \
USB_REQ_RECIPIENT_INTERFACE;
phost->ctrlparam.setup.b.bRequest = USB_REQ_BOT_RESET;
phost->ctrlparam.setup.b.wValue.w = 0U;
phost->ctrlparam.setup.b.wIndex.w = 0U;
phost->ctrlparam.setup.b.wLength.w = 0U;
return usb_host_ctrlreq(pdev, phost, NULL, 0U);
}
/**
* @brief this request is used to issue a request to get the max logic unit of
* the msc device.
* @param [in] pdev device instance
* @param [in] phost host state set
* @retval status defined by HOST_STATUS
*/
HOST_STATUS usb_host_msc_maxlun_get(usb_core_instance *pdev, USBH_HOST *phost)
{
phost->ctrlparam.setup.b.bmRequestType = USB_D2H | USB_REQ_TYPE_CLASS | \
USB_REQ_RECIPIENT_INTERFACE;
phost->ctrlparam.setup.b.bRequest = USB_REQ_GET_MAX_LUN;
phost->ctrlparam.setup.b.wValue.w = 0U;
phost->ctrlparam.setup.b.wIndex.w = 0U;
phost->ctrlparam.setup.b.wLength.w = 1U;
return usb_host_ctrlreq(pdev, phost, MSC_Machine.buff, 1U);
}
/**
* @brief The function is used for handling errors during processing the MSC
* state machine
* @param [in] status
* @retval None
*/
void usb_host_msc_error_process(USB_HOST_MSC_STATUS status)
{
switch (status) {
case USB_HOST_MSC_FAIL:
MSCErrorCount++;
if (MSCErrorCount < USBH_MSC_ERROR_RETRY_LIMIT) {
/* Try MSC level error recovery, Issue the request Sense to get
driver error reason */
USBH_MSC_BOTXferParam.MSCState = HOST_MSC_REQUEST_SENSE;
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_SEND;
} else {
/* Error trials exceeded the limit, go to unrecovered state */
USBH_MSC_BOTXferParam.MSCState = HOST_MSC_UNRECOVERED_STATE;
}
break;
case USB_HOST_MSC_PHASE_ERROR:
/* Phase error, Go to Unrecoovered state */
USBH_MSC_BOTXferParam.MSCState = HOST_MSC_UNRECOVERED_STATE;
break;
default:
break;
}
}
/**
* @brief Interface initialization for msc class application, the channels for
* the IN and OUT EP will be distributed.
* @param [in] pdev device instance
* @param [in] phost host state set
* @retval status defined by HOST_STATUS
*/
HOST_STATUS usb_host_msc_itfinit(usb_core_instance *pdev, void *phost)
{
USBH_HOST *pphost = phost;
if ((pphost->device_prop.devitfdesc[0].bInterfaceClass == MSC_CLASS) && \
(pphost->device_prop.devitfdesc[0].bInterfaceProtocol == MSC_PROTOCOL)) {
if ((pphost->device_prop.devepdesc[0][0].bEndpointAddress & 0x80U) == 0x80U) {
MSC_Machine.MSC_BulkInEp = (pphost->device_prop.devepdesc[0][0].bEndpointAddress);
MSC_Machine.MSC_BulkInEpSize = pphost->device_prop.devepdesc[0][0].wMaxPacketSize;
} else {
MSC_Machine.MSC_BulkOutEp = (pphost->device_prop.devepdesc[0][0].bEndpointAddress);
MSC_Machine.MSC_BulkOutEpSize = pphost->device_prop.devepdesc[0] [0].wMaxPacketSize;
}
if ((pphost->device_prop.devepdesc[0][1].bEndpointAddress & 0x80U) == 0x80U) {
MSC_Machine.MSC_BulkInEp = (pphost->device_prop.devepdesc[0][1].bEndpointAddress);
MSC_Machine.MSC_BulkInEpSize = pphost->device_prop.devepdesc[0][1].wMaxPacketSize;
} else {
MSC_Machine.MSC_BulkOutEp = (pphost->device_prop.devepdesc[0][1].bEndpointAddress);
MSC_Machine.MSC_BulkOutEpSize = pphost->device_prop.devepdesc[0][1].wMaxPacketSize;
}
/* distribute the channels for the EPs */
MSC_Machine.hc_num_out = usb_host_distrch(pdev, MSC_Machine.MSC_BulkOutEp);
MSC_Machine.hc_num_in = usb_host_distrch(pdev, MSC_Machine.MSC_BulkInEp);
/* open the channels that have distributed */
usb_host_chopen(pdev,
MSC_Machine.hc_num_out,
pphost->device_prop.devaddr,
pphost->device_prop.devspeed,
EP_TYPE_BULK,
MSC_Machine.MSC_BulkOutEpSize);
usb_host_chopen(pdev,
MSC_Machine.hc_num_in,
pphost->device_prop.devaddr,
pphost->device_prop.devspeed,
EP_TYPE_BULK,
MSC_Machine.MSC_BulkInEpSize);
} else {
pphost->user_callbk->huser_devunsupported();
}
return HSTATUS_OK ;
}
/**
* @brief deinitialize interface of msc class by freeing host channels
* @param [in] pdev device instance
* @retval None
*/
void usb_host_msc_itfdeinit(usb_core_instance *pdev)
{
if (MSC_Machine.hc_num_out != 0U) {
usb_hchstop(&pdev->regs, MSC_Machine.hc_num_out);
(void)usb_host_freech(pdev, MSC_Machine.hc_num_out);
MSC_Machine.hc_num_out = 0U;
}
if (MSC_Machine.hc_num_in != 0U) {
usb_hchstop(&pdev->regs, MSC_Machine.hc_num_in);
(void)usb_host_freech(pdev, MSC_Machine.hc_num_in);
MSC_Machine.hc_num_in = 0U;
}
}
/**
* @brief initialize the msc state machine
* @param [in] pdev device instance
* @param [in] phost host state set
* @retval status defined by HOST_STATUS
*/
HOST_STATUS usb_host_msc_classreq(usb_core_instance *pdev, void *phost)
{
USBH_MSC_BOTXferParam.MSCState = HOST_MSC_BOT_INIT_STATE;
return HSTATUS_OK;
}
/**
* @brief process the msc state machine
* @param [in] pdev device instance
* @param [in] phost host state set
* @retval status defined by HOST_STATUS
*/
HOST_STATUS usb_host_msc_process(usb_core_instance *pdev, void *phost)
{
USBH_HOST *pphost = phost;
HOST_STATUS status = HSTATUS_BUSY;
USB_HOST_MSC_STATUS mscStatus;
uint8_t appliStatus;
static uint8_t maxLunExceed = FALSE;
if (host_driver_ifdevconnected(pdev) != 0UL) {
switch (USBH_MSC_BOTXferParam.MSCState) {
case HOST_MSC_BOT_INIT_STATE:
usb_host_msc_init(pdev);
USBH_MSC_BOTXferParam.MSCState = HOST_MSC_BOT_RESET;
break;
case HOST_MSC_BOT_RESET:
/* issue a request to reset the bot. */
status = usb_host_msc_bot_reset(pdev, phost);
if (status == HSTATUS_OK) {
USBH_MSC_BOTXferParam.MSCState = HOST_MSC_GET_MAX_LUN;
}
if (status == HSTATUS_UNSUPPORTED) {
/* if the request fails, it needs to move to next state and should save the next state as backup */
USBH_MSC_BOTXferParam.MSCStateBkp = HOST_MSC_GET_MAX_LUN;
/* a clear feature should be issued if the request fails. */
USBH_MSC_BOTXferParam.MSCState = HOST_MSC_CTRL_ERROR_STATE;
}
break;
case HOST_MSC_GET_MAX_LUN:
/* issue a request to get the max logical unit(MAXLUN). */
status = usb_host_msc_maxlun_get(pdev, phost);
if (status == HSTATUS_OK) {
MSC_Machine.maxLun = *(MSC_Machine.buff) ;
if ((MSC_Machine.maxLun > 0U) && (maxLunExceed == FALSE)) {
maxLunExceed = TRUE;
pphost->user_callbk->huser_devunsupported();
break;
}
USBH_MSC_BOTXferParam.MSCState = HOST_MSC_TEST_UNIT_READY;
}
if (status == HSTATUS_UNSUPPORTED) {
/* if the request fails, it needs to move to next state and should save the next state as backup */
USBH_MSC_BOTXferParam.MSCStateBkp = HOST_MSC_TEST_UNIT_READY;
/* a clear feature should be issued if the request fails. */
USBH_MSC_BOTXferParam.MSCState = HOST_MSC_CTRL_ERROR_STATE;
}
break;
case HOST_MSC_CTRL_ERROR_STATE:
/* issue a request to clear feature */
status = usb_host_clrfeature(pdev,
phost,
0x00U,
pphost->ctrlparam.hc_num_out);
if (status == HSTATUS_OK) {
/* If GetMaxLun Request not support, assume Single LUN configuration */
MSC_Machine.maxLun = 0U;
USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOTXferParam.MSCStateBkp;
}
break;
case HOST_MSC_TEST_UNIT_READY:
/* issue the request Test Unit Ready[0] of SCSI command */
mscStatus = usb_host_msc_TestUnitReady(pdev);
if (mscStatus == USB_HOST_MSC_OK) {
USBH_MSC_BOTXferParam.MSCState = HOST_MSC_READ_CAPACITY10;
MSCErrorCount = 0U;
status = HSTATUS_OK;
} else {
usb_host_msc_error_process(mscStatus);
}
break;
case HOST_MSC_READ_CAPACITY10:
/* issue the request Read Capacity[0] of SCSI command. */
mscStatus = usb_host_msc_ReadCapacity10(pdev);
if (mscStatus == USB_HOST_MSC_OK) {
USBH_MSC_BOTXferParam.MSCState = HOST_MSC_MODE_SENSE6;
MSCErrorCount = 0U;
status = HSTATUS_OK;
} else {
usb_host_msc_error_process(mscStatus);
}
break;
case HOST_MSC_MODE_SENSE6:
/* issue the request ModeSense6 of SCSI command for detecting whelth the deviec is write-protected. */
mscStatus = usb_host_msc_ModeSense6(pdev);
if (mscStatus == USB_HOST_MSC_OK) {
USBH_MSC_BOTXferParam.MSCState = HOST_MSC_DEFAULT_APPLI_STATE;
MSCErrorCount = 0U;
status = HSTATUS_OK;
} else {
usb_host_msc_error_process(mscStatus);
}
break;
case HOST_MSC_REQUEST_SENSE:
/* issue the request RequestSense of SCSI command for retreiving error code. */
mscStatus = usb_host_msc_RequestSense(pdev);
if (mscStatus == USB_HOST_MSC_OK) {
USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOTXferParam.MSCStateBkp;
status = HSTATUS_OK;
} else {
usb_host_msc_error_process(mscStatus);
}
break;
case HOST_MSC_BOT_USB_TRANSFERS:
/* handle the BOT state machine. */
usb_host_msc_botxferprocess(pdev, phost);
break;
case HOST_MSC_DEFAULT_APPLI_STATE:
/* handle the user callback for the msc application. */
appliStatus = pphost->user_callbk->huser_application();
if (appliStatus == 0U) {
USBH_MSC_BOTXferParam.MSCState = HOST_MSC_DEFAULT_APPLI_STATE;
} else if (appliStatus == 1U) {
/* deinit requested from the application layer. */
status = HSTATUS_APP_DEINIT;
} else {
;
}
break;
case HOST_MSC_UNRECOVERED_STATE:
status = HSTATUS_UNRECOVERED_ERROR;
break;
default:
break;
}
}
return status;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/*******************************************************************************
* EOF (not truncated)
******************************************************************************/

View File

@ -0,0 +1,113 @@
/**
*******************************************************************************
* @file usb_host_msc_class.h
* @brief Head file for usb_host_msc_class.c
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
@endverbatim
*******************************************************************************
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
#ifndef __USB_HOST_MSC_CLASS_H__
#define __USB_HOST_MSC_CLASS_H__
/* C binding of definitions if building with C++ compiler */
#ifdef __cplusplus
extern "C"
{
#endif
/*******************************************************************************
* Include files
******************************************************************************/
#include "usb_host_core.h"
#include "usb_host_stdreq.h"
#include "usb_bsp.h"
#include "usb_host_ctrltrans.h"
#include "usb_host_cfgch.h"
#include "usb_host_msc_class.h"
#include "usb_host_msc_scsi.h"
#include "usb_host_msc_bot.h"
/**
* @addtogroup LL_USB_LIB
* @{
*/
/**
* @addtogroup LL_USB_HOST_CLASS
* @{
*/
/**
* @addtogroup LL_USB_HOST_MSC
* @{
*/
/*******************************************************************************
* Global type definitions ('typedef')
******************************************************************************/
/* Structure for MSC process */
typedef struct {
uint8_t hc_num_in;
uint8_t hc_num_out;
uint8_t MSC_BulkOutEp;
uint8_t MSC_BulkInEp;
uint16_t MSC_BulkInEpSize;
uint16_t MSC_BulkOutEpSize;
uint8_t buff[USBH_MSC_MPS_SIZE];
uint8_t maxLun;
} MSC_Machine_TypeDef;
/*******************************************************************************
* Global pre-processor symbols/macros ('#define')
******************************************************************************/
#define USB_REQ_BOT_RESET (0xFFU)
#define USB_REQ_GET_MAX_LUN (0xFEU)
/*******************************************************************************
* Global variable definitions ('extern')
******************************************************************************/
extern usb_host_class_callback_func USBH_MSC_cb;
extern MSC_Machine_TypeDef MSC_Machine;
extern uint8_t MSCErrorCount;
/*******************************************************************************
Global function prototypes (definition in C source)
******************************************************************************/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USB_HOST_MSC_CLASS_H__ */
/*******************************************************************************
* EOF (not truncated)
******************************************************************************/

View File

@ -0,0 +1,241 @@
/**
*******************************************************************************
* @file usb_host_msc_fatfs.c
* @brief The fatfs functions.
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
@endverbatim
*******************************************************************************
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
/*******************************************************************************
* Include files
******************************************************************************/
#include "usb_app_conf.h"
#include "usb_host_driver.h"
#ifdef USB_MSC_FAT_VALID
#include "ff.h"
#include "diskio.h"
#include "usb_host_msc_class.h"
/**
* @addtogroup LL_USB_LIB
* @{
*/
/**
* @addtogroup LL_USB_HOST_CLASS
* @{
*/
/**
* @addtogroup LL_USB_HOST_MSC
* @{
*/
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
static volatile DSTATUS Stat = STA_NOINIT; /* Disk status */
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
extern usb_core_instance usb_app_instance;
extern USBH_HOST usb_app_host;
/**
* @brief Initialize Disk Drive
* @param [in] drv Physical drive number (0)
* @retval DSTATUS
*/
DSTATUS disk_initialize(BYTE drv)
{
if (host_driver_ifdevconnected(&usb_app_instance) != 0UL) {
Stat &= (DSTATUS)~STA_NOINIT;
}
return Stat;
}
/**
* @brief Get Disk Status
* @param [in] drv Physical drive number (0)
* @retval DSTATUS
*/
DSTATUS disk_status(BYTE drv)
{
DSTATUS status = Stat;
if (drv != 0U) {
status = STA_NOINIT; /* Supports only single drive */
}
return status;
}
/**
* @brief Read Sector(s)
* @param [in] drv Physical drive number (0)
* @param [in] buff Pointer to the data buffer to store read data
* @param [in] sector Start sector number (LBA)
* @param [in] count Sector count (1..255)
* @retval DSTATUS
*/
DRESULT disk_read(BYTE pdrv, BYTE *buff, LBA_t sector, UINT count)
{
USB_HOST_MSC_STATUS status = USB_HOST_MSC_OK;
if ((pdrv != 0U) || (count == 0UL)) {
return RES_PARERR;
}
if ((Stat & STA_NOINIT) == STA_NOINIT) {
return RES_NOTRDY;
}
if (host_driver_ifdevconnected(&usb_app_instance) != 0UL) {
do {
status = usb_host_msc_Read10(&usb_app_instance, buff, sector, 512UL * (uint32_t)count);
usb_host_msc_botxferprocess(&usb_app_instance, &usb_app_host);
if (host_driver_ifdevconnected(&usb_app_instance) == 0UL) {
return RES_ERROR;
}
} while (status == USB_HOST_MSC_BUSY);
}
if (status == USB_HOST_MSC_OK) {
return RES_OK;
}
return RES_ERROR;
}
#if _READONLY == 0
/**
* @brief Write Sector(s)
* @param [in] drv Physical drive number (0)
* @param [in] buff Pointer to the data to be written
* @param [in] sector Start sector number (LBA)
* @param [in] count Sector count (1..255)
* @retval DSTATUS
*/
DRESULT disk_write(BYTE pdrv, const BYTE *buff, LBA_t sector, UINT count)
{
USB_HOST_MSC_STATUS status = USB_HOST_MSC_OK;
if ((pdrv != 0U) || (count == 0UL)) {
return RES_PARERR;
}
if ((Stat & STA_NOINIT) == STA_NOINIT) {
return RES_NOTRDY;
}
if ((Stat & STA_PROTECT) == STA_PROTECT) {
return RES_WRPRT;
}
if (host_driver_ifdevconnected(&usb_app_instance) != 0UL) {
do {
status = usb_host_msc_Write10(&usb_app_instance, (BYTE *)buff, sector, 512UL * (uint32_t)count);
usb_host_msc_botxferprocess(&usb_app_instance, &usb_app_host);
if (host_driver_ifdevconnected(&usb_app_instance) == 0UL) {
return RES_ERROR;
}
} while (status == USB_HOST_MSC_BUSY);
}
if (status == USB_HOST_MSC_OK) {
return RES_OK;
}
return RES_ERROR;
}
#endif /* _READONLY == 0 */
//#if _USE_IOCTL != 0
/**
* @brief Miscellaneous Functions
* @param [in] drv Physical drive number (0)
* @param [in] ctrl Control code
* @param [in] buff Buffer to send/receive control data
**
* @retval DSTATUS
*/
DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff)
{
DRESULT res;
if (pdrv != 0U) {
return RES_PARERR;
}
res = RES_ERROR;
if ((Stat & STA_NOINIT) == STA_NOINIT) {
return RES_NOTRDY;
}
switch (cmd) {
case CTRL_SYNC : /* Make sure that no pending write process */
res = RES_OK;
break;
case GET_SECTOR_COUNT : /* Get number of sectors on the disk (DWORD) */
*(DWORD *)buff = (DWORD) USB_HOST_MSC_Param.MSC_Capacity;
res = RES_OK;
break;
case GET_SECTOR_SIZE : /* Get R/W sector size (WORD) */
*(WORD *)buff = 512U;
res = RES_OK;
break;
case GET_BLOCK_SIZE : /* Get erase block size in unit of sector (DWORD) */
*(DWORD *)buff = 512UL;
break;
default:
res = RES_PARERR;
break;
}
return res;
}
//#endif
#endif /* _USE_IOCTL != 0 */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/*******************************************************************************
* EOF (not truncated)
******************************************************************************/

View File

@ -0,0 +1,528 @@
/**
*******************************************************************************
* @file usb_host_msc_scsi.c
* @brief The SCSI commands
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
@endverbatim
*******************************************************************************
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
/*******************************************************************************
* Include files
******************************************************************************/
#include "usb_host_msc_class.h"
#include "usb_host_msc_scsi.h"
#include "usb_host_msc_bot.h"
#include "usb_host_ctrltrans.h"
#include "usb_host_def.h"
#include "usb_host_driver.h"
#include <stdio.h>
/**
* @addtogroup LL_USB_LIB
* @{
*/
/**
* @addtogroup LL_USB_HOST_CLASS
* @{
*/
/**
* @addtogroup LL_USB_HOST_MSC
* @{
*/
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
MSC_PARAMETER USB_HOST_MSC_Param;
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
#ifdef USB_INTERNAL_DMA_ENABLED
#if defined ( __ICCARM__ )
#pragma data_alignment=4
#endif
#endif
__USB_ALIGN_BEGIN static uint8_t USB_HOST_DataInBuf[512];
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/**
* @brief Issues 'Test Unit Ready' command to the device. Once the response
* received, it updates the status to upper layer, the length of the
* command are 31bytes.
* @param [in] pdev device instance
* @retval status define by USB_HOST_MSC_STATUS
*/
USB_HOST_MSC_STATUS usb_host_msc_TestUnitReady(usb_core_instance *pdev)
{
uint8_t index;
USB_HOST_MSC_STATUS status = USB_HOST_MSC_BUSY;
if (host_driver_ifdevconnected(pdev) != 0UL) {
switch (USBH_MSC_BOTXferParam.CmdStateMachine) {
case USB_HOST_MSC_CMD_SEND:
USBH_MSC_CBWData.field.CBWTransferLength = 0UL;
USBH_MSC_CBWData.field.CBWFlags = USB_EP_DIR_OUT;
USBH_MSC_CBWData.field.CBWLength = CBW_LENGTH_TEST_UNIT_READY;
USBH_MSC_BOTXferParam.pRxTxBuff = USBH_MSC_CSWData.CSWArray;
USBH_MSC_BOTXferParam.DataLength = HOST_MSC_CSW_MAX_LENGTH;
USBH_MSC_BOTXferParam.MSCStateCurrent = HOST_MSC_TEST_UNIT_READY;
for (index = 0U; index < CBW_CB_LENGTH; index++) {
USBH_MSC_CBWData.field.CBWCB[index] = 0x00U;
}
USBH_MSC_CBWData.field.CBWCB[0] = OPCODE_TEST_UNIT_READY;
USBH_MSC_BOTXferParam.BOTState = HOST_MSC_SEND_CBW;
/* Start the transfer, then let the state machine magage the other transactions */
USBH_MSC_BOTXferParam.MSCState = HOST_MSC_BOT_USB_TRANSFERS;
USBH_MSC_BOTXferParam.BOTXferStatus = (uint8_t)USB_HOST_MSC_BUSY;
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_WAIT;
status = USB_HOST_MSC_BUSY;
break;
case USB_HOST_MSC_CMD_WAIT:
switch (USBH_MSC_BOTXferParam.BOTXferStatus) {
case USB_HOST_MSC_OK:
/* Commands successfully sent and Response Received */
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_SEND;
status = USB_HOST_MSC_OK;
break;
case USB_HOST_MSC_FAIL:
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_SEND;
status = USB_HOST_MSC_FAIL;
break;
case USB_HOST_MSC_PHASE_ERROR:
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_SEND;
status = USB_HOST_MSC_PHASE_ERROR;
break;
default:
break;
}
break;
default:
break;
}
}
return status;
}
/**
* @brief Issue the 'Read capacity10' command to the device. Once the response
* received, it updates the status to upper layer
* @param [in] pdev device instance
* @retval status define by USB_HOST_MSC_STATUS
*/
USB_HOST_MSC_STATUS usb_host_msc_ReadCapacity10(usb_core_instance *pdev)
{
uint8_t index;
USB_HOST_MSC_STATUS status = USB_HOST_MSC_BUSY;
if (host_driver_ifdevconnected(pdev) != 0UL) {
switch (USBH_MSC_BOTXferParam.CmdStateMachine) {
case USB_HOST_MSC_CMD_SEND:
/*Prepare the CBW and relevent field*/
USBH_MSC_CBWData.field.CBWTransferLength = XFER_LEN_READ_CAPACITY10;
USBH_MSC_CBWData.field.CBWFlags = USB_EP_DIR_IN;
USBH_MSC_CBWData.field.CBWLength = CBW_LENGTH;
USBH_MSC_BOTXferParam.pRxTxBuff = USB_HOST_DataInBuf;
USBH_MSC_BOTXferParam.MSCStateCurrent = HOST_MSC_READ_CAPACITY10;
for (index = 0U; index < CBW_CB_LENGTH; index++) {
USBH_MSC_CBWData.field.CBWCB[index] = 0x00U;
}
USBH_MSC_CBWData.field.CBWCB[0] = OPCODE_READ_CAPACITY10;
USBH_MSC_BOTXferParam.BOTState = HOST_MSC_SEND_CBW;
/* Start the transfer, then let the state machine manage the other
transactions */
USBH_MSC_BOTXferParam.MSCState = HOST_MSC_BOT_USB_TRANSFERS;
USBH_MSC_BOTXferParam.BOTXferStatus = (uint8_t)USB_HOST_MSC_BUSY;
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_WAIT;
status = USB_HOST_MSC_BUSY;
break;
case USB_HOST_MSC_CMD_WAIT:
switch (USBH_MSC_BOTXferParam.BOTXferStatus) {
case USB_HOST_MSC_OK:
/*assign the capacity*/
(((uint8_t *)&USB_HOST_MSC_Param.MSC_Capacity)[3]) = USB_HOST_DataInBuf[0];
(((uint8_t *)&USB_HOST_MSC_Param.MSC_Capacity)[2]) = USB_HOST_DataInBuf[1];
(((uint8_t *)&USB_HOST_MSC_Param.MSC_Capacity)[1]) = USB_HOST_DataInBuf[2];
(((uint8_t *)&USB_HOST_MSC_Param.MSC_Capacity)[0]) = USB_HOST_DataInBuf[3];
/*assign the page length*/
(((uint8_t *)&USB_HOST_MSC_Param.MSC_PageLength)[1]) = USB_HOST_DataInBuf[6];
(((uint8_t *)&USB_HOST_MSC_Param.MSC_PageLength)[0]) = USB_HOST_DataInBuf[7];
/* Commands successfully sent and Response Received */
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_SEND;
status = USB_HOST_MSC_OK;
break;
case USB_HOST_MSC_FAIL:
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_SEND;
status = USB_HOST_MSC_FAIL;
break;
case USB_HOST_MSC_PHASE_ERROR:
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_SEND;
status = USB_HOST_MSC_PHASE_ERROR;
break;
default:
break;
}
break;
default:
break;
}
}
return status;
}
/**
* @brief Issue the 'Mode Sense6' Command to the device. This function is used
* for reading the WriteProtect Status of the MSC device.
* @param [in] pdev device instance
* @retval status by USB_HOST_MSC_STATUS
*/
USB_HOST_MSC_STATUS usb_host_msc_ModeSense6(usb_core_instance *pdev)
{
uint8_t index;
USB_HOST_MSC_STATUS status = USB_HOST_MSC_BUSY;
if (host_driver_ifdevconnected(pdev) != 0UL) {
switch (USBH_MSC_BOTXferParam.CmdStateMachine) {
case USB_HOST_MSC_CMD_SEND:
/*Prepare the CBW and relevent field*/
USBH_MSC_CBWData.field.CBWTransferLength = XFER_LEN_MODE_SENSE6;
USBH_MSC_CBWData.field.CBWFlags = USB_EP_DIR_IN;
USBH_MSC_CBWData.field.CBWLength = CBW_LENGTH;
USBH_MSC_BOTXferParam.pRxTxBuff = USB_HOST_DataInBuf;
USBH_MSC_BOTXferParam.MSCStateCurrent = HOST_MSC_MODE_SENSE6;
for (index = 0U; index < CBW_CB_LENGTH; index++) {
USBH_MSC_CBWData.field.CBWCB[index] = 0x00U;
}
USBH_MSC_CBWData.field.CBWCB[0] = OPCODE_MODE_SENSE6;
USBH_MSC_CBWData.field.CBWCB[2] = MODE_SENSE_PAGE_CONTROL_FIELD | \
MODE_SENSE_PAGE_CODE;
USBH_MSC_CBWData.field.CBWCB[4] = XFER_LEN_MODE_SENSE6;
USBH_MSC_BOTXferParam.BOTState = HOST_MSC_SEND_CBW;
/* Start the transfer, then let the state machine manage the other
transactions */
USBH_MSC_BOTXferParam.MSCState = HOST_MSC_BOT_USB_TRANSFERS;
USBH_MSC_BOTXferParam.BOTXferStatus = (uint8_t)USB_HOST_MSC_BUSY;
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_WAIT;
status = USB_HOST_MSC_BUSY;
break;
case USB_HOST_MSC_CMD_WAIT:
switch (USBH_MSC_BOTXferParam.BOTXferStatus) {
case USB_HOST_MSC_OK:
/* Assign the Write Protect status */
/* If WriteProtect = 0, Writing is allowed
If WriteProtect != 0, Disk is Write Protected */
if (0U != (USB_HOST_DataInBuf[2] & MASK_MODE_SENSE_WRITE_PROTECT)) {
USB_HOST_MSC_Param.MSC_WriteProtect = DISK_WRITE_PROTECTED;
} else {
USB_HOST_MSC_Param.MSC_WriteProtect = 0U;
}
/* Commands successfully sent and Response Received */
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_SEND;
status = USB_HOST_MSC_OK;
break;
case USB_HOST_MSC_FAIL:
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_SEND;
status = USB_HOST_MSC_FAIL;
break;
case USB_HOST_MSC_PHASE_ERROR:
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_SEND;
status = USB_HOST_MSC_PHASE_ERROR;
break;
default:
break;
}
break;
default:
break;
}
}
return status;
}
/**
* @brief usb_host_msc_RequestSense
* Issues the Request Sense command to the device. Once the response
* received, it updates the status to upper layer
* @param [in] pdev device instance
* @retval status defined by USB_HOST_MSC_STATUS
*/
USB_HOST_MSC_STATUS usb_host_msc_RequestSense(usb_core_instance *pdev)
{
USB_HOST_MSC_STATUS status = USB_HOST_MSC_BUSY;
uint8_t index;
if (host_driver_ifdevconnected(pdev) != 0UL) {
switch (USBH_MSC_BOTXferParam.CmdStateMachine) {
case USB_HOST_MSC_CMD_SEND:
/*Prepare the CBW and relevent field*/
USBH_MSC_CBWData.field.CBWTransferLength = \
ALLOCATION_LENGTH_REQUEST_SENSE;
USBH_MSC_CBWData.field.CBWFlags = USB_EP_DIR_IN;
USBH_MSC_CBWData.field.CBWLength = CBW_LENGTH;
USBH_MSC_BOTXferParam.pRxTxBuff = USB_HOST_DataInBuf;
USBH_MSC_BOTXferParam.MSCStateBkp = USBH_MSC_BOTXferParam.MSCStateCurrent;
USBH_MSC_BOTXferParam.MSCStateCurrent = HOST_MSC_REQUEST_SENSE;
for (index = 0U; index < CBW_CB_LENGTH; index++) {
USBH_MSC_CBWData.field.CBWCB[index] = 0x00U;
}
USBH_MSC_CBWData.field.CBWCB[0] = OPCODE_REQUEST_SENSE;
USBH_MSC_CBWData.field.CBWCB[1] = DESC_REQUEST_SENSE;
USBH_MSC_CBWData.field.CBWCB[4] = ALLOCATION_LENGTH_REQUEST_SENSE;
USBH_MSC_BOTXferParam.BOTState = HOST_MSC_SEND_CBW;
/* Start the transfer, then let the state machine magage
the other transactions */
USBH_MSC_BOTXferParam.MSCState = HOST_MSC_BOT_USB_TRANSFERS;
USBH_MSC_BOTXferParam.BOTXferStatus = (uint8_t)USB_HOST_MSC_BUSY;
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_WAIT;
status = USB_HOST_MSC_BUSY;
break;
case USB_HOST_MSC_CMD_WAIT:
switch (USBH_MSC_BOTXferParam.BOTXferStatus) {
case USB_HOST_MSC_OK:
/* Get Sense data*/
(((uint8_t *)&USB_HOST_MSC_Param.MSC_Sense)[3]) = USB_HOST_DataInBuf[0];
(((uint8_t *)&USB_HOST_MSC_Param.MSC_Sense)[2]) = USB_HOST_DataInBuf[1];
(((uint8_t *)&USB_HOST_MSC_Param.MSC_Sense)[1]) = USB_HOST_DataInBuf[2];
(((uint8_t *)&USB_HOST_MSC_Param.MSC_Sense)[0]) = USB_HOST_DataInBuf[3];
/* Commands successfully sent and Response Received */
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_SEND;
status = USB_HOST_MSC_OK;
break;
case USB_HOST_MSC_FAIL:
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_SEND;
status = USB_HOST_MSC_FAIL;
break;
case USB_HOST_MSC_PHASE_ERROR:
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_SEND;
status = USB_HOST_MSC_PHASE_ERROR;
break;
default:
break;
}
break;
default:
break;
}
}
return status;
}
/**
* @brief issue the 'Write10 ' command to the device. Once the response received,
* it updates the status to upper layer
* @param [in] pdev device instance
* @param [in] dataBuffer data buffer contains the data to write
* @param [in] address address to which the data will be written
* @param [in] nbOfbytes NbOfbytes to be written
* @retval status define by USB_HOST_MSC_STATUS
*/
USB_HOST_MSC_STATUS usb_host_msc_Write10(usb_core_instance *pdev,
uint8_t *dataBuffer,
uint32_t address,
uint32_t nbOfbytes)
{
uint8_t index;
USB_HOST_MSC_STATUS status = USB_HOST_MSC_BUSY;
uint16_t nbOfPages;
if (host_driver_ifdevconnected(pdev) != 0UL) {
switch (USBH_MSC_BOTXferParam.CmdStateMachine) {
case USB_HOST_MSC_CMD_SEND:
USBH_MSC_CBWData.field.CBWTransferLength = nbOfbytes;
USBH_MSC_CBWData.field.CBWFlags = USB_EP_DIR_OUT;
USBH_MSC_CBWData.field.CBWLength = CBW_LENGTH;
USBH_MSC_BOTXferParam.pRxTxBuff = dataBuffer;
for (index = 0U; index < CBW_CB_LENGTH; index++) {
USBH_MSC_CBWData.field.CBWCB[index] = 0x00U;
}
USBH_MSC_CBWData.field.CBWCB[0] = OPCODE_WRITE10;
/*logical block address*/
USBH_MSC_CBWData.field.CBWCB[2] = (((uint8_t *)&address)[3]) ;
USBH_MSC_CBWData.field.CBWCB[3] = (((uint8_t *)&address)[2]);
USBH_MSC_CBWData.field.CBWCB[4] = (((uint8_t *)&address)[1]);
USBH_MSC_CBWData.field.CBWCB[5] = (((uint8_t *)&address)[0]);
/*HOST_MSC_PAGE_LENGTH = 512*/
nbOfPages = (uint16_t)(nbOfbytes / HOST_MSC_PAGE_LENGTH);
/*Tranfer length */
USBH_MSC_CBWData.field.CBWCB[7] = (((uint8_t *)&nbOfPages)[1]) ;
USBH_MSC_CBWData.field.CBWCB[8] = (((uint8_t *)&nbOfPages)[0]) ;
USBH_MSC_BOTXferParam.BOTState = HOST_MSC_SEND_CBW;
/* Start the transfer, then let the state machine
magage the other transactions */
USBH_MSC_BOTXferParam.MSCState = HOST_MSC_BOT_USB_TRANSFERS;
USBH_MSC_BOTXferParam.BOTXferStatus = (uint8_t)USB_HOST_MSC_BUSY;
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_WAIT;
status = USB_HOST_MSC_BUSY;
break;
case USB_HOST_MSC_CMD_WAIT:
switch (USBH_MSC_BOTXferParam.BOTXferStatus) {
case USB_HOST_MSC_OK:
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_SEND;
status = USB_HOST_MSC_OK;
break;
case USB_HOST_MSC_FAIL:
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_SEND;
break;
case USB_HOST_MSC_PHASE_ERROR:
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_SEND;
status = USB_HOST_MSC_PHASE_ERROR;
break;
default:
break;
}
break;
default:
break;
}
}
return status;
}
/**
* @brief issue the read command to the device. Once the response received,
* it updates the status to upper layer
* @param [in] pdev device instance
* @param [in] dataBuffer data buffer will contain the data to be read
* @param [in] address Address from which the data will be read
* @param [in] nbOfbytes number of bytes to be read
* @retval status defined by USB_HOST_MSC_STATUS
*/
USB_HOST_MSC_STATUS usb_host_msc_Read10(usb_core_instance *pdev,
uint8_t *dataBuffer,
uint32_t address,
uint32_t nbOfbytes)
{
uint8_t index;
static USB_HOST_MSC_STATUS status = USB_HOST_MSC_BUSY;
uint16_t nbOfPages;
status = USB_HOST_MSC_BUSY;
if (host_driver_ifdevconnected(pdev) != 0UL) {
switch (USBH_MSC_BOTXferParam.CmdStateMachine) {
case USB_HOST_MSC_CMD_SEND:
/*Prepare the CBW and relevent field*/
USBH_MSC_CBWData.field.CBWTransferLength = nbOfbytes;
USBH_MSC_CBWData.field.CBWFlags = USB_EP_DIR_IN;
USBH_MSC_CBWData.field.CBWLength = CBW_LENGTH;
USBH_MSC_BOTXferParam.pRxTxBuff = dataBuffer;
for (index = 0U; index < CBW_CB_LENGTH; index++) {
USBH_MSC_CBWData.field.CBWCB[index] = 0x00U;
}
USBH_MSC_CBWData.field.CBWCB[0] = OPCODE_READ10;
/*logical block address*/
USBH_MSC_CBWData.field.CBWCB[2] = (((uint8_t *)&address)[3]);
USBH_MSC_CBWData.field.CBWCB[3] = (((uint8_t *)&address)[2]);
USBH_MSC_CBWData.field.CBWCB[4] = (((uint8_t *)&address)[1]);
USBH_MSC_CBWData.field.CBWCB[5] = (((uint8_t *)&address)[0]);
/*HOST_MSC_PAGE_LENGTH = 512*/
nbOfPages = (uint16_t)(nbOfbytes / HOST_MSC_PAGE_LENGTH);
/*Tranfer length */
USBH_MSC_CBWData.field.CBWCB[7] = (((uint8_t *)&nbOfPages)[1]) ;
USBH_MSC_CBWData.field.CBWCB[8] = (((uint8_t *)&nbOfPages)[0]) ;
USBH_MSC_BOTXferParam.BOTState = HOST_MSC_SEND_CBW;
/* Start the transfer, then let the state machine
magage the other transactions */
USBH_MSC_BOTXferParam.MSCState = HOST_MSC_BOT_USB_TRANSFERS;
USBH_MSC_BOTXferParam.BOTXferStatus = (uint8_t)USB_HOST_MSC_BUSY;
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_WAIT;
status = USB_HOST_MSC_BUSY;
break;
case USB_HOST_MSC_CMD_WAIT:
switch (USBH_MSC_BOTXferParam.BOTXferStatus) {
case USB_HOST_MSC_OK:
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_SEND;
status = USB_HOST_MSC_OK;
break;
case USB_HOST_MSC_FAIL:
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_SEND;
break;
case USB_HOST_MSC_PHASE_ERROR:
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_SEND;
status = USB_HOST_MSC_PHASE_ERROR;
break;
default:
break;
}
break;
default:
break;
}
}
return status;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/******************************************************************************
* EOF (not truncated)
*****************************************************************************/

View File

@ -0,0 +1,136 @@
/**
*******************************************************************************
* @file usb_host_msc_scsi.h
* @brief Head file for usb_host_msc_scsi.c
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
@endverbatim
*******************************************************************************
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
#ifndef __USB_HOST_MSC_SCSI_H__
#define __USB_HOST_MSC_SCSI_H__
/* C binding of definitions if building with C++ compiler */
#ifdef __cplusplus
extern "C"
{
#endif
/*******************************************************************************
* Include files
******************************************************************************/
#include "usb_host_stdreq.h"
/**
* @addtogroup LL_USB_LIB
* @{
*/
/**
* @addtogroup LL_USB_HOST_CLASS
* @{
*/
/**
* @addtogroup LL_USB_HOST_MSC
* @{
*/
/*******************************************************************************
* Global type definitions ('typedef')
******************************************************************************/
/* USBH_MSC_SCSI_Exported_Types */
typedef enum {
USB_HOST_MSC_OK = 0U,
USB_HOST_MSC_FAIL,
USB_HOST_MSC_PHASE_ERROR,
USB_HOST_MSC_BUSY
} USB_HOST_MSC_STATUS;
typedef struct {
uint32_t MSC_Capacity;
uint32_t MSC_Sense;
uint16_t MSC_PageLength;
uint8_t MSC_BulkOutEP;
uint8_t MSC_BulkInEP;
uint8_t MSC_WriteProtect;
} MSC_PARAMETER;
/*******************************************************************************
* Global pre-processor symbols/macros ('#define')
******************************************************************************/
#define USB_HOST_MSC_CMD_SEND (1)
#define USB_HOST_MSC_CMD_WAIT (2)
#define OPCODE_TEST_UNIT_READY (0x00U)
#define OPCODE_READ_CAPACITY10 (0x25U)
#define OPCODE_MODE_SENSE6 (0x1AU)
#define OPCODE_READ10 (0x28U)
#define OPCODE_WRITE10 (0x2AU)
#define OPCODE_REQUEST_SENSE (0x03U)
#define DESC_REQUEST_SENSE (0x00U)
#define ALLOCATION_LENGTH_REQUEST_SENSE (63U)
#define XFER_LEN_READ_CAPACITY10 (8U)
#define XFER_LEN_MODE_SENSE6 (63U)
#define MASK_MODE_SENSE_WRITE_PROTECT (0x80U)
#define MODE_SENSE_PAGE_CONTROL_FIELD (0x00U)
#define MODE_SENSE_PAGE_CODE (0x3FU)
#define DISK_WRITE_PROTECTED (0x01U)
/*******************************************************************************
* Global variable definitions ('extern')
******************************************************************************/
extern MSC_PARAMETER USB_HOST_MSC_Param;
/*******************************************************************************
Global function prototypes (definition in C source)
******************************************************************************/
extern USB_HOST_MSC_STATUS usb_host_msc_TestUnitReady(usb_core_instance *pdev);
extern USB_HOST_MSC_STATUS usb_host_msc_ReadCapacity10(usb_core_instance *pdev);
extern USB_HOST_MSC_STATUS usb_host_msc_ModeSense6(usb_core_instance *pdev);
extern USB_HOST_MSC_STATUS usb_host_msc_RequestSense(usb_core_instance *pdev);
extern USB_HOST_MSC_STATUS usb_host_msc_Write10(usb_core_instance *pdev,
uint8_t *dataBuffer,
uint32_t address,
uint32_t nbOfbytes);
extern USB_HOST_MSC_STATUS usb_host_msc_Read10(usb_core_instance *pdev,
uint8_t *dataBuffer,
uint32_t address,
uint32_t nbOfbytes);
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USB_HOST_MSC_SCSI_H__ */
/*******************************************************************************
* EOF (not truncated)
******************************************************************************/

View File

@ -0,0 +1,3 @@
SRC_FILES := usb_host_cfgch.c usb_host_core.c usb_host_ctrltrans.c usb_host_driver.c usb_host_int.c usb_host_stdreq.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,202 @@
/**
*******************************************************************************
* @file usb_host_cfgch.c
* @brief Functions for opening and closing host channels
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
@endverbatim
*******************************************************************************
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
/*******************************************************************************
* Include files
******************************************************************************/
#include "usb_host_cfgch.h"
/**
* @addtogroup LL_USB_LIB
* @{
*/
/**
* @addtogroup LL_USB_HOST_CORE LL USB Host Core
* @{
*/
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
uint16_t usb_host_getfreech(usb_core_instance *pdev);
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/**
* @brief configure and open a pipe
* @param [in] pdev device instance
* @param [in] hc_num host channel index
* @param [in] dev_address USB Device address allocated to attached device
* @param [in] speed core speed
* @param [in] ep_type communication type of the EP
* @param [in] mps max size of the packet
* @retval None
*/
void usb_host_chopen(usb_core_instance *pdev,
uint8_t hc_num,
uint8_t dev_address,
uint8_t speed,
uint8_t ep_type,
uint16_t mps)
{
pdev->host.hc[hc_num].ep_idx = (uint8_t) pdev->host.channel[hc_num] & 0x7Fu;
pdev->host.hc[hc_num].is_epin = (uint8_t)((pdev->host.channel[hc_num] & 0x80U) == 0x80U);
pdev->host.hc[hc_num].dev_addr = dev_address;
pdev->host.hc[hc_num].ep_type = ep_type;
pdev->host.hc[hc_num].max_packet = mps;
pdev->host.hc[hc_num].ch_speed = speed;
pdev->host.hc[hc_num].in_toggle = 0U;
pdev->host.hc[hc_num].out_toggle = 0U;
(void)usb_inithch(&pdev->regs, hc_num, &pdev->host.hc[hc_num], pdev->basic_cfgs.dmaen);
}
/**
* @brief change a pipe on host
* @param [in] pdev device instance
* @param [in] hc_num host channel index
* @param [in] dev_address USB Device address allocated to attached device
* @param [in] speed core speed
* @param [in] ep_type communication type of EP
* @param [in] mps max size of packet
* @retval None
*/
void usb_host_mdfch(usb_core_instance *pdev,
uint8_t hc_num,
uint8_t dev_address,
uint8_t speed,
uint8_t ep_type,
uint16_t mps)
{
(void)(ep_type);
if (dev_address != 0U) {
pdev->host.hc[hc_num].dev_addr = dev_address;
}
if ((pdev->host.hc[hc_num].max_packet != mps) && (mps != 0U)) {
pdev->host.hc[hc_num].max_packet = mps;
}
if ((pdev->host.hc[hc_num].ch_speed != speed) && (speed != 0U)) {
pdev->host.hc[hc_num].ch_speed = speed;
}
(void)usb_inithch(&pdev->regs, hc_num, &pdev->host.hc[hc_num], pdev->basic_cfgs.dmaen);
}
/**
* @brief distribute a new channel for the pipe
* @param [in] pdev device instance
* @param [in] ep_addr EP index the channel distributed for
* @retval hc_num host channel index
*/
uint8_t usb_host_distrch(usb_core_instance *pdev, uint8_t ep_addr)
{
__IO uint16_t hc_num;
hc_num = usb_host_getfreech(pdev);
if (hc_num != HC_ERROR) {
pdev->host.channel[hc_num & (USB_MAX_TX_FIFOS - 1U)] = HC_USED | ep_addr;
}
return (uint8_t)hc_num;
}
/**
* @brief free the USB host channel assigned by idx
* @param [in] pdev device instance
* @param [in] idx Channel number to be freed
* @retval Status
*/
uint8_t usb_host_freech(usb_core_instance *pdev, uint8_t idx)
{
if (idx < MAX_CHNUM) {
pdev->host.channel[idx & (USB_MAX_TX_FIFOS - 1U)] &= HC_USED_MASK;
}
return (uint8_t)HSTATUS_OK;
}
/**
* @brief free all the USB host channels
* @param [in] pdev device instance
* @retval None
*/
void usb_host_dedistrallch(usb_core_instance *pdev)
{
uint8_t idx;
for (idx = 2U; idx < MAX_CHNUM ; idx ++) {
pdev->host.channel[idx & (USB_MAX_TX_FIFOS - 1U)] = 0U;
}
}
/**
* @brief Get a free channel number so that can be distributed to a device endpoint
* @param [in] pdev device instance
* @retval idx the free channel index
*/
uint16_t usb_host_getfreech(usb_core_instance *pdev)
{
uint8_t tmp_idx;
uint16_t u16Ret = HC_ERROR;
for (tmp_idx = 0U ; tmp_idx < MAX_CHNUM ; tmp_idx++) {
if ((pdev->host.channel[tmp_idx & (USB_MAX_TX_FIFOS - 1U)] & HC_USED) == 0U) {
u16Ret = HC_OK;
break;
}
}
if (u16Ret == HC_OK) {
u16Ret = tmp_idx;
} else {
u16Ret = HC_ERROR;
}
return u16Ret;
}
/**
* @}
*/
/**
* @}
*/
/******************************************************************************
* EOF (not truncated)
*****************************************************************************/

View File

@ -0,0 +1,103 @@
/**
*******************************************************************************
* @file usb_host_cfgch.h
* @brief header file for the usb_host_cfgch.c
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
@endverbatim
*******************************************************************************
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
#ifndef __USB_HOST_CFGCH_H__
#define __USB_HOST_CFGCH_H__
/* C binding of definitions if building with C++ compiler */
#ifdef __cplusplus
extern "C"
{
#endif
/*******************************************************************************
* Include files
******************************************************************************/
#include "usb_host_def.h"
/**
* @addtogroup LL_USB_LIB
* @{
*/
/**
* @addtogroup LL_USB_HOST_CORE
* @{
*/
/*******************************************************************************
* Global type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Global pre-processor symbols/macros ('#define')
******************************************************************************/
/* USBH_HCS_Exported_Defines */
#define MAX_CHNUM (12U)
#define HC_OK (0x0000U)
#define HC_USED (0x8000U)
#define HC_ERROR (0xFFFFU)
#define HC_USED_MASK (0x7FFFU)
/*******************************************************************************
* Global variable definitions ('extern')
******************************************************************************/
/*******************************************************************************
Global function prototypes (definition in C source)
******************************************************************************/
extern uint8_t usb_host_distrch(usb_core_instance *pdev, uint8_t ep_addr);
extern uint8_t usb_host_freech(usb_core_instance *pdev, uint8_t idx);
extern void usb_host_dedistrallch(usb_core_instance *pdev);
extern void usb_host_chopen(usb_core_instance *pdev,
uint8_t hc_num,
uint8_t dev_address,
uint8_t speed,
uint8_t ep_type,
uint16_t mps);
extern void usb_host_mdfch(usb_core_instance *pdev,
uint8_t hc_num,
uint8_t dev_address,
uint8_t speed,
uint8_t ep_type,
uint16_t mps);
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USB_HOST_CFGCH_H__ */
/*******************************************************************************
* EOF (not truncated)
******************************************************************************/

View File

@ -0,0 +1,539 @@
/**
*******************************************************************************
* @file usb_host_core.c
* @brief The core state machine process the enumeration and the control transfer process
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
@endverbatim
*******************************************************************************
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
/*******************************************************************************
* Include files
******************************************************************************/
#include <stdio.h>
#include "usb_host_core.h"
#include "usb_host_cfgch.h"
#include "usb_host_ctrltrans.h"
#include "usb_host_driver.h"
#include "usb_host_stdreq.h"
#include "usb_host_int.h"
#include "usb_bsp.h"
/**
* @addtogroup LL_USB_LIB
* @{
*/
/**
* @addtogroup LL_USB_HOST_CORE
* @{
*/
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
HOST_STATUS usb_host_ctrlprocess(usb_core_instance *pdev, USBH_HOST *phost);
HOST_STATUS usb_host_enumprocess(usb_core_instance *pdev, USBH_HOST *phost);
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
static uint8_t Local_Buffer[ENUM_LOCAL_BUF];
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/**
* @brief initialization for the host application
* @param [in] pdev device instance
* @param [in] phost host state set
* @param [in] class_cbk the call back function for the class application
* @param [in] user_cbk the call back function for user
* @retval None
*/
void usb_host_init(usb_core_instance *pdev,
USBH_HOST *phost,
usb_host_class_callback_func *class_cbk,
usb_host_user_callback_func *user_cbk)
{
usb_bsp_init(pdev);
usb_host_deinit(pdev, phost);
phost->class_callbk = class_cbk;
phost->user_callbk = user_cbk;
host_driver_init(pdev);
phost->user_callbk->huser_init();
usb_bsp_nvicconfig();
}
/**
* @brief deinitialize the host application
* @param [in] pdev device instance
* @param [in] phost host state set
* @retval None
*/
void usb_host_deinit(usb_core_instance *pdev, USBH_HOST *phost)
{
phost->host_state = HOST_IDLE;
phost->host_state_backup = HOST_IDLE;
phost->enum_state = ENUM_IDLE;
phost->req_state = REQ_CMD_TX;
phost->ctrlparam.ctrl_state = CTRL_SETUP;
phost->ctrlparam.ctrlmaxsize = USB_MAX_EP0_SIZE;
phost->device_prop.devaddr = DEV_DEFAULT_ADDRESS;
phost->device_prop.devspeed = PRTSPD_FULL_SPEED;
(void)usb_host_freech(pdev, phost->ctrlparam.hc_num_in);
(void)usb_host_freech(pdev, phost->ctrlparam.hc_num_out);
}
/**
* @brief This is the main process function for the host core, it will process
* the main machine, such as connect,disconnect, emunation etc.
* @param [in] pdev device instance
* @param [in] phost host state set
* @retval None
*/
int usb_host_mainprocess(usb_core_instance *pdev, USBH_HOST *phost)
{
__IO HOST_STATUS tmp_status;
tmp_status = HSTATUS_FAIL;
HOST_HANDLE_STATE tmp_host_state;
if ((host_driver_ifdevconnected(pdev) == 0UL) && (phost->host_state != HOST_IDLE)) {
if (phost->host_state != HOST_DEV_DISCONNECTED) {
phost->host_state = HOST_DEV_DISCONNECTED;
}
}
if ((host_driver_ifdevconnected(pdev) == 0UL) && (phost->host_state == HOST_IDLE)
&& (host_driver_getvbusdrivestate(pdev) == 0UL)) {
phost->host_state = HOST_DEV_DISCONNECTED;
}
tmp_host_state = phost->host_state;
if (tmp_host_state == HOST_IDLE) {
if (0U != host_driver_ifdevconnected(pdev)) {
phost->host_state = HOST_DEV_CONNECTED;
usb_mdelay(50UL);
}
} else if (tmp_host_state == HOST_DEV_CONNECTED) {
#ifdef MSC_HID_COMPOSITE
if (host_driver_getcurrentspd(pdev) == 2) {
host_driver_init(pdev);
}
#endif /* MSC_HID_COMPOSITE */
phost->user_callbk->huser_devattached();
phost->ctrlparam.hc_num_out = usb_host_distrch(pdev, 0x00U);
phost->ctrlparam.hc_num_in = usb_host_distrch(pdev, 0x80U);
host_driver_portrst(pdev);
phost->user_callbk->huser_devreset();
phost->device_prop.devspeed = (uint8_t)host_driver_getcurrentspd(pdev);
phost->host_state = HOST_ENUM;
phost->user_callbk->huser_devspddetected(phost->device_prop.devspeed);
usb_host_chopen(pdev,
phost->ctrlparam.hc_num_in,
phost->device_prop.devaddr,
phost->device_prop.devspeed,
EP_TYPE_CTRL,
(uint16_t)phost->ctrlparam.ctrlmaxsize);
usb_host_chopen(pdev,
phost->ctrlparam.hc_num_out,
phost->device_prop.devaddr,
phost->device_prop.devspeed,
EP_TYPE_CTRL,
(uint16_t)phost->ctrlparam.ctrlmaxsize);
} else if (tmp_host_state == HOST_ENUM) {
if (usb_host_enumprocess(pdev, phost) == HSTATUS_OK) {
phost->user_callbk->huser_enumcompl();
phost->host_state = HOST_USER_INPUT;
}
} else if (tmp_host_state == HOST_USER_INPUT) {
if ((phost->class_callbk->host_class_init(pdev, phost)) == HSTATUS_OK) {
phost->host_state = HOST_CLASS_REQ;
}
} else if (tmp_host_state == HOST_CLASS_REQ) {
tmp_status = phost->class_callbk->host_class_request(pdev, phost);
if (tmp_status == HSTATUS_OK) {
phost->host_state = HOST_CLASS_PROCESS;
} else {
usb_host_errorprocess(phost, tmp_status);
}
} else if (tmp_host_state == HOST_CLASS_PROCESS) {
tmp_status = phost->class_callbk->host_class_process(pdev, phost);
usb_host_errorprocess(phost, tmp_status);
} else if (tmp_host_state == HOST_CTRL_TRANSMIT) {
(void)usb_host_ctrlprocess(pdev, phost);
} else if (tmp_host_state == HOST_ERROR_STATE) {
usb_host_deinit(pdev, phost);
phost->user_callbk->huser_deinit();
phost->class_callbk->host_class_deinit(pdev);
} else if (tmp_host_state == HOST_DEV_DISCONNECTED) {
phost->user_callbk->huser_devdisconn();
usb_host_deinit(pdev, phost);
phost->user_callbk->huser_deinit();
phost->class_callbk->host_class_deinit(pdev);
usb_host_dedistrallch(pdev);
phost->host_state = HOST_IDLE;
host_driver_init(pdev);
} else {
;
}
return 0;
}
/**
* @brief process the status when related error status happens.
* @param [in] phost host state set
* @param [in] errType host status
* @retval None
*/
void usb_host_errorprocess(USBH_HOST *phost, HOST_STATUS errType)
{
switch (errType) {
case HSTATUS_APP_DEINIT:
phost->host_state = HOST_ERROR_STATE;
phost->user_callbk->huser_init();
break;
case HSTATUS_SPEED_UNKNOWN:
case HSTATUS_UNRECOVERED_ERROR:
phost->user_callbk->huser_unrecoverederror();
phost->host_state = HOST_ERROR_STATE;
break;
default:
break;
}
}
/**
* @brief this function process all the emunation steps.
* @param [in] pdev device instance
* @param [in] phost host state set
* @retval status
*/
HOST_STATUS usb_host_enumprocess(usb_core_instance *pdev, USBH_HOST *phost)
{
HOST_STATUS tmp_status;
ENUM_HANDLE_STATE tmp_enum_state;
tmp_status = HSTATUS_BUSY;
tmp_enum_state = phost->enum_state;
if (tmp_enum_state == ENUM_IDLE) {
if (usb_host_getdevdesc(pdev, phost, 8U) == HSTATUS_OK) {
phost->ctrlparam.ctrlmaxsize = phost->device_prop.devdesc.bMaxPacketSize0;
host_driver_portrst(pdev);
phost->enum_state = ENUM_GET_FULL_DEVDESC;
usb_host_mdfch(pdev,
phost->ctrlparam.hc_num_out,
0U,
0U,
0U,
(uint16_t)phost->ctrlparam.ctrlmaxsize);
usb_host_mdfch(pdev,
phost->ctrlparam.hc_num_in,
0U,
0U,
0U,
(uint16_t)phost->ctrlparam.ctrlmaxsize);
}
}
if (tmp_enum_state == ENUM_GET_FULL_DEVDESC) {
if (usb_host_getdevdesc(pdev, phost, USB_DEVICE_DESC_SIZE) == HSTATUS_OK) {
phost->user_callbk->huser_devdescavailable(&phost->device_prop.devdesc);
phost->enum_state = ENUM_SET_DEVADDR;
}
}
if (tmp_enum_state == ENUM_SET_DEVADDR) {
if (usb_host_setdevaddr(pdev, phost, DEV_ASSIGNED_ADDRESS) == HSTATUS_OK) {
usb_mdelay(2UL);
phost->device_prop.devaddr = DEV_ASSIGNED_ADDRESS;
phost->user_callbk->huser_devaddrdistributed();
phost->enum_state = ENUM_GET_CFGDESC;
usb_host_mdfch(pdev,
phost->ctrlparam.hc_num_in,
phost->device_prop.devaddr,
0U,
0U,
0U);
usb_host_mdfch(pdev,
phost->ctrlparam.hc_num_out,
phost->device_prop.devaddr,
0U,
0U,
0U);
}
}
if (tmp_enum_state == ENUM_GET_CFGDESC) {
if (usb_host_getcfgdesc(pdev, phost, USB_CONFIGURATION_DESC_SIZE) == HSTATUS_OK) {
phost->enum_state = ENUM_GET_FULL_CFGDESC;
}
}
if (tmp_enum_state == ENUM_GET_FULL_CFGDESC) {
if (usb_host_getcfgdesc(pdev, phost, phost->device_prop.devcfgdesc.wTotalLength) == HSTATUS_OK) {
phost->user_callbk->huser_cfgdescavailable(&phost->device_prop.devcfgdesc,
phost->device_prop.devitfdesc,
phost->device_prop.devepdesc[0]);
phost->enum_state = ENUM_GET_MFCSTRINGDESC;
}
}
if (tmp_enum_state == ENUM_GET_MFCSTRINGDESC) {
if (phost->device_prop.devdesc.iManufacturer != (uint8_t)0) {
if (usb_host_getstringdesc(pdev,
phost,
phost->device_prop.devdesc.iManufacturer,
Local_Buffer,
0xffu) == HSTATUS_OK) {
phost->user_callbk->huser_mfcstring(Local_Buffer);
phost->enum_state = ENUM_GET_PRODUCT_STRINGDESC;
}
} else {
phost->user_callbk->huser_mfcstring("N/A");
phost->enum_state = ENUM_GET_PRODUCT_STRINGDESC;
}
}
if (tmp_enum_state == ENUM_GET_PRODUCT_STRINGDESC) {
if (phost->device_prop.devdesc.iProduct != (uint8_t)0) {
if (usb_host_getstringdesc(pdev,
phost,
phost->device_prop.devdesc.iProduct,
Local_Buffer,
0xffu) == HSTATUS_OK) {
phost->user_callbk->huser_productstring(Local_Buffer);
phost->enum_state = ENUM_GET_SERIALNUM_STRINGDESC;
}
} else {
phost->user_callbk->huser_productstring("N/A");
phost->enum_state = ENUM_GET_SERIALNUM_STRINGDESC;
}
}
if (tmp_enum_state == ENUM_GET_SERIALNUM_STRINGDESC) {
if (phost->device_prop.devdesc.iSerialNumber != (uint8_t)0) {
if (usb_host_getstringdesc(pdev,
phost,
phost->device_prop.devdesc.iSerialNumber,
Local_Buffer,
0xffu) == HSTATUS_OK) {
phost->user_callbk->huser_serialnum(Local_Buffer);
phost->enum_state = ENUM_SET_CFG;
}
} else {
phost->user_callbk->huser_serialnum("N/A");
phost->enum_state = ENUM_SET_CFG;
}
}
if (tmp_enum_state == ENUM_SET_CFG) {
if (usb_host_setconfig(pdev, phost,
(uint16_t)phost->device_prop.devcfgdesc.bConfigurationValue) == HSTATUS_OK) {
phost->enum_state = ENUM_DEV_CFG_OVER;
}
}
if (tmp_enum_state == ENUM_DEV_CFG_OVER) {
tmp_status = HSTATUS_OK;
} else {
;
}
return tmp_status;
}
/**
* @brief process the state machine of control transfer
* @param [in] pdev device instance
* @param [in] phost host state set
* @retval status
*/
HOST_STATUS usb_host_ctrlprocess(usb_core_instance *pdev, USBH_HOST *phost)
{
uint8_t direction;
CTRL_HANDLE_STATE tmp_ctrl_state;
static uint16_t timeout = 0;
HOST_STATUS status = HSTATUS_OK;
HOST_CH_XFER_STATE URB_Status;
phost->ctrlparam.ctrl_status = CTRL_START;
tmp_ctrl_state = phost->ctrlparam.ctrl_state;
if (tmp_ctrl_state == CTRL_SETUP) {
/* transmit a setup packet to the device */
usb_host_sendctrlsetup(pdev, phost->ctrlparam.setup.d8, phost->ctrlparam.hc_num_out);
phost->ctrlparam.ctrl_state = CTRL_SETUP_WAIT;
timeout = DATA_STAGE_TIMEOUT * 6U;
phost->ctrlparam.sof_num = (uint16_t)host_driver_getcurrentfrm(pdev);
} else if (tmp_ctrl_state == CTRL_SETUP_WAIT) {
URB_Status = host_driver_getxferstate(pdev, phost->ctrlparam.hc_num_out);
/* case SETUP packet sent successfully */
if (URB_Status == HOST_CH_XFER_DONE) {
/* parse the direction of the request from the setup just sent */
direction = (phost->ctrlparam.setup.b.bmRequestType & USB_REQ_DIR_MASK);
/* judge if there is a data stage, if wLength is not zero, there may be a in or out
data stage */
if (phost->ctrlparam.setup.b.wLength.w != 0U) {
timeout = DATA_STAGE_TIMEOUT;
if (direction == USB_D2H) {
/* Data Direction is IN, device should send data in */
phost->ctrlparam.ctrl_state = CTRL_DATA_IN;
} else {
/* Data Direction is OUT, host will send data out for device */
phost->ctrlparam.ctrl_state = CTRL_DATA_OUT;
}
}
/* No DATA stage */
else {
timeout = NODATA_STAGE_TIMEOUT;
/* If there is No Data Transfer Stage */
if (direction == USB_D2H) {
/* Data Direction is IN */
phost->ctrlparam.ctrl_state = CTRL_STATUS_OUT;
} else {
/* Data Direction is OUT */
phost->ctrlparam.ctrl_state = CTRL_STATUS_IN;
}
}
/* Set the delay timer to enable timeout for data stage completion */
phost->ctrlparam.sof_num = (uint16_t)host_driver_getcurrentfrm(pdev);
} else if (URB_Status == HOST_CH_XFER_ERROR) {
phost->ctrlparam.ctrl_state = CTRL_ERROR;
phost->ctrlparam.ctrl_status = CTRL_XACTERR;
} else if ((host_driver_getcurrentfrm(pdev) - phost->ctrlparam.sof_num) > timeout) {
#if (LL_PRINT_ENABLE == DDL_ON)
DDL_Printf("Device not responding\r\n");
#endif
} else {
;
}
} else if (tmp_ctrl_state == CTRL_DATA_IN) {
/* Issue an IN token */
usb_host_recvctrldata(pdev, phost->ctrlparam.buff, phost->ctrlparam.length, phost->ctrlparam.hc_num_in);
phost->ctrlparam.ctrl_state = CTRL_DATA_IN_WAIT;
} else if (tmp_ctrl_state == CTRL_DATA_IN_WAIT) {
URB_Status = host_driver_getxferstate(pdev, phost->ctrlparam.hc_num_in);
/* check is DATA packet transfered successfully */
if (URB_Status == HOST_CH_XFER_DONE) {
phost->ctrlparam.ctrl_state = CTRL_STATUS_OUT;
}
/* manage error cases*/
if (URB_Status == HOST_CH_XFER_STALL) {
/* In stall case, return to previous machine state*/
phost->host_state = phost->host_state_backup;
} else if (URB_Status == HOST_CH_XFER_ERROR) {
/* Device error */
phost->ctrlparam.ctrl_state = CTRL_ERROR;
} else if ((host_driver_getcurrentfrm(pdev) - phost->ctrlparam.sof_num) > timeout) {
/* timeout for IN transfer */
phost->ctrlparam.ctrl_state = CTRL_ERROR;
} else {
;
}
} else if (tmp_ctrl_state == CTRL_DATA_OUT) {
/* Start DATA out transfer (only one DATA packet)*/
pdev->host.hc[phost->ctrlparam.hc_num_out].out_toggle = 1;
usb_host_sendctrldata(pdev,
phost->ctrlparam.buff,
phost->ctrlparam.length,
phost->ctrlparam.hc_num_out);
phost->ctrlparam.ctrl_state = CTRL_DATA_OUT_WAIT;
} else if (tmp_ctrl_state == CTRL_DATA_OUT_WAIT) {
URB_Status = host_driver_getxferstate(pdev, phost->ctrlparam.hc_num_out);
switch (URB_Status) {
case HOST_CH_XFER_DONE:
phost->ctrlparam.ctrl_state = CTRL_STATUS_IN;
break;
case HOST_CH_XFER_STALL:
phost->host_state = phost->host_state_backup;
phost->ctrlparam.ctrl_state = CTRL_STALLED;
break;
case HOST_CH_XFER_UNREADY:
phost->ctrlparam.ctrl_state = CTRL_DATA_OUT;
break;
case HOST_CH_XFER_ERROR:
phost->ctrlparam.ctrl_state = CTRL_ERROR;
break;
default:
break;
}
} else if (tmp_ctrl_state == CTRL_STATUS_IN) {
/* receive a packet with 0 byte */
usb_host_recvctrldata(pdev, NULL, 0U, phost->ctrlparam.hc_num_in);
phost->ctrlparam.ctrl_state = CTRL_STATUS_IN_WAIT;
} else if (tmp_ctrl_state == CTRL_STATUS_IN_WAIT) {
URB_Status = host_driver_getxferstate(pdev, phost->ctrlparam.hc_num_in);
if (URB_Status == HOST_CH_XFER_DONE) {
/* Control transfers completed, Exit the State Machine */
phost->host_state = phost->host_state_backup;
phost->ctrlparam.ctrl_state = CTRL_COMPLETE;
} else if (URB_Status == HOST_CH_XFER_ERROR) {
phost->ctrlparam.ctrl_state = CTRL_ERROR;
} else if ((host_driver_getcurrentfrm(pdev) - phost->ctrlparam.sof_num) > timeout) {
phost->ctrlparam.ctrl_state = CTRL_ERROR;
} else if (URB_Status == HOST_CH_XFER_STALL) {
/* Control transfers completed, Exit the State Machine */
phost->host_state = phost->host_state_backup;
phost->ctrlparam.ctrl_status = CTRL_STALL;
status = HSTATUS_UNSUPPORTED;
} else {
;
}
} else if (tmp_ctrl_state == CTRL_STATUS_OUT) {
pdev->host.hc[phost->ctrlparam.hc_num_out].out_toggle ^= 1U;
usb_host_sendctrldata(pdev, NULL, 0U, phost->ctrlparam.hc_num_out);
phost->ctrlparam.ctrl_state = CTRL_STATUS_OUT_WAIT;
} else if (tmp_ctrl_state == CTRL_STATUS_OUT_WAIT) {
URB_Status = host_driver_getxferstate(pdev, phost->ctrlparam.hc_num_out);
switch (URB_Status) {
case HOST_CH_XFER_DONE:
phost->host_state = phost->host_state_backup;
phost->ctrlparam.ctrl_state = CTRL_COMPLETE;
break;
case HOST_CH_XFER_UNREADY:
phost->ctrlparam.ctrl_state = CTRL_STATUS_OUT;
break;
case HOST_CH_XFER_ERROR:
phost->ctrlparam.ctrl_state = CTRL_ERROR;
break;
default:
break;
}
} else if (tmp_ctrl_state == CTRL_ERROR) {
if (++ phost->ctrlparam.err_cnt <= HOST_MAX_ERROR_CNT) {
/* re-start the transmission, starting from SETUP packet */
phost->ctrlparam.ctrl_state = CTRL_SETUP;
} else {
phost->ctrlparam.ctrl_status = CTRL_FAIL;
phost->host_state = phost->host_state_backup;
status = HSTATUS_FAIL;
}
} else {
;
}
return status;
}
/**
* @}
*/
/**
* @}
*/
/*******************************************************************************
* EOF (not truncated)
******************************************************************************/

View File

@ -0,0 +1,95 @@
/**
*******************************************************************************
* @file usb_host_core.h
* @brief header file for the usb_host_core.c
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
@endverbatim
*******************************************************************************
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
#ifndef __USB_HOST_CORE_H__
#define __USB_HOST_CORE_H__
/* C binding of definitions if building with C++ compiler */
#ifdef __cplusplus
extern "C"
{
#endif
/*******************************************************************************
* Include files
******************************************************************************/
#include "usb_host_def.h"
/**
* @addtogroup LL_USB_LIB
* @{
*/
/**
* @addtogroup LL_USB_HOST_CORE
* @{
*/
/*******************************************************************************
* Global type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Global pre-processor symbols/macros ('#define')
******************************************************************************/
/* USBH_CORE_Exported_Defines */
#define MSC_CLASS (0x08U)
#define HID_CLASS (0x03U)
#define MSC_PROTOCOL (0x50U)
#define CBI_PROTOCOL (0x01U)
#define DEV_DEFAULT_ADDRESS (0U)
#define DEV_ASSIGNED_ADDRESS (1U)
#define HOST_MAX_ERROR_CNT (2U)
#define ENUM_LOCAL_BUF (256U)
/*******************************************************************************
* Global variable definitions ('extern')
******************************************************************************/
/*******************************************************************************
Global function prototypes (definition in C source)
******************************************************************************/
extern void usb_host_init(usb_core_instance *pdev,
USBH_HOST *phost,
usb_host_class_callback_func *class_cbk,
usb_host_user_callback_func *user_cbk);
extern void usb_host_deinit(usb_core_instance *pdev, USBH_HOST *phost);
extern int usb_host_mainprocess(usb_core_instance *pdev, USBH_HOST *phost);
extern void usb_host_errorprocess(USBH_HOST *phost, HOST_STATUS errType);
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USB_HOST_CORE_H__ */
/*******************************************************************************
* EOF (not truncated)
******************************************************************************/

View File

@ -0,0 +1,320 @@
/**
*******************************************************************************
* @file usb_host_ctrltrans.c
* @brief This file handles the issuing of the USB transactions
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
@endverbatim
*******************************************************************************
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
/*******************************************************************************
* Include files
******************************************************************************/
#include "usb_host_ctrltrans.h"
#include "usb_host_driver.h"
/**
* @addtogroup LL_USB_LIB
* @{
*/
/**
* @addtogroup LL_USB_HOST_CORE
* @{
*/
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
void usb_host_submitsetupreq(USBH_HOST *phost, uint8_t *buff, uint16_t length);
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/**
* @brief Start a setup transfer by changing the state-machine and
* initializing the required variables needed for the Control Transfer
* @param [in] phost host state set
* @param [in] buff data buffer used for setup request
* @param [in] length data length in byte
* @retval status
*/
void usb_host_submitsetupreq(USBH_HOST *phost, uint8_t *buff, uint16_t length)
{
/* Save Global State */
phost->host_state_backup = phost->host_state;
/* Prepare the Transactions */
phost->host_state = HOST_CTRL_TRANSMIT;
phost->ctrlparam.buff = buff;
phost->ctrlparam.length = length;
phost->ctrlparam.ctrl_state = CTRL_SETUP;
}
/**
* @brief send a control request and update the status after the request sent.
* @param [in] pdev device instance
* @param [in] phost host state set
* @param [in] buff data buffer whose data will be sent in the control pipe.
* @param [in] length length of the data sent.
* @retval status
*/
HOST_STATUS usb_host_ctrlreq(usb_core_instance *pdev,
USBH_HOST *phost,
uint8_t *buff,
uint16_t length)
{
HOST_STATUS status;
REQ_HANDLE_STATE tmp_req_state;
(void)(pdev);
status = HSTATUS_BUSY;
tmp_req_state = phost->req_state;
if (tmp_req_state == REQ_CMD_TX) {
/* prepare a setup packet for transferring */
usb_host_submitsetupreq(phost, buff, length);
/* update the request state */
phost->req_state = REQ_CMD_WAIT;
/* The status would be returned in this function */
status = HSTATUS_BUSY;
} else if (tmp_req_state == REQ_CMD_WAIT) {
switch (phost->ctrlparam.ctrl_state) {
case CTRL_COMPLETE:
/* Commands have been successfully sent and Responses have been Received */
phost->req_state = REQ_CMD_TX;
/* update the control state */
phost->ctrlparam.ctrl_state = CTRL_IDLE;
status = HSTATUS_OK;
break;
case CTRL_ERROR:
/* fail transfer */
phost->req_state = REQ_CMD_TX;
status = HSTATUS_FAIL;
break;
case CTRL_STALLED:
/* Commands have been successfully sent and Responses have been Received */
phost->req_state = REQ_CMD_TX;
status = HSTATUS_UNSUPPORTED;
break;
default:
break;
}
} else {
;
}
return status;
}
/**
* @brief sends a setup packet to the control EP of the USB device
* @param [in] pdev device instance
* @param [in] buff data buffer whose data will be sent in the control pipe to the control EP of the device.
* @param [in] hc_num host channel index
* @retval None
*/
void usb_host_sendctrlsetup(usb_core_instance *pdev, uint8_t *buff, uint8_t hc_num)
{
pdev->host.hc[hc_num].is_epin = 0U;
pdev->host.hc[hc_num].pid_type = PID_SETUP;
pdev->host.hc[hc_num].xfer_buff = buff;
pdev->host.hc[hc_num].xfer_len = 8;
(void)host_driver_submitrequest(pdev, hc_num);
}
/**
* @brief sends a data packet to the USB device
* @param [in] pdev device instance
* @param [in] buff data buffer whose data will be sent to the USB device
* @param [in] length the data length in byte that would be sent
* @param [in] hc_num host channel index
* @retval None
*/
void usb_host_sendctrldata(usb_core_instance *pdev, uint8_t *buff, uint16_t length, uint8_t hc_num)
{
pdev->host.hc[hc_num].is_epin = 0;
pdev->host.hc[hc_num].xfer_buff = buff;
pdev->host.hc[hc_num].xfer_len = length;
if (length == 0U) {
/* For Status OUT stage, Length==0, Status Out PID = 1 always */
pdev->host.hc[hc_num].out_toggle = 1;
}
/* Set the Data Toggle bit */
if (pdev->host.hc[hc_num].out_toggle == 0U) {
pdev->host.hc[hc_num].pid_type = PID_DATA0;
} else {
pdev->host.hc[hc_num].pid_type = PID_DATA1 ;
}
(void)host_driver_submitrequest(pdev, hc_num);
}
/**
* @brief Receives the response data to the setup packet
* @param [in] pdev device instance
* @param [in] buff data buffer when received data.
* @param [in] length the length data in byte have received.
* @param [in] hc_num host channel index
* @retval None
*/
void usb_host_recvctrldata(usb_core_instance *pdev, uint8_t *buff, uint16_t length, uint8_t hc_num)
{
pdev->host.hc[hc_num].is_epin = (uint8_t)1;
pdev->host.hc[hc_num].pid_type = PID_DATA1;
pdev->host.hc[hc_num].xfer_buff = buff;
pdev->host.hc[hc_num].xfer_len = length;
(void)host_driver_submitrequest(pdev, hc_num);
}
/**
* @brief sent the bulk packet to the device
* @param [in] pdev device instance
* @param [in] buff data buffer whose data will be sent
* @param [in] length data length in byte
* @param [in] hc_num host channel index
* @retval None
*/
void usb_host_sendbulkdata(usb_core_instance *pdev, uint8_t *buff, uint16_t length, uint8_t hc_num)
{
pdev->host.hc[hc_num].is_epin = 0;
pdev->host.hc[hc_num].xfer_buff = buff;
pdev->host.hc[hc_num].xfer_len = length;
/* Set the Data Toggle bit */
if (pdev->host.hc[hc_num].out_toggle == 0U) {
pdev->host.hc[hc_num].pid_type = PID_DATA0;
} else {
pdev->host.hc[hc_num].pid_type = PID_DATA1 ;
}
(void)host_driver_submitrequest(pdev, hc_num);
}
/**
* @brief receives bulk packet from device
* @param [in] pdev device instance
* @param [in] buff buffer to save the data received from the device
* @param [in] length data length in byte
* @param [in] hc_num host channel index
* @retval status
*/
void usb_host_recvbulkdata(usb_core_instance *pdev, uint8_t *buff, uint16_t length, uint8_t hc_num)
{
pdev->host.hc[hc_num].is_epin = (uint8_t)1;
pdev->host.hc[hc_num].xfer_buff = buff;
pdev->host.hc[hc_num].xfer_len = length;
if (pdev->host.hc[hc_num].in_toggle == (uint8_t)0) {
pdev->host.hc[hc_num].pid_type = PID_DATA0;
} else {
pdev->host.hc[hc_num].pid_type = PID_DATA1;
}
(void)host_driver_submitrequest(pdev, hc_num);
}
/**
* @brief receives the device response to the Interrupt IN token
* @param [in] pdev device instance
* @param [in] buff buffer to save the data received from the device
* @param [in] length data length in byte
* @param [in] hc_num host channel index
* @retval None
*/
void usb_host_recvintdata(usb_core_instance *pdev, uint8_t *buff, uint16_t length, uint8_t hc_num)
{
pdev->host.hc[hc_num].is_epin = (uint8_t)1;
pdev->host.hc[hc_num].xfer_buff = buff;
pdev->host.hc[hc_num].xfer_len = length;
if (pdev->host.hc[hc_num].in_toggle == (uint8_t)0) {
pdev->host.hc[hc_num].pid_type = PID_DATA0;
} else {
pdev->host.hc[hc_num].pid_type = PID_DATA1;
}
/* toggle the DATA PID */
pdev->host.hc[hc_num].in_toggle ^= (uint8_t)1;
(void)host_driver_submitrequest(pdev, hc_num);
}
/**
* @brief send the data on Interrupt OUT Endpoint
* @param [in] pdev device instance
* @param [in] buff data buffer whose data will be sent
* @param [in] length data length in byte
* @param [in] hc_num host channel index
* @retval None
*/
void usb_host_sentintdata(usb_core_instance *pdev, uint8_t *buff, uint16_t length, uint8_t hc_num)
{
pdev->host.hc[hc_num].is_epin = (uint8_t)0;
pdev->host.hc[hc_num].xfer_buff = buff;
pdev->host.hc[hc_num].xfer_len = length;
if (pdev->host.hc[hc_num].in_toggle == (uint8_t)0) {
pdev->host.hc[hc_num].pid_type = PID_DATA0;
} else {
pdev->host.hc[hc_num].pid_type = PID_DATA1;
}
pdev->host.hc[hc_num].in_toggle ^= (uint8_t)1;
(void)host_driver_submitrequest(pdev, hc_num);
}
/**
* @brief receives the Device Response to the Isochronous IN token
* @param [in] pdev device instance
* @param [in] buff buffer to save the data received from the device
* @param [in] length data length in byte
* @param [in] hc_num host channel index
* @retval None
*/
void usb_host_recvisocdata(usb_core_instance *pdev, uint8_t *buff, uint32_t length, uint8_t hc_num)
{
pdev->host.hc[hc_num].is_epin = (uint8_t)1;
pdev->host.hc[hc_num].xfer_buff = buff;
pdev->host.hc[hc_num].xfer_len = length;
pdev->host.hc[hc_num].pid_type = PID_DATA0;
(void)host_driver_submitrequest(pdev, hc_num);
}
/**
* @brief Sends the data through Isochronous OUT Endpoint
* @param [in] pdev device instance
* @param [in] buff data buffer whose data will be sent
* @param [in] length data length in byte
* @param [in] hc_num host channel index
* @retval None
*/
void usb_host_sendisocdata(usb_core_instance *pdev, uint8_t *buff, uint32_t length, uint8_t hc_num)
{
pdev->host.hc[hc_num].is_epin = (uint8_t)0;
pdev->host.hc[hc_num].xfer_buff = buff;
pdev->host.hc[hc_num].xfer_len = length;
pdev->host.hc[hc_num].pid_type = PID_DATA0;
(void)host_driver_submitrequest(pdev, hc_num);
}
/**
* @}
*/
/**
* @}
*/
/******************************************************************************
* EOF (not truncated)
*****************************************************************************/

View File

@ -0,0 +1,86 @@
/**
*******************************************************************************
* @file usb_host_ctrltrans.h
* @brief header file for the usb_host_ctrltrans.c
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
@endverbatim
*******************************************************************************
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
#ifndef __USB_HOST_CTRLTRANS_H__
#define __USB_HOST_CTRLTRANS_H__
/* C binding of definitions if building with C++ compiler */
#ifdef __cplusplus
extern "C"
{
#endif
/*******************************************************************************
* Include files
******************************************************************************/
#include "usb_host_def.h"
/**
* @addtogroup LL_USB_LIB
* @{
*/
/**
* @addtogroup LL_USB_HOST_CORE
* @{
*/
/*******************************************************************************
* Global type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Global pre-processor symbols/macros ('#define')
******************************************************************************/
/*******************************************************************************
* Global variable definitions ('extern')
******************************************************************************/
/*******************************************************************************
Global function prototypes (definition in C source)
******************************************************************************/
extern void usb_host_sendctrlsetup(usb_core_instance *pdev, uint8_t *buff, uint8_t hc_num);
extern void usb_host_sendctrldata(usb_core_instance *pdev, uint8_t *buff, uint16_t length, uint8_t hc_num);
extern void usb_host_recvctrldata(usb_core_instance *pdev, uint8_t *buff, uint16_t length, uint8_t hc_num);
extern void usb_host_recvbulkdata(usb_core_instance *pdev, uint8_t *buff, uint16_t length, uint8_t hc_num);
extern void usb_host_sendbulkdata(usb_core_instance *pdev, uint8_t *buff, uint16_t length, uint8_t hc_num);
extern void usb_host_recvintdata(usb_core_instance *pdev, uint8_t *buff, uint16_t length, uint8_t hc_num);
extern void usb_host_sentintdata(usb_core_instance *pdev, uint8_t *buff, uint16_t length, uint8_t hc_num);
extern HOST_STATUS usb_host_ctrlreq(usb_core_instance *pdev, USBH_HOST *phost, uint8_t *buff, uint16_t length);
extern void usb_host_recvisocdata(usb_core_instance *pdev, uint8_t *buff, uint32_t length, uint8_t hc_num);
extern void usb_host_sendisocdata(usb_core_instance *pdev, uint8_t *buff, uint32_t length, uint8_t hc_num);
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USB_HOST_CTRLTRANS_H__ */
/*******************************************************************************
* EOF (not truncated)
******************************************************************************/

View File

@ -0,0 +1,430 @@
/**
*******************************************************************************
* @file usb_host_def.h
* @brief Definitions used in the USB host library
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
@endverbatim
*******************************************************************************
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
#ifndef __USB_HOST_DEF_H__
#define __USB_HOST_DEF_H__
/* C binding of definitions if building with C++ compiler */
#ifdef __cplusplus
extern "C"
{
#endif
/*******************************************************************************
* Include files
******************************************************************************/
#include <stdint.h>
#include "usb_app_conf.h"
#include "usb_lib.h"
#include "hc32_ll.h"
/**
* @addtogroup LL_USB_LIB
* @{
*/
/**
* @addtogroup LL_USB_HOST_CORE
* @{
*/
/*******************************************************************************
* Global type definitions ('typedef')
******************************************************************************/
/* This Union is copied from usb_core.h */
typedef union {
uint16_t w;
struct BW {
uint8_t msb;
uint8_t lsb;
}
bw;
} uint16_t_uint8_t;
/* standard setup packet defination */
typedef union {
uint8_t d8[8];
struct _SetupPkt_Struc {
uint8_t bmRequestType;
uint8_t bRequest;
uint16_t_uint8_t wValue;
uint16_t_uint8_t wIndex;
uint16_t_uint8_t wLength;
} b;
} usb_setup_typedef;
typedef struct {
uint8_t bLength;
uint8_t bDescriptorType;
} USB_HOST_DescHeader_TypeDef;
/* Standard Device Descriptor */
typedef struct {
uint8_t bLength; /* Size of this descriptor in bytes */
uint8_t bDescriptorType; /* Device descriptor type */
uint16_t bcdUSB; /* USB Specification Release Numbrer in Binary-Coded Decimal(i.e.,2.10 is 210H) */
uint8_t bDeviceClass; /* Class code(assigned by the USB-IF) */
uint8_t bDeviceSubClass; /* Subclass code(assigned by the USB-IF) this code is qualified by the value of the \
bDeviceClass field. */
uint8_t bDeviceProtocol; /* Protocol code(assigned by the USB-IF), this code is qualified by the value of the \
bDeviceClass and the bDeviceSubClass fields. */
uint8_t bMaxPacketSize0; /* Maximum packet size for EP0 */
uint16_t idVendor; /* Vendor ID (assigned by the USB-IF) */
uint16_t idProduct; /* Product ID (assigned by manufacturer) */
uint16_t bcdDevice; /* 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's serial number */
uint8_t bNumConfigurations; /* Number of possible configurations */
} usb_host_devdesc_typedef;
/* Standard Configuration Descriptor */
typedef struct {
uint8_t bLength; /* Size of this descriptor in bytes */
uint8_t bDescriptorType; /* CONFIGURATION descriptor type */
uint16_t wTotalLength; /* Total length of data returned for this configuration */
uint8_t bNumInterfaces; /* Number of interfaces supported by this configuration */
uint8_t bConfigurationValue; /* Value to use as an argument to the SetConfiguration() request to select this configuration */
uint8_t iConfiguration; /* Index of string descriptor describing this configuration */
uint8_t bmAttributes; /* Configuration characteristics: D7:Reserved(set to one) D6:Self-powered D5:Remote Wakeup D4..0 Reserved(set to zero) */
uint8_t bMaxPower; /* Maximum power consumption of the device from the bus in this specific configuration when the device is fully operational */
} usb_host_cfgdesc_typedef;
typedef struct {
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t bcdHID; /* indicates what endpoint this descriptor is describing */
uint8_t bCountryCode; /* specifies the transfer type. */
uint8_t bNumDescriptors; /* specifies the transfer type. */
uint8_t bReportDescriptorType; /* Maximum Packet Size this endpoint is capable of sending or receiving */
uint16_t wItemLength; /* is used to specify the polling interval of certain transfers. */
} USB_HOST_HIDDesc_TypeDef;
/* Standard Interface Descriptor */
typedef struct {
uint8_t bLength; /* Size of this descriptor in bytes */
uint8_t bDescriptorType; /* INTERFACE Descriptor Type */
uint8_t bInterfaceNumber; /* Number of this interface */
uint8_t bAlternateSetting; /* Value used to select this alternate setting for the interface identifiled in the \
prior field */
uint8_t bNumEndpoints; /* Number of Endpoints used by this interface */
uint8_t bInterfaceClass; /* Class code (assigned by the USB-IF) */
uint8_t bInterfaceSubClass; /* Subclass code (assigned by the USB-IF) */
uint8_t bInterfaceProtocol; /* Protocol code (assigned by the USB) */
uint8_t iInterface; /* Index of string descriptor describing this interface */
} usb_host_itfdesc_typedef;
/* Standard Endpoint Descriptor */
typedef struct {
uint8_t bLength; /* Size of this descriptor in bytes */
uint8_t bDescriptorType; /* ENDPOINT descriptor type */
uint8_t bEndpointAddress; /* The address of the endpoint on the device described by this descriptor */
uint8_t bmAttributes; /* refer to the related standard of USB 2.0 */
uint16_t wMaxPacketSize; /* Maximum Packet Size this endpoint is capable of sending or receiving when this \
configuration is selected */
uint8_t bInterval; /* Interval for servicing the endpoint for data transfers */
} USB_HOST_EPDesc_TypeDef;
/* USBH_CORE_Exported_Types */
/* Host status */
typedef enum {
HSTATUS_OK = 0,
HSTATUS_BUSY,
HSTATUS_FAIL,
HSTATUS_UNSUPPORTED,
HSTATUS_UNRECOVERED_ERROR,
HSTATUS_SPEED_UNKNOWN,
HSTATUS_APP_DEINIT
} HOST_STATUS;
/* states about the handle stages on the host side */
typedef enum {
HOST_IDLE = 0,
HOST_DEV_CONNECTED,
HOST_DEV_DISCONNECTED,
HOST_GET_DEVSPEED,
HOST_ENUM,
HOST_CLASS_REQ,
HOST_CLASS_PROCESS,
HOST_CTRL_TRANSMIT,
HOST_USER_INPUT,
HOST_SUSPENDED,
HOST_ERROR_STATE
} HOST_HANDLE_STATE;
/* states of the enumeration stage on the host side */
typedef enum {
ENUM_IDLE = 0,
ENUM_GET_FULL_DEVDESC,
ENUM_SET_DEVADDR,
ENUM_GET_CFGDESC,
ENUM_GET_FULL_CFGDESC,
ENUM_GET_MFCSTRINGDESC,
ENUM_GET_PRODUCT_STRINGDESC,
ENUM_GET_SERIALNUM_STRINGDESC,
ENUM_SET_CFG,
ENUM_DEV_CFG_OVER
} ENUM_HANDLE_STATE;
/* states of the control stages on the host side */
typedef enum {
CTRL_IDLE = 0,
CTRL_SETUP,
CTRL_SETUP_WAIT,
CTRL_DATA_IN,
CTRL_DATA_IN_WAIT,
CTRL_DATA_OUT,
CTRL_DATA_OUT_WAIT,
CTRL_STATUS_IN,
CTRL_STATUS_IN_WAIT,
CTRL_STATUS_OUT,
CTRL_STATUS_OUT_WAIT,
CTRL_ERROR,
CTRL_STALLED,
CTRL_COMPLETE
} CTRL_HANDLE_STATE;
/* Following states are state machine for the request transferring */
typedef enum {
REQ_CMD_IDLE = 0,
REQ_CMD_TX,
REQ_CMD_WAIT
} REQ_HANDLE_STATE;
typedef enum {
USER_HAVE_RESP = 0,
USER_NONE_RESP
} HOST_USER_STATUS;
typedef struct {
uint8_t hc_num_in; /* channel number for the IN EP */
uint8_t hc_num_out; /* channel number for the OUT EP */
uint8_t ctrlmaxsize; /* the max size of EP0 parsed from the device descriptor */
uint8_t err_cnt; /* the error counter */
uint16_t sof_num; /* the frame number for sof packet */
uint16_t length; /* length of data in byte */
uint8_t *buff; /* data buffer */
CTRL_HANDLE_STATUS ctrl_status; /* status of control pipe */
CTRL_HANDLE_STATE ctrl_state; /* running state of the control transfer */
usb_setup_typedef setup; /* setup packet */
} usb_host_ctrl_param;
/* Device information parsed from the related descriptors requested from the connected device
the following data are all parsed from the data sent by the connnected device */
typedef struct {
uint8_t devaddr; /* the address of the connected device */
uint8_t devspeed; /* the core speed of the connected device */
usb_host_devdesc_typedef devdesc; /* the device descriptor parsed from the data sent by device */
usb_host_cfgdesc_typedef devcfgdesc; /* the device configuration descriptor parsed from the data sent by device */
usb_host_itfdesc_typedef devitfdesc[USBH_MAX_NUM_INTERFACES]; /* the interface descritpor */
USB_HOST_EPDesc_TypeDef devepdesc[USBH_MAX_NUM_INTERFACES][USBH_MAX_NUM_ENDPOINTS]; /* the endpoint descriptor */
USB_HOST_HIDDesc_TypeDef hiddesc; /* the hid descriptor */
} usb_host_devinformation;
typedef struct {
HOST_STATUS(*host_class_init)(usb_core_instance *pdev, void *phost);
void (*host_class_deinit)(usb_core_instance *pdev);
HOST_STATUS(*host_class_request)(usb_core_instance *pdev, void *phost);
HOST_STATUS(*host_class_process)(usb_core_instance *pdev, void *phost);
} usb_host_class_callback_func;
typedef struct {
void (*huser_init)(void);
void (*huser_deinit)(void);
void (*huser_devattached)(void);
void (*huser_devreset)(void);
void (*huser_devdisconn)(void);
void (*huser_overcurrent)(void);
void (*huser_devspddetected)(uint8_t DeviceSpeed);
void (*huser_devdescavailable)(void *);
void (*huser_devaddrdistributed)(void);
void (*huser_cfgdescavailable)(usb_host_cfgdesc_typedef *,
usb_host_itfdesc_typedef *,
USB_HOST_EPDesc_TypeDef *);
/* Configuration Descriptor available */
void (*huser_mfcstring)(void *);
void (*huser_productstring)(void *);
void (*huser_serialnum)(void *);
void (*huser_enumcompl)(void);
HOST_USER_STATUS(*huser_userinput)(void);
int (*huser_application)(void);
void (*huser_devunsupported)(void);
void (*huser_unrecoverederror)(void);
} usb_host_user_callback_func;
typedef struct {
/* states for the host, enumeration, request */
REQ_HANDLE_STATE req_state; /* value of state machine about the request */
ENUM_HANDLE_STATE enum_state; /* state machine while enumerating */
HOST_HANDLE_STATE host_state_backup; /* backup value of state machine about the host */
HOST_HANDLE_STATE host_state; /* value of state machine about the host */
/* control informations */
usb_host_ctrl_param ctrlparam; /* values about the control parameters */
/* device information parsed from the descriptors from the device */
usb_host_devinformation device_prop;
/* functions: call back functions for the class and user */
usb_host_class_callback_func *class_callbk;
usb_host_user_callback_func *user_callbk;
} USBH_HOST;
/*******************************************************************************
* Global pre-processor symbols/macros ('#define')
******************************************************************************/
#ifndef FALSE
#define FALSE 0U
#endif
#ifndef TRUE
#define TRUE 1U
#endif
/* Get a 16bits data from buffer in little end mode. */
#define SMALL_END(addr) (((uint16_t)(*((uint8_t *)(addr)))) + (((uint16_t)(*(((uint8_t *)(addr)) + 1U))) << 8U))
#define USB_LEN_CFG_DESC (0x09U)
/* bmRequestType
D7: Data transfer direction
0 = Host-to-device
1 = Device-to-host
*/
#define USB_REQ_DIR_MASK (0x80U)
#define USB_H2D (0x00U)
#define USB_D2H (0x80U)
/* bmRequestType
D6...5: Type
0 = Standard
1 = Class
2 = Vendor
3 = Reserved
*/
#define USB_REQ_TYPE_STANDARD (0x00U)
#define USB_REQ_TYPE_CLASS (0x20U)
#define USB_REQ_TYPE_VENDOR (0x40U)
#define USB_REQ_TYPE_RESERVED (0x60U)
/* bmRequestType
D4...0: Recipient
0 = Device
1 = Interface
2 = Endpoint
3 = Other
4...31 = Reserved
*/
#define USB_REQ_RECIPIENT_DEVICE (0x00U)
#define USB_REQ_RECIPIENT_INTERFACE (0x01U)
#define USB_REQ_RECIPIENT_ENDPOINT (0x02U)
#define USB_REQ_RECIPIENT_OTHER (0x03U)
/* Table 9-4. Standard Request Codes [USB Specification] */
/* bRequest Value */
#define USB_REQ_GET_STATUS (0x00U)
#define USB_REQ_CLEAR_FEATURE (0x01U)
#define USB_REQ_SET_FEATURE (0x03U)
#define USB_REQ_SET_ADDRESS (0x05U)
#define USB_REQ_GET_DESCRIPTOR (0x06U)
#define USB_REQ_SET_DESCRIPTOR (0x07U)
#define USB_REQ_GET_CONFIGURATION (0x08U)
#define USB_REQ_SET_CONFIGURATION (0x09U)
#define USB_REQ_GET_INTERFACE (0x0AU)
#define USB_REQ_SET_INTERFACE (0x0BU)
#define USB_REQ_SYNCH_FRAME (0x0Cu)
/* Table 9-5. Descriptor Types [USB Specification] */
/* Descriptor Types Value */
#define USB_DESC_TYPE_DEVICE (1U)
#define USB_DESC_TYPE_CONFIGURATION (2U)
#define USB_DESC_TYPE_STRING (3U)
#define USB_DESC_TYPE_INTERFACE (4U)
#define USB_DESC_TYPE_ENDPOINT (5U)
#define USB_DESC_TYPE_DEVICE_QUALIFIER (6U)
#define USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION (7U)
#define USB_DESC_TYPE_INTERFACE_POWER (8U)
#define USB_DESC_TYPE_HID (0x21U)
#define USB_DESC_TYPE_HID_REPORT (0x22U)
#define USB_DEVICE_DESC_SIZE (18U)
#define USB_CONFIGURATION_DESC_SIZE (9U)
#define USB_HID_DESC_SIZE (9U)
#define USB_INTERFACE_DESC_SIZE (9U)
#define USB_ENDPOINT_DESC_SIZE (7U)
/* Descriptor Type and Descriptor Index */
/* Use the following values when calling the function usb_host_getdesc */
#define USB_DESC_DEVICE (((uint16_t)USB_DESC_TYPE_DEVICE << 8U) & 0xFF00U)
#define USB_DESC_CONFIGURATION (((uint16_t)USB_DESC_TYPE_CONFIGURATION << 8U) & 0xFF00U)
#define USB_DESC_STRING (((uint16_t)USB_DESC_TYPE_STRING << 8U) & 0xFF00U)
#define USB_DESC_INTERFACE (((uint16_t)USB_DESC_TYPE_INTERFACE << 8U) & 0xFF00U)
#define USB_DESC_ENDPOINT (((uint16_t)USB_DESC_TYPE_INTERFACE << 8U) & 0xFF00U)
#define USB_DESC_DEVICE_QUALIFIER (((uint16_t)USB_DESC_TYPE_DEVICE_QUALIFIER << 8U) & 0xFF00U)
#define USB_DESC_OTHER_SPEED_CONFIGURATION (((uint16_t)USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION << 8U) & 0xFF00U)
#define USB_DESC_INTERFACE_POWER (((uint16_t)USB_DESC_TYPE_INTERFACE_POWER << 8U) & 0xFF00U)
#define USB_DESC_HID_REPORT (((uint16_t)USB_DESC_TYPE_HID_REPORT << 8U) & 0xFF00U)
#define USB_DESC_HID (((uint16_t)USB_DESC_TYPE_HID << 8U) & 0xFF00U)
#define USB_EP_DIR_OUT (0x00U)
#define USB_EP_DIR_IN (0x80U)
#define USB_EP_DIR_MSK (0x80U)
/* supported classes */
#define USB_MSC_CLASS (0x08U)
#define USB_HID_CLASS (0x03U)
/* Interface Descriptor field values for HID Boot Protocol */
#define HID_BOOT_CODE (0x01U)
#define HID_KEYBRD_BOOT_CODE (0x01U)
#define HID_MOUSE_BOOT_CODE (0x02U)
/* As per USB specs 9.2.6.4 :Standard request with data request timeout: 5sec
Standard request with no data stage timeout : 50ms */
#define DATA_STAGE_TIMEOUT (5000U)
#define NODATA_STAGE_TIMEOUT (50U)
/* Macro definations for host mode */
#define PID_DATA0 (0U)
#define PID_DATA2 (1U)
#define PID_DATA1 (2U)
#define PID_SETUP (3U)
/*******************************************************************************
* Global variable definitions ('extern')
******************************************************************************/
/*******************************************************************************
Global function prototypes (definition in C source)
******************************************************************************/
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USB_HOST_DEF_H__ */
/******************************************************************************
* EOF (not truncated)
*****************************************************************************/

View File

@ -0,0 +1,231 @@
/**
*******************************************************************************
* @file usb_host_driver.c
* @brief Host Interface Layer.
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
@endverbatim
*******************************************************************************
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
/*******************************************************************************
* Include files
******************************************************************************/
#include "usb_host_driver.h"
#include "usb_bsp.h"
/**
* @addtogroup LL_USB_LIB
* @{
*/
/**
* @addtogroup LL_USB_HOST_CORE
* @{
*/
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/**
* @brief Initialize the driver for the host mode
* @param [in] pdev device instance
* @retval None
*/
void host_driver_init(usb_core_instance *pdev)
{
uint8_t i;
pdev->host.is_dev_connect = 0U;
for (i = 0U; i < USB_MAX_TX_FIFOS; i++) {
pdev->host.ErrCnt[i] = 0U;
pdev->host.XferCnt[i] = 0U;
pdev->host.HC_Status[i] = HOST_CH_IDLE;
}
pdev->host.hc[0].max_packet = 8U;
usb_setregaddr(&pdev->regs, &pdev->basic_cfgs);;
usb_gintdis(&pdev->regs);
usb_initusbcore(&pdev->regs, &pdev->basic_cfgs);
/* force to work in host mode*/
usb_modeset(&pdev->regs, HOST_MODE);
/* configure charge pump IO */
usb_bsp_cfgvbus(&pdev->regs);
usb_vbusctrl(&pdev->regs, 1U);
usb_mdelay(50UL);
usb_hostmodeinit(&pdev->regs, &pdev->basic_cfgs);
usb_ginten(&pdev->regs);
}
/**
* @brief get current speed when in host mode
* @param [in] pdev device instance
* @retval current speed
*/
uint32_t host_driver_getcurrentspd(usb_core_instance *pdev)
{
uint32_t u32hppt;
u32hppt = READ_REG32(*pdev->regs.HPRT);
return ((u32hppt & USBFS_HPRT_PSPD) >> USBFS_HPRT_PSPD_POS);
}
/**
* @brief get current DM DP state
* @param [in] pdev device instance
* @retval DM DP state
* 0x00 DM L, DP L
* 0x01 DM L, DP H
* 0x02 DM H, DP L
* 0x03 DM H, DP H
*/
uint32_t host_driver_getdmdpstate(usb_core_instance *pdev)
{
uint32_t u32hppt;
u32hppt = READ_REG32(*pdev->regs.HPRT);
return ((u32hppt & USBFS_HPRT_PLSTS) >> USBFS_HPRT_PLSTS_POS);
}
/**
* @brief get vbus drive state
* @param [in] pdev device instance
* @retval vbus driver state
* 0x00 vbus driver disable
* 0x01 vbus driver enable
*/
uint32_t host_driver_getvbusdrivestate(usb_core_instance *pdev)
{
uint32_t u32hppt;
u32hppt = READ_REG32(*pdev->regs.HPRT);
return ((u32hppt & USBFS_HPRT_PWPR) >> USBFS_HPRT_PWPR_POS);
}
/**
* @brief reset the port
* @param [in] pdev device instance
* @retval None
*/
void host_driver_portrst(usb_core_instance *pdev)
{
usb_hprtrst(&pdev->regs);
}
/**
* @brief get the connected status of the device
* @param [in] pdev device instance
* @retval 1 connected or 0 disconnected
*/
uint32_t host_driver_ifdevconnected(usb_core_instance *pdev)
{
return (pdev->host.is_dev_connect);
}
/**
* @brief gets the frame number for of sof packet
* @param [in] pdev device instance
* @retval number of frame
*/
uint32_t host_driver_getcurrentfrm(usb_core_instance *pdev)
{
return (READ_REG32(pdev->regs.HREGS->HFNUM) & 0xFFFFUL) ;
}
/**
* @brief gets the last xfer state
* @param [in] pdev device instance
* @param [in] ch_num channel number
* @retval HOST_CH_XFER_STATE
*/
HOST_CH_XFER_STATE host_driver_getxferstate(usb_core_instance *pdev, uint8_t ch_num)
{
return pdev->host.URB_State[ch_num] ;
}
/**
* @brief gets the xfer count
* @param [in] pdev device instance
* @param [in] ch_num channel number
* @retval number of data trandmitted in bytes
*/
uint32_t host_driver_getxfercnt(usb_core_instance *pdev, uint8_t ch_num)
{
return pdev->host.XferCnt[ch_num] ;
}
/**
* @brief gets the host channel status
* @param [in] pdev device instance
* @param [in] ch_num channel number
* @retval HOST_CH_STATUS
*/
HOST_CH_STATUS host_driver_gethostchstate(usb_core_instance *pdev, uint8_t ch_num)
{
return pdev->host.HC_Status[ch_num] ;
}
/**
* @brief prepare a host channel and start a transfer
* @param [in] pdev device instance
* @param [in] hc_num channel number
* @retval status
*/
uint32_t host_driver_hostch_init(usb_core_instance *pdev, uint8_t hc_num)
{
return usb_inithch(&pdev->regs, hc_num, &pdev->host.hc[hc_num], pdev->basic_cfgs.dmaen);
}
/**
* @brief prepare a host channel and start a transfer
* @param [in] pdev device instance
* @param [in] hc_num channel number
* @retval status
*/
uint32_t host_driver_submitrequest(usb_core_instance *pdev, uint8_t hc_num)
{
pdev->host.URB_State[hc_num] = HOST_CH_XFER_IDLE;
pdev->host.hc[hc_num].xfer_count = 0U ;
return usb_hchtransbegin(&pdev->regs, hc_num, &pdev->host.hc[hc_num], pdev->basic_cfgs.dmaen);
}
/**
* @}
*/
/**
* @}
*/
/*******************************************************************************
* EOF (not truncated)
******************************************************************************/

View File

@ -0,0 +1,90 @@
/**
*******************************************************************************
* @file usb_host_driver.h
* @brief Head file for usb_host_driver.c
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
@endverbatim
*******************************************************************************
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
#ifndef __USB_HOST_DRIVER_H__
#define __USB_HOST_DRIVER_H__
/* C binding of definitions if building with C++ compiler */
#ifdef __cplusplus
extern "C"
{
#endif
/*******************************************************************************
* Include files
******************************************************************************/
#include "usb_host_def.h"
/**
* @addtogroup LL_USB_LIB
* @{
*/
/**
* @addtogroup LL_USB_HOST_CORE
* @{
*/
/*******************************************************************************
* Global type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Global pre-processor symbols/macros ('#define')
******************************************************************************/
/*******************************************************************************
* Global variable definitions ('extern')
******************************************************************************/
/*******************************************************************************
Global function prototypes (definition in C source)
******************************************************************************/
extern void host_driver_init(usb_core_instance *pdev);
extern uint32_t host_driver_hostch_init(usb_core_instance *pdev, uint8_t hc_num);
extern uint32_t host_driver_submitrequest(usb_core_instance *pdev, uint8_t hc_num);
extern uint32_t host_driver_getcurrentspd(usb_core_instance *pdev);
extern uint32_t host_driver_getdmdpstate(usb_core_instance *pdev);
extern uint32_t host_driver_getvbusdrivestate(usb_core_instance *pdev);
extern void host_driver_portrst(usb_core_instance *pdev);
extern uint32_t host_driver_ifdevconnected(usb_core_instance *pdev);
extern uint32_t host_driver_getcurrentfrm(usb_core_instance *pdev);
extern HOST_CH_XFER_STATE host_driver_getxferstate(usb_core_instance *pdev, uint8_t ch_num);
extern uint32_t host_driver_getxfercnt(usb_core_instance *pdev, uint8_t ch_num);
extern HOST_CH_STATUS host_driver_gethostchstate(usb_core_instance *pdev, uint8_t ch_num);
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USB_HOST_DRIVER_H__ */
/*******************************************************************************
* EOF (not truncated)
******************************************************************************/

View File

@ -0,0 +1,575 @@
/**
*******************************************************************************
* @file usb_host_int.c
* @brief Host driver interrupt subroutines.
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
@endverbatim
*******************************************************************************
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
/*******************************************************************************
* Include files
******************************************************************************/
#include "usb_host_int.h"
#include "usb_host_driver.h"
/**
* @addtogroup LL_USB_LIB
* @{
*/
/**
* @addtogroup LL_USB_HOST_CORE
* @{
*/
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
void usb_host_hc_isr(usb_core_instance *pdev);
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/**
* @brief processes interrupt for a specific host channel which is used for OUT EP
* @param [in] pdev device instance
* @param [in] chnum channel index
* @retval None
*/
static void usb_host_chx_out_isr(usb_core_instance *pdev, uint8_t chnum)
{
uint32_t u32hcchar;
uint32_t u32hcint;
uint32_t u32hcintmsk;
u32hcchar = READ_REG32(pdev->regs.HC_REGS[chnum]->HCCHAR);
u32hcint = READ_REG32(pdev->regs.HC_REGS[chnum]->HCINT);
u32hcintmsk = READ_REG32(pdev->regs.HC_REGS[chnum]->HCINTMSK);
u32hcint = u32hcint & u32hcintmsk;
if (0UL != (u32hcint & USBFS_HCINT_ACK)) {
usb_host_clrint(pdev, chnum, USBFS_HCINT_ACK);
}
#if defined (HC32F4A0)
else if (0UL != (u32hcint & USBFS_HCINT_AHBERR)) {
usb_host_clrint(pdev, chnum, USBFS_HCINT_AHBERR);
usb_host_int_unmskchhltd(pdev, chnum);
}
#endif
else if (0UL != (u32hcint & USBFS_HCINT_FRMOR)) {
usb_host_int_unmskchhltd(pdev, chnum);
usb_hchstop(&pdev->regs, chnum);
usb_host_clrint(pdev, chnum, USBFS_HCINT_FRMOR);
} else if (0UL != (u32hcint & USBFS_HCINT_XFRC)) {
pdev->host.ErrCnt[chnum] = 0U;
usb_host_int_unmskchhltd(pdev, chnum);
usb_hchstop(&pdev->regs, chnum);
usb_host_clrint(pdev, chnum, USBFS_HCINT_XFRC);
pdev->host.HC_Status[chnum] = HOST_CH_XFERCOMPL;
} else if (0UL != (u32hcint & USBFS_HCINT_STALL)) {
usb_host_clrint(pdev, chnum, USBFS_HCINT_STALL);
usb_host_int_unmskchhltd(pdev, chnum);
usb_hchstop(&pdev->regs, chnum);
pdev->host.HC_Status[chnum] = HOST_CH_STALL;
} else if (0UL != (u32hcint & USBFS_HCINT_NAK)) {
pdev->host.ErrCnt[chnum] = 0U;
usb_host_int_unmskchhltd(pdev, chnum);
usb_hchstop(&pdev->regs, chnum);
usb_host_clrint(pdev, chnum, USBFS_HCINT_NAK);
pdev->host.HC_Status[chnum] = HOST_CH_NAK;
} else if (0UL != (u32hcint & USBFS_HCINT_TXERR)) {
usb_host_int_unmskchhltd(pdev, chnum);
usb_hchstop(&pdev->regs, chnum);
pdev->host.ErrCnt[chnum] ++;
pdev->host.HC_Status[chnum] = HOST_CH_XACTERR;
usb_host_clrint(pdev, chnum, USBFS_HCINT_TXERR);
} else if (0UL != (u32hcint & HCINT_NYET)) {
pdev->host.ErrCnt[chnum] = 0U;
usb_host_int_unmskchhltd(pdev, chnum);
usb_hchstop(&pdev->regs, chnum);
usb_host_clrint(pdev, chnum, HCINT_NYET);
pdev->host.HC_Status[chnum] = HOST_CH_NYET;
} else if (0UL != (u32hcint & USBFS_HCINT_DTERR)) {
usb_host_int_unmskchhltd(pdev, chnum);
usb_hchstop(&pdev->regs, chnum);
usb_host_clrint(pdev, chnum, USBFS_HCINT_NAK);
pdev->host.HC_Status[chnum] = HOST_CH_DATATGLERR;
usb_host_clrint(pdev, chnum, USBFS_HCINT_DTERR);
} else if (0UL != (u32hcint & USBFS_HCINT_CHH)) {
usb_host_int_mskchhltd(pdev, chnum);
if (pdev->host.HC_Status[chnum] == HOST_CH_XFERCOMPL) {
pdev->host.URB_State[chnum] = HOST_CH_XFER_DONE;
if (((u32hcchar & USBFS_HCCHAR_EPTYP) >> USBFS_HCCHAR_EPTYP_POS) == EP_TYPE_BULK) {
pdev->host.hc[chnum].out_toggle ^= 1U;
}
} else if (pdev->host.HC_Status[chnum] == HOST_CH_NAK) {
pdev->host.URB_State[chnum] = HOST_CH_XFER_UNREADY;
} else if (pdev->host.HC_Status[chnum] == HOST_CH_NYET) {
if (pdev->host.hc[chnum].do_ping == 1U) {
usb_pingtokenissue(&pdev->regs, chnum);
}
pdev->host.URB_State[chnum] = HOST_CH_XFER_UNREADY;
} else if (pdev->host.HC_Status[chnum] == HOST_CH_STALL) {
pdev->host.URB_State[chnum] = HOST_CH_XFER_STALL;
} else if (pdev->host.HC_Status[chnum] == HOST_CH_XACTERR) {
if (pdev->host.ErrCnt[chnum] == 3UL) {
pdev->host.URB_State[chnum] = HOST_CH_XFER_ERROR;
pdev->host.ErrCnt[chnum] = 0UL;
}
} else {
;
}
usb_host_clrint(pdev, chnum, USBFS_HCINT_CHH);
} else {
;
}
}
/**
* @brief processes interrupt for a specific host Channel which is used for IN EP
* @param [in] pdev device instance
* @param [in] chnum channel index
* @retval None
*/
static void usb_host_chx_in_isr(usb_core_instance *pdev, uint8_t chnum)
{
uint32_t u32hcchar;
uint32_t u32hctsiz;
uint32_t u32eptypetmp;
uint32_t u32hcint;
uint32_t u32hcintmsk;
u32hcchar = READ_REG32(pdev->regs.HC_REGS[chnum]->HCCHAR);
u32hcint = READ_REG32(pdev->regs.HC_REGS[chnum]->HCINT);
u32hcintmsk = READ_REG32(pdev->regs.HC_REGS[chnum]->HCINTMSK);
u32hcint = u32hcint & u32hcintmsk;
u32eptypetmp = (u32hcchar & USBFS_HCCHAR_EPTYP) >> USBFS_HCCHAR_EPTYP_POS;
if (0UL != (u32hcint & USBFS_HCINT_ACK)) {
usb_host_clrint(pdev, chnum, USBFS_HCINT_ACK);
}
#if defined (HC32F4A0)
else if (0UL != (u32hcint & USBFS_HCINT_AHBERR)) {
usb_host_clrint(pdev, chnum, USBFS_HCINT_AHBERR);
usb_host_int_unmskchhltd(pdev, chnum);
}
#endif
else if (0UL != (u32hcint & USBFS_HCINT_STALL)) {
usb_host_int_unmskchhltd(pdev, chnum);
pdev->host.HC_Status[chnum] = HOST_CH_STALL;
usb_host_clrint(pdev, chnum, USBFS_HCINT_NAK);
usb_host_clrint(pdev, chnum, USBFS_HCINT_STALL);
usb_hchstop(&pdev->regs, chnum);
} else if (0UL != (u32hcint & USBFS_HCINT_DTERR)) {
usb_host_int_unmskchhltd(pdev, chnum);
usb_hchstop(&pdev->regs, chnum);
usb_host_clrint(pdev, chnum, USBFS_HCINT_NAK);
pdev->host.HC_Status[chnum] = HOST_CH_DATATGLERR;
usb_host_clrint(pdev, chnum, USBFS_HCINT_DTERR);
} else if (0UL != (u32hcint & USBFS_HCINT_FRMOR)) {
usb_host_int_unmskchhltd(pdev, chnum);
usb_hchstop(&pdev->regs, chnum);
usb_host_clrint(pdev, chnum, USBFS_HCINT_FRMOR);
} else if (0UL != (u32hcint & USBFS_HCINT_XFRC)) {
if (pdev->basic_cfgs.dmaen == 1U) {
u32hctsiz = READ_REG32(pdev->regs.HC_REGS[chnum]->HCTSIZ);
pdev->host.XferCnt[chnum] = pdev->host.hc[chnum].xfer_len - (u32hctsiz & USBFS_HCTSIZ_XFRSIZ);
}
pdev->host.HC_Status[chnum] = HOST_CH_XFERCOMPL;
pdev->host.ErrCnt [chnum] = 0U;
usb_host_clrint(pdev, chnum, USBFS_HCINT_XFRC);
switch (u32eptypetmp) {
case EP_TYPE_CTRL:
case EP_TYPE_BULK:
usb_host_int_unmskchhltd(pdev, chnum);
usb_hchstop(&pdev->regs, chnum);
usb_host_clrint(pdev, chnum, USBFS_HCINT_NAK);
pdev->host.hc[chnum].in_toggle ^= (uint8_t)1;
break;
case EP_TYPE_INTR:
u32hcchar |= USBFS_HCCHAR_ODDFRM;
WRITE_REG32(pdev->regs.HC_REGS[chnum]->HCCHAR, u32hcchar);
pdev->host.URB_State[chnum] = HOST_CH_XFER_DONE;
break;
case EP_TYPE_ISOC:
if (pdev->host.HC_Status[chnum] == HOST_CH_XFERCOMPL) {
pdev->host.URB_State[chnum] = HOST_CH_XFER_DONE;
}
break;
default:
break;
}
} else if (0UL != (u32hcint & USBFS_HCINT_CHH)) {
usb_host_int_mskchhltd(pdev, chnum);
if (pdev->host.HC_Status[chnum] == HOST_CH_XFERCOMPL) {
pdev->host.URB_State[chnum] = HOST_CH_XFER_DONE;
} else if (pdev->host.HC_Status[chnum] == HOST_CH_STALL) {
pdev->host.URB_State[chnum] = HOST_CH_XFER_STALL;
} else if (pdev->host.HC_Status[chnum] == HOST_CH_XACTERR) {
pdev->host.ErrCnt[chnum] = 0U;
pdev->host.URB_State[chnum] = HOST_CH_XFER_ERROR;
} else if (pdev->host.HC_Status[chnum] == HOST_CH_DATATGLERR) {
pdev->host.ErrCnt[chnum] = 0U;
pdev->host.URB_State[chnum] = HOST_CH_XFER_ERROR;
} else if (u32eptypetmp == EP_TYPE_INTR) {
pdev->host.hc[chnum].in_toggle ^= (uint8_t)1;
} else {
;
}
usb_host_clrint(pdev, chnum, USBFS_HCINT_CHH);
} else if (0UL != (u32hcint & USBFS_HCINT_TXERR)) {
usb_host_int_unmskchhltd(pdev, chnum);
pdev->host.ErrCnt[chnum] ++;
pdev->host.HC_Status[chnum] = HOST_CH_XACTERR;
usb_hchstop(&pdev->regs, chnum);
usb_host_clrint(pdev, chnum, USBFS_HCINT_TXERR);
} else if (0UL != (u32hcint & USBFS_HCINT_NAK)) {
if (u32eptypetmp == EP_TYPE_INTR) {
usb_host_int_unmskchhltd(pdev, chnum);
usb_hchstop(&pdev->regs, chnum);
} else if ((u32eptypetmp == EP_TYPE_CTRL) || (u32eptypetmp == EP_TYPE_BULK)) {
u32hcchar |= USBFS_HCCHAR_CHENA;
u32hcchar &= ~USBFS_HCCHAR_CHDIS;
WRITE_REG32(pdev->regs.HC_REGS[chnum]->HCCHAR, u32hcchar);
} else {
;
}
pdev->host.HC_Status[chnum] = HOST_CH_NAK;
usb_host_clrint(pdev, chnum, USBFS_HCINT_NAK);
} else {
;
}
}
/**
* @brief this function processes the channel interrupt
* @param [in] pdev device instance
* @retval None
*/
void usb_host_hc_isr(usb_core_instance *pdev)
{
uint32_t u32hcchar;
uint8_t u8Cnt;
uint32_t u32haint;
u32haint = READ_REG32(pdev->regs.HREGS->HAINT);
for (u8Cnt = 0U; u8Cnt < pdev->basic_cfgs.host_chnum; u8Cnt++) {
if (0UL != (u32haint & (1UL << u8Cnt))) {
u32hcchar = READ_REG32(pdev->regs.HC_REGS[u8Cnt]->HCCHAR);
if (0UL != ((u32hcchar & USBFS_HCCHAR_EPDIR) >> USBFS_HCCHAR_EPDIR_POS)) {
usb_host_chx_in_isr(pdev, u8Cnt);
} else {
usb_host_chx_out_isr(pdev, u8Cnt);
}
}
}
}
/**
* @brief process the start-of-frame interrupt in host mode.
* @param [in] pdev device instance
* @retval None
*/
static void usb_host_sof_isr(usb_core_instance *pdev)
{
WRITE_REG32(pdev->regs.GREGS->GINTSTS, USBFS_GINTSTS_SOF);
}
/**
* @brief processes disconnect interrupt
* @param [in] pdev device instance
* @retval None
*/
static void usb_host_disconn_isr(usb_core_instance *pdev)
{
usb_gintdis(&pdev->regs);
usb_vbusctrl(&pdev->regs, 0U);
WRITE_REG32(pdev->regs.GREGS->GINTSTS, USBFS_GINTSTS_DISCINT);
pdev->host.is_dev_connect = 0U;
}
#define USBFS_HNPTXSTS_NPTXQTOP_CHEPNUM_POS (27U)
#define USBFS_HNPTXSTS_NPTXQTOP_CHEPNUM (0x78000000UL)
/**
* @brief processes non-periodic txFIFO empty interrupt.
* @param [in] pdev device instance
* @retval None
*/
static void usb_host_nptxfifoempty_isr(usb_core_instance *pdev)
{
uint32_t u32hnptxsts;
uint16_t u16LenWord;
uint16_t u16Len;
uint8_t u8ChNum;
u32hnptxsts = READ_REG32(pdev->regs.GREGS->HNPTXSTS);
u8ChNum = (uint8_t)((u32hnptxsts & USBFS_HNPTXSTS_NPTXQTOP_CHEPNUM) >> USBFS_HNPTXSTS_NPTXQTOP_CHEPNUM_POS);
u16LenWord = (uint16_t)((pdev->host.hc[u8ChNum].xfer_len + 3UL) / 4UL);
while (((u32hnptxsts & USBFS_HNPTXSTS_NPTXFSAV) > u16LenWord) && (pdev->host.hc[u8ChNum].xfer_len != 0U)) {
u16Len = (uint16_t)((u32hnptxsts & USBFS_HNPTXSTS_NPTXFSAV) * 4UL);
if (u16Len > pdev->host.hc[u8ChNum].xfer_len) {
u16Len = (uint16_t)pdev->host.hc[u8ChNum].xfer_len;
CLR_REG32_BIT(pdev->regs.GREGS->GINTMSK, USBFS_GINTSTS_NPTXFE);
}
u16LenWord = (uint16_t)((pdev->host.hc[u8ChNum].xfer_len + 3UL) / 4UL);
usb_wrpkt(&pdev->regs, pdev->host.hc[u8ChNum].xfer_buff, u8ChNum, u16Len, pdev->basic_cfgs.dmaen);
pdev->host.hc[u8ChNum].xfer_buff += u16Len;
pdev->host.hc[u8ChNum].xfer_len -= u16Len;
pdev->host.hc[u8ChNum].xfer_count += u16Len;
u32hnptxsts = READ_REG32(pdev->regs.GREGS->HNPTXSTS);
}
}
#define USBFS_HPTXSTS_PTXQTOP_CHNUM_POS (27U)
#define USBFS_HPTXSTS_PTXQTOP_CHNUM (0x78000000UL)
/**
* @brief processes periodic txFIFO empty interrupt
* @param [in] pdev device instance
* @retval None
*/
static void usb_host_ptxfifoempty_isr(usb_core_instance *pdev)
{
uint32_t u32hptxsts;
uint16_t u16LenWord;
uint16_t u16Len;
uint8_t u8ChNum;
u32hptxsts = READ_REG32(pdev->regs.HREGS->HPTXSTS);
u8ChNum = (uint8_t)((u32hptxsts & USBFS_HPTXSTS_PTXQTOP_CHNUM) >> USBFS_HPTXSTS_PTXQTOP_CHNUM_POS);
u16LenWord = (uint16_t)((pdev->host.hc[u8ChNum].xfer_len + 3UL) / 4UL);
while ((((u32hptxsts & USBFS_HPTXSTS_PTXFSAVL)) > u16LenWord) && (pdev->host.hc[u8ChNum].xfer_len != 0U)) {
u16Len = (uint16_t)((u32hptxsts & USBFS_HPTXSTS_PTXFSAVL) * 4UL);
if (u16Len > pdev->host.hc[u8ChNum].xfer_len) {
u16Len = (uint16_t)pdev->host.hc[u8ChNum].xfer_len;
CLR_REG32_BIT(pdev->regs.GREGS->GINTMSK, USBFS_GINTMSK_PTXFEM);
}
u16LenWord = (uint16_t)((pdev->host.hc[u8ChNum].xfer_len + 3UL) / 4UL);
usb_wrpkt(&pdev->regs, pdev->host.hc[u8ChNum].xfer_buff, u8ChNum, u16Len, pdev->basic_cfgs.dmaen);
pdev->host.hc[u8ChNum].xfer_buff += u16Len;
pdev->host.hc[u8ChNum].xfer_len -= u16Len;
pdev->host.hc[u8ChNum].xfer_count += u16Len;
u32hptxsts = READ_REG32(pdev->regs.HREGS->HPTXSTS);
}
}
/**
* @brief This function determines which interrupt conditions have occurred
* @param [in] pdev device instance
* @retval None
*/
static void usb_host_port_isr(usb_core_instance *pdev)
{
uint32_t u32hprt;
uint32_t u32hprt_bk;
uint8_t u8fslspclksel;
uint32_t do_reset = 0UL;
uint8_t u8PortSpeed;
u32hprt = READ_REG32(*pdev->regs.HPRT);
u32hprt_bk = u32hprt;
/* Clear the interrupt bits in GINTSTS */
//tmp_hprt_bk.b.prtovrcurrchng = 0U; //todo don't have this bit
u32hprt_bk &= ~(USBFS_HPRT_PENA | USBFS_HPRT_PCDET | USBFS_HPRT_PENCHNG);
/* check if a port connect have been detected */
if ((u32hprt & USBFS_HPRT_PCDET) != 0UL) {
u32hprt_bk |= USBFS_HPRT_PCDET;
if (host_driver_getvbusdrivestate(pdev) != 0UL) {
pdev->host.is_dev_connect = 1U;
}
}
/* check if port enable or disable change */
if ((u32hprt & USBFS_HPRT_PENCHNG) != 0UL) {
u32hprt_bk |= USBFS_HPRT_PENCHNG;
if ((u32hprt & USBFS_HPRT_PENA) != 0UL) {
u8PortSpeed = (uint8_t)((u32hprt & USBFS_HPRT_PSPD) >> USBFS_HPRT_PSPD_POS);
if ((u8PortSpeed == PRTSPD_LOW_SPEED) || (u8PortSpeed == PRTSPD_FULL_SPEED)) {
u8fslspclksel = (uint8_t)(READ_REG32(pdev->regs.HREGS->HCFG) & USBFS_HCFG_FSLSPCS);
if (u8PortSpeed == PRTSPD_LOW_SPEED) {
if (u8fslspclksel != HCFG_6_MHZ) {
do_reset = 1U;
}
} else {
/* 1ms*(PHY clock frequency for FS/LS)-1 */
WRITE_REG32(pdev->regs.HREGS->HFIR, 48000UL);
if (u8fslspclksel != HCFG_48_MHZ) {
usb_fslspclkselset(&pdev->regs, HCFG_48_MHZ);
do_reset = 1U;
}
}
} else {
do_reset = 1U;
}
}
}
//todo don't have this bit
//if ((u32hprt & USBFS_HPRT_PRTOVRCURRCHNG) != 0UL) {
// u32hprt_bk |= USBFS_HPRT_PRTOVRCURRCHNG;
//}
if (0UL != do_reset) {
usb_hprtrst(&pdev->regs);
}
WRITE_REG32(*pdev->regs.HPRT, u32hprt_bk);
}
/**
* @brief processes the rxFIFO non-empty interrupt
* @param [in] pdev device instance
* @retval None
*/
static void usb_host_rxflvl_isr(usb_core_instance *pdev)
{
uint32_t u32grxsts;
uint32_t u32hctsiz;
uint32_t u32hcchar;
uint8_t u8chnum;
uint8_t *pu8Tmp;
uint16_t u16bcnt;
CLR_REG32_BIT(pdev->regs.GREGS->GINTMSK, USBFS_GINTSTS_RXFNE);
u32grxsts = READ_REG32(pdev->regs.GREGS->GRXSTSP);
u8chnum = (uint8_t)(u32grxsts & USBFS_GRXSTSP_CHNUM_EPNUM);
u16bcnt = (uint16_t)((u32grxsts & USBFS_GRXSTSP_BCNT) >> USBFS_GRXSTSP_BCNT_POS);
u32hcchar = READ_REG32(pdev->regs.HC_REGS[u8chnum]->HCCHAR);
switch ((u32grxsts & USBFS_GRXSTSP_PKTSTS) >> USBFS_GRXSTSP_PKTSTS_POS) {
case 2: /* IN dat packet received */
pu8Tmp = pdev->host.hc[u8chnum].xfer_buff;
if ((u16bcnt > 0U) && (pu8Tmp != (void *)0U)) {
usb_rdpkt(&pdev->regs, pdev->host.hc[u8chnum].xfer_buff, u16bcnt);
pdev->host.hc[u8chnum].xfer_buff += u16bcnt;
pdev->host.hc[u8chnum].xfer_count += u16bcnt;
pdev->host.XferCnt[u8chnum] = pdev->host.hc[u8chnum].xfer_count;
u32hctsiz = READ_REG32(pdev->regs.HC_REGS[u8chnum]->HCTSIZ);
if (((u32hctsiz & USBFS_HCTSIZ_PKTCNT) >> USBFS_HCTSIZ_PKTCNT_POS) > 0U) {
u32hcchar |= USBFS_HCCHAR_CHENA;
u32hcchar &= ~USBFS_HCCHAR_CHDIS;
WRITE_REG32(pdev->regs.HC_REGS[u8chnum]->HCCHAR, u32hcchar);
}
}
break;
case 3: /* IN transfer completed(trigger an interrupt) */
break;
case 5: /* Daat toggle error(trigger an interrupt) */
break;
case 7: /* Channel halted(trigger an interrupt) */
break;
default:
break;
}
SET_REG32_BIT(pdev->regs.GREGS->GINTMSK, USBFS_GINTSTS_RXFNE);
}
/**
* @brief process the incomplete periodic transfer interrupt(incompIP)
* @param [in] pdev device instance
* @retval None
*/
static void usb_host_incomplisoout_isr(usb_core_instance *pdev)
{
SET_REG32_BIT(pdev->regs.HC_REGS[0]->HCCHAR, USBFS_HCCHAR_CHENA | USBFS_HCCHAR_CHDIS);
WRITE_REG32(pdev->regs.GREGS->GINTSTS, USBFS_GINTSTS_IPXFR_INCOMPISOOUT);
}
/**
* @brief process the resume/remote wakeup detected interrupt(WkUpInt)
* @param [in] pdev device instance
* @retval None
*/
static void usb_host_wkupint_isr(usb_core_instance *pdev)
{
uint32_t u32hprt;
u32hprt = usb_rdhprt(&pdev->regs);
u32hprt &= ~USBFS_HPRT_PRES;
WRITE_REG32(*pdev->regs.HPRT, u32hprt);
}
/**
* @brief This function process all interrupt of USB in host mode
* @param [in] pdev device instance
* @retval None
*/
void usb_host_isr(usb_core_instance *pdev)
{
uint32_t gintstsval;
if (0U != usb_getcurmod(&pdev->regs)) {
gintstsval = usb_getcoreintr(&pdev->regs);
if (0UL != (gintstsval & USBFS_GINTSTS_SOF)) {
usb_host_sof_isr(pdev);
}
if (0UL != (gintstsval & USBFS_GINTSTS_RXFNE)) {
usb_host_rxflvl_isr(pdev);
}
if (0UL != (gintstsval & USBFS_GINTSTS_NPTXFE)) {
usb_host_nptxfifoempty_isr(pdev);
}
if (0UL != (gintstsval & USBFS_GINTSTS_PTXFE)) {
usb_host_ptxfifoempty_isr(pdev);
}
if (0UL != (gintstsval & USBFS_GINTSTS_HCINT)) {
usb_host_hc_isr(pdev);
}
if (0UL != (gintstsval & USBFS_GINTSTS_HPRTINT)) {
usb_host_port_isr(pdev);
}
if (0UL != (gintstsval & USBFS_GINTSTS_DISCINT)) {
usb_host_disconn_isr(pdev);
}
if (0UL != (gintstsval & USBFS_GINTSTS_IPXFR_INCOMPISOOUT)) {
usb_host_incomplisoout_isr(pdev);
}
if (0UL != (gintstsval & USBFS_GINTSTS_WKUINT)) {
usb_host_wkupint_isr(pdev);
}
}
}
/**
* @}
*/
/**
* @}
*/
/******************************************************************************
* EOF (not truncated)
*****************************************************************************/

View File

@ -0,0 +1,128 @@
/**
*******************************************************************************
* @file usb_host_int.h
* @brief Head file for usb_host_int.c
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
@endverbatim
*******************************************************************************
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
#ifndef __USB_HOST_INT_H__
#define __USB_HOST_INT_H__
/* C binding of definitions if building with C++ compiler */
#ifdef __cplusplus
extern "C"
{
#endif
/*******************************************************************************
* Include files
******************************************************************************/
#include "usb_host_def.h"
/**
* @addtogroup LL_USB_LIB
* @{
*/
/**
* @addtogroup LL_USB_HOST_CORE
* @{
*/
/*******************************************************************************
* Global pre-processor symbols/macros ('#define')
******************************************************************************/
#define HCINT_NYET (1UL << 6)
/*******************************************************************************
Global function prototypes (definition in C source)
******************************************************************************/
/**
* @brief clear the interrupt flag bit
* @param [in] pdev device instance
* @param [in] ch_num the channel index
* @param [in] intbit the interrupt bit of the register HCINTn
* @retval None
*/
__STATIC_INLINE void usb_host_clrint(usb_core_instance *pdev, uint32_t ch_num, uint32_t intbit)
{
WRITE_REG32(pdev->regs.HC_REGS[ch_num]->HCINT, intbit);
}
/**
* @brief mask the interrupt of ChHltd
* @param [in] pdev device instance
* @param [in] ch_num channel index of the host application
* @retval None
*/
__STATIC_INLINE void usb_host_int_mskchhltd(usb_core_instance *pdev, uint32_t ch_num)
{
CLR_REG32_BIT(pdev->regs.HC_REGS[ch_num]->HCINTMSK, USBFS_HCINTMSK_CHHM);
}
/**
* @brief unmask the interrupt of ChHltd
* @param [in] pdev device instance
* @param [in] ch_num channel index of the host application
* @retval None
*/
__STATIC_INLINE void usb_host_int_unmskchhltd(usb_core_instance *pdev, uint32_t ch_num)
{
SET_REG32_BIT(pdev->regs.HC_REGS[ch_num]->HCINTMSK, USBFS_HCINTMSK_CHHM);
}
/**
* @brief mask the interrupt of ACK
* @param [in] pdev device instance
* @param [in] ch_num channel index of the host application
* @retval None
*/
__STATIC_INLINE void usb_host_int_mskack(usb_core_instance *pdev, uint32_t ch_num)
{
CLR_REG32_BIT(pdev->regs.HC_REGS[ch_num]->HCINTMSK, USBFS_HCINTMSK_ACKM);
}
/**
* @brief unmask the interrupt of ACK
* @param [in] pdev device instance
* @param [in] ch_num channel index of the host application
* @retval None
*/
__STATIC_INLINE void usb_host_int_unmskack(usb_core_instance *pdev, uint32_t ch_num)
{
SET_REG32_BIT(pdev->regs.HC_REGS[ch_num]->HCINTMSK, USBFS_HCINTMSK_ACKM);
}
void usb_host_isr(usb_core_instance *pdev);
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USB_HOST_INT_H__ */
/*******************************************************************************
* EOF (not truncated)
******************************************************************************/

View File

@ -0,0 +1,482 @@
/**
*******************************************************************************
* @file usb_host_stdreq.c
* @brief Standard requests for device enumeration
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
@endverbatim
*******************************************************************************
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
/*******************************************************************************
* Include files
******************************************************************************/
#include "usb_host_stdreq.h"
#include "usb_host_ctrltrans.h"
/**
* @addtogroup LL_USB_LIB
* @{
*/
/**
* @addtogroup LL_USB_HOST_CORE
* @{
*/
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
/*******************************************************************************
* Local function prototypes declared in the last part.
******************************************************************************/
void usb_host_parsedevdesc(usb_host_devdesc_typedef *, uint8_t *buf, uint16_t length);
void usb_host_parsecfgdesc(usb_host_cfgdesc_typedef *cfg_desc,
usb_host_itfdesc_typedef *itf_desc,
USB_HOST_EPDesc_TypeDef ep_desc[][USBH_MAX_NUM_ENDPOINTS],
uint8_t *buf,
uint16_t length);
void usb_host_parseitfdesc(usb_host_itfdesc_typedef *if_descriptor, uint8_t *buf);
void usb_host_parseepdesc(USB_HOST_EPDesc_TypeDef *ep_descriptor, uint8_t *buf);
void usb_host_parsestringdesc(uint8_t *psrc, uint8_t *pdest, uint16_t length);
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
/**
* @brief issue a command descriptor from the connected device. parses the
* descriptor and updates the status once the response has been received.
* @param [in] pdev device instance
* @param [in] phost host state set
* @param [in] req_type type of the descriptor
* @param [in] value_idx wValue of setup for the request to get Descriptr
* @param [in] buff: buffer to save the the descriptor
* @param [in] length the length of the description.
* @retval status
*/
HOST_STATUS usb_host_getdesc(usb_core_instance *pdev,
USBH_HOST *phost,
uint8_t req_type,
uint16_t value_idx,
uint8_t *buff,
uint16_t length)
{
phost->ctrlparam.setup.b.bmRequestType = USB_D2H | req_type;
phost->ctrlparam.setup.b.bRequest = USB_REQ_GET_DESCRIPTOR;
phost->ctrlparam.setup.b.wValue.w = value_idx;
if ((value_idx & 0xff00U) == USB_DESC_STRING) {
phost->ctrlparam.setup.b.wIndex.w = 0x0409U;
} else {
phost->ctrlparam.setup.b.wIndex.w = 0U;
}
phost->ctrlparam.setup.b.wLength.w = length;
return usb_host_ctrlreq(pdev, phost, buff, length);
}
/**
* @brief Issue command to the device to get the device discription. it parses
* the device descriptor and updates the status once getting the device
* description.
* @param [in] pdev device instance
* @param [in] phost host state set.
* @param [in] length the length of the description.
* @retval status
*/
HOST_STATUS usb_host_getdevdesc(usb_core_instance *pdev,
USBH_HOST *phost,
uint8_t length)
{
HOST_STATUS status;
status = usb_host_getdesc(pdev,
phost,
(uint8_t)(USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD),
USB_DESC_DEVICE,
pdev->host.Rx_Buffer,
(uint16_t)length);
if (status == HSTATUS_OK) {
/* Commands successfully sent and Response Received */
usb_host_parsedevdesc(&phost->device_prop.devdesc, pdev->host.Rx_Buffer, (uint16_t)length);
}
return status;
}
/**
* @brief Issue a command to get the configuration description from the device
* connected, parse the configuration descriptor and update the
* status once the response has been received.
* @param [in] pdev device instance
* @param [in] phost host state set.
* @param [in] length the length of the description.
* @retval status
*/
HOST_STATUS usb_host_getcfgdesc(usb_core_instance *pdev,
USBH_HOST *phost,
uint16_t length)
{
HOST_STATUS status;
status = usb_host_getdesc(pdev,
phost,
USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD,
USB_DESC_CONFIGURATION,
pdev->host.Rx_Buffer,
length);
if (status == HSTATUS_OK) {
usb_host_parsecfgdesc(&phost->device_prop.devcfgdesc,
phost->device_prop.devitfdesc,
phost->device_prop.devepdesc,
pdev->host.Rx_Buffer,
length);
}
return status;
}
/**
* @brief Issues string Descriptor command to the device. Once the response
* received, it parses the string descriptor and updates the status.
* @param [in] pdev device instance
* @param [in] phost host state set
* @param [in] string_index the index for the string
* @param [in] buff buffer to save the the string descriptor
* @param [in] length the length of the description.
* @retval status
*/
HOST_STATUS usb_host_getstringdesc(usb_core_instance *pdev,
USBH_HOST *phost,
uint8_t string_index,
uint8_t *buff,
uint16_t length)
{
HOST_STATUS status;
status = usb_host_getdesc(pdev,
phost,
USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD,
USB_DESC_STRING | string_index,
pdev->host.Rx_Buffer,
length);
if (status == HSTATUS_OK) {
usb_host_parsestringdesc(pdev->host.Rx_Buffer, buff, length);
}
return status;
}
/**
* @brief issue a command to set the address for the device that have connected.
* @param [in] pdev device instance
* @param [in] phost host state set
* @param [in] DeviceAddress Device address which would be set to the conected device
* @retval status
*/
HOST_STATUS usb_host_setdevaddr(usb_core_instance *pdev,
USBH_HOST *phost,
uint8_t DeviceAddress)
{
/*
Refer to table9-3 of 9.4
*/
phost->ctrlparam.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD;
phost->ctrlparam.setup.b.bRequest = USB_REQ_SET_ADDRESS;
phost->ctrlparam.setup.b.wValue.w = (uint16_t)DeviceAddress;
phost->ctrlparam.setup.b.wIndex.w = 0U;
phost->ctrlparam.setup.b.wLength.w = 0U;
return usb_host_ctrlreq(pdev, phost, NULL, 0U);
}
/**
* @brief issue a command to set the configuration to the connected device.
* @param [in] pdev device instance
* @param [in] phost host state set
* @param [in] cfg_idx value for the configuration setup
* @retval status
*/
HOST_STATUS usb_host_setconfig(usb_core_instance *pdev,
USBH_HOST *phost,
uint16_t cfg_idx)
{
phost->ctrlparam.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD;
phost->ctrlparam.setup.b.bRequest = USB_REQ_SET_CONFIGURATION;
phost->ctrlparam.setup.b.wValue.w = cfg_idx;
phost->ctrlparam.setup.b.wIndex.w = 0U;
phost->ctrlparam.setup.b.wLength.w = 0U;
return usb_host_ctrlreq(pdev, phost, NULL, 0U);
}
/**
* @brief issue a command to set the Interface value to the connected device
* @param [in] pdev device instance
* @param [in] phost host state set
* @param [in] ep_num the index of the endpoint
* @param [in] altSetting the value for the setup of set interface
* @retval status
*/
HOST_STATUS usb_host_setintf(usb_core_instance *pdev,
USBH_HOST *phost,
uint8_t ep_num,
uint8_t altSetting)
{
phost->ctrlparam.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_INTERFACE | USB_REQ_TYPE_STANDARD;
phost->ctrlparam.setup.b.bRequest = USB_REQ_SET_INTERFACE;
phost->ctrlparam.setup.b.wValue.w = altSetting;
phost->ctrlparam.setup.b.wIndex.w = ep_num;
phost->ctrlparam.setup.b.wLength.w = 0U;
return usb_host_ctrlreq(pdev, phost, NULL, 0U);
}
/**
* @brief issue a comman to clear or disable a specific feature in the device.
* @param [in] pdev device instance
* @param [in] phost host state set
* @param [in] ep_num index of the endpoint
* @param [in] hc_num host channel index
* @retval status
*/
HOST_STATUS usb_host_clrfeature(usb_core_instance *pdev,
USBH_HOST *phost,
uint8_t ep_num,
uint8_t hc_num)
{
phost->ctrlparam.setup.b.bmRequestType = USB_H2D |
USB_REQ_RECIPIENT_ENDPOINT |
USB_REQ_TYPE_STANDARD;
phost->ctrlparam.setup.b.bRequest = USB_REQ_CLEAR_FEATURE;
phost->ctrlparam.setup.b.wValue.w = FEATURE_SELECTOR_ENDPOINT;
phost->ctrlparam.setup.b.wIndex.w = ep_num;
phost->ctrlparam.setup.b.wLength.w = 0U;
if ((ep_num & USB_REQ_DIR_MASK) == USB_D2H) {
pdev->host.hc[hc_num].in_toggle = 0U;
} else {
pdev->host.hc[hc_num].out_toggle = 0U;
}
return usb_host_ctrlreq(pdev, phost, NULL, 0U);
}
/**
* @brief parse the data frame of device descriptor
* @param [in] dev_desc the structure of the device descriptor
* @param [in] buf buffer where the source descriptor is save
* @param [in] length Length of the descriptor in byte
* @retval None
*/
void usb_host_parsedevdesc(usb_host_devdesc_typedef *dev_desc,
uint8_t *buf,
uint16_t length)
{
dev_desc->bLength = *(uint8_t *)(buf + 0U);
dev_desc->bDescriptorType = *(uint8_t *)(buf + 1U);
dev_desc->bcdUSB = SMALL_END(buf + 2U);
dev_desc->bDeviceClass = *(uint8_t *)(buf + 4U);
dev_desc->bDeviceSubClass = *(uint8_t *)(buf + 5U);
dev_desc->bDeviceProtocol = *(uint8_t *)(buf + 6U);
dev_desc->bMaxPacketSize0 = *(uint8_t *)(buf + 7U);
if (length > (uint16_t)8) {
dev_desc->idVendor = SMALL_END(buf + 8U);
dev_desc->idProduct = SMALL_END(buf + 10U);
dev_desc->bcdDevice = SMALL_END(buf + 12U);
dev_desc->iManufacturer = *(uint8_t *)(buf + 14U);
dev_desc->iProduct = *(uint8_t *)(buf + 15U);
dev_desc->iSerialNumber = *(uint8_t *)(buf + 16U);
dev_desc->bNumConfigurations = *(uint8_t *)(buf + 17U);
}
}
/**
* @brief This function Parses the configuration descriptor from the received buffer
* @param [in] cfg_desc the structure of configuration descriptor
* @param [in] itf_desc the structure of interface descriptor
* @param [in] ep_desc the structure of endpoint descriptor
* @param [in] buf buffer where the source descriptor is save
* @param [in] length Length of the descriptor in byte
* @retval None
*/
void usb_host_parsecfgdesc(usb_host_cfgdesc_typedef *cfg_desc,
usb_host_itfdesc_typedef *itf_desc,
USB_HOST_EPDesc_TypeDef ep_desc[][USBH_MAX_NUM_ENDPOINTS],
uint8_t *buf,
uint16_t length)
{
usb_host_itfdesc_typedef *pif ;
usb_host_itfdesc_typedef temp_pif ;
USB_HOST_EPDesc_TypeDef *pep;
USB_HOST_DescHeader_TypeDef *pdesc = (USB_HOST_DescHeader_TypeDef *)buf;
uint16_t ptr;
int8_t if_ix;
int8_t ep_ix;
static uint16_t prev_ep_size = 0U;
static uint8_t prev_itf = 0U;
/* Parse the configuration descriptor */
cfg_desc->bLength = *(uint8_t *)(buf + 0U);
cfg_desc->bDescriptorType = *(uint8_t *)(buf + 1U);
cfg_desc->wTotalLength = SMALL_END(buf + 2U);
cfg_desc->bNumInterfaces = *(uint8_t *)(buf + 4U);
cfg_desc->bConfigurationValue = *(uint8_t *)(buf + 5U);
cfg_desc->iConfiguration = *(uint8_t *)(buf + 6U);
cfg_desc->bmAttributes = *(uint8_t *)(buf + 7U);
cfg_desc->bMaxPower = *(uint8_t *)(buf + 8U);
if (length > USB_CONFIGURATION_DESC_SIZE) {
ptr = USB_LEN_CFG_DESC;
if (cfg_desc->bNumInterfaces <= USBH_MAX_NUM_INTERFACES) {
while (ptr < cfg_desc->wTotalLength) {
pdesc = usb_host_getnextdesc((uint8_t *)pdesc, &ptr);
if (pdesc->bDescriptorType == USB_DESC_TYPE_INTERFACE) {
if_ix = (int8_t) * (((uint8_t *)pdesc) + 2U);
pif = &itf_desc[if_ix];
if ((*((uint8_t *)pdesc + 3U)) < 3U) {
usb_host_parseitfdesc(&temp_pif, (uint8_t *)pdesc);
ep_ix = (int8_t)0;
/* Parse Ep descriptors relative to the current interface */
if (temp_pif.bNumEndpoints <= USBH_MAX_NUM_ENDPOINTS) {
while (ep_ix < (int8_t)temp_pif.bNumEndpoints) {
pdesc = usb_host_getnextdesc((void *)pdesc, &ptr);
if (pdesc->bDescriptorType == USB_DESC_TYPE_ENDPOINT) {
pep = &ep_desc[if_ix][ep_ix];
if (prev_itf != (uint8_t)if_ix) {
prev_itf = (uint8_t)if_ix;
usb_host_parseitfdesc(pif, (uint8_t *)&temp_pif);
} else {
if (prev_ep_size > SMALL_END((uint8_t *)pdesc + 4U)) {
break;
} else {
usb_host_parseitfdesc(pif, (uint8_t *)&temp_pif);
}
}
usb_host_parseepdesc(pep, (uint8_t *)pdesc);
prev_ep_size = SMALL_END((uint8_t *)pdesc + 4U);
ep_ix++;
}
}
}
}
}
}
}
prev_ep_size = 0U;
prev_itf = 0U;
}
}
/**
* @brief This function parses the interface descriptor from the received buffer.
* @param [in] if_descriptor structure of interface descriptor
* @param [in] buf buffer where the source descriptor is save
* @retval None
*/
void usb_host_parseitfdesc(usb_host_itfdesc_typedef *if_descriptor, uint8_t *buf)
{
if_descriptor->bLength = *(uint8_t *)(buf + 0U);
if_descriptor->bDescriptorType = *(uint8_t *)(buf + 1U);
if_descriptor->bInterfaceNumber = *(uint8_t *)(buf + 2U);
if_descriptor->bAlternateSetting = *(uint8_t *)(buf + 3U);
if_descriptor->bNumEndpoints = *(uint8_t *)(buf + 4U);
if_descriptor->bInterfaceClass = *(uint8_t *)(buf + 5U);
if_descriptor->bInterfaceSubClass = *(uint8_t *)(buf + 6U);
if_descriptor->bInterfaceProtocol = *(uint8_t *)(buf + 7U);
if_descriptor->iInterface = *(uint8_t *)(buf + 8U);
}
/**
* @brief This function parses the endpoint descriptor from the received buffer.
* @param [in] ep_descriptor the structure of endpoint descriptor.
* @param [in] buf buffer where the source descriptor is save
* @retval None
*/
void usb_host_parseepdesc(USB_HOST_EPDesc_TypeDef *ep_descriptor, uint8_t *buf)
{
ep_descriptor->bLength = *(uint8_t *)(buf + 0U);
ep_descriptor->bDescriptorType = *(uint8_t *)(buf + 1U);
ep_descriptor->bEndpointAddress = *(uint8_t *)(buf + 2U);
ep_descriptor->bmAttributes = *(uint8_t *)(buf + 3U);
ep_descriptor->wMaxPacketSize = SMALL_END(buf + 4U);
ep_descriptor->bInterval = *(uint8_t *)(buf + 6U);
}
/**
* @brief This function parses the string descriptor from the received buffer.
* @param [in] psrc source data
* @param [in] pdest destination data
* @param [in] length Length of the descriptor in byte
* @retval None
*/
void usb_host_parsestringdesc(uint8_t *psrc, uint8_t *pdest, uint16_t length)
{
uint16_t strlength;
uint16_t tmp_idx;
/*
The describ of String Desctipor refers to 9.6.8
psrc[0] = bLength bLength = N+2
psrc[1] = bDescriptorType STRING Descriptor Type
...
*/
if (psrc[1] == USB_DESC_TYPE_STRING) {
strlength = ((((uint16_t)psrc[0]) - 2U) <= length) ? (((uint16_t)psrc[0]) - 2U) : length;
psrc += 2U;
for (tmp_idx = 0U; tmp_idx < strlength; tmp_idx += 2U) {
*pdest = psrc[tmp_idx];
pdest++;
}
*pdest = 0U;
}
}
/**
* @brief This function gets the header of next descriptor.
* @param [in] pbuf buffer where the configuration descriptor is contained.
* @param [in] ptr data popinter inside the cfg descriptor
* @retval header of next descriptor
*/
USB_HOST_DescHeader_TypeDef *usb_host_getnextdesc(uint8_t *pbuf, uint16_t *ptr)
{
USB_HOST_DescHeader_TypeDef *pnext;
*ptr += ((USB_HOST_DescHeader_TypeDef *)pbuf)->bLength;
pnext = (USB_HOST_DescHeader_TypeDef *)((uint8_t *)pbuf + ((USB_HOST_DescHeader_TypeDef *)pbuf)->bLength);
return (pnext);
}
/**
* @}
*/
/**
* @}
*/
/******************************************************************************
* EOF (not truncated)
*****************************************************************************/

View File

@ -0,0 +1,107 @@
/**
*******************************************************************************
* @file usb_host_stdreq.h
* @brief Header file for usb_host_stdreq.c
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
@endverbatim
*******************************************************************************
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
#ifndef __USB_HOST_STDREQ_H__
#define __USB_HOST_STDREQ_H__
/* C binding of definitions if building with C++ compiler */
#ifdef __cplusplus
extern "C"
{
#endif
/*******************************************************************************
* Include files
******************************************************************************/
#include "usb_host_def.h"
/**
* @addtogroup LL_USB_LIB
* @{
*/
/**
* @addtogroup LL_USB_HOST_CORE
* @{
*/
/*******************************************************************************
* Global type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Global pre-processor symbols/macros ('#define')
******************************************************************************/
/* USBH_STDREQ_Exported_Defines */
/* Standard Feature Selector for clear feature command */
#define FEATURE_SELECTOR_ENDPOINT (0x00U)
#define FEATURE_SELECTOR_DEVICE (0x01U)
/*******************************************************************************
* Global variable definitions ('extern')
******************************************************************************/
/*******************************************************************************
Global function prototypes (definition in C source)
******************************************************************************/
extern HOST_STATUS usb_host_getdesc(usb_core_instance *pdev,
USBH_HOST *phost,
uint8_t req_type,
uint16_t value_idx,
uint8_t *buff,
uint16_t length);
extern HOST_STATUS usb_host_getdevdesc(usb_core_instance *pdev, USBH_HOST *phost, uint8_t length);
HOST_STATUS usb_host_getstringdesc(usb_core_instance *pdev,
USBH_HOST *phost,
uint8_t string_index,
uint8_t *buff,
uint16_t length);
extern HOST_STATUS usb_host_setconfig(usb_core_instance *pdev, USBH_HOST *phost, uint16_t cfg_idx);
extern HOST_STATUS usb_host_getcfgdesc(usb_core_instance *pdev, USBH_HOST *phost, uint16_t length);
extern HOST_STATUS usb_host_setdevaddr(usb_core_instance *pdev, USBH_HOST *phost, uint8_t DeviceAddress);
extern HOST_STATUS usb_host_clrfeature(usb_core_instance *pdev, USBH_HOST *phost, uint8_t ep_num, uint8_t hc_num);
extern HOST_STATUS usb_host_setintf(usb_core_instance *pdev, USBH_HOST *phost, uint8_t ep_num, uint8_t altSetting);
extern USB_HOST_DescHeader_TypeDef *usb_host_getnextdesc(uint8_t *pbuf, uint16_t *ptr);
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USB_HOST_STDREQ_H__ */
/*******************************************************************************
* EOF (not truncated)
******************************************************************************/

View File

@ -0,0 +1,199 @@
/**
*******************************************************************************
* @file usb_lib.h
* @brief Header of the Core Layer Driver
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
@endverbatim
*******************************************************************************
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
#ifndef __USB_LIB_H__
#define __USB_LIB_H__
/* C binding of definitions if building with C++ compiler */
#ifdef __cplusplus
extern "C"
{
#endif
/*******************************************************************************
* Include files
******************************************************************************/
#include <hc32_ll_usb.h>
#include <hc32_ll.h>
/**
* @addtogroup LL_USB_LIB LL USB Lib
* @{
*/
/**
* @addtogroup LL_USB_LIB_DEF LL USB Lib Define
* @{
*/
/*******************************************************************************
* Global pre-processor symbols/macros ('#define')
******************************************************************************/
#define MAX_DATA_LENGTH (0x200U)
/*******************************************************************************
* Global type definitions ('typedef')
******************************************************************************/
/* status of the host channel */
typedef enum {
HOST_CH_IDLE = 0U,
HOST_CH_XFERCOMPL,
HOST_CH_CHHLTD,
HOST_CH_NAK,
HOST_CH_NYET,
HOST_CH_STALL,
HOST_CH_XACTERR,
HOST_CH_BBLERR,
HOST_CH_DATATGLERR,
HOST_CH_AHBERR,
HOST_CH_FRMOVRUN,
HOST_CH_BNAINTR,
HOST_CH_XCS_XACT_ERR,
HOST_CH_DESC_LST_ROLLINTR
} HOST_CH_STATUS;
typedef enum {
HOST_CH_XFER_IDLE = 0U,
HOST_CH_XFER_DONE,
HOST_CH_XFER_UNREADY,
HOST_CH_XFER_ERROR,
HOST_CH_XFER_STALL
} HOST_CH_XFER_STATE;
typedef enum {
CTRL_START = 0U,
CTRL_XFRC,
CTRL_HALTED,
CTRL_NAK,
CTRL_STALL,
CTRL_XACTERR,
CTRL_BBLERR,
CTRL_DATATGLERR,
CTRL_FAIL
} CTRL_HANDLE_STATUS;
typedef struct {
uint8_t bmRequest;
uint8_t bRequest;
uint16_t wValue;
uint16_t wIndex;
uint16_t wLength;
} USB_SETUP_REQ;
typedef struct {
uint8_t *(*get_dev_desc)(uint16_t *length);
uint8_t *(*get_dev_langiddesc)(uint16_t *length);
uint8_t *(*get_dev_manufacturerstr)(uint16_t *length);
uint8_t *(*get_dev_productstr)(uint16_t *length);
uint8_t *(*get_dev_serialstr)(uint16_t *length);
uint8_t *(*get_dev_configstr)(uint16_t *length);
uint8_t *(*get_dev_interfacestr)(uint16_t *length);
} usb_dev_desc_func;
typedef struct {
void (*class_init)(void *pdev);
void (*class_deinit)(void *pdev);
uint8_t (*ep0_setup)(void *pdev, USB_SETUP_REQ *req);
void (*ep0_datain)(void *pdev);
void (*ep0_dataout)(void *pdev);
uint8_t *(*class_getconfigdesc)(uint16_t *length);
uint8_t (*class_sof)(void *pdev);
void (*class_datain)(void *pdev, uint8_t epnum);
void (*class_dataout)(void *pdev, uint8_t epnum);
void (*class_syn_in_incomplt)(void *pdev);
void (*class_syn_out_incomplt)(void *pdev);
} usb_dev_class_func;
typedef struct {
void (*user_init)(void);
void (*user_devrst)(void);
void (*user_devconfig)(void);
void (*user_devsusp)(void);
void (*user_devresume)(void);
void (*user_devconn)(void);
void (*user_devdisconn)(void);
} usb_dev_user_func;
typedef struct {
__IO uint8_t device_config;
__IO uint8_t device_address;
__IO uint8_t device_state;
__IO uint8_t device_old_status;
__IO uint8_t device_cur_status;
__IO uint8_t connection_status;
__IO uint8_t device_remote_wakeup;
__IO uint8_t test_mode;
USB_DEV_EP in_ep[USB_MAX_TX_FIFOS];
USB_DEV_EP out_ep[USB_MAX_TX_FIFOS];
uint8_t setup_pkt_buf[24];
usb_dev_class_func *class_callback;
usb_dev_user_func *user_callback;
usb_dev_desc_func *desc_callback;
} USB_DEV_PARAM;
typedef struct {
uint16_t channel[USB_MAX_TX_FIFOS];
USB_HOST_CH hc[USB_MAX_TX_FIFOS];
__IO uint32_t is_dev_connect;
uint8_t Rx_Buffer[MAX_DATA_LENGTH];
__IO uint32_t ErrCnt[USB_MAX_TX_FIFOS];
__IO uint32_t XferCnt[USB_MAX_TX_FIFOS];
__IO HOST_CH_STATUS HC_Status[USB_MAX_TX_FIFOS];
__IO HOST_CH_XFER_STATE URB_State[USB_MAX_TX_FIFOS];
} USB_HOST_PARAM;
typedef struct {
USB_CORE_BASIC_CFGS basic_cfgs;
LL_USB_TypeDef regs;
#ifdef USE_DEVICE_MODE
USB_DEV_PARAM dev;
#endif
#ifdef USE_HOST_MODE
USB_HOST_PARAM host;
#endif
} usb_core_instance;
/*******************************************************************************
* Global variable definitions ('extern')
******************************************************************************/
/*******************************************************************************
Global function prototypes (definition in C source)
******************************************************************************/
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USB_LIB_H__ */
/*******************************************************************************
* EOF (not truncated)
******************************************************************************/

View File

@ -0,0 +1,333 @@
/**
*******************************************************************************
* @file usb/usb_host_msc/source/usb_host_user.c
* @brief user application layer.
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
@endverbatim
*******************************************************************************
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
/**
* @file usb_host_user.c
* @brief support hc32f4a0-board usb function
* @version 2.0
* @author AIIT XUOS Lab
* @date 2022-11-07
*/
/*************************************************
File name: usb_host_user.c
Description: support hc32f4a0-board usb function
Others:
History:
1. Date: 2022-11-07
Author: AIIT XUOS Lab
Modification:
1. delete useless usb host configure and define
2. add KPrintf function
3. add UsbMountFileSystem() and UsbUnmountFileSystem()
*************************************************/
/*******************************************************************************
* Include files
******************************************************************************/
#include <string.h>
#include <stdio.h>
#include <device.h>
#include "usb_host_user.h"
#include "usb_host_msc_class.h"
#include "usb_host_msc_scsi.h"
#include "usb_host_msc_bot.h"
#include "usb_host_driver.h"
/**
* @addtogroup HC32F4A0_DDL_Applications
* @{
*/
/**
* @addtogroup USB_Host_Msc
* @{
*/
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
extern void UsbMountFileSystem();
extern void UsbUnmountFileSystem();
/* USBH_USR_Private_Macros */
extern usb_core_instance usb_app_instance;
/* Points to the DEVICE_PROP structure of current device */
/* The purpose of this register is to speed up the execution */
usb_host_user_callback_func USR_cb = {
&host_user_init,
&host_user_denint,
&host_user_devattached,
&host_user_devreset,
&host_user_devdisconn,
&host_user_overcurrent,
&host_user_devspddetected,
&host_user_devdescavailable,
&host_user_devaddrdistributed,
&host_user_cfgdescavailable,
&host_user_mfcstring,
&host_user_productstring,
&host_user_serialnum,
&host_user_enumcompl,
&host_user_userinput,
&host_user_msc_app,
&host_user_devunsupported,
&host_user_unrecoverederror
};
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
uint8_t USB_HOST_USER_AppState = USH_USR_FS_INIT;
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/**
* @brief Displays the message on terminal for host lib initialization
* @param None
* @retval None
*/
void host_user_init(void)
{
static uint8_t startup = 0U;
if (startup == 0U) {
startup = 1U;
KPrintf("USB Host library v2.1.0 started\r\n");
}
}
/**
* @brief Displays the message on terminal via DDL_Printf
* @param None
* @retval None
*/
void host_user_devattached(void)
{
KPrintf("USB device attached\r\n");
UsbMountFileSystem();
}
/**
* @brief host_user_unrecoverederror
* @param None
* @retval None
*/
void host_user_unrecoverederror(void)
{
KPrintf("USB device unrecovered error\r\n");
}
/**
* @brief Device disconnect event
* @param None
* @retval None
*/
void host_user_devdisconn(void)
{
KPrintf("USB device disconnect\r\n");
UsbUnmountFileSystem();
}
/**
* @brief USBH_USR_ResetUSBDevice
* @param None
* @retval None
*/
void host_user_devreset(void)
{
/* callback for USB-Reset */
KPrintf("USB device reset\r\n");
}
/**
* @brief host_user_devspddetected
* @param [in] DeviceSpeed USB speed
* @retval None
*/
void host_user_devspddetected(uint8_t DeviceSpeed)
{
if (DeviceSpeed == PRTSPD_FULL_SPEED) {
KPrintf("USB device speed PRTSPD_FULL_SPEED\r\n");
} else if (DeviceSpeed == PRTSPD_LOW_SPEED) {
KPrintf("USB device speed PRTSPD_LOW_SPEED\r\n");
} else {
KPrintf("USB device speed error\r\n");
}
}
/**
* @brief host_user_devdescavailable
* @param [in] DeviceDesc device descriptor
* @retval None
*/
void host_user_devdescavailable(void *DeviceDesc)
{
usb_host_devdesc_typedef *hs;
hs = DeviceDesc;
KPrintf("USB device VID : %04lXh PID : %04lXh\r\n", (uint32_t)(*hs).idVendor, (uint32_t)(*hs).idProduct);
}
/**
* @brief host_user_devaddrdistributed
* @param None
* @retval None
*/
void host_user_devaddrdistributed(void)
{
}
/**
* @brief host_user_cfgdescavailable
* @param [in] cfgDesc Configuration desctriptor
* @param [in] itfDesc Interface desctriptor
* @param [in] epDesc Endpoint desctriptor
* @retval None
*/
void host_user_cfgdescavailable(usb_host_cfgdesc_typedef *cfgDesc,
usb_host_itfdesc_typedef *itfDesc,
USB_HOST_EPDesc_TypeDef *epDesc)
{
usb_host_itfdesc_typedef *id;
id = itfDesc;
if ((*id).bInterfaceClass == 0x08U) {
KPrintf("USB Mass storage device connected\r\n");
} else if ((*id).bInterfaceClass == 0x03U) {
KPrintf("USB HID device connected\r\n");
} else {
;
}
}
/**
* @brief Displays the message on terminal for Manufacturer String
* @param [in] ManufacturerString
* @retval None
*/
void host_user_mfcstring(void *ManufacturerString)
{
KPrintf("Manufacturer : %s\r\n", (char *)ManufacturerString);
}
/**
* @brief Displays the message on terminal for product String
* @param [in] ProductString
* @retval None
*/
void host_user_productstring(void *ProductString)
{
KPrintf("Product : %s\r\n", (char *)ProductString);
}
/**
* @brief Displays the message on terminal for SerialNum_String
* @param [in] SerialNumString
* @retval None
*/
void host_user_serialnum(void *SerialNumString)
{
KPrintf("Serial Number : %s\r\n", (char *)SerialNumString);
}
/**
* @brief User response request is displayed to ask application jump to class
* @param None
* @retval None
*/
void host_user_enumcompl(void)
{
}
/**
* @brief Device is not supported
* @param None
* @retval None
*/
void host_user_devunsupported(void)
{
KPrintf("USB Device not supported.\r\n");
}
/**
* @brief User Action for application state entry
* @param None
* @retval HOST_USER_STATUS User response for key button
*/
HOST_USER_STATUS host_user_userinput(void)
{
}
/**
* @brief Over Current Detected on VBUS
* @param None
* @retval None
*/
void host_user_overcurrent(void)
{
KPrintf("USB HOST Overcurrent detected.\r\n");
}
/**
* @brief Demo application for mass storage
* @param None
* @retval None
*/
int host_user_msc_app(void)
{
return ((int)0);
}
/**
* @brief Deint User state and associated variables
* @param None
* @retval None
*/
void host_user_denint(void)
{
USB_HOST_USER_AppState = USH_USR_FS_INIT;
}
/**
* @}
*/
/**
* @}
*/
/*******************************************************************************
* EOF (not truncated)
******************************************************************************/

View File

@ -0,0 +1,109 @@
/**
*******************************************************************************
* @file usb/usb_host_msc/source/usb_host_user.h
* @brief Header file for usb_host_user.c
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
@endverbatim
*******************************************************************************
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
#ifndef __USB_HOST_USER_H__
#define __USB_HOST_USER_H__
/* C binding of definitions if building with C++ compiler */
#ifdef __cplusplus
extern "C"
{
#endif
/*******************************************************************************
* Include files
******************************************************************************/
//#include "ff.h"
#include "usb_host_core.h"
#include "usb_app_conf.h"
#include <stdio.h>
#include "usb_host_msc_class.h"
/**
* @addtogroup HC32F4A0_DDL_Applications
* @{
*/
/**
* @addtogroup USB_Host_Msc
* @{
*/
/*******************************************************************************
* Global type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Global pre-processor symbols/macros ('#define')
******************************************************************************/
/* State Machine for the USBH_USR_ApplicationState */
#define USH_USR_FS_INIT (0U)
#define USH_USR_FS_READLIST (1U)
#define USH_USR_FS_WRITEFILE (2U)
#define USH_USR_FS_IDLE (3U)
/*******************************************************************************
* Global variable definitions ('extern')
******************************************************************************/
extern usb_host_user_callback_func USR_cb;
extern uint8_t USB_HOST_USER_AppState;
/*******************************************************************************
Global function prototypes (definition in C source)
******************************************************************************/
extern void host_user_init(void);
extern void host_user_denint(void);
extern void host_user_devattached(void);
extern void host_user_devreset(void);
extern void host_user_devdisconn(void);
extern void host_user_overcurrent(void);
extern void host_user_devspddetected(uint8_t DeviceSpeed);
extern void host_user_devdescavailable(void *DeviceDesc);
extern void host_user_devaddrdistributed(void);
extern void host_user_cfgdescavailable(usb_host_cfgdesc_typedef *cfgDesc,
usb_host_itfdesc_typedef *itfDesc,
USB_HOST_EPDesc_TypeDef *epDesc);
extern void host_user_mfcstring(void *ManufacturerString);
extern void host_user_productstring(void *ProductString);
extern void host_user_serialnum(void *SerialNumString);
extern void host_user_enumcompl(void);
extern HOST_USER_STATUS host_user_userinput(void);
extern void host_user_devunsupported(void);
extern void host_user_unrecoverederror(void);
extern int host_user_msc_app(void);
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /*__USB_HOST_USER_H__*/
/*******************************************************************************
* EOF (not truncated)
******************************************************************************/

View File

@ -402,6 +402,10 @@ KERNELPATHS += \
-I$(BSP_ROOT)/third_party_driver/CMSIS/include \ -I$(BSP_ROOT)/third_party_driver/CMSIS/include \
-I$(BSP_ROOT)/third_party_driver/spi/third_party_spi_lora/sx12xx/inc \ -I$(BSP_ROOT)/third_party_driver/spi/third_party_spi_lora/sx12xx/inc \
-I$(BSP_ROOT)/third_party_driver/spi/third_party_spi_lora/sx12xx/src/radio \ -I$(BSP_ROOT)/third_party_driver/spi/third_party_spi_lora/sx12xx/src/radio \
-I$(BSP_ROOT)/third_party_driver/usb/hc32_usb_driver \
-I$(BSP_ROOT)/third_party_driver/usb/hc32_usb_driver/usb_host_lib \
-I$(BSP_ROOT)/third_party_driver/usb/hc32_usb_driver/usb_host_lib/host_class/msc \
-I$(BSP_ROOT)/third_party_driver/usb/hc32_usb_driver/usb_host_lib/host_core \
-I$(KERNEL_ROOT)/include # -I$(KERNEL_ROOT)/include #
endif endif

View File

@ -53,9 +53,11 @@
#include <bus_usb.h> #include <bus_usb.h>
#include <dev_usb.h> #include <dev_usb.h>
#ifdef RESOURCES_USB_HOST #ifdef RESOURCES_USB_HOST
#ifdef BSP_USING_STM32_USBH
#include <stm32_usb_host.h> #include <stm32_usb_host.h>
#endif #endif
#endif #endif
#endif
#ifdef RESOURCES_SERIAL #ifdef RESOURCES_SERIAL
#include <bus_serial.h> #include <bus_serial.h>