/*********************************************************************************************************//**
* @file ht32_usbd_core.c
* @version $Rev:: 1684 $
* @date $Date:: 2019-05-07 #$
* @brief The standard protocol related function of HT32 USB Device Library.
*************************************************************************************************************
* @attention
*
* Firmware Disclaimer Information
*
* 1. The customer hereby acknowledges and agrees that the program technical documentation, including the
* code, which is supplied by Holtek Semiconductor Inc., (hereinafter referred to as "HOLTEK") is the
* proprietary and confidential intellectual property of HOLTEK, and is protected by copyright law and
* other intellectual property laws.
*
* 2. The customer hereby acknowledges and agrees that the program technical documentation, including the
* code, is confidential information belonging to HOLTEK, and must not be disclosed to any third parties
* other than HOLTEK and the customer.
*
* 3. The program technical documentation, including the code, is provided "as is" and for customer reference
* only. After delivery by HOLTEK, the customer shall use the program technical documentation, including
* the code, at their own risk. HOLTEK disclaims any expressed, implied or statutory warranties, including
* the warranties of merchantability, satisfactory quality and fitness for a particular purpose.
*
*
Copyright (C) Holtek Semiconductor Inc. All rights reserved
************************************************************************************************************/
/* Includes ------------------------------------------------------------------------------------------------*/
#include "ht32.h"
#include "ht32_usbd_core.h"
#include "usb_port.h"
#ifdef USBD_VENDOR_SUPPORT
#include "ht32_usbd_vendor.c"
#endif
/** @addtogroup HT32_USBD_Library HT32 USB Device Library
* @{
*/
/** @defgroup USBDCore USB Device Core
* @brief USB Device Core standard protocol related function
* @{
*/
/* Private types -------------------------------------------------------------------------------------------*/
/** @defgroup USBDCore_Private_TypesDefinitions USB Device Core private types definitions
* @{
*/
typedef enum
{
Device = 0,
Interface = 1,
Endpoint = 2,
Other = 3,
} USBDCore_Recipient_Enum;
typedef enum
{
ClearFeature = 0,
SetFeature = 1,
} USBDCore_SetClearFeature_Enum;
/**
* @}
*/
/* Private constants ---------------------------------------------------------------------------------------*/
/** @defgroup USBDCore_Private_Define USB Device Core private definitions
* @{
*/
/* USBD Debug mode */
#if (USBDCORE_DEBUG == 1)
#ifdef RETARGET_IS_USB
#warning "USB debug mode can not work when retaget to USB Virtual COM. Turn off automatically."
#undef USBDCORE_DEBUG
#define USBDCORE_DEBUG 0
#else
u32 __DBG_USBCount;
#warning "USB debug mode has been enabled which degrade the performance."
#warning "After the debug operation, please remember to turn off USB debug mode."
#endif
#endif
/** @defgroup USBDCore_STD Definition for standard request
* @{
*/
#define REQ_00_GET_STAT ((u16)(0 << 8))
#define REQ_01_CLR_FETU ((u16)(1 << 8))
#define REQ_03_SET_FETU ((u16)(3 << 8))
#define REQ_05_SET_ADDR ((u16)(5 << 8))
#define REQ_06_GET_DESC ((u16)(6 << 8))
#define REQ_07_SET_DESC ((u16)(7 << 8))
#define REQ_08_GET_CONF ((u16)(8 << 8))
#define REQ_09_SET_CONF ((u16)(9 << 8))
#define REQ_10_GET_INF ((u16)(10 << 8))
#define REQ_11_SET_INF ((u16)(11 << 8))
#define REQ_12_SYN_FRME ((u16)(12 << 8))
/**
* @}
*/
#define DESC_TYPE_01_DEV (0x1)
#define DESC_TYPE_02_CONFN (0x2)
#define DESC_TYPE_03_STR (0x3)
#define USB_NO_DATA (-1) /*!< For Device.Transfer.sByteLength */
#define BMREQUEST_TYPE_MASK (0x6 << 4) /*!< bmRequestType[6:5] */
#define USB_FEATURE_REMOTE_WAKEUP (1)
#define MAX_CONTROL_OUT_SIZE (64)
/**
* @}
*/
/* Private function prototypes -----------------------------------------------------------------------------*/
static void _USBDCore_PowerHandler(USBDCore_TypeDef *pCore);
static void _USBDCore_Reset(USBDCore_TypeDef *pCore);
static void _USBDCore_Resume(USBDCore_TypeDef *pCore);
static void _USBDCore_Suspend(USBDCore_TypeDef *pCore);
static void _USBDCore_Setup(USBDCore_TypeDef *pCore);
static void _USBDCore_Standard_Request(USBDCore_TypeDef *pCore);
static void _USBDCore_Standard_GetStatus(USBDCore_TypeDef *pCore, USBDCore_Recipient_Enum recipient);
static void _USBDCore_Standard_SetClearFeature(USBDCore_TypeDef *pCore, USBDCore_Recipient_Enum recipient, USBDCore_SetClearFeature_Enum type);
static void _USBDCore_Standard_SetAddress(USBDCore_TypeDef *pCore);
static void _USBDCore_Standard_GetDescriptor(USBDCore_TypeDef *pCore);
static void _USBDCore_Standard_GetConfiguration(USBDCore_TypeDef *pCore);
static void _USBDCore_Standard_SetConfiguration(USBDCore_TypeDef *pCore);
static void _USBDCore_ControlIN(USBDCore_TypeDef *pCore);
static void _USBDCore_ControlOUT(USBDCore_TypeDef *pCore);
/* Private macro -------------------------------------------------------------------------------------------*/
/** @defgroup USBDCore_Private_Macro USB Device Core private macros
* @{
*/
/**
* @brief Get self powered bit from Device descriptor
*/
#define _GET_SELFPOWERED_FROM_DESC() (((pCore->Device.Desc.pConfnDesc[7]) >> 6) & 0x01)
/**
* @}
*/
/* Private variables ---------------------------------------------------------------------------------------*/
/** @defgroup USBDCore_Private_Variable USB Device Core private variables
* @{
*/
USBDCore_TypeDef *pUSBCore;
/**
* @}
*/
/* Global Function -----------------------------------------------------------------------------------------*/
/** @defgroup USBDCore_Exported_Functions USB Device Core exported functions
* @{
*/
/*********************************************************************************************************//**
* @brief USB Core initialization.
* @param pCore: pointer of USB Device
* @retval None
***********************************************************************************************************/
void USBDCore_Init(USBDCore_TypeDef *pCore)
{
pUSBCore = pCore;
pCore->Info.CurrentStatus = USER_USER_USB_STATE_POWERED;
API_USB_INIT(pCore->pDriver);
__DBG_USBPrintf("\r\n%06ld \r\n", ++__DBG_USBCount);
return;
}
/*********************************************************************************************************//**
* @brief USB Interrupt Service Routine.
* @param pCore: pointer of USB Device
* @retval None
***********************************************************************************************************/
void USBDCore_IRQHandler(USBDCore_TypeDef *pCore)
{
u32 USBISRFlag = API_USB_GET_INT();
u32 USBEPTISRFlag;
USBD_EPTn_Enum EPTn;
#if (USBDCORE_DEBUG == 1)
u32 USBAddr = HT_USB->DEVAR;
#endif
/*--------------------------------------------------------------------------------------------------------*/
/* USB SOF Interrupt */
/*--------------------------------------------------------------------------------------------------------*/
if (API_USB_IS_SOF_INT(USBISRFlag))
{
__DBG_USBPrintf("%06ld SOF[%02d][%02lX]\r\n", ++__DBG_USBCount, pCore->Info.CurrentStatus, USBAddr);
if (pCore->Class.CallBack_StartOfFrame.func != NULL)
{
pCore->Class.CallBack_StartOfFrame.func(pCore->Class.CallBack_StartOfFrame.uPara);
}
usbd_sof_callback(pCore);
API_USB_CLR_SOF_INT();
}
/*--------------------------------------------------------------------------------------------------------*/
/* USB SUSPEND Interrupt */
/*--------------------------------------------------------------------------------------------------------*/
if (API_USB_IS_SUSPEND_INT(USBISRFlag))
{
__DBG_USBPrintf("%06ld SUSPEND[%02d]\r\n", ++__DBG_USBCount, pCore->Info.CurrentStatus);
API_USB_CLR_SUSPEND_INT();
_USBDCore_Suspend(pCore);
// usbd_suspend_callback(pCore);
}
/*--------------------------------------------------------------------------------------------------------*/
/* USB RESET Interrupt */
/*--------------------------------------------------------------------------------------------------------*/
if (API_USB_IS_RESET_INT(USBISRFlag))
{
if (API_USB_IS_FRES_INT(USBISRFlag))
{
API_USB_CLR_FRES_INT();
}
else
{
__DBG_USBPrintf("%06ld RESET[%02d][%02lX]\r\n", ++__DBG_USBCount, pCore->Info.CurrentStatus, USBAddr);
_USBDCore_Reset(pCore);
if (pCore->Class.CallBack_Reset.func != NULL)
{
pCore->Class.CallBack_Reset.func(pCore->Class.CallBack_Reset.uPara);
}
usbd_reset_callback(pCore);
}
API_USB_CLR_RESET_INT();
}
/*--------------------------------------------------------------------------------------------------------*/
/* USB RESUME Interrupt */
/*--------------------------------------------------------------------------------------------------------*/
if (API_USB_IS_RESUME_INT(USBISRFlag))
{
__DBG_USBPrintf("%06ld RESUME\r\n", ++__DBG_USBCount);
_USBDCore_Resume(pCore);
// usbd_resume_callback(pCore);
API_USB_CLR_RESUME_INT();
}
/*--------------------------------------------------------------------------------------------------------*/
/* USB Endpoint 0 interrupt */
/*--------------------------------------------------------------------------------------------------------*/
if (API_USB_IS_EPTn_INT(USBISRFlag, USBD_EPT0))
{
USBEPTISRFlag = API_USB_EPTn_GET_INT(USBD_EPT0);
/*------------------------------------------------------------------------------------------------------*/
/* Control SETUP Stage */
/*------------------------------------------------------------------------------------------------------*/
if (API_USB_IS_SETUP_INT(USBEPTISRFlag))
{
API_USB_READ_SETUP(&(pCore->Device.Request)); /* Read SETUP Command data from USB Buffer*/
__DBG_USBPrintf("%06ld SETUP\t[08]\r\n", ++__DBG_USBCount);
__DBG_USBDump((uc8 *) & (pCore->Device.Request), 8);
// _USBDCore_Setup(pCore);
usbd_setup_callback(pCore);
API_USB_CLR_SETUP_INT(); /* Clear SETUP Interrupt */
}
/*------------------------------------------------------------------------------------------------------*/
/* Control Endpoint 0 IN */
/*------------------------------------------------------------------------------------------------------*/
if (API_USB_EPTn_IS_IN_INT(USBEPTISRFlag))
{
__DBG_USBPrintf("%06ld EP0IN\t[%02ld]", ++__DBG_USBCount, pCore->Device.Transfer.sByteLength);
// _USBDCore_ControlIN(pCore);
usbd_ep0_in_callback(pCore);
API_USB_EPTn_CLR_IN_INT(USBD_EPT0);
}
/*------------------------------------------------------------------------------------------------------*/
/* Control Endpoint 0 OUT */
/*------------------------------------------------------------------------------------------------------*/
if (API_USB_EPTn_IS_OUT_INT(USBEPTISRFlag))
{
__DBG_USBPrintf("%06ld EP0OUT\t[%02ld]", ++__DBG_USBCount, pCore->Device.Transfer.sByteLength);
/*----------------------------------------------------------------------------------------------------*/
/* Clear interrupt flag before USBDCore_ControlOUT is meaning since USBDCore_ControlOUT clear NAKRX */
/* bit which will cause another interrupt occur. */
/*----------------------------------------------------------------------------------------------------*/
API_USB_EPTn_CLR_OUT_INT(USBD_EPT0);
// _USBDCore_ControlOUT(pCore);
usbd_ep0_out_callback(pCore);
}
/*------------------------------------------------------------------------------------------------------*/
/* Clear Control Endpoint 0 global interrupt */
/*------------------------------------------------------------------------------------------------------*/
API_USB_CLR_EPTn_INT(USBD_EPT0);
} /* if (API_USB_IS_EP_INT(USBISRFlag, USBD_EPT0)) */
/*--------------------------------------------------------------------------------------------------------*/
/* USB Endpoint n call back function */
/*--------------------------------------------------------------------------------------------------------*/
while ((EPTn = API_USB_GET_EPT_NUM(API_USB_GET_INT())) != USBD_NOEPT)
{
USBEPTISRFlag = API_USB_EPTn_GET_INT((USBD_EPTn_Enum)EPTn);
if (API_USB_EPTn_IS_INT(USBEPTISRFlag))
{
API_USB_EPTn_CLR_INT(EPTn);
API_USB_CLR_EPTn_INT(EPTn);
if (pCore->Class.CallBack_EPTn[EPTn] != NULL)
{
pCore->Class.CallBack_EPTn[EPTn](EPTn);
}
/* 在此处调用端点输入输出回调函数*/
if (USBEPTISRFlag & IDTXIF)
{
/* 在此处调用端点输入函数 */
usbd_ep_in_callback(pCore, (USBD_EPTn_Enum)EPTn);
}
else
{
/* 在此处调用端点输出函数 */
usbd_ep_out_callback(pCore, (USBD_EPTn_Enum)EPTn);
}
}
} /* while ((EPTn = API_USB_GET_EPTn_NUM(API_USB_GET_INT())) != USBD_NOEPT) */
return;
}
/*********************************************************************************************************//**
* @brief USB Core Main Routine for application.
* @param pCore: pointer of USB Device
* @retval None
***********************************************************************************************************/
void USBDCore_MainRoutine(USBDCore_TypeDef *pCore)
{
_USBDCore_PowerHandler(pCore);
/*--------------------------------------------------------------------------------------------------------*/
/* Class main routine call back function */
/*--------------------------------------------------------------------------------------------------------*/
if ((pCore->Class.CallBack_MainRoutine.func != NULL) && (pCore->Info.CurrentStatus == USER_USER_USB_STATE_CONFIGURED))
{
pCore->Class.CallBack_MainRoutine.func(pCore->Class.CallBack_MainRoutine.uPara);
}
return;
}
/*********************************************************************************************************//**
* @brief Return Suspend status
* @param pCore: pointer of USB Device
* @retval TRUE or FALSE
***********************************************************************************************************/
u32 USBDCore_IsSuspend(USBDCore_TypeDef *pCore)
{
return ((pCore->Info.CurrentStatus == USER_USER_USB_STATE_SUSPENDED) ? TRUE : FALSE);
}
/*********************************************************************************************************//**
* @brief Return remote wake status which set by SET FEATURE standard command
* @param pCore: pointer of USB Device
* @retval TRUE or FALSE
***********************************************************************************************************/
u32 USBDCore_GetRemoteWakeUpFeature(USBDCore_TypeDef *pCore)
{
return (pCore->Info.CurrentFeature.Bits.bRemoteWakeup);
}
/*********************************************************************************************************//**
* @brief Turn on USB power and remote wakeup the Host
* @retval None
***********************************************************************************************************/
void USBDCore_TriggerRemoteWakeup(void)
{
API_USB_POWER_ON(); /* Turn on USB Power */
API_USB_REMOTE_WAKEUP(); /* Generate Remote Wakeup request to Host (RESUME) */
return;
}
/*********************************************************************************************************//**
* @brief Get USB Device status
* @retval USBDCore_Status_Enum
***********************************************************************************************************/
USBDCore_Status_Enum USBDCore_GetStatus(void)
{
return pUSBCore->Info.CurrentStatus;
}
/*********************************************************************************************************//**
* @brief Dump memory data for debug purpose.
* @param memory: buffer pointer to dump
* @param len: dump length
* @retval None
***********************************************************************************************************/
#if (USBDCORE_DEBUG == 1 && USBDCORE_DEBUG_DATA == 1)
void __DBG_USBDump(uc8 *memory, u32 len)
{
u32 i;
for (i = 0; i < len; i++)
{
if (i % 8 == 0)
{
if (i != 0)
{
__DBG_USBPrintf("\r\n");
}
__DBG_USBPrintf("\t\t");
}
__DBG_USBPrintf("%02X ", *((u8 *)(memory + i)));
}
__DBG_USBPrintf("\r\n");
return;
}
#endif
/**
* @}
*/
/* Private functions ---------------------------------------------------------------------------------------*/
/** @defgroup USBDCore_Private_Function USB Device Core private functions
* @{
*/
/*********************************************************************************************************//**
* @brief USB Core Power handler for application.
* @param pCore: pointer of USB Device
* @retval None
***********************************************************************************************************/
static void _USBDCore_PowerHandler(USBDCore_TypeDef *pCore)
{
API_USB_POWER_UP(pCore->pDriver, pCore->Info.CurrentFeature.Bits.bSelfPowered);
if (pCore->Info.CurrentStatus == USER_USER_USB_STATE_SUSPENDED)
{
/*------------------------------------------------------------------------------------------------------*/
/* System Low Power call back function */
/*------------------------------------------------------------------------------------------------------*/
if (pCore->Power.CallBack_Suspend.func != NULL)
{
__DBG_USBPrintf("%06ld >LOWPOWER\r\n", ++__DBG_USBCount);
pCore->Power.CallBack_Suspend.func(pCore->Power.CallBack_Suspend.uPara);
__DBG_USBPrintf("%06ld pDriver;
pCore->Device.Transfer.sByteLength = USB_NO_DATA;
pCore->Info.uCurrentConfiguration = 0;
pCore->Info.uCurrentInterface = 0;
pCore->Info.CurrentFeature.Bits.bRemoteWakeup = 0;
pCore->Info.CurrentStatus = USER_USER_USB_STATE_DEFAULT;
pCore->Info.uIsDiscardClearFeature = FALSE;
API_USB_DEINIT();
API_USB_POWER_ON();
/* Endpoint 0 initialization */
API_USB_EPTn_INIT(USBD_EPT0, pCore->pDriver); // To be modify, init from desc
/* Enable USB interrupt */
API_USB_ENABLE_INT(pDrv->uInterruptMask);
return;
}
/*********************************************************************************************************//**
* @brief USB Resume
* @param pCore: pointer of USB Device
* @retval None
***********************************************************************************************************/
static void _USBDCore_Resume(USBDCore_TypeDef *pCore)
{
API_USB_POWER_ON();
pCore->Info.CurrentStatus = pCore->Info.LastStatus;
return;
}
/*********************************************************************************************************//**
* @brief USB Suspend
* @param pCore: pointer of USB Device
* @retval None
***********************************************************************************************************/
static void _USBDCore_Suspend(USBDCore_TypeDef *pCore)
{
/*--------------------------------------------------------------------------------------------------------*/
/* When Device has been suspended, Change CurrentStatus as SUSPEND and then USBDCore_PowerHandler will */
/* turn off chip power. */
/*--------------------------------------------------------------------------------------------------------*/
if (pCore->Info.CurrentStatus >= USER_USER_USB_STATE_POWERED)
{
API_USB_POWER_OFF();
pCore->Info.LastStatus = pCore->Info.CurrentStatus;
pCore->Info.CurrentStatus = USER_USER_USB_STATE_SUSPENDED;
}
return;
}
/*********************************************************************************************************//**
* @brief USB Setup Stage
* @param pCore: pointer of USB Device
* @retval None
***********************************************************************************************************/
static void _USBDCore_Setup(USBDCore_TypeDef *pCore)
{
pCore->Device.Transfer.Action = USB_ACTION_STALL;
pCore->Device.Transfer.sByteLength = 0;
switch (pCore->Device.Request.bmRequestType & BMREQUEST_TYPE_MASK)
{
/*------------------------------------------------------------------------------------------------------*/
/* Standard requests */
/*------------------------------------------------------------------------------------------------------*/
case REQ_TYPE_00_STD:
{
_USBDCore_Standard_Request(pCore);
break;
}
/*------------------------------------------------------------------------------------------------------*/
/* Class requests */
/*------------------------------------------------------------------------------------------------------*/
case REQ_TYPE_01_CLS:
{
if (pCore->Class.CallBack_ClassRequest != NULL)
{
pCore->Class.CallBack_ClassRequest(&(pCore->Device));
}
break;
}
/*------------------------------------------------------------------------------------------------------*/
/* Vendor requests */
/*------------------------------------------------------------------------------------------------------*/
case REQ_TYPE_02_VND:
{
if (pCore->Class.CallBack_VendorRequest != NULL)
{
pCore->Class.CallBack_VendorRequest(&(pCore->Device));
}
/* Add Vendor requests handler here.... */
#ifdef USBD_VENDOR_SUPPORT
USBDVendor_Request(pCore);
#endif
break;
}
} /* switch (gUSBReq.bmRequestType.byte) */
switch (pCore->Device.Transfer.Action)
{
/*------------------------------------------------------------------------------------------------------*/
/* Control IN */
/*------------------------------------------------------------------------------------------------------*/
case USB_ACTION_DATAIN:
{
/*----------------------------------------------------------------------------------------------------*/
/* When the Control IN length is large than the Host required, transfer the length which specified */
/* by SETUP Data Packet. */
/*----------------------------------------------------------------------------------------------------*/
if (pCore->Device.Transfer.sByteLength > pCore->Device.Request.wLength)
{
pCore->Device.Transfer.sByteLength = pCore->Device.Request.wLength;
}
__DBG_USBPrintf("%06ld EP0IN\t[%02ld]", __DBG_USBCount, pCore->Device.Transfer.sByteLength);
_USBDCore_ControlIN(pCore);
break;
}
/*------------------------------------------------------------------------------------------------------*/
/* Control OUT */
/*------------------------------------------------------------------------------------------------------*/
case USB_ACTION_DATAOUT:
{
if (pCore->Device.Transfer.sByteLength == 0)
{
API_USB_EPTn_WRITE_IN(USBD_EPT0, (u32 *)0, 0); /* Prepare ZLP ack for Control OUT */
}
break;
}
/*------------------------------------------------------------------------------------------------------*/
/* STALL */
/*------------------------------------------------------------------------------------------------------*/
default:
{
__DBG_USBPrintf("%06ld EP0 STALL\r\n", __DBG_USBCount);
API_USB_EPTn_SEND_STALL(USBD_EPT0);
break;
}
}
return;
}
/*********************************************************************************************************//**
* @brief USB Stand Request.
* @param pCore: pointer of USB Device
* @retval None
***********************************************************************************************************/
static void _USBDCore_Standard_Request(USBDCore_TypeDef *pCore)
{
u16 USBCmd = *((u16 *)(&(pCore->Device.Request)));
switch (USBCmd)
{
/*------------------------------------------------------------------------------------------------------*/
/* | bRequest | Data transfer direction | Type | Recipient | Data */
/*------------------------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------------------------*/
/* | 00_Get Status | 80_Device-to-Host | 00_Standard Request | 0_Device | 0080h */
/*------------------------------------------------------------------------------------------------------*/
case (REQ_00_GET_STAT | REQ_DIR_01_D2H | REQ_TYPE_00_STD | REQ_REC_00_DEV):
{
__DBG_USBPrintf("%06ld GET DST\t[%02d]\r\n", __DBG_USBCount, pCore->Info.CurrentFeature.uByte);
_USBDCore_Standard_GetStatus(pCore, Device);
break;
}
/*------------------------------------------------------------------------------------------------------*/
/* | 00_Get Status | 80_Device-to-Host | 00_Standard Request | 1_Interface | 0081h */
/*------------------------------------------------------------------------------------------------------*/
case (REQ_00_GET_STAT | REQ_DIR_01_D2H | REQ_TYPE_00_STD | REQ_REC_01_INF):
{
__DBG_USBPrintf("%06ld GET IST\t[%02d]\r\n", __DBG_USBCount, 0);
_USBDCore_Standard_GetStatus(pCore, Interface);
break;
}
/*------------------------------------------------------------------------------------------------------*/
/* | 00_Get Status | 80_Device-to-Host | 00_Standard Request | 2_Endpoint | 0082h */
/*------------------------------------------------------------------------------------------------------*/
case (REQ_00_GET_STAT | REQ_DIR_01_D2H | REQ_TYPE_00_STD | REQ_REC_02_EPT):
{
__DBG_USBPrintf("%06ld GET EST\t[%02d]\r\n", __DBG_USBCount, pCore->Device.Request.wIndex);
_USBDCore_Standard_GetStatus(pCore, Endpoint);
break;
}
/*------------------------------------------------------------------------------------------------------*/
/* | 01_Clear Feature | 00_Host-to-Device | 00_Standard Request | 0_Device | 0100h */
/*------------------------------------------------------------------------------------------------------*/
case (REQ_01_CLR_FETU | REQ_DIR_00_H2D | REQ_TYPE_00_STD | REQ_REC_00_DEV):
{
__DBG_USBPrintf("%06ld CLR DFEA\t[%02d]\r\n", __DBG_USBCount, pCore->Device.Request.wValueL);
_USBDCore_Standard_SetClearFeature(pCore, Device, ClearFeature);
break;
}
/*------------------------------------------------------------------------------------------------------*/
/* | 01_Clear Feature | 00_Host-to-Device | 00_Standard Request | 2_Endpoint | 0102h */
/*------------------------------------------------------------------------------------------------------*/
case (REQ_01_CLR_FETU | REQ_DIR_00_H2D | REQ_TYPE_00_STD | REQ_REC_02_EPT):
{
__DBG_USBPrintf("%06ld CLR EFEA\t[0x%02x]\r\n", __DBG_USBCount, pCore->Device.Request.wIndex);
_USBDCore_Standard_SetClearFeature(pCore, Endpoint, ClearFeature);
break;
}
/*------------------------------------------------------------------------------------------------------*/
/* | 03_Set Feature | 00_Host-to-Device | 00_Standard Request | 0_Device | 0300h */
/*------------------------------------------------------------------------------------------------------*/
case (REQ_03_SET_FETU | REQ_DIR_00_H2D | REQ_TYPE_00_STD | REQ_REC_00_DEV):
{
__DBG_USBPrintf("%06ld SET DFEA\t[%02d]\r\n", __DBG_USBCount, pCore->Device.Request.wValueL);
_USBDCore_Standard_SetClearFeature(pCore, Device, SetFeature);
break;
}
/*------------------------------------------------------------------------------------------------------*/
/* | 03_Set Feature | 00_Host-to-Device | 00_Standard Request | 2_Endpoint | 0302h */
/*------------------------------------------------------------------------------------------------------*/
case (REQ_03_SET_FETU | REQ_DIR_00_H2D | REQ_TYPE_00_STD | REQ_REC_02_EPT):
{
__DBG_USBPrintf("%06ld SET EFEA\t[%02d]\r\n", __DBG_USBCount, pCore->Device.Request.wIndex);
_USBDCore_Standard_SetClearFeature(pCore, Endpoint, SetFeature);
break;
}
/*------------------------------------------------------------------------------------------------------*/
/* | 05_Set Address | 00_Host-to-Device | 00_Standard Request | 0_Device | 0500h */
/*------------------------------------------------------------------------------------------------------*/
case (REQ_05_SET_ADDR | REQ_DIR_00_H2D | REQ_TYPE_00_STD | REQ_REC_00_DEV):
{
__DBG_USBPrintf("%06ld SET ADDR\t[%02d]\r\n", __DBG_USBCount, pCore->Device.Request.wValueL);
_USBDCore_Standard_SetAddress(pCore);
break;
}
/*------------------------------------------------------------------------------------------------------*/
/* | 06_Get Descriptor | 80_Device-to-Host | 00_Standard Request | 0_Device | 0680h */
/*------------------------------------------------------------------------------------------------------*/
case (REQ_06_GET_DESC | REQ_DIR_01_D2H | REQ_TYPE_00_STD | REQ_REC_00_DEV):
{
__DBG_USBPrintf("%06ld GET DDESC\t[%02X]\r\n", __DBG_USBCount, pCore->Device.Request.wValueH);
_USBDCore_Standard_GetDescriptor(pCore);
break;
}
/*------------------------------------------------------------------------------------------------------*/
/* | 06_Get Descriptor | 80_Device-to-Host | 00_Standard Request | 1_Interface | 0681h */
/*------------------------------------------------------------------------------------------------------*/
case (REQ_06_GET_DESC | REQ_DIR_01_D2H | REQ_TYPE_00_STD | REQ_REC_01_INF):
{
__DBG_USBPrintf("%06ld GET IDESC\t[%02X]\r\n", __DBG_USBCount, pCore->Device.Request.wValueH);
if (pCore->Class.CallBack_ClassGetDescriptor != NULL)
{
pCore->Class.CallBack_ClassGetDescriptor((USBDCore_Device_TypeDef *) & (pCore->Device));
}
break;
}
/*------------------------------------------------------------------------------------------------------*/
/* | 08_Get Configuration | 80_Host-to-Device | 00_Standard Request | 0_Device | 0880h */
/*------------------------------------------------------------------------------------------------------*/
case (REQ_08_GET_CONF | REQ_DIR_01_D2H | REQ_TYPE_00_STD | REQ_REC_00_DEV):
{
__DBG_USBPrintf("%06ld GET CONF\t[%02X]\r\n", __DBG_USBCount, pCore->Info.uCurrentConfiguration);
_USBDCore_Standard_GetConfiguration(pCore);
break;
}
/*------------------------------------------------------------------------------------------------------*/
/* | 09_Set Configuration | 00_Host-to-Device | 00_Standard Request | 0_Device | 0900h */
/*------------------------------------------------------------------------------------------------------*/
case (REQ_09_SET_CONF | REQ_DIR_00_H2D | REQ_TYPE_00_STD | REQ_REC_00_DEV):
{
__DBG_USBPrintf("%06ld SET CONF\t[%02X]\r\n", __DBG_USBCount, pCore->Device.Request.wValueL);
_USBDCore_Standard_SetConfiguration(pCore);
break;
}
/*------------------------------------------------------------------------------------------------------*/
/* | 11_Set Interface | 00_Host-to-Device | 00_Standard Request | 1_Interface | 0B01h */
/*------------------------------------------------------------------------------------------------------*/
case (REQ_11_SET_INF | REQ_DIR_00_H2D | REQ_TYPE_00_STD | REQ_REC_01_INF):
{
__DBG_USBPrintf("%06ld SET INF\t[%02X]\r\n", __DBG_USBCount, pCore->Device.Request.wValueL);
if (pCore->Class.CallBack_ClassSetInterface != NULL)
{
pCore->Class.CallBack_ClassSetInterface((USBDCore_Device_TypeDef *) & (pCore->Device));
}
break;
}
/*------------------------------------------------------------------------------------------------------*/
/* | 10_Get Interface | 80_Device-to-Host | 00_Standard Request | 1_Interface | 0A81h */
/*------------------------------------------------------------------------------------------------------*/
case (REQ_10_GET_INF | REQ_DIR_01_D2H | REQ_TYPE_00_STD | REQ_REC_01_INF):
{
__DBG_USBPrintf("%06ld GET INF\t[%02X]\r\n", __DBG_USBCount, pCore->Device.Request.wValueL);
if (pCore->Class.CallBack_ClassGetInterface != NULL)
{
pCore->Class.CallBack_ClassGetInterface((USBDCore_Device_TypeDef *) & (pCore->Device));
}
break;
}
}
return;
}
/*********************************************************************************************************//**
* @brief USB Standard Request - GET_STATUS.
* @param pCore: pointer of USB Device
* @param recipient: Recipient
* @arg Device: 0
* @arg Interface: 1
* @arg Endpoint: 2
* @retval None
***********************************************************************************************************/
static void _USBDCore_Standard_GetStatus(USBDCore_TypeDef *pCore, USBDCore_Recipient_Enum recipient)
{
pCore->Device.Transfer.uBuffer[1] = 0;
switch (recipient)
{
case Device:
{
pCore->Device.Transfer.uBuffer[0] = pCore->Info.CurrentFeature.uByte;
break;
}
case Interface:
{
pCore->Device.Transfer.uBuffer[0] = 0;
break;
}
case Endpoint:
{
pCore->Device.Transfer.uBuffer[0] = API_USB_EPTn_GET_HALT((USBD_EPTn_Enum)(pCore->Device.Request.wIndex & 0xF));
break;
}
default:
{
return;
}
}
pCore->Device.Transfer.pData = (uc8 *) & (pCore->Device.Transfer.uBuffer);
pCore->Device.Transfer.sByteLength = 2;
pCore->Device.Transfer.Action = USB_ACTION_DATAIN;
return;
}
/*********************************************************************************************************//**
* @brief USB Standard Request - SET_FEATURE / CLEAR_FEATURE.
* @param pCore: pointer of USB Device
* @param recipient: Recipient
* @arg Device: 0
* @arg Interface: 1
* @arg Endpoint: 2
* @param type:
* @arg ClearFeature: 0
@arg SerFeature: 1
* @retval None
***********************************************************************************************************/
static void _USBDCore_Standard_SetClearFeature(USBDCore_TypeDef *pCore,
USBDCore_Recipient_Enum recipient,
USBDCore_SetClearFeature_Enum type)
{
u32 i;
switch (recipient)
{
case Device:
{
if (pCore->Device.Request.wValueL == USB_FEATURE_REMOTE_WAKEUP)
{
pCore->Info.CurrentFeature.Bits.bRemoteWakeup = type;
pCore->Device.Transfer.Action = USB_ACTION_DATAIN;
}
break;
}
case Endpoint:
{
i = pCore->Device.Request.wIndex & 0xF;
if (i != 0)
{
if (type == ClearFeature)
{
if (pCore->Info.uIsDiscardClearFeature == FALSE)
{
API_USB_EPTn_CLR_HALT((USBD_EPTn_Enum)i);
API_USB_EPTn_CLR_DTG((USBD_EPTn_Enum)i);
}
}
else
{
API_USB_EPTn_SET_HALT((USBD_EPTn_Enum)i);
}
}
pCore->Device.Transfer.Action = USB_ACTION_DATAIN;
break;
}
default:
{
break;
}
}
return;
}
/*********************************************************************************************************//**
* @brief USB Standard Request - SET_ADDRESS.
* @param pCore: pointer of USB Device
* @retval None
***********************************************************************************************************/
static void _USBDCore_Standard_SetAddress(USBDCore_TypeDef *pCore)
{
API_USB_SET_ADDR(pCore->Device.Request.wValueL);
pCore->Device.Transfer.Action = USB_ACTION_DATAIN;
pCore->Info.CurrentStatus = USER_USER_USB_STATE_ADDRESS;
return;
}
/*********************************************************************************************************//**
* @brief USB Standard Request - GET_DESCRIPTOR.
* @param pCore: pointer of USB Device
* @retval None
***********************************************************************************************************/
static void _USBDCore_Standard_GetDescriptor(USBDCore_TypeDef *pCore)
{
u32 value = pCore->Device.Request.wValueH;
uc8 *pTemp;
switch (value)
{
case DESC_TYPE_01_DEV:
{
pCore->Device.Transfer.pData = pCore->Device.Desc.pDeviceDesc;
pCore->Device.Transfer.sByteLength = *(pCore->Device.Desc.pDeviceDesc);
pCore->Device.Transfer.Action = USB_ACTION_DATAIN;
break;
}
case DESC_TYPE_02_CONFN:
{
pCore->Device.Transfer.pData = pCore->Device.Desc.pConfnDesc;
pCore->Device.Transfer.sByteLength = *(u16 *)((pCore->Device.Desc.pConfnDesc) + 2);
pCore->Device.Transfer.Action = USB_ACTION_DATAIN;
break;
}
case DESC_TYPE_03_STR:
{
value = pCore->Device.Request.wValueL;
if (value < pCore->Device.Desc.uStringDescNumber)
{
if (*(pCore->Device.Desc.ppStringDesc + value) != NULL)
{
pTemp = *(pCore->Device.Desc.ppStringDesc + value);
pCore->Device.Transfer.pData = (uc8 *)(pTemp);
pCore->Device.Transfer.sByteLength = *(pTemp);
pCore->Device.Transfer.Action = USB_ACTION_DATAIN;
}
}
break;
}
}
#ifdef USBD_VENDOR_SUPPORT
USBDVendor_StandardGetDescriptor(pCore);
#endif
return;
}
/*********************************************************************************************************//**
* @brief USB Standard Request - GET_CONFIGURATION.
* @param pCore: pointer of USB Device
* @retval None
***********************************************************************************************************/
static void _USBDCore_Standard_GetConfiguration(USBDCore_TypeDef *pCore)
{
pCore->Device.Transfer.pData = &(pCore->Info.uCurrentConfiguration);
pCore->Device.Transfer.sByteLength = 1;
pCore->Device.Transfer.Action = USB_ACTION_DATAIN;
return;
}
/*********************************************************************************************************//**
* @brief USB Standard Request - SET_CONFIGURATION.
* @param pCore: pointer of USB Device
* @retval None
***********************************************************************************************************/
static void _USBDCore_Standard_SetConfiguration(USBDCore_TypeDef *pCore)
{
u32 i;
pCore->Info.uCurrentConfiguration = pCore->Device.Request.wValueL;
pCore->Device.Transfer.Action = USB_ACTION_DATAIN;
/* Endpoint n settings */
for (i = 1; i < MAX_EP_NUM; i++)
{
API_USB_EPTn_INIT((USBD_EPTn_Enum)i, pCore->pDriver); // To be modify, init from desc
}
pCore->Info.CurrentStatus = USER_USER_USB_STATE_CONFIGURED;
return;
}
/*********************************************************************************************************//**
* @brief USB Control IN transfer.
* @param pCore: pointer of USB Device
* @retval None
***********************************************************************************************************/
static void _USBDCore_ControlIN(USBDCore_TypeDef *pCore)
{
s32 EP0INLen = API_USB_GET_CTRL_IN_LEN();
u32 len;
if (pCore->Device.Transfer.sByteLength != USB_NO_DATA && pCore->Device.Transfer.Action == USB_ACTION_DATAIN)
{
if (pCore->Device.Transfer.sByteLength >= EP0INLen)
{
len = EP0INLen;
pCore->Device.Transfer.sByteLength -= len;
}
else
{
len = pCore->Device.Transfer.sByteLength;
pCore->Device.Transfer.sByteLength = USB_NO_DATA;
pCore->Device.Transfer.Action = USB_ACTION_DATAOUT;
}
__DBG_USBPrintf("[%02ld]\r\n", len);
__DBG_USBDump((uc8 *)pCore->Device.Transfer.pData, len);
API_USB_EPTn_WRITE_IN(USBD_EPT0, (u32 *)pCore->Device.Transfer.pData, len);
pCore->Device.Transfer.pData = pCore->Device.Transfer.pData + len;
}
else
{
__DBG_USBPrintf("[-1]\r\n");
}
return;
}
/*********************************************************************************************************//**
* @brief USB Control OUT transfer.
* @param pCore: pointer of USB Device
* @retval None
***********************************************************************************************************/
static void _USBDCore_ControlOUT(USBDCore_TypeDef *pCore)
{
u32 len;
if (pCore->Device.Transfer.sByteLength != USB_NO_DATA && pCore->Device.Transfer.Action == USB_ACTION_DATAOUT)
{
len = API_USB_EPTn_READ_OUT(USBD_EPT0, (u32 *)pCore->Device.Transfer.pData, MAX_CONTROL_OUT_SIZE);
__DBG_USBPrintf("[%02ld]\r\n", len);
__DBG_USBDump((uc8 *)pCore->Device.Transfer.pData, len);
pCore->Device.Transfer.pData = pCore->Device.Transfer.pData + len;
pCore->Device.Transfer.sByteLength -= len;
if (pCore->Device.Transfer.sByteLength == 0)
{
pCore->Device.Transfer.Action = USB_ACTION_DATAIN;
if (pCore->Device.Transfer.CallBack_OUT.func != NULL)
{
pCore->Device.Transfer.CallBack_OUT.func(pCore->Device.Transfer.CallBack_OUT.uPara);
pCore->Device.Transfer.CallBack_OUT.func = NULL;
}
pCore->Device.Transfer.sByteLength = USB_NO_DATA;
API_USB_EPTn_WRITE_IN(USBD_EPT0, (u32 *)0, 0);
}
}
else
{
__DBG_USBPrintf("[-1]\r\n");
}
return;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/