forked from xuos/xiuos
feat add third_party_driver/usb for hc32f4a0 board, compile OK
This commit is contained in:
parent
636f803b7b
commit
9a818b1ef4
|
@ -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 },
|
||||||
};
|
};
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
SRC_DIR := hc32_usb_driver
|
||||||
|
|
||||||
|
SRC_FILES := connect_usb.c
|
||||||
|
|
||||||
|
include $(KERNEL_ROOT)/compiler.mk
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
SRC_FILES := usb_host_user.c usb_bsp.c
|
||||||
|
|
||||||
|
SRC_DIR := usb_host_lib
|
||||||
|
|
||||||
|
include $(KERNEL_ROOT)/compiler.mk
|
|
@ -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)
|
||||||
|
******************************************************************************/
|
|
@ -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)
|
||||||
|
{
|
||||||
|
}
|
|
@ -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)
|
||||||
|
******************************************************************************/
|
|
@ -0,0 +1,3 @@
|
||||||
|
SRC_DIR := host_class host_core
|
||||||
|
|
||||||
|
include $(KERNEL_ROOT)/compiler.mk
|
|
@ -0,0 +1,3 @@
|
||||||
|
SRC_DIR := msc
|
||||||
|
|
||||||
|
include $(KERNEL_ROOT)/compiler.mk
|
|
@ -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
|
|
@ -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)
|
||||||
|
******************************************************************************/
|
|
@ -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)
|
||||||
|
******************************************************************************/
|
|
@ -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)
|
||||||
|
******************************************************************************/
|
|
@ -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)
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
******************************************************************************/
|
|
@ -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)
|
||||||
|
*****************************************************************************/
|
|
@ -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)
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
@ -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)
|
||||||
|
*****************************************************************************/
|
|
@ -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)
|
||||||
|
******************************************************************************/
|
|
@ -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)
|
||||||
|
******************************************************************************/
|
|
@ -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)
|
||||||
|
******************************************************************************/
|
|
@ -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)
|
||||||
|
*****************************************************************************/
|
|
@ -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)
|
||||||
|
******************************************************************************/
|
|
@ -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)
|
||||||
|
*****************************************************************************/
|
|
@ -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)
|
||||||
|
******************************************************************************/
|
|
@ -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)
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
*****************************************************************************/
|
|
@ -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)
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
*****************************************************************************/
|
|
@ -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)
|
||||||
|
******************************************************************************/
|
|
@ -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)
|
||||||
|
******************************************************************************/
|
|
@ -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)
|
||||||
|
******************************************************************************/
|
|
@ -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)
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
|
|
Loading…
Reference in New Issue