first submission

This commit is contained in:
qiyongshuang
2023-02-01 14:19:13 +08:00
parent d534aad004
commit b79c6ac80d
3711 changed files with 745432 additions and 2 deletions
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,71 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : usbhd_host_km.h
* Author : WCH
* Version : V1.0.0
* Date : 2020/04/30
* Description : This file contains all the functions prototypes for the USB
* firmware library.
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#ifndef __APP_KM_H
#define __APP_KM_H
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************/
/* Header File */
#include "stdint.h"
/*******************************************************************************/
/* Macro Definition */
/* General */
#define DEF_COM_BUF_LEN 1024
/* USB HID Device Interface Type */
#define DEC_KEY 0x01
#define DEC_MOUSE 0x02
#define DEC_UNKNOW 0xFF
/* USB Keyboard Lighting Key */
#define DEF_KEY_NUM 0x53
#define DEF_KEY_CAPS 0x39
#define DEF_KEY_SCROLL 0x47
/*******************************************************************************/
/* Variable Declaration */
extern uint8_t DevDesc_Buf[ ];
extern uint8_t Com_Buf[ ];
/*******************************************************************************/
/* Function Declaration */
extern void TIM3_Init( uint16_t arr, uint16_t psc );
extern void USBH_AnalyseType( uint8_t *pdev_buf, uint8_t *pcfg_buf, uint8_t *ptype );
extern uint8_t USBH_EnumRootDevice( void );
extern uint8_t KM_AnalyzeConfigDesc( uint8_t index, uint8_t ep0_size );
extern void KM_AnalyzeHidReportDesc( uint8_t index, uint8_t intf_num );
extern uint8_t KM_DealHidReportDesc( uint8_t index, uint8_t ep0_size );
extern uint8_t USBH_EnumHidDevice( uint8_t index, uint8_t ep0_size );
extern uint8_t HUB_AnalyzeConfigDesc( uint8_t index );
extern uint8_t HUB_Port_PreEnum1( uint8_t hub_port, uint8_t *pbuf );
extern uint8_t HUB_Port_PreEnum2( uint8_t hub_port, uint8_t *pbuf );
extern uint8_t HUB_CheckPortSpeed( uint8_t hub_port, uint8_t *pbuf );
extern uint8_t USBH_EnumHubPortDevice( uint8_t hub_port, uint8_t *paddr, uint8_t *ptype );
extern void KB_AnalyzeKeyValue( uint8_t index, uint8_t intf_num, uint8_t *pbuf, uint16_t len );
extern uint8_t KB_SetReport( uint8_t index, uint8_t ep0_size, uint8_t intf_num );
extern void USBH_MainDeal( void );
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,675 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : ch32f20x_usbfs_host.c
* Author : WCH
* Version : V1.0.0
* Date : 2022/09/01
* Description : USB full-speed port host operation functions.
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
/*******************************************************************************/
/* Header File */
#include "usb_host_config.h"
/*******************************************************************************/
/* Variable Definition */
__attribute__((aligned(4))) uint8_t USBFS_RX_Buf[ USBFS_MAX_PACKET_SIZE ]; // IN, must even address
__attribute__((aligned(4))) uint8_t USBFS_TX_Buf[ USBFS_MAX_PACKET_SIZE ]; // OUT, must even address
/*********************************************************************
* @fn USBFS_RCC_Init
*
* @brief Set USB port clock.
* Note: If the SystemCoreClock is selected as the USB clock source,
* only the frequency specified below can be used.
*
* @return none
*/
void USBFS_RCC_Init( void )
{
if( SystemCoreClock == 144000000 )
{
RCC_USBCLKConfig( RCC_USBCLKSource_PLLCLK_Div3 );
}
else if( SystemCoreClock == 96000000 )
{
RCC_USBCLKConfig( RCC_USBCLKSource_PLLCLK_Div2 );
}
else if( SystemCoreClock == 48000000 )
{
RCC_USBCLKConfig( RCC_USBCLKSource_PLLCLK_Div1 );
}
RCC_AHBPeriphClockCmd( RCC_AHBPeriph_OTG_FS, ENABLE );
}
/*********************************************************************
* @fn USBFS_Host_Init
*
* @brief Initialize USB port host configuration.
*
* @param sta - ENABLE or DISABLE
*
* @return none
*/
void USBFS_Host_Init( FunctionalState sta )
{
if( sta == ENABLE )
{
/* Reset USB module */
USBOTG_H_FS->BASE_CTRL = USBFS_UC_RESET_SIE | USBFS_UC_CLR_ALL;
Delay_Us( 10 );
USBOTG_H_FS->BASE_CTRL = 0;
/* Initialize USB host configuration */
USBOTG_H_FS->BASE_CTRL = USBFS_UC_HOST_MODE | USBFS_UC_INT_BUSY | USBFS_UC_DMA_EN;
USBOTG_H_FS->HOST_EP_MOD = USBFS_UH_EP_TX_EN | USBFS_UH_EP_RX_EN;
USBOTG_H_FS->HOST_RX_DMA = (uint32_t)USBFS_RX_Buf;
USBOTG_H_FS->HOST_TX_DMA = (uint32_t)USBFS_TX_Buf;
}
else
{
USBOTG_H_FS->BASE_CTRL = USBFS_UC_RESET_SIE | USBFS_UC_CLR_ALL;
Delay_Us( 10 );
USBOTG_H_FS->BASE_CTRL = 0;
}
}
/*********************************************************************
* @fn USBFSH_CheckRootHubPortStatus
*
* @brief Check the current status of the USB port in combination with
* the saved status of the root device connected to this port.
*
* @para dev_sta: The saved status of the root device.
*
* @return The current status of the port.
*/
uint8_t USBFSH_CheckRootHubPortStatus( uint8_t dev_sta )
{
if( USBOTG_H_FS->INT_FG & USBFS_UIF_DETECT )// Check that there is a device connection or disconnection event on the port
{
USBOTG_H_FS->INT_FG = USBFS_UIF_DETECT; // Clear flag
if( USBOTG_H_FS->MIS_ST & USBFS_UMS_DEV_ATTACH ) // Check that there is a device connection to the port
{
if( ( dev_sta == ROOT_DEV_DISCONNECT ) || ( ( dev_sta != ROOT_DEV_FAILED ) && ( USBFSH_CheckRootHubPortEnable( ) == 0x00 ) ) )
{
return ROOT_DEV_CONNECTED;
}
else
{
return ROOT_DEV_FAILED;
}
}
else // Check that there is no device connection to the port
{
return ROOT_DEV_DISCONNECT;
}
}
else
{
return ROOT_DEV_FAILED;
}
}
/*********************************************************************
* @fn USBFSH_CheckRootHubPortEnable
*
* @brief Check the enable status of the USB port.
* Note: This bit is automatically cleared when the device is disconnected.
*
* @return The current enable status of the port.
*/
uint8_t USBFSH_CheckRootHubPortEnable( void )
{
return ( USBOTG_H_FS->HOST_CTRL & USBFS_UH_PORT_EN );
}
/*********************************************************************
* @fn USBFSH_CheckRootHubPortSpeed
*
* @brief Check the speed of the USB port.
*
* @return The current speed of the port.
*/
uint8_t USBFSH_CheckRootHubPortSpeed( void )
{
return ( USBOTG_H_FS->MIS_ST & USBFS_UMS_DM_LEVEL? USB_LOW_SPEED: USB_FULL_SPEED );
}
/*********************************************************************
* @fn USBFSH_SetSelfAddr
*
* @brief Set the USB device address.
*
* @para addr: USB device address.
*
* @return none
*/
void USBFSH_SetSelfAddr( uint8_t addr )
{
USBOTG_H_FS->DEV_ADDR = ( USBOTG_H_FS->DEV_ADDR & USBFS_UDA_GP_BIT ) | ( addr & USBFS_USB_ADDR_MASK );
}
/*********************************************************************
* @fn USBFSH_SetSelfSpeed
*
* @brief Set USB speed.
*
* @para speed: USB speed.
*
* @return none
*/
void USBFSH_SetSelfSpeed( uint8_t speed )
{
if( speed == USB_FULL_SPEED )
{
USBOTG_H_FS->BASE_CTRL &= ~USBFS_UC_LOW_SPEED;
USBOTG_H_FS->HOST_CTRL &= ~USBFS_UH_LOW_SPEED;
USBOTG_H_FS->HOST_SETUP &= ~USBFS_UH_PRE_PID_EN;
}
else
{
USBOTG_H_FS->BASE_CTRL |= USBFS_UC_LOW_SPEED;
USBOTG_H_FS->HOST_CTRL |= USBFS_UH_LOW_SPEED;
USBOTG_H_FS->HOST_SETUP |= USBFS_UH_PRE_PID_EN;
}
}
/*********************************************************************
* @fn USBFSH_ResetRootHubPort
*
* @brief Reset USB port.
*
* @para mod: Reset host port operating mode.
* 0 -> reset and wait end
* 1 -> begin reset
* 2 -> end reset
*
* @return none
*/
void USBFSH_ResetRootHubPort( uint8_t mode )
{
USBFSH_SetSelfAddr( 0x00 );
USBFSH_SetSelfSpeed( USB_FULL_SPEED );
if( mode <= 1 )
{
USBOTG_H_FS->HOST_CTRL |= USBFS_UH_BUS_RESET; // Start reset
}
if( mode == 0 )
{
Delay_Ms( DEF_BUS_RESET_TIME ); // Reset time from 10mS to 20mS
}
if( mode != 1 )
{
USBOTG_H_FS->HOST_CTRL &= ~USBFS_UH_BUS_RESET; // End reset
}
Delay_Ms( 2 );
if( USBOTG_H_FS->INT_FG & USBFS_UIF_DETECT )
{
if( USBOTG_H_FS->MIS_ST & USBFS_UMS_DEV_ATTACH )
{
USBOTG_H_FS->INT_FG = USBFS_UIF_DETECT;
}
}
}
/*********************************************************************
* @fn USBFSH_EnableRootHubPort
*
* @brief Enable USB host port.
*
* @para *pspeed: USB speed.
*
* @return Operation result of the enabled port.
*/
uint8_t USBFSH_EnableRootHubPort( uint8_t *pspeed )
{
if( USBOTG_H_FS->MIS_ST & USBFS_UMS_DEV_ATTACH )
{
if( USBFSH_CheckRootHubPortEnable( ) == 0x00 )
{
*pspeed = USBFSH_CheckRootHubPortSpeed( );
if( *pspeed == USB_LOW_SPEED )
{
USBFSH_SetSelfSpeed( USB_LOW_SPEED );
}
}
USBOTG_H_FS->HOST_CTRL |= USBFS_UH_PORT_EN;
USBOTG_H_FS->HOST_SETUP |= USBFS_UH_SOF_EN;
return ERR_SUCCESS;
}
return ERR_USB_DISCON;
}
/*********************************************************************
* @fn USBFSH_Transact
*
* @brief Perform USB transaction.
*
* @para endp_pid: Token PID.
* endp_tog: Toggle
* timeout: Timeout time.
*
* @return USB transfer result.
*/
uint8_t USBFSH_Transact( uint8_t endp_pid, uint8_t endp_tog, uint16_t timeout )
{
uint8_t r, trans_retry;
uint16_t i;
USBOTG_H_FS->HOST_TX_CTRL = USBOTG_H_FS->HOST_RX_CTRL = endp_tog;
trans_retry = 0;
do
{
USBOTG_H_FS->HOST_EP_PID = endp_pid; // Specify token PID and endpoint number
USBOTG_H_FS->INT_FG = USBFS_UIF_TRANSFER; // Allow transfer
for( i = DEF_WAIT_USB_TRANSFER_CNT; ( i != 0 ) && ( ( USBOTG_H_FS->INT_FG & USBFS_UIF_TRANSFER ) == 0 ); i-- )
{
Delay_Us( 1 ); // Delay for USB transfer
}
USBOTG_H_FS->HOST_EP_PID = 0x00; // Stop USB transfer
if( ( USBOTG_H_FS->INT_FG & USBFS_UIF_TRANSFER ) == 0 )
{
return ERR_USB_UNKNOWN;
}
else // Complete transfer
{
if( USBOTG_H_FS->INT_ST & USBFS_UIS_TOG_OK )
{
return ERR_SUCCESS;
}
r = USBOTG_H_FS->INT_ST & USBFS_UIS_H_RES_MASK; // Response status of current USB transaction
if( r == USB_PID_STALL )
{
return ( r | ERR_USB_TRANSFER );
}
if( r == USB_PID_NAK )
{
if( timeout == 0 )
{
return ( r | ERR_USB_TRANSFER );
}
if( timeout < 0xFFFF )
{
timeout--;
}
--trans_retry;
}
else switch ( endp_pid >> 4 )
{
case USB_PID_SETUP:
case USB_PID_OUT:
if( r )
{
return ( r | ERR_USB_TRANSFER );
}
break;
case USB_PID_IN:
if( ( r == USB_PID_DATA0 ) || ( r == USB_PID_DATA1 ) )
{
;
}
else if( r )
{
return ( r | ERR_USB_TRANSFER );
}
break;
default:
return ERR_USB_UNKNOWN;
}
}
Delay_Us( 20 );
if( USBOTG_H_FS->INT_FG & USBFS_UIF_DETECT )
{
Delay_Us( 200 );
if( USBFSH_CheckRootHubPortEnable( ) == 0x00 )
{
return ERR_USB_DISCON; // USB device disconnect event
}
else
{
USBOTG_H_FS->INT_FG = USBFS_UIF_DETECT;
}
}
}while( ++trans_retry < 10 );
return ERR_USB_TRANSFER; // Reply timeout
}
/*********************************************************************
* @fn USBFSH_CtrlTransfer
*
* @brief USB host control transfer.
*
* @para ep0_size: Device endpoint 0 size
* pbuf: Data buffer
* plen: Data length
*
* @return USB control transfer result.
*/
uint8_t USBFSH_CtrlTransfer( uint8_t ep0_size, uint8_t *pbuf, uint16_t *plen )
{
uint8_t s;
uint16_t rem_len, rx_len, rx_cnt, tx_cnt;
Delay_Us( 100 );
if( plen )
{
*plen = 0;
}
USBOTG_H_FS->HOST_TX_LEN = sizeof( USB_SETUP_REQ );
s = USBFSH_Transact( ( USB_PID_SETUP << 4 ) | 0x00, 0x00, DEF_CTRL_TRANS_TIMEOVER_CNT ); // SETUP stage
if( s != ERR_SUCCESS )
{
return s;
}
USBOTG_H_FS->HOST_TX_CTRL = USBOTG_H_FS->HOST_RX_CTRL = USBFS_UH_T_TOG | USBFS_UH_R_TOG; // Default DATA1
rem_len = pUSBFS_SetupRequest->wLength;
if( rem_len && pbuf )
{
if( pUSBFS_SetupRequest->bRequestType & USB_REQ_TYP_IN )
{
/* Receive data */
while( rem_len )
{
Delay_Us( 100 );
s = USBFSH_Transact( ( USB_PID_IN << 4 ) | 0x00, USBOTG_H_FS->HOST_RX_CTRL, DEF_CTRL_TRANS_TIMEOVER_CNT ); // IN
if( s != ERR_SUCCESS )
{
return s;
}
USBOTG_H_FS->HOST_RX_CTRL ^= USBFS_UH_R_TOG;
rx_len = ( USBOTG_H_FS->RX_LEN < rem_len )? USBOTG_H_FS->RX_LEN : rem_len;
rem_len -= rx_len;
if( plen )
{
*plen += rx_len; // The total length of the actual successful transmission and reception
}
for( rx_cnt = 0; rx_cnt != rx_len; rx_cnt++ )
{
*pbuf = USBFS_RX_Buf[ rx_cnt ];
pbuf++;
}
if( ( USBOTG_H_FS->RX_LEN == 0 ) || ( USBOTG_H_FS->RX_LEN & ( ep0_size - 1 ) ) )
{
break; // Short package
}
}
USBOTG_H_FS->HOST_TX_LEN = 0; // Status stage is OUT
}
else
{
/* Send data */
while( rem_len )
{
Delay_Us( 100 );
USBOTG_H_FS->HOST_TX_LEN = ( rem_len >= ep0_size )? ep0_size : rem_len;
for( tx_cnt = 0; tx_cnt != USBOTG_H_FS->HOST_TX_LEN; tx_cnt++ )
{
USBFS_TX_Buf[ tx_cnt ] = *pbuf;
pbuf++;
}
s = USBFSH_Transact( USB_PID_OUT << 4 | 0x00, USBOTG_H_FS->HOST_TX_CTRL, DEF_CTRL_TRANS_TIMEOVER_CNT ); // OUT
if( s != ERR_SUCCESS )
{
return s;
}
USBOTG_H_FS->HOST_TX_CTRL ^= USBFS_UH_T_TOG;
rem_len -= USBOTG_H_FS->HOST_TX_LEN;
if( plen )
{
*plen += USBOTG_H_FS->HOST_TX_LEN; // The total length of the actual successful transmission and reception
}
}
}
}
Delay_Us( 100 );
s = USBFSH_Transact( ( USBOTG_H_FS->HOST_TX_LEN )? ( USB_PID_IN << 4 | 0x00 ) : ( USB_PID_OUT << 4 | 0x00 ), USBFS_UH_R_TOG | USBFS_UH_T_TOG, DEF_CTRL_TRANS_TIMEOVER_CNT ); // STATUS stage
if( s != ERR_SUCCESS )
{
return s;
}
if( USBOTG_H_FS->HOST_TX_LEN == 0 )
{
return ERR_SUCCESS;
}
if( USBOTG_H_FS->RX_LEN == 0 )
{
return ERR_SUCCESS;
}
return ERR_USB_BUF_OVER;
}
/*********************************************************************
* @fn USBFSH_GetDeviceDescr
*
* @brief Get the device descriptor of the USB device.
*
* @para pep0_size: Device endpoint 0 size
* pbuf: Data buffer
*
* @return The result of getting the device descriptor.
*/
uint8_t USBFSH_GetDeviceDescr( uint8_t *pep0_size, uint8_t *pbuf )
{
uint8_t s;
uint16_t len;
*pep0_size = DEFAULT_ENDP0_SIZE;
memcpy( pUSBFS_SetupRequest, SetupGetDevDesc, sizeof( USB_SETUP_REQ ) );
s = USBFSH_CtrlTransfer( *pep0_size, pbuf, &len );
if( s != ERR_SUCCESS )
{
return s;
}
*pep0_size = ( (PUSB_DEV_DESCR)pbuf )->bMaxPacketSize0;
if( len < ( (PUSB_SETUP_REQ)SetupGetDevDesc )->wLength )
{
return ERR_USB_BUF_OVER;
}
return ERR_SUCCESS;
}
/*********************************************************************
* @fn USBFSH_GetConfigDescr
*
* @brief Get the configuration descriptor of the USB device.
*
* @para ep0_size: Device endpoint 0 size
* pbuf: Data buffer
* buf_len: Data buffer length
* pcfg_len: The length of the device configuration descriptor
*
* @return The result of getting the configuration descriptor.
*/
uint8_t USBFSH_GetConfigDescr( uint8_t ep0_size, uint8_t *pbuf, uint16_t buf_len, uint16_t *pcfg_len )
{
uint8_t s;
memcpy( pUSBFS_SetupRequest, SetupGetCfgDesc, sizeof( USB_SETUP_REQ ) );
s = USBFSH_CtrlTransfer( ep0_size, pbuf, pcfg_len );
if( s != ERR_SUCCESS )
{
return s;
}
if( *pcfg_len < ( (PUSB_SETUP_REQ)SetupGetCfgDesc )->wLength )
{
return ERR_USB_BUF_OVER;
}
*pcfg_len = ( (PUSB_CFG_DESCR)pbuf )->wTotalLength;
if( *pcfg_len > buf_len )
{
*pcfg_len = buf_len;
}
memcpy( pUSBFS_SetupRequest, SetupGetCfgDesc, sizeof( USB_SETUP_REQ ) );
pUSBFS_SetupRequest->wLength = *pcfg_len;
s = USBFSH_CtrlTransfer( ep0_size, pbuf, pcfg_len );
return s;
}
/*********************************************************************
* @fn USBFSH_GetStrDescr
*
* @brief Get the string descriptor of the USB device.
*
* @para ep0_size: Device endpoint 0 size
* str_num: Index of string descriptor
* pbuf: Data buffer
*
* @return The result of getting the string descriptor.
*/
uint8_t USBFSH_GetStrDescr( uint8_t ep0_size, uint8_t str_num, uint8_t *pbuf )
{
uint8_t s;
uint16_t len;
/* Get the string descriptor of the first 4 bytes */
memcpy( pUSBFS_SetupRequest, SetupGetStrDesc, sizeof( USB_SETUP_REQ ) );
pUSBFS_SetupRequest->wValue = ( (uint16_t)USB_DESCR_TYP_STRING << 8 ) | str_num;
s = USBFSH_CtrlTransfer( ep0_size, pbuf, &len );
if( s != ERR_SUCCESS )
{
return s;
}
/* Get the complete string descriptor */
len = pbuf[ 0 ];
memcpy( pUSBFS_SetupRequest, SetupGetStrDesc, sizeof( USB_SETUP_REQ ) );
pUSBFS_SetupRequest->wValue = ( (uint16_t)USB_DESCR_TYP_STRING << 8 ) | str_num;
pUSBFS_SetupRequest->wLength = len;
s = USBFSH_CtrlTransfer( ep0_size, pbuf, &len );
if( s != ERR_SUCCESS )
{
return s;
}
return ERR_SUCCESS;
}
/*********************************************************************
* @fn USBFSH_SetUsbAddress
*
* @brief Set USB device address.
*
* @para ep0_size: Device endpoint 0 size
* addr: Device address
*
* @return The result of setting device address.
*/
uint8_t USBFSH_SetUsbAddress( uint8_t ep0_size, uint8_t addr )
{
uint8_t s;
memcpy( pUSBFS_SetupRequest, SetupSetAddr, sizeof( USB_SETUP_REQ ) );
pUSBFS_SetupRequest->wValue = (uint16_t)addr;
s = USBFSH_CtrlTransfer( ep0_size, NULL, NULL );
if( s != ERR_SUCCESS )
{
return s;
}
USBFSH_SetSelfAddr( addr );
Delay_Ms( DEF_BUS_RESET_TIME >> 1 ); // Wait for the USB device to complete its operation.
return ERR_SUCCESS;
}
/*********************************************************************
* @fn USBFSH_SetUsbConfig
*
* @brief Set USB configuration.
*
* @para ep0_size: Device endpoint 0 size
* cfg: Device configuration value
*
* @return The result of setting device configuration.
*/
uint8_t USBFSH_SetUsbConfig( uint8_t ep0_size, uint8_t cfg_val )
{
memcpy( pUSBFS_SetupRequest, SetupSetConfig, sizeof( USB_SETUP_REQ ) );
pUSBFS_SetupRequest->wValue = (uint16_t)cfg_val;
return USBFSH_CtrlTransfer( ep0_size, NULL, NULL );
}
/*********************************************************************
* @fn USBFSH_ClearEndpStall
*
* @brief Clear endpoint stall.
*
* @para ep0_size: Device endpoint 0 size
* endp_num: Endpoint number.
*
* @return The result of clearing endpoint stall.
*/
uint8_t USBFSH_ClearEndpStall( uint8_t ep0_size, uint8_t endp_num )
{
memcpy( pUSBFS_SetupRequest, SetupClearEndpStall, sizeof( USB_SETUP_REQ ) );
pUSBFS_SetupRequest->wIndex = (uint16_t)endp_num;
return USBFSH_CtrlTransfer( ep0_size, NULL, NULL );
}
/*********************************************************************
* @fn USBFSH_GetEndpData
*
* @brief Get data from USB device input endpoint.
*
* @para endp_num: Endpoint number
* endp_tog: Endpoint toggle
* pbuf: Data Buffer
* plen: Data length
*
* @return The result of getting data.
*/
uint8_t USBFSH_GetEndpData( uint8_t endp_num, uint8_t *pendp_tog, uint8_t *pbuf, uint16_t *plen )
{
uint8_t s;
s = USBFSH_Transact( ( USB_PID_IN << 4 ) | endp_num, *pendp_tog, 0 );
if( s == ERR_SUCCESS )
{
*plen = USBOTG_H_FS->RX_LEN;
memcpy( pbuf, USBFS_RX_Buf, *plen );
*pendp_tog ^= USBFS_UH_R_TOG;
}
return s;
}
/*********************************************************************
* @fn USBFSH_SendEndpData
*
* @brief Send data to the USB device output endpoint.
*
* @para endp_num: Endpoint number
* endp_tog: Endpoint toggle
* pbuf: Data Buffer
* len: Data length
*
* @return The result of sending data.
*/
uint8_t USBFSH_SendEndpData( uint8_t endp_num, uint8_t *pendp_tog, uint8_t *pbuf, uint16_t len )
{
uint8_t s;
memcpy( USBFS_TX_Buf, pbuf, len );
USBOTG_H_FS->HOST_TX_LEN = len;
s = USBFSH_Transact( ( USB_PID_OUT << 4 ) | endp_num, *pendp_tog, 0 );
if( s == ERR_SUCCESS )
{
*pendp_tog ^= USBFS_UH_T_TOG;
}
return s;
}
@@ -0,0 +1,117 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : ch32v20x_usbfs_host.h
* Author : WCH
* Version : V1.0.0
* Date : 2021/06/06
* Description : USBOTG full speed host header file
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#ifndef __CH32V20x_USBFS_HOST_H__
#define __CH32V20x_USBFS_HOST_H__
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************/
/* Header File */
#include "ch32v20x.h"
#include "ch32v20x_usb.h"
/*******************************************************************************/
/* Macro Definition */
/* USB Setup Request */
#define pUSBFS_SetupRequest ( (PUSB_SETUP_REQ)USBFS_TX_Buf )
/* USB Buffer Size */
#ifndef USBFS_MAX_PACKET_SIZE
#define USBFS_MAX_PACKET_SIZE 64
#endif
/*******************************************************************************/
/* Constant Definition */
#ifndef DEF_USB_GEN_ENUM_CMD
#define DEF_USB_GEN_ENUM_CMD
/* Get Device Descriptor Command Packet */
__attribute__((aligned(4))) static const uint8_t SetupGetDevDesc[ ] =
{
USB_REQ_TYP_IN, USB_GET_DESCRIPTOR, 0x00, USB_DESCR_TYP_DEVICE, 0x00, 0x00, sizeof( USB_DEV_DESCR ), 0x00
};
/* Get Configuration Descriptor Command Packet */
__attribute__((aligned(4))) static const uint8_t SetupGetCfgDesc[ ] =
{
USB_REQ_TYP_IN, USB_GET_DESCRIPTOR, 0x00, USB_DESCR_TYP_CONFIG, 0x00, 0x00, 0x04, 0x00
};
/* Get String Descriptor Command Packet */
__attribute__((aligned(4))) static const uint8_t SetupGetStrDesc[ ] =
{
USB_REQ_TYP_IN, USB_GET_DESCRIPTOR, 0x00, USB_DESCR_TYP_STRING, 0x09, 0x04, 0x04, 0x00
};
/* Set USB Address Command Packet */
__attribute__((aligned(4))) static const uint8_t SetupSetAddr[ ] =
{
USB_REQ_TYP_OUT, USB_SET_ADDRESS, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
/* Set USB Configuration Command Packet */
__attribute__((aligned(4))) static const uint8_t SetupSetConfig[ ] =
{
USB_REQ_TYP_OUT, USB_SET_CONFIGURATION, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
/* Clear Endpoint STALL Command Packet */
__attribute__((aligned(4))) static const uint8_t SetupClearEndpStall[ ] =
{
USB_REQ_TYP_OUT | USB_REQ_RECIP_ENDP, USB_CLEAR_FEATURE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
/* Set Device Interface Command Packet */
__attribute__((aligned(4))) static const uint8_t SetupSetInterface[ ] =
{
USB_REQ_RECIP_INTERF, USB_SET_INTERFACE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
#endif
/*******************************************************************************/
/* Variable Declaration */
extern __attribute__((aligned(4))) uint8_t USBFS_RX_Buf[ ];
extern __attribute__((aligned(4))) uint8_t USBFS_TX_Buf[ ];
/*******************************************************************************/
/* Function Declaration */
extern void USBFS_RCC_Init( void );
extern void USBFS_Host_Init( FunctionalState sta );
extern uint8_t USBFSH_CheckRootHubPortStatus( uint8_t dev_sta );
extern uint8_t USBFSH_CheckRootHubPortEnable( void );
extern uint8_t USBFSH_CheckRootHubPortSpeed( void );
extern void USBFSH_SetSelfAddr( uint8_t addr );
extern void USBFSH_SetSelfSpeed( uint8_t speed );
extern void USBFSH_ResetRootHubPort( uint8_t mode );
extern uint8_t USBFSH_EnableRootHubPort( uint8_t *pspeed );
extern uint8_t USBFSH_Transact( uint8_t endp_pid, uint8_t endp_tog, uint16_t timeout );
extern uint8_t USBFSH_CtrlTransfer( uint8_t ep0_size, uint8_t *pbuf, uint16_t *plen );
extern uint8_t USBFSH_GetDeviceDescr( uint8_t *pep0_size, uint8_t *pbuf );
extern uint8_t USBFSH_GetConfigDescr( uint8_t ep0_size, uint8_t *pbuf, uint16_t buf_len, uint16_t *pcfg_len );
extern uint8_t USBFSH_GetStrDescr( uint8_t ep0_size, uint8_t str_num, uint8_t *pbuf );
extern uint8_t USBFSH_SetUsbAddress( uint8_t ep0_size, uint8_t addr );
extern uint8_t USBFSH_SetUsbConfig( uint8_t ep0_size, uint8_t cfg_val );
extern uint8_t USBFSH_ClearEndpStall( uint8_t ep0_size, uint8_t endp_num );
extern uint8_t USBFSH_GetEndpData( uint8_t endp_num, uint8_t *pendp_tog, uint8_t *pbuf, uint16_t *plen );
extern uint8_t USBFSH_SendEndpData( uint8_t endp_num, uint8_t *pendp_tog, uint8_t *pbuf, uint16_t len );
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,178 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : usb_host_config.h
* Author : WCH
* Version : V1.0.0
* Date : 2022/08/29
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#ifndef __USB_HOST_CONFIG_H
#define __USB_HOST_CONFIG_H
#ifdef __cplusplus
extern "C" {
#endif
/******************************************************************************/
/* Header File */
#include "string.h"
#include "debug.h"
#include "ch32v20x_usb.h"
#include "ch32v20x_usbfs_host.h"
#include "usb_host_hid.h"
#include "usb_host_hub.h"
#include "app_km.h"
/******************************************************************************/
/* Debug Macro Definition */
#define DEF_DEBUG_PRINTF 1
#if ( DEF_DEBUG_PRINTF == 1 )
#define DUG_PRINTF( format, arg... ) printf( format, ##arg )
#else
#define DUG_PRINTF( format, arg... ) do{ if( 0 )printf( format, ##arg ); }while( 0 );
#endif
/******************************************************************************/
/* USB Host Communication Related Macro Definition */
/* USB Host Port General Control */
#define DEF_TOTAL_ROOT_HUB 1
#define DEF_USBFS_PORT_EN 1
#define DEF_USBFS_PORT_INDEX 0x00
#define DEF_ONE_USB_SUP_DEV_TOTAL 5
#define DEF_NEXT_HUB_PORT_NUM_MAX 4
#define DEF_INTERFACE_NUM_MAX 4
/* USB Root Device Status */
#define ROOT_DEV_DISCONNECT 0
#define ROOT_DEV_CONNECTED 1
#define ROOT_DEV_FAILED 2
#define ROOT_DEV_SUCCESS 3
/* USB Device Address */
#define USB_DEVICE_ADDR 0x02
/* USB Speed */
#define USB_LOW_SPEED 0x00
#define USB_FULL_SPEED 0x01
#define USB_HIGH_SPEED 0x02
#define USB_SPEED_CHECK_ERR 0xFF
/* Configuration Descriptor Type */
#define DEF_DECR_CONFIG 0x02
#define DEF_DECR_INTERFACE 0x04
#define DEF_DECR_ENDPOINT 0x05
#define DEF_DECR_HID 0x21
/* USB Communication Status Code */
#define ERR_SUCCESS 0x00
#define ERR_USB_CONNECT 0x15
#define ERR_USB_DISCON 0x16
#define ERR_USB_BUF_OVER 0x17
#define ERR_USB_DISK_ERR 0x1F
#define ERR_USB_TRANSFER 0x20
#define ERR_USB_UNSUPPORT 0xFB
#define ERR_USB_UNAVAILABLE 0xFC
#define ERR_USB_UNKNOWN 0xFE
/* USB Device Enumeration Status Code */
#define DEF_DEV_DESCR_GETFAIL 0x45
#define DEF_DEV_ADDR_SETFAIL 0x46
#define DEF_CFG_DESCR_GETFAIL 0x47
#define DEF_REP_DESCR_GETFAIL 0x48
#define DEF_CFG_VALUE_SETFAIL 0x49
#define DEF_DEV_TYPE_UNKNOWN 0xFF
/* USB Communication Time */
#define DEF_BUS_RESET_TIME 11 // USB bus reset time
#define DEF_RE_ATTACH_TIMEOUT 100 // Wait for the USB device to reconnect after reset, 100mS timeout
#define DEF_WAIT_USB_TRANSFER_CNT 1000 // Wait for the USB transfer to complete
#define DEF_CTRL_TRANS_TIMEOVER_CNT 200000/20 // Control transmission delay timing
/*******************************************************************************/
/* Struct Definition */
/* Note: Please modify it according to your project. */
/* HUB Port Device */
typedef struct _HUB_DEVICE
{
uint8_t bStatus;
uint8_t bType;
uint8_t bAddress;
uint8_t bSpeed;
uint8_t bEp0MaxPks;
uint8_t DeviceIndex;
}HUB_DEVICE, *PHUB_DEVICE;
/* Root HUB Device Structure */
typedef struct _ROOT_HUB_DEVICE
{
uint8_t bStatus;
uint8_t bType;
uint8_t bAddress;
uint8_t bSpeed;
uint8_t bEp0MaxPks;
uint8_t DeviceIndex;
uint8_t bPortNum;
HUB_DEVICE Device[ DEF_NEXT_HUB_PORT_NUM_MAX ];
} ROOT_HUB_DEVICE, *PROOT_HUB_DEVICE;
/* USB Host Control Structure */
typedef struct __HOST_CTL
{
uint8_t InterfaceNum;
uint8_t ErrorCount;
struct interface
{
uint8_t Type;
uint16_t HidDescLen;
uint8_t HidReportID;
uint8_t Full_KB_Flag;
uint8_t InEndpNum;
uint8_t InEndpAddr[ 4 ];
uint8_t InEndpType[ 4 ];
uint16_t InEndpSize[ 4 ];
uint8_t InEndpTog[ 4 ];
uint8_t InEndpInterval[ 4 ];
uint8_t InEndpTimeCount[ 4 ];
uint8_t OutEndpNum;
uint8_t OutEndpAddr[ 4 ];
uint8_t OutEndpType[ 4 ];
uint16_t OutEndpSize[ 4 ];
uint8_t OutEndpTog[ 4 ];
uint8_t IDFlag;
uint8_t ReportID;
uint8_t LED_Usage_Min;
uint8_t LED_Usage_Max;
uint8_t SetReport_Swi;
uint8_t SetReport_Value;
uint8_t SetReport_Flag;
}Interface[ DEF_INTERFACE_NUM_MAX ];
} HOST_CTL, *PHOST_CTL;
/*******************************************************************************/
/* Struct Declaration */
extern struct _ROOT_HUB_DEVICE RootHubDev;
extern struct __HOST_CTL HostCtl[ ];
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,71 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : usb_hid.c
* Author : WCH
* Version : V1.0.0
* Date : 2022/08/29
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
/********************************************************************************/
/* Header File */
#include "usb_host_config.h"
/*********************************************************************
* @fn HID_GetHidDesr
*
* @brief Get USB device report descriptor.
*
* @para num: Interface number.
* pbuf: Buffer for saving descriptor.
* len: Descriptor length.
*
* @return none
*/
uint8_t HID_GetHidDesr( uint8_t ep0_size, uint8_t intf_num, uint8_t *pbuf, uint16_t *plen )
{
memcpy( pUSBFS_SetupRequest, SetupGetHidDes, sizeof( USB_SETUP_REQ ) );
pUSBFS_SetupRequest->wIndex = (uint16_t)intf_num;
pUSBFS_SetupRequest->wLength = *plen;
return USBFSH_CtrlTransfer( ep0_size, pbuf, plen );
}
/*********************************************************************
* @fn HID_SetReport
*
* @brief Set report.
*
* @para report: Desired report value.
* len: Report length.
* index: USB port num
*
* @return none
*/
uint8_t HID_SetReport( uint8_t ep0_size, uint8_t intf_num, uint8_t *pbuf, uint16_t *plen )
{
memcpy( pUSBFS_SetupRequest, SetupSetReport, sizeof( USB_SETUP_REQ ) );
pUSBFS_SetupRequest->wIndex = (uint16_t)intf_num;
return USBFSH_CtrlTransfer( ep0_size, pbuf, plen );
}
/*********************************************************************
* @fn HID_SetIdleSpeed
*
* @brief Set idle.
*
* @para speed: Report ID.
* index: Interface number.
*
* @return none
*/
uint8_t HID_SetIdle( uint8_t ep0_size, uint8_t intf_num, uint8_t duration, uint8_t reportid )
{
memcpy( pUSBFS_SetupRequest, SetupSetidle, sizeof( USB_SETUP_REQ ) );
pUSBFS_SetupRequest->wValue = ( (uint16_t)duration << 8 ) | reportid;
pUSBFS_SetupRequest->wIndex = (uint16_t)intf_num;
return USBFSH_CtrlTransfer( ep0_size, NULL, NULL );
}
@@ -0,0 +1,64 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : usb_hid.h
* Author : WCH
* Version : V1.0.0
* Date : 2022/08/29
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#ifndef __USB_HOST_HID_H
#define __USB_HOST_HID_H
#ifdef __cplusplus
extern "C" {
#endif
/********************************************************************************/
/* Header File */
#include "stdint.h"
/********************************************************************************/
/* Constant Definition */
#ifndef DEF_HID_DED_CMD
#define DEF_HID_DED_CMD
/* Set Protocol Command Packet */
__attribute__((aligned(4))) static const uint8_t SetupSetprotocol[ ] =
{
0x21, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
/* Set Idle Command Packet */
__attribute__((aligned(4))) static const uint8_t SetupSetidle[ ] =
{
0x21, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
/* Set Report Command Packet */
__attribute__((aligned(4))) static const uint8_t SetupSetReport[ ] =
{
0x21, 0x09, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00
};
/* Get Report Descriptor Command Packet */
__attribute__((aligned(4))) static const uint8_t SetupGetHidDes[ ] =
{
0x81, 0x06, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00
};
#endif
/*******************************************************************************/
/* Function Declaration */
extern uint8_t HID_GetHidDesr( uint8_t ep0_size, uint8_t intf_num, uint8_t *pbuf, uint16_t *plen );
extern uint8_t HID_SetReport( uint8_t ep0_size, uint8_t intf_num, uint8_t *pbuf, uint16_t *plen );
extern uint8_t HID_SetIdle( uint8_t ep0_size, uint8_t intf_num, uint8_t duration, uint8_t reportid );
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,96 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : usb_host_hub.c
* Author : WCH
* Version : V1.0.0
* Date : 2022/08/29
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
/********************************************************************************/
/* Header File */
#include "usb_host_config.h"
/*********************************************************************
* @fn HUB_ClearPortFeature
*
* @brief
*
* @para
*
* @return none
*/
uint8_t HUB_GetPortStatus( uint8_t hub_ep0_size, uint8_t hub_port, uint8_t *pbuf )
{
uint16_t len;
memcpy( pUSBFS_SetupRequest, GetPortStatus, sizeof( USB_SETUP_REQ ) );
pUSBFS_SetupRequest->wIndex = (uint16_t)hub_port;
return USBFSH_CtrlTransfer( hub_ep0_size, pbuf, &len );
}
/*********************************************************************
* @fn HUB_ClearPortFeature
*
* @brief
*
* @para
*
* @return none
*/
uint8_t HUB_ClearPortFeature( uint8_t hub_ep0_size, uint8_t hub_port, uint8_t selector )
{
memcpy( pUSBFS_SetupRequest, ClearPortFeature, sizeof( USB_SETUP_REQ ) );
pUSBFS_SetupRequest->wValue = (uint16_t)selector;
pUSBFS_SetupRequest->wIndex = (uint16_t)hub_port;
return USBFSH_CtrlTransfer( hub_ep0_size, NULL, NULL );
}
/*********************************************************************
* @fn HUB_SetPortFeature
*
* @brief
*
* @para
*
* @return none
*/
uint8_t HUB_SetPortFeature( uint8_t hub_ep0_size, uint8_t hub_port, uint8_t selector )
{
memcpy( pUSBFS_SetupRequest, SetPortFeature, sizeof( USB_SETUP_REQ ) );
pUSBFS_SetupRequest->wValue = (uint16_t)selector;
pUSBFS_SetupRequest->wIndex = (uint16_t)hub_port;
return USBFSH_CtrlTransfer( hub_ep0_size, NULL, NULL );
}
/*********************************************************************
* @fn HUB_GetClassDevDescr
*
* @brief
*
* @para
*
* @return none
*/
uint8_t HUB_GetClassDevDescr( uint8_t hub_ep0_size, uint8_t *pbuf, uint16_t *plen )
{
uint8_t s;
memcpy( pUSBFS_SetupRequest, GetHubDescr, sizeof( USB_SETUP_REQ ) );
s = USBFSH_CtrlTransfer( hub_ep0_size, pbuf, plen );
if( s != ERR_SUCCESS )
{
return s;
}
else
{
pUSBFS_SetupRequest->wLength = *plen = (uint16_t)pbuf[ 0 ];
s = USBFSH_CtrlTransfer( hub_ep0_size, pbuf, plen );
}
return s;
}
@@ -0,0 +1,66 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : usb_host_hub.h
* Author : WCH
* Version : V1.0.0
* Date : 2022/08/29
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#ifndef __USB_HOST_HUB_H
#define __USB_HOST_HUB_H
#ifdef __cplusplus
extern "C" {
#endif
/********************************************************************************/
/* Header File */
#include "stdint.h"
/********************************************************************************/
/* Constant Definition */
#ifndef DEF_HUB_DED_CMD
#define DEF_HUB_DED_CMD
/* Get Port Status Command Packet */
__attribute__((aligned(4))) static const uint8_t GetPortStatus[ ] =
{
0xA3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00
};
/* Clear Port Feature Command Packet */
__attribute__((aligned(4))) static const uint8_t ClearPortFeature[ ] =
{
0x23, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
/* Set Port Feature Command Packet */
__attribute__((aligned(4))) static const uint8_t SetPortFeature[ ] =
{
0x23, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
/* Get Hub Descriptor Command Packet */
__attribute__((aligned(4))) static const uint8_t GetHubDescr[ ] =
{
0xA0, 0x06, 0x00, 0x29, 0x00, 0x00, 0x02, 0x00
};
/*******************************************************************************/
/* Function Declaration */
extern uint8_t HUB_GetPortStatus( uint8_t hub_ep0_size, uint8_t hub_port, uint8_t *pbuf );
extern uint8_t HUB_ClearPortFeature( uint8_t hub_ep0_size, uint8_t hub_port, uint8_t selector );
extern uint8_t HUB_SetPortFeature( uint8_t hub_ep0_size, uint8_t hub_port, uint8_t selector );
extern uint8_t HUB_GetClassDevDescr( uint8_t hub_ep0_size, uint8_t *pbuf, uint16_t *plen );
#endif
#ifdef __cplusplus
}
#endif
#endif