This commit is contained in:
moyuhai
2026-06-11 13:04:09 +08:00
commit 966451d245
2022 changed files with 513671 additions and 0 deletions
@@ -0,0 +1,75 @@
/*!
* \file usb_device.c
*
* \brief Target usb device implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usb_device.h"
#include "usbd_cdc.h"
#include "usbd_cdc_if.h"
#include "usbd_core.h"
#include "usbd_desc.h"
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
/* USB Device Core handle declaration. */
USBD_HandleTypeDef hUsbDeviceFS;
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
/**
* @brief This function handles USB On The Go FS global interrupt.
* @param void
* @retval void
*/
void USB_Handler(void) { HAL_PCD_IRQHandler(&hpcd_USB_OTG_FS); }
/**
* @brief Init USB device Library, add supported class and start the library
* @param void
* @retval void
*/
void USB_DEVICE_Init(void)
{
/* Init Device Library, add supported class and start the library. */
if (USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS) != USBD_OK) {
USBD_UsrLog("__USB_INIT_FAIL__\r\n");
Error_Handler();
}
if (USBD_RegisterClass(&hUsbDeviceFS, &USBD_CDC) != USBD_OK) {
USBD_UsrLog("__USB_CLASS_FAIL__\r\n");
Error_Handler();
}
if (USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_Interface_fops_FS) !=
USBD_OK) {
USBD_UsrLog("__USB_CDC_FAIL__\r\n");
Error_Handler();
}
if (USBD_Start(&hUsbDeviceFS) != USBD_OK) {
USBD_UsrLog("__USB_START_FAIL__\r\n");
Error_Handler();
}
}
@@ -0,0 +1,47 @@
/*!
* \file usb_device.h
*
* \brief Target usb device implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USB_DEVICE_H
#define __USB_DEVICE_H
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_def.h"
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
void USB_DEVICE_Init( void );
#ifdef __cplusplus
}
#endif
#endif /* __USB_DEVICE_H */
@@ -0,0 +1,322 @@
/*!
* \file usbd_cdc_if.c
*
* \brief Usb device for Virtual Com Port.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_cdc_if.h"
#include "ringbuffer.h"
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
/** @defgroup USBD_CDC_IF_Exported_Variables USBD_CDC_IF_Exported_Variables
* @brief Public variables.
* @{
*/
uint8_t Next_ep = 0;
extern USBD_HandleTypeDef hUsbDeviceFS;
/**
* @}
*/
/*------------------------------------------------------------------------------------
Local Variables
-------------------------------------------------------------------------------------*/
/** Received data over USB are stored in this buffer */
uint8_t UserRxBufferFS[APP_RX_DATA_SIZE];
uint16_t UserRxBufferLen = 0;
/** Data to send over USB CDC are stored in this buffer */
uint8_t UserTxBufferFS[APP_TX_DATA_SIZE];
uint8_t UserReTx = false;
uint8_t TempBuffer[APP_TX_DATA_SIZE / 2];
/**
* @}
*/
/*------------------------------------------------------------------------------------
Func Prototype
-------------------------------------------------------------------------------------*/
/** @defgroup USBD_CDC_IF_Private_FunctionPrototypes
* USBD_CDC_IF_Private_FunctionPrototypes
* @brief Private functions declaration.
* @{
*/
static int8_t CDC_Init_FS(void);
static int8_t CDC_DeInit_FS(void);
static int8_t CDC_Control_FS(uint8_t cmd, uint8_t *pbuf, uint16_t length);
static int8_t CDC_Receive_FS(uint8_t *pbuf, uint32_t *Len);
static int8_t CDC_TransmitCplt_FS(uint8_t *pbuf, uint32_t *Len, uint8_t epnum);
/**
* @}
*/
USBD_CDC_ItfTypeDef USBD_Interface_fops_FS = {CDC_Init_FS, CDC_DeInit_FS,
CDC_Control_FS, CDC_Receive_FS,
CDC_TransmitCplt_FS};
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
/**
* @brief Initializes the CDC media low layer over the FS USB IP
* @retval USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Init_FS(void)
{
/* Set Application Buffers */
memset(TempBuffer, 0, sizeof(TempBuffer));
UserRxBufferLen = 0;
// USB_FlushTxFifo(hpcd_USB_OTG_FS.Instance, 0x10U);
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, UserTxBufferFS, 0);
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, UserRxBufferFS);
return (USBD_OK);
}
/**
* @brief DeInitializes the CDC media low layer
* @retval USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_DeInit_FS(void) { return (USBD_OK); }
/**
* @brief Manage the CDC class requests
* @param cmd: Command code
* @param pbuf: Buffer containing command data (request parameters)
* @param length: Number of data to be sent (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else
* USBD_FAIL
*/
static int8_t CDC_Control_FS(uint8_t cmd, uint8_t *pbuf, uint16_t length)
{
switch (cmd) {
case CDC_SEND_ENCAPSULATED_COMMAND:
break;
case CDC_GET_ENCAPSULATED_RESPONSE:
break;
case CDC_SET_COMM_FEATURE:
break;
case CDC_GET_COMM_FEATURE:
break;
case CDC_CLEAR_COMM_FEATURE:
break;
/*******************************************************************************/
/* Line Coding Structure */
/*-----------------------------------------------------------------------------*/
/* Offset | Field | Size | Value | Description */
/* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per
* second*/
/* 4 | bCharFormat | 1 | Number | Stop bits */
/* 0 - 1 Stop bit */
/* 1 - 1.5 Stop bits */
/* 2 - 2 Stop bits */
/* 5 | bParityType | 1 | Number | Parity */
/* 0 - None */
/* 1 - Odd */
/* 2 - Even */
/* 3 - Mark */
/* 4 - Space */
/* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
/*******************************************************************************/
case CDC_SET_LINE_CODING:
break;
case CDC_GET_LINE_CODING:
break;
case CDC_SET_CONTROL_LINE_STATE:
break;
case CDC_SEND_BREAK:
break;
default:
break;
}
return (USBD_OK);
}
/**
* @brief Data received over USB OUT endpoint are sent over CDC interface
* through this function.
*
* @note
* This function will issue a NAK packet on any OUT packet received on
* USB endpoint until exiting this function. If you exit this function
* before transfer is complete on CDC interface (ie. using DMA
* controller) it will result in receiving more data while previous ones are
* still not sent.
*
* @param Buf: Buffer of data to be received
* @param Len: Number of data received (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else
* USBD_FAIL
*/
static int8_t CDC_Receive_FS(uint8_t *Buf, uint32_t *Len)
{
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
// Receive Timer Refresh
// TIMER_SetUs(XC_TIMER0, CDC_RECV_TIMEOUT_MS);
// TIMER_Start_IT(XC_TIMER0);
// DEBUG("len %d\n", *Len);
//// Delay_Ms(10);
// if(*Len != 0)
// {
// if(UserRxBufferLen < (APP_TX_DATA_SIZE/2))
// {
// ring_buffer_queue_arr(&CDC_Rx, Buf, *Len);
// UserRxBufferLen += *Len;
// }
// }
// DEBUG("u_len %d\n", UserRxBufferLen);
CDC_Transmit_FS(UserRxBufferFS, *Len, CDC_IN_EP);
return (USBD_OK);
}
/**
* @brief CDC_Transmit_FS
* Data to send over USB IN endpoint are sent over CDC interface
* through this function.
* @note
*
*
* @param Buf: Buffer of data to be sent
* @param Len: Number of data to be sent (in bytes)
* @retval USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY
*/
uint8_t CDC_Transmit_FS(uint8_t *Buf, uint16_t Len, uint8_t epnum)
{
uint8_t result = USBD_OK;
// DEBUG("cdc_epnum: %d\n", epnum);
USBD_CDC_HandleTypeDef *hcdc =
(USBD_CDC_HandleTypeDef *)hUsbDeviceFS.pClassData;
if (hcdc->TxState != 0) {
// DEBUG("bsy: %d\n", hcdc->TxState);
return USBD_BUSY;
}
// DEBUG("tx_len %d\r", Len);
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS, epnum);
// uint8_t packetSendCnt = Len / 64;
// uint8_t packetSendRem = Len % 64;
//
// for(uint8_t i=0; i<packetSendCnt; i++)
// {
// USBD_CDC_SetTxBuffer(&hUsbDeviceFS, &Buf[i * 64], 64);
// result = USBD_CDC_TransmitPacket(&hUsbDeviceFS, epnum);
// while(hcdc->TxState != 0);
// USBD_CDC_SetTxBuffer(&hUsbDeviceFS, NULL, 0);
// result = USBD_CDC_TransmitPacket(&hUsbDeviceFS, epnum);
// while(hcdc->TxState != 0);
// }
//
// if(packetSendRem != 0)
// {
// DEBUG("SendRem\r");
// USBD_CDC_SetTxBuffer(&hUsbDeviceFS, &Buf[Len - packetSendRem],
// packetSendRem); result = USBD_CDC_TransmitPacket(&hUsbDeviceFS,
// epnum);
// }
// while(hcdc->TxState != 0);
// memset(TempBuffer, 0, sizeof(TempBuffer));
// UserRxBufferLen = 0;
return result;
}
/**
* @brief CDC_TransmitCplt_FS
* Data transmitted callback
*
* @note
* This function is IN transfer complete callback used to inform user
* that the submitted Data is successfully sent over USB.
*
* @param Buf: Buffer of data to be received
* @param Len: Number of data received (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else
* USBD_FAIL
*/
static int8_t CDC_TransmitCplt_FS(uint8_t *Buf, uint32_t *Len, uint8_t epnum)
{
uint8_t result = USBD_OK;
// static uint8_t offset = 0;
UNUSED(Buf);
UNUSED(Len);
UNUSED(epnum);
// if(UserReTx == true)
// {
// UserRxBufferLen -= CDC_DATA_FS_MAX_PACKET_SIZE;
// offset++;
// if(UserRxBufferLen > CDC_DATA_FS_MAX_PACKET_SIZE)
// CDC_Transmit_FS(TempBuffer+offset*CDC_DATA_FS_MAX_PACKET_SIZE,
// CDC_DATA_FS_MAX_PACKET_SIZE, CDC_IN_EP);
// else
// {
// UserReTx = false;
// CDC_Transmit_FS(TempBuffer+offset*CDC_DATA_FS_MAX_PACKET_SIZE,
// UserRxBufferLen, CDC_IN_EP);
// }
// }
// else
// {
// if(UserRxBufferLen <= CDC_DATA_FS_MAX_PACKET_SIZE)
// {
// offset = 0;
// memset(TempBuffer, 0, sizeof(TempBuffer));
// UserRxBufferLen = 0;
// }
// }
return result;
}
@@ -0,0 +1,84 @@
/*!
* \file usbd_cdc_if.h
*
* \brief Header for usbd_cdc_if.c file.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_CDC_IF_H
#define __USBD_CDC_IF_H
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_cdc.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------——----------------------------------------*/
/** @defgroup USBD_CDC_IF_Exported_Defines USBD_CDC_IF_Exported_Defines
* @brief Defines.
* @{
*/
/* Define size for the receive and transmit buffer over CDC */
#define APP_RX_DATA_SIZE 1024
#define APP_TX_DATA_SIZE 1024
#define CDC_RECV_TIMEOUT_MS 5000U
/**
* @}
*/
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
/** CDC Interface callback. */
extern USBD_CDC_ItfTypeDef USBD_Interface_fops_FS;
extern uint8_t Next_ep;
//extern tHandler_callback CDC_Recv_Timer_Cbk[4];
extern uint16_t UserRxBufferLen;
extern uint8_t UserTxBufferFS[APP_TX_DATA_SIZE];
extern uint8_t UserTxEnable;
/**
* @}
*/
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len, uint8_t epnum);
void CDC_Receive_Timeout(uint16_t val);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_CDC_IF_H */
@@ -0,0 +1,348 @@
/*!
* \file usbd_desc.c
*
* \brief Target the USB device descriptors implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_desc.h"
#include "usbd_conf.h"
#include "usbd_core.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------
-----------------------------------------*/
/** @defgroup USBD_DESC_Private_Defines USBD_DESC_Private_Defines
* @brief Private defines.
* @{
*/
#define USBD_VID 0x0483
#define USBD_LANGID_STRING 0x0409
#define USBD_MANUFACTURER_STRING "XinChip"
#define USBD_PID_FS 22336
#define USBD_PRODUCT_STRING_FS "XinChip Virtual ComPort"
#define USBD_CONFIGURATION_STRING_FS "CDC Config"
#define USBD_INTERFACE_STRING_FS "CDC Interface"
#define USB_SIZ_BOS_DESC 0x0C
/*------------------------------------------------------------------------------------
Func Prototypes
-------------------------------------------------------------------------------------*/
/** @defgroup USBD_DESC_Private_FunctionPrototypes
* USBD_DESC_Private_FunctionPrototypes
* @brief Private functions declaration.
* @{
*/
static void Get_SerialNum(void);
static void IntToUnicode(uint32_t value, uint8_t *pbuf, uint8_t len);
/** @defgroup USBD_DESC_Private_FunctionPrototypes
* USBD_DESC_Private_FunctionPrototypes
* @brief Private functions declaration for FS.
* @{
*/
uint8_t *USBD_FS_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *USBD_FS_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *USBD_FS_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length);
uint8_t *USBD_FS_ProductStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length);
uint8_t *USBD_FS_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *USBD_FS_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *USBD_FS_InterfaceStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length);
#if (USBD_LPM_ENABLED == 1)
uint8_t *USBD_FS_USR_BOSDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
#endif /* (USBD_LPM_ENABLED == 1) */
/*------------------------------------------------------------------------------------
Local Variables
-------------------------------------------------------------------------------------*/
/** @defgroup USBD_DESC_Private_Variables USBD_DESC_Private_Variables
* @brief Private variables.
* @{
*/
USBD_DescriptorsTypeDef FS_Desc = {USBD_FS_DeviceDescriptor,
USBD_FS_LangIDStrDescriptor,
USBD_FS_ManufacturerStrDescriptor,
USBD_FS_ProductStrDescriptor,
USBD_FS_SerialStrDescriptor,
USBD_FS_ConfigStrDescriptor,
USBD_FS_InterfaceStrDescriptor
#if (USBD_LPM_ENABLED == 1)
,
USBD_FS_USR_BOSDescriptor
#endif /* (USBD_LPM_ENABLED == 1) */
};
#if defined(__ICCARM__) /* IAR Compiler */
#pragma data_alignment = 4
#endif /* defined ( __ICCARM__ ) */
/** USB standard device descriptor. */
__ALIGN_BEGIN uint8_t USBD_FS_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END = {
0x12, /*bLength */
USB_DESC_TYPE_DEVICE, /*bDescriptorType*/
#if (USBD_LPM_ENABLED == 1)
0x01,
/*bcdUSB */ /* changed to USB version 2.01
in order to support LPM L1 suspend
resume test of USBCV3.0*/
#else
0x00, /*bcdUSB */
#endif /* (USBD_LPM_ENABLED == 1) */
0x02,
DEV_CLASS, /*bDeviceClass*/
DEV_SUB_CLASS, /*bDeviceSubClass*/
DEV_PROTOCOL, /*bDeviceProtocol*/
USB_MAX_EP0_SIZE, /*bMaxPacketSize*/
LOBYTE(USBD_VID), /*idVendor*/
HIBYTE(USBD_VID), /*idVendor*/
LOBYTE(USBD_PID_FS), /*idProduct*/
HIBYTE(USBD_PID_FS), /*idProduct*/
0x00, /*bcdDevice rel. 2.00*/
0x02,
USBD_IDX_MFC_STR, /*Index of manufacturer string*/
USBD_IDX_PRODUCT_STR, /*Index of product string*/
USBD_IDX_SERIAL_STR, /*Index of serial number string*/
USBD_MAX_NUM_CONFIGURATION /*bNumConfigurations*/
};
/* USB_DeviceDescriptor */
/** BOS descriptor. */
#if (USBD_LPM_ENABLED == 1)
#if defined(__ICCARM__) /* IAR Compiler */
#pragma data_alignment = 4
#endif /* defined ( __ICCARM__ ) */
__ALIGN_BEGIN uint8_t USBD_FS_BOSDesc[USB_SIZ_BOS_DESC] __ALIGN_END = {
0x5, USB_DESC_TYPE_BOS, 0xC, 0x0, 0x1, /* 1 device capability*/
/* device capability*/
0x7, USB_DEVICE_CAPABITY_TYPE, 0x2, 0x2, /* LPM capability bit set*/
0x0, 0x0, 0x0};
#endif /* (USBD_LPM_ENABLED == 1) */
/** @defgroup USBD_DESC_Private_Variables USBD_DESC_Private_Variables
* @brief Private variables.
* @{
*/
#if defined(__ICCARM__) /* IAR Compiler */
#pragma data_alignment = 4
#endif /* defined ( __ICCARM__ ) */
/** USB lang identifier descriptor. */
__ALIGN_BEGIN uint8_t USBD_LangIDDesc[USB_LEN_LANGID_STR_DESC] __ALIGN_END = {
USB_LEN_LANGID_STR_DESC, USB_DESC_TYPE_STRING, LOBYTE(USBD_LANGID_STRING),
HIBYTE(USBD_LANGID_STRING)};
#if defined(__ICCARM__) /* IAR Compiler */
#pragma data_alignment = 4
#endif /* defined ( __ICCARM__ ) */
/* Internal string descriptor. */
__ALIGN_BEGIN uint8_t USBD_StrDesc[USBD_MAX_STR_DESC_SIZ] __ALIGN_END;
#if defined(__ICCARM__) /*!< IAR Compiler */
#pragma data_alignment = 4
#endif
__ALIGN_BEGIN uint8_t USBD_StringSerial[USB_SIZ_STRING_SERIAL] __ALIGN_END = {
USB_SIZ_STRING_SERIAL,
USB_DESC_TYPE_STRING,
};
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
/**
* @brief Return the device descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
UNUSED(speed);
*length = sizeof(USBD_FS_DeviceDesc);
return USBD_FS_DeviceDesc;
}
/**
* @brief Return the LangID string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
UNUSED(speed);
*length = sizeof(USBD_LangIDDesc);
return USBD_LangIDDesc;
}
/**
* @brief Return the product string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
if (speed == 0) {
USBD_GetString((uint8_t *)USBD_PRODUCT_STRING_FS, USBD_StrDesc, length);
} else {
USBD_GetString((uint8_t *)USBD_PRODUCT_STRING_FS, USBD_StrDesc, length);
}
return USBD_StrDesc;
}
/**
* @brief Return the manufacturer string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length)
{
UNUSED(speed);
USBD_GetString((uint8_t *)USBD_MANUFACTURER_STRING, USBD_StrDesc, length);
return USBD_StrDesc;
}
/**
* @brief Return the serial number string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
UNUSED(speed);
*length = USB_SIZ_STRING_SERIAL;
/* Update the serial number string descriptor with the data from the unique
* ID */
Get_SerialNum();
/* USER CODE BEGIN USBD_FS_SerialStrDescriptor */
/* USER CODE END USBD_FS_SerialStrDescriptor */
return (uint8_t *)USBD_StringSerial;
}
/**
* @brief Return the configuration string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
USBD_GetString((uint8_t *)USBD_CONFIGURATION_STRING_FS, USBD_StrDesc,
length);
return USBD_StrDesc;
}
/**
* @brief Return the interface string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_InterfaceStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length)
{
if (speed == 0) {
USBD_GetString((uint8_t *)USBD_INTERFACE_STRING_FS, USBD_StrDesc,
length);
} else {
USBD_GetString((uint8_t *)USBD_INTERFACE_STRING_FS, USBD_StrDesc,
length);
}
return USBD_StrDesc;
}
#if (USBD_LPM_ENABLED == 1)
/**
* @brief Return the BOS descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_USR_BOSDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
UNUSED(speed);
*length = sizeof(USBD_FS_BOSDesc);
return (uint8_t *)USBD_FS_BOSDesc;
}
#endif /* (USBD_LPM_ENABLED == 1) */
/**
* @brief Create the serial number string descriptor
* @param None
* @retval None
*/
static void Get_SerialNum(void)
{
uint32_t deviceserial0, deviceserial1, deviceserial2;
deviceserial0 = DEVICE_ID1;
deviceserial1 = DEVICE_ID2;
deviceserial2 = DEVICE_ID3;
deviceserial0 += deviceserial2;
if (deviceserial0 != 0) {
IntToUnicode(deviceserial0, &USBD_StringSerial[2], 8);
IntToUnicode(deviceserial1, &USBD_StringSerial[18], 4);
}
}
/**
* @brief Convert Hex 32Bits value into char
* @param value: value to convert
* @param pbuf: pointer to the buffer
* @param len: buffer length
* @retval None
*/
static void IntToUnicode(uint32_t value, uint8_t *pbuf, uint8_t len)
{
uint8_t idx = 0;
for (idx = 0; idx < len; idx++) {
if (((value >> 28)) < 0xA) {
pbuf[2 * idx] = (value >> 28) + '0';
} else {
pbuf[2 * idx] = (value >> 28) + 'A' - 10;
}
value = value << 4;
pbuf[2 * idx + 1] = 0;
}
}
/**
* @}
*/
@@ -0,0 +1,76 @@
/*!
* \file usbd_desc.h
*
* \brief Target the USB device descriptors implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_DESC__C
#define __USBD_DESC__C
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_def.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
/** @defgroup USBD_DESC_Exported_Constants USBD_DESC_Exported_Constants
* @brief Constants.
* @{
*/
#define DEV_CLASS 0x02
#define DEV_SUB_CLASS 0x02
#define DEV_PROTOCOL 0x00
#define DEVICE_ID1 0x20220000
#define DEVICE_ID2 0x1B0000
#define DEVICE_ID3 0x0914
#define USB_SIZ_STRING_SERIAL 0x1A
/**
* @}
*/
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
/** Descriptor for the Usb device. */
extern USBD_DescriptorsTypeDef FS_Desc;
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_DESC__C */
@@ -0,0 +1,184 @@
/*!
* \file usb_device.c
*
* \brief Target usb device implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usb_device.h"
#include "usbd_core.h"
#include "usbd_desc.h"
#include "usbd_hid.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
#if ((HID_CLASS_MODE & HID_MOUSE) == HID_MOUSE)
#define CURSOR_STEP 2U
#define CURSOR_WIDTH 200U
#elif ((HID_CLASS_MODE & HID_KEYBOARD) == HID_KEYBOARD)
#define KEY_CAPS_DATA 0x39
#endif
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
/* USB Device Core handle declaration. */
USBD_HandleTypeDef hUsbDeviceFS;
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
/**
* @brief This function handles USB On The Go FS global interrupt.
* @param void
* @retval void
*/
void USB_Handler(void) { HAL_PCD_IRQHandler(&hpcd_USB_OTG_FS); }
/**
* @brief Init USB device Library, add supported class and start the library
* @param void
* @retval void
*/
void USB_DEVICE_Init(void)
{
/* Init Device Library, add supported class and start the library. */
if (USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS) != USBD_OK) {
Error_Handler();
}
if (USBD_RegisterClass(&hUsbDeviceFS, &USBD_HID) != USBD_OK) {
Error_Handler();
}
if (USBD_Start(&hUsbDeviceFS) != USBD_OK) {
Error_Handler();
}
}
#if ((HID_CLASS_MODE & HID_MOUSE) == HID_MOUSE)
/**
* @brief Mouse get pointer datas
* @param uint8_t *pbuf
* @retval void
*/
void GetPointerData(uint8_t *pbuf)
{
static int32_t move_cnt = 0;
static uint8_t step_x_y = 0;
static int8_t x = 0, y = 0;
static uint16_t cnt = 0;
move_cnt++;
if (move_cnt > CURSOR_WIDTH) {
step_x_y++;
step_x_y = step_x_y % 4;
move_cnt = 0;
}
switch (step_x_y) {
case 0: {
y = 0;
x = CURSOR_STEP;
} break;
case 1: {
x = 0;
y = CURSOR_STEP;
} break;
case 2: {
y = 0;
x = (int8_t)(-CURSOR_STEP);
} break;
case 3: {
x = 0;
y = (int8_t)(-CURSOR_STEP);
} break;
}
cnt++;
pbuf[0] = 0; // 1;
if (cnt > 1000) {
pbuf[0] = 16; // 17;
cnt = 0;
}
pbuf[1] = x;
pbuf[2] = y;
pbuf[3] = 0;
}
/**
* @brief Usb mouse test send report
* @param void
* @retval void
*/
void USB_Mouse_Test_SendReport(void)
{
uint8_t buff[4] = {0};
USBD_HID_SendReport(&hUsbDeviceFS, HID_EPIN_ADDR, buff, HID_EPIN_SIZE);
}
#endif
#if ((HID_CLASS_MODE & HID_KEYBOARD) == HID_KEYBOARD)
/**
* @brief Usb Keyboard test send report
* @param void
* @retval void
*/
void USB_Keyboard_Test_SendReport(eKeyState key_sta)
{
uint8_t buff[HID_EPIN_SIZE] = {0};
if (key_sta == KEY_PRESS) {
buff[2] = KEY_CAPS_DATA;
USBD_HID_SendReport(&hUsbDeviceFS, HID_EPIN_ADDR, buff, HID_EPIN_SIZE);
} else if (key_sta == KEY_RELEASE) {
USBD_HID_SendReport(&hUsbDeviceFS, HID_EPIN_ADDR, buff, HID_EPIN_SIZE);
} else if (key_sta == KEY_HOLD_PRESS) {
return;
}
}
#endif
#if (HID_CLASS_MODE == HID_CUSTOM)
/**
* @brief Usb custom hid test send report
* @param void
* @retval void
*/
void USB_Custom_Test_SendReport(void)
{
uint8_t usb_tx_data[64] = {0};
// usb_tx_data[0] = 0x01;
for (uint8_t i = 0; i < 64; i++)
usb_tx_data[i] = i;
USBD_HID_SendReport(&hUsbDeviceFS, HID_EPIN_ADDR, usb_tx_data, 64);
}
#endif
@@ -0,0 +1,66 @@
/*!
* \file usb_device.h
*
* \brief Target usb device implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USB_DEVICE_H__
#define __USB_DEVICE_H__
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_def.h"
extern USBD_HandleTypeDef hUsbDeviceFS;
typedef enum {
KEY_RELEASE = 0,
KEY_PRESS,
KEY_HOLD_PRESS
} eKeyState;
extern USBD_HandleTypeDef hUsbDeviceFS;
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
void USB_DEVICE_Init( void );
void USB_Mouse_Test_SendReport( void );
void USB_Keyboard_Test_SendReport(eKeyState key_sta);
void USB_Custom_Test_SendReport( void );
void GetPointerData(uint8_t *pbuf);
#ifdef __cplusplus
}
#endif
#endif /* __USB_DEVICE_H__ */
@@ -0,0 +1,352 @@
/*!
* \file usbd_desc.c
*
* \brief Target the USB device descriptors implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_desc.h"
#include "usbd_conf.h"
#include "usbd_core.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------
-----------------------------------------*/
/** @defgroup USBD_DESC_Private_Defines USBD_DESC_Private_Defines
* @brief Private defines.
* @{
*/
#define USBD_VID VID_VAL
#define USBD_LANGID_STRING LANG_ID_STR
#define USBD_MANUFACTURER_STRING "XinChip"
#define USBD_PID_FS PID_FS_VAL
#define USBD_PRODUCT_STRING_FS \
"XinChip Custom Human interface" //"XinChip Human interface"
#define USBD_CONFIGURATION_STRING_FS "Custom HID Config" //"HID Config"
#define USBD_INTERFACE_STRING_FS "Custom HID Interface" //"HID Interface"
#define USB_SIZ_BOS_DESC 0x0C
/*------------------------------------------------------------------------------------
Func Prototypes
-------------------------------------------------------------------------------------*/
/** @defgroup USBD_DESC_Private_FunctionPrototypes
* USBD_DESC_Private_FunctionPrototypes
* @brief Private functions declaration.
* @{
*/
static void Get_SerialNum(void);
static void IntToUnicode(uint32_t value, uint8_t *pbuf, uint8_t len);
/** @defgroup USBD_DESC_Private_FunctionPrototypes
* USBD_DESC_Private_FunctionPrototypes
* @brief Private functions declaration for FS.
* @{
*/
uint8_t *USBD_FS_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *USBD_FS_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *USBD_FS_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length);
uint8_t *USBD_FS_ProductStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length);
uint8_t *USBD_FS_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *USBD_FS_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *USBD_FS_InterfaceStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length);
#if (USBD_LPM_ENABLED == 1)
uint8_t *USBD_FS_USR_BOSDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
#endif /* (USBD_LPM_ENABLED == 1) */
/*------------------------------------------------------------------------------------
Local Variables
-------------------------------------------------------------------------------------*/
/** @defgroup USBD_DESC_Private_Variables USBD_DESC_Private_Variables
* @brief Private variables.
* @{
*/
USBD_DescriptorsTypeDef FS_Desc = {USBD_FS_DeviceDescriptor,
USBD_FS_LangIDStrDescriptor,
USBD_FS_ManufacturerStrDescriptor,
USBD_FS_ProductStrDescriptor,
USBD_FS_SerialStrDescriptor,
USBD_FS_ConfigStrDescriptor,
USBD_FS_InterfaceStrDescriptor
#if (USBD_LPM_ENABLED == 1)
,
USBD_FS_USR_BOSDescriptor
#endif /* (USBD_LPM_ENABLED == 1) */
};
#if defined(__ICCARM__) /* IAR Compiler */
#pragma data_alignment = 4
#endif /* defined ( __ICCARM__ ) */
/** USB standard device descriptor. */
__ALIGN_BEGIN uint8_t USBD_FS_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END = {
0x12, /*bLength */
USB_DESC_TYPE_DEVICE, /*bDescriptorType*/
#if (USBD_LPM_ENABLED == 1)
0x01,
/*bcdUSB */ /* changed to USB version 2.01
in order to support LPM L1 suspend
resume test of USBCV3.0*/
#else
0x00, /*bcdUSB */
#endif /* (USBD_LPM_ENABLED == 1) */
0x02,
DEV_CLASS, /*bDeviceClass*/
DEV_SUB_CLASS, /*bDeviceSubClass*/
DEV_PROTOCOL, /*bDeviceProtocol*/
USB_MAX_EP0_SIZE, /*bMaxPacketSize*/
LOBYTE(USBD_VID), /*idVendor*/
HIBYTE(USBD_VID), /*idVendor*/
LOBYTE(USBD_PID_FS), /*idProduct*/
HIBYTE(USBD_PID_FS), /*idProduct*/
0x00, /*bcdDevice rel. 2.00*/
0x02,
USBD_IDX_MFC_STR, /*Index of manufacturer string*/
USBD_IDX_PRODUCT_STR, /*Index of product string*/
USBD_IDX_SERIAL_STR, /*Index of serial number string*/
USBD_MAX_NUM_CONFIGURATION /*bNumConfigurations*/
};
/* USB_DeviceDescriptor */
/** BOS descriptor. */
#if (USBD_LPM_ENABLED == 1)
#if defined(__ICCARM__) /* IAR Compiler */
#pragma data_alignment = 4
#endif /* defined ( __ICCARM__ ) */
__ALIGN_BEGIN uint8_t USBD_FS_BOSDesc[USB_SIZ_BOS_DESC] __ALIGN_END = {
0x5, USB_DESC_TYPE_BOS, 0xC, 0x0, 0x1, /* 1 device capability*/
/* device capability*/
0x7, USB_DEVICE_CAPABITY_TYPE, 0x2, 0x2, /* LPM capability bit set*/
0x0, 0x0, 0x0};
#endif /* (USBD_LPM_ENABLED == 1) */
/** @defgroup USBD_DESC_Private_Variables USBD_DESC_Private_Variables
* @brief Private variables.
* @{
*/
#if defined(__ICCARM__) /* IAR Compiler */
#pragma data_alignment = 4
#endif /* defined ( __ICCARM__ ) */
/** USB lang identifier descriptor. */
__ALIGN_BEGIN uint8_t USBD_LangIDDesc[USB_LEN_LANGID_STR_DESC] __ALIGN_END = {
USB_LEN_LANGID_STR_DESC, USB_DESC_TYPE_STRING, LOBYTE(USBD_LANGID_STRING),
HIBYTE(USBD_LANGID_STRING)};
#if defined(__ICCARM__) /* IAR Compiler */
#pragma data_alignment = 4
#endif /* defined ( __ICCARM__ ) */
/* Internal string descriptor. */
__ALIGN_BEGIN uint8_t USBD_StrDesc[USBD_MAX_STR_DESC_SIZ] __ALIGN_END;
#if defined(__ICCARM__) /*!< IAR Compiler */
#pragma data_alignment = 4
#endif
__ALIGN_BEGIN uint8_t USBD_StringSerial[USB_SIZ_STRING_SERIAL] __ALIGN_END = {
USB_SIZ_STRING_SERIAL,
USB_DESC_TYPE_STRING,
};
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
/**
* @brief Return the device descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
*length = sizeof(USBD_FS_DeviceDesc);
return USBD_FS_DeviceDesc;
}
/**
* @brief Return the LangID string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
UNUSED(speed);
*length = sizeof(USBD_LangIDDesc);
return USBD_LangIDDesc;
}
/**
* @brief Return the product string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
if (speed == 0) {
USBD_GetString((uint8_t *)USBD_PRODUCT_STRING_FS, USBD_StrDesc, length);
} else {
USBD_GetString((uint8_t *)USBD_PRODUCT_STRING_FS, USBD_StrDesc, length);
}
return USBD_StrDesc;
}
/**
* @brief Return the manufacturer string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length)
{
UNUSED(speed);
USBD_GetString((uint8_t *)USBD_MANUFACTURER_STRING, USBD_StrDesc, length);
return USBD_StrDesc;
}
/**
* @brief Return the serial number string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
UNUSED(speed);
*length = USB_SIZ_STRING_SERIAL;
/* Update the serial number string descriptor with the data from the unique
* ID */
Get_SerialNum();
/* USER CODE BEGIN USBD_FS_SerialStrDescriptor */
/* USER CODE END USBD_FS_SerialStrDescriptor */
return (uint8_t *)USBD_StringSerial;
}
/**
* @brief Return the configuration string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
if (speed == USBD_SPEED_HIGH) {
USBD_GetString((uint8_t *)USBD_CONFIGURATION_STRING_FS, USBD_StrDesc,
length);
} else {
USBD_GetString((uint8_t *)USBD_CONFIGURATION_STRING_FS, USBD_StrDesc,
length);
}
return USBD_StrDesc;
}
/**
* @brief Return the interface string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_InterfaceStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length)
{
if (speed == 0) {
USBD_GetString((uint8_t *)USBD_INTERFACE_STRING_FS, USBD_StrDesc,
length);
} else {
USBD_GetString((uint8_t *)USBD_INTERFACE_STRING_FS, USBD_StrDesc,
length);
}
return USBD_StrDesc;
}
#if (USBD_LPM_ENABLED == 1)
/**
* @brief Return the BOS descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_USR_BOSDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
UNUSED(speed);
*length = sizeof(USBD_FS_BOSDesc);
return (uint8_t *)USBD_FS_BOSDesc;
}
#endif /* (USBD_LPM_ENABLED == 1) */
/**
* @brief Create the serial number string descriptor
* @param None
* @retval None
*/
static void Get_SerialNum(void)
{
uint32_t deviceserial0, deviceserial1, deviceserial2;
deviceserial0 = DEVICE_ID1;
deviceserial1 = DEVICE_ID2;
deviceserial2 = DEVICE_ID3;
deviceserial0 += deviceserial2;
if (deviceserial0 != 0) {
IntToUnicode(deviceserial0, &USBD_StringSerial[2], 8);
IntToUnicode(deviceserial1, &USBD_StringSerial[18], 4);
}
}
/**
* @brief Convert Hex 32Bits value into char
* @param value: value to convert
* @param pbuf: pointer to the buffer
* @param len: buffer length
* @retval None
*/
static void IntToUnicode(uint32_t value, uint8_t *pbuf, uint8_t len)
{
uint8_t idx = 0;
for (idx = 0; idx < len; idx++) {
if (((value >> 28)) < 0xA) {
pbuf[2 * idx] = (value >> 28) + '0';
} else {
pbuf[2 * idx] = (value >> 28) + 'A' - 10;
}
value = value << 4;
pbuf[2 * idx + 1] = 0;
}
}
/**
* @}
*/
@@ -0,0 +1,120 @@
/*!
* \file usbd_desc.h
*
* \brief Target the USB device descriptors implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_DESC__C__
#define __USBD_DESC__C__
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_def.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
/** @defgroup USBD_DESC_Exported_Constants USBD_DESC_Exported_Constants
* @brief Constants.
* @{
*/
#if (HID_CLASS_MODE == HID_MOUSE)
#define VID_VAL 1155
#define LANG_ID_STR 1033
#define PID_FS_VAL 17799
#define DEVICE_ID1 0x20220000
#define DEVICE_ID2 0x1D0000
#define DEVICE_ID3 0x1122
#elif (HID_CLASS_MODE == HID_KEYBOARD)
#define VID_VAL 1155
#define LANG_ID_STR 1033
#define PID_FS_VAL 17780
#define DEVICE_ID1 0x20220000
#define DEVICE_ID2 0x1F0000
#define DEVICE_ID3 0x1123
#elif (HID_CLASS_MODE == HID_CUSTOM)
#define VID_VAL 1155
#define LANG_ID_STR 1033
#define PID_FS_VAL 17781
#define DEVICE_ID1 0x20220000
#define DEVICE_ID2 0x1F0000
#define DEVICE_ID3 0x1124
#elif (HID_CLASS_MODE == (HID_MOUSE | HID_CUSTOM))
#define VID_VAL 1156
#define LANG_ID_STR 1033
#define PID_FS_VAL 22353
#define DEVICE_ID1 0x20220000
#define DEVICE_ID2 0x1E0000
#define DEVICE_ID3 0x1123
#elif (HID_CLASS_MODE == (HID_KEYBOARD | HID_CUSTOM))
#define VID_VAL 1156
#define LANG_ID_STR 1033
#define PID_FS_VAL 22354
#define DEVICE_ID1 0x20220000
#define DEVICE_ID2 0x200000
#define DEVICE_ID3 0x1215
#elif (HID_CLASS_MODE == (HID_KEYBOARD | HID_MOUSE))
#define VID_VAL 1157
#define LANG_ID_STR 1033
#define PID_FS_VAL 22355
#define DEVICE_ID1 0x20230000
#define DEVICE_ID2 0x210000
#define DEVICE_ID3 0x0228
#endif
#define DEV_CLASS 0x00
#define DEV_SUB_CLASS 0x00
#define DEV_PROTOCOL 0x00
#define USB_SIZ_STRING_SERIAL 0x1A
/**
* @}
*/
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
/** Descriptor for the Usb device. */
extern USBD_DescriptorsTypeDef FS_Desc;
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_DESC__C__ */
@@ -0,0 +1,194 @@
/*!
* \file usb_device.c
*
* \brief Target usb device implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usb_device.h"
#include "usbd_core.h"
#include "usbd_desc.h"
#include "usbd_hid.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
#define CURSOR_STEP 2U
#define CURSOR_WIDTH 200U
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
/* USB Device Core handle declaration. */
USBD_HandleTypeDef hUsbDeviceFS;
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
/**
* @brief This function handles USB On The Go FS global interrupt.
* @param void
* @retval void
*/
void USB_Handler(void) { HAL_PCD_IRQHandler(&hpcd_USB_OTG_FS); }
/**
* @brief Init USB device Library, add supported class and start the library
* @param void
* @retval void
*/
void USB_DEVICE_Init(void)
{
/* Init Device Library, add supported class and start the library. */
if (USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS) != USBD_OK) {
Error_Handler();
}
if (USBD_RegisterClass(&hUsbDeviceFS, &USBD_HID) != USBD_OK) {
Error_Handler();
}
if (USBD_Start(&hUsbDeviceFS) != USBD_OK) {
Error_Handler();
}
}
#if ((HID_CLASS_MODE & HID_MOUSE) == HID_MOUSE)
/**
* @brief Mouse get pointer datas
* @param uint8_t *pbuf
* @retval void
*/
void GetPointerData(uint8_t *pbuf)
{
static int32_t move_cnt = 0;
static uint8_t step_x_y = 0;
static int8_t x = 0, y = 0;
static uint16_t cnt = 0;
move_cnt++;
if (move_cnt > CURSOR_WIDTH) {
step_x_y++;
step_x_y = step_x_y % 4;
move_cnt = 0;
}
switch (step_x_y) {
case 0: {
y = 0;
x = CURSOR_STEP;
} break;
case 1: {
x = 0;
y = CURSOR_STEP;
} break;
case 2: {
y = 0;
x = (int8_t)(-CURSOR_STEP);
} break;
case 3: {
x = 0;
y = (int8_t)(-CURSOR_STEP);
} break;
}
cnt++;
if (cnt > 1000) {
if (pbuf[0] != 16)
pbuf[0] = 16;
else
pbuf[0] = 0;
cnt = 0;
}
pbuf[1] = x;
pbuf[2] = y;
pbuf[3] = 0;
}
/**
* @brief Usb mouse test send report
* @param void
* @retval void
*/
void USB_Mouse_Test_SendReport(void)
{
uint8_t buff[4] = {0};
#if (HID_CLASS_MODE == (HID_KEYBOARD | HID_MOUSE))
USBD_Mouse_HID_SendReport(&hUsbDeviceFS, buff, HID_EP2IN_SIZE);
#elif (HID_CLASS_MODE == (HID_CUSTOM | HID_MOUSE))
USBD_Mouse_HID_SendReport(&hUsbDeviceFS, buff, HID_EPIN_SIZE);
#endif
}
#endif
#if ((HID_CLASS_MODE & HID_CUSTOM) == HID_CUSTOM)
#define CUSTOM_SR_LEN 64U
/**
* @brief Usb custom hid test send report
* @param void
* @retval void
*/
void USB_Custom_Test_SendReport(void)
{
uint8_t usb_tx_data[CUSTOM_SR_LEN] = {0};
for (uint8_t i = 0; i < CUSTOM_SR_LEN; i++)
usb_tx_data[i] = i;
USBD_Custom_HID_SendReport(&hUsbDeviceFS, usb_tx_data, CUSTOM_SR_LEN);
}
#endif
#if (HID_CLASS_MODE == HID_DOUBLE_CUSTOM)
/**
* @brief Usb custom1 hid test send report
* @param void
* @retval void
*/
void USB_Custom1_Test_SendReport(void)
{
uint8_t usb_tx_data[64] = {0};
usb_tx_data[0] = 0x81;
for (uint8_t i = 1; i < 64; i++)
usb_tx_data[i] = i;
USBD_Custom1_HID_SendReport(&hUsbDeviceFS, usb_tx_data, 64);
}
/**
* @brief Usb custom2 hid test send report
* @param void
* @retval void
*/
void USB_Custom2_Test_SendReport(void)
{
uint8_t usb_tx_data[64] = {0};
usb_tx_data[0] = 0x82;
for (uint8_t i = 1; i < 64; i++)
usb_tx_data[i] = i;
USBD_Custom2_HID_SendReport(&hUsbDeviceFS, usb_tx_data, 64);
}
#endif
@@ -0,0 +1,56 @@
/*!
* \file usb_device.h
*
* \brief Target usb device implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USB_DEVICE_H__
#define __USB_DEVICE_H__
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_def.h"
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
void USB_DEVICE_Init( void );
uint8_t USB_Dev_State_Judge(uint8_t * rtc_cnt);
void USB_Mouse_Test_SendReport( void );
void USB_Custom_Test_SendReport( void );
#if (HID_CLASS_MODE == HID_DOUBLE_CUSTOM)
void USB_Custom1_Test_SendReport( void );
void USB_Custom2_Test_SendReport( void );
#endif
#ifdef __cplusplus
}
#endif
#endif /* __USB_DEVICE_H__ */
@@ -0,0 +1,351 @@
/*!
* \file usbd_desc.c
*
* \brief Target the USB device descriptors implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_desc.h"
#include "usbd_conf.h"
#include "usbd_core.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------
-----------------------------------------*/
/** @defgroup USBD_DESC_Private_Defines USBD_DESC_Private_Defines
* @brief Private defines.
* @{
*/
#define USBD_VID VID_VAL
#define USBD_LANGID_STRING LANG_ID_STR
#define USBD_MANUFACTURER_STRING "XinChip"
#define USBD_PID_FS PID_FS_VAL
#define USBD_PRODUCT_STRING_FS "XinChip Human interface"
#define USBD_CONFIGURATION_STRING_FS "HID Config"
#define USBD_INTERFACE_STRING_FS "HID Interface"
#define USB_SIZ_BOS_DESC 0x0C
/*------------------------------------------------------------------------------------
Func Prototypes
-------------------------------------------------------------------------------------*/
/** @defgroup USBD_DESC_Private_FunctionPrototypes
* USBD_DESC_Private_FunctionPrototypes
* @brief Private functions declaration.
* @{
*/
static void Get_SerialNum(void);
static void IntToUnicode(uint32_t value, uint8_t *pbuf, uint8_t len);
/** @defgroup USBD_DESC_Private_FunctionPrototypes
* USBD_DESC_Private_FunctionPrototypes
* @brief Private functions declaration for FS.
* @{
*/
uint8_t *USBD_FS_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *USBD_FS_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *USBD_FS_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length);
uint8_t *USBD_FS_ProductStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length);
uint8_t *USBD_FS_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *USBD_FS_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *USBD_FS_InterfaceStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length);
#if (USBD_LPM_ENABLED == 1)
uint8_t *USBD_FS_USR_BOSDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
#endif /* (USBD_LPM_ENABLED == 1) */
/*------------------------------------------------------------------------------------
Local Variables
-------------------------------------------------------------------------------------*/
/** @defgroup USBD_DESC_Private_Variables USBD_DESC_Private_Variables
* @brief Private variables.
* @{
*/
USBD_DescriptorsTypeDef FS_Desc = {USBD_FS_DeviceDescriptor,
USBD_FS_LangIDStrDescriptor,
USBD_FS_ManufacturerStrDescriptor,
USBD_FS_ProductStrDescriptor,
USBD_FS_SerialStrDescriptor,
USBD_FS_ConfigStrDescriptor,
USBD_FS_InterfaceStrDescriptor
#if (USBD_LPM_ENABLED == 1)
,
USBD_FS_USR_BOSDescriptor
#endif /* (USBD_LPM_ENABLED == 1) */
};
#if defined(__ICCARM__) /* IAR Compiler */
#pragma data_alignment = 4
#endif /* defined ( __ICCARM__ ) */
/** USB standard device descriptor. */
__ALIGN_BEGIN uint8_t USBD_FS_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END = {
0x12, /*bLength */
USB_DESC_TYPE_DEVICE, /*bDescriptorType*/
#if (USBD_LPM_ENABLED == 1)
0x01,
/*bcdUSB */ /* changed to USB version 2.01
in order to support LPM L1 suspend
resume test of USBCV3.0*/
#else
0x00, /*bcdUSB */
#endif /* (USBD_LPM_ENABLED == 1) */
0x02,
DEV_CLASS, /*bDeviceClass*/
DEV_SUB_CLASS, /*bDeviceSubClass*/
DEV_PROTOCOL, /*bDeviceProtocol*/
USB_MAX_EP0_SIZE, /*bMaxPacketSize*/
LOBYTE(USBD_VID), /*idVendor*/
HIBYTE(USBD_VID), /*idVendor*/
LOBYTE(USBD_PID_FS), /*idProduct*/
HIBYTE(USBD_PID_FS), /*idProduct*/
0x00, /*bcdDevice rel. 2.00*/
0x02,
USBD_IDX_MFC_STR, /*Index of manufacturer string*/
USBD_IDX_PRODUCT_STR, /*Index of product string*/
USBD_IDX_SERIAL_STR, /*Index of serial number string*/
USBD_MAX_NUM_CONFIGURATION /*bNumConfigurations*/
};
/* USB_DeviceDescriptor */
/** BOS descriptor. */
#if (USBD_LPM_ENABLED == 1)
#if defined(__ICCARM__) /* IAR Compiler */
#pragma data_alignment = 4
#endif /* defined ( __ICCARM__ ) */
__ALIGN_BEGIN uint8_t USBD_FS_BOSDesc[USB_SIZ_BOS_DESC] __ALIGN_END = {
0x5, USB_DESC_TYPE_BOS, 0xC, 0x0, 0x1, /* 1 device capability*/
/* device capability*/
0x7, USB_DEVICE_CAPABITY_TYPE, 0x2, 0x2, /* LPM capability bit set*/
0x0, 0x0, 0x0};
#endif /* (USBD_LPM_ENABLED == 1) */
/** @defgroup USBD_DESC_Private_Variables USBD_DESC_Private_Variables
* @brief Private variables.
* @{
*/
#if defined(__ICCARM__) /* IAR Compiler */
#pragma data_alignment = 4
#endif /* defined ( __ICCARM__ ) */
/** USB lang identifier descriptor. */
__ALIGN_BEGIN uint8_t USBD_LangIDDesc[USB_LEN_LANGID_STR_DESC] __ALIGN_END = {
USB_LEN_LANGID_STR_DESC, USB_DESC_TYPE_STRING, LOBYTE(USBD_LANGID_STRING),
HIBYTE(USBD_LANGID_STRING)};
#if defined(__ICCARM__) /* IAR Compiler */
#pragma data_alignment = 4
#endif /* defined ( __ICCARM__ ) */
/* Internal string descriptor. */
__ALIGN_BEGIN uint8_t USBD_StrDesc[USBD_MAX_STR_DESC_SIZ] __ALIGN_END;
#if defined(__ICCARM__) /*!< IAR Compiler */
#pragma data_alignment = 4
#endif
__ALIGN_BEGIN uint8_t USBD_StringSerial[USB_SIZ_STRING_SERIAL] __ALIGN_END = {
USB_SIZ_STRING_SERIAL,
USB_DESC_TYPE_STRING,
};
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
/**
* @brief Return the device descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
*length = sizeof(USBD_FS_DeviceDesc);
return USBD_FS_DeviceDesc;
}
/**
* @brief Return the LangID string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
UNUSED(speed);
*length = sizeof(USBD_LangIDDesc);
return USBD_LangIDDesc;
}
/**
* @brief Return the product string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
if (speed == 0) {
USBD_GetString((uint8_t *)USBD_PRODUCT_STRING_FS, USBD_StrDesc, length);
} else {
USBD_GetString((uint8_t *)USBD_PRODUCT_STRING_FS, USBD_StrDesc, length);
}
return USBD_StrDesc;
}
/**
* @brief Return the manufacturer string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length)
{
UNUSED(speed);
USBD_GetString((uint8_t *)USBD_MANUFACTURER_STRING, USBD_StrDesc, length);
return USBD_StrDesc;
}
/**
* @brief Return the serial number string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
UNUSED(speed);
*length = USB_SIZ_STRING_SERIAL;
/* Update the serial number string descriptor with the data from the unique
* ID */
Get_SerialNum();
/* USER CODE BEGIN USBD_FS_SerialStrDescriptor */
/* USER CODE END USBD_FS_SerialStrDescriptor */
return (uint8_t *)USBD_StringSerial;
}
/**
* @brief Return the configuration string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
if (speed == USBD_SPEED_HIGH) {
USBD_GetString((uint8_t *)USBD_CONFIGURATION_STRING_FS, USBD_StrDesc,
length);
} else {
USBD_GetString((uint8_t *)USBD_CONFIGURATION_STRING_FS, USBD_StrDesc,
length);
}
return USBD_StrDesc;
}
/**
* @brief Return the interface string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_InterfaceStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length)
{
if (speed == 0) {
USBD_GetString((uint8_t *)USBD_INTERFACE_STRING_FS, USBD_StrDesc,
length);
} else {
USBD_GetString((uint8_t *)USBD_INTERFACE_STRING_FS, USBD_StrDesc,
length);
}
return USBD_StrDesc;
}
#if (USBD_LPM_ENABLED == 1)
/**
* @brief Return the BOS descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_USR_BOSDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
UNUSED(speed);
*length = sizeof(USBD_FS_BOSDesc);
return (uint8_t *)USBD_FS_BOSDesc;
}
#endif /* (USBD_LPM_ENABLED == 1) */
/**
* @brief Create the serial number string descriptor
* @param None
* @retval None
*/
static void Get_SerialNum(void)
{
uint32_t deviceserial0, deviceserial1, deviceserial2;
deviceserial0 = DEVICE_ID1;
deviceserial1 = DEVICE_ID2;
deviceserial2 = DEVICE_ID3;
deviceserial0 += deviceserial2;
if (deviceserial0 != 0) {
IntToUnicode(deviceserial0, &USBD_StringSerial[2], 8);
IntToUnicode(deviceserial1, &USBD_StringSerial[18], 4);
}
}
/**
* @brief Convert Hex 32Bits value into char
* @param value: value to convert
* @param pbuf: pointer to the buffer
* @param len: buffer length
* @retval None
*/
static void IntToUnicode(uint32_t value, uint8_t *pbuf, uint8_t len)
{
uint8_t idx = 0;
for (idx = 0; idx < len; idx++) {
if (((value >> 28)) < 0xA) {
pbuf[2 * idx] = (value >> 28) + '0';
} else {
pbuf[2 * idx] = (value >> 28) + 'A' - 10;
}
value = value << 4;
pbuf[2 * idx + 1] = 0;
}
}
/**
* @}
*/
@@ -0,0 +1,128 @@
/*!
* \file usbd_desc.h
*
* \brief Target the USB device descriptors implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_DESC__C__
#define __USBD_DESC__C__
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_def.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
/** @defgroup USBD_DESC_Exported_Constants USBD_DESC_Exported_Constants
* @brief Constants.
* @{
*/
#if (HID_CLASS_MODE == HID_MOUSE)
#define VID_VAL 1155
#define LANG_ID_STR 1033
#define PID_FS_VAL 17799
#define DEVICE_ID1 0x20220000
#define DEVICE_ID2 0x1D0000
#define DEVICE_ID3 0x1122
#elif (HID_CLASS_MODE == HID_KEYBOARD)
#define VID_VAL 1155
#define LANG_ID_STR 1033
#define PID_FS_VAL 17780
#define DEVICE_ID1 0x20220000
#define DEVICE_ID2 0x1F0000
#define DEVICE_ID3 0x1123
#elif (HID_CLASS_MODE == HID_CUSTOM)
#define VID_VAL 1155
#define LANG_ID_STR 1033
#define PID_FS_VAL 17781
#define DEVICE_ID1 0x20220000
#define DEVICE_ID2 0x1F0000
#define DEVICE_ID3 0x1124
#elif (HID_CLASS_MODE == (HID_MOUSE | HID_CUSTOM))
#define VID_VAL 1156
#define LANG_ID_STR 1033
#define PID_FS_VAL 22353
#define DEVICE_ID1 0x20220000
#define DEVICE_ID2 0x1E0000
#define DEVICE_ID3 0x1123
#elif (HID_CLASS_MODE == (HID_KEYBOARD | HID_CUSTOM))
#define VID_VAL 1156
#define LANG_ID_STR 1033
#define PID_FS_VAL 22354
#define DEVICE_ID1 0x20220000
#define DEVICE_ID2 0x200000
#define DEVICE_ID3 0x1215
#elif (HID_CLASS_MODE == (HID_KEYBOARD | HID_MOUSE))
#define VID_VAL 1157
#define LANG_ID_STR 1033
#define PID_FS_VAL 22355
#define DEVICE_ID1 0x20230000
#define DEVICE_ID2 0x210000
#define DEVICE_ID3 0x0228
#elif (HID_CLASS_MODE == HID_DOUBLE_CUSTOM)
#define VID_VAL 1158
#define LANG_ID_STR 1033
#define PID_FS_VAL 22356
#define DEVICE_ID1 0x20230000
#define DEVICE_ID2 0x210000
#define DEVICE_ID3 0x0816
#endif
#define DEV_CLASS 0x00
#define DEV_SUB_CLASS 0x00
#define DEV_PROTOCOL 0x00
#define USB_SIZ_STRING_SERIAL 0x1A
/**
* @}
*/
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
/** Descriptor for the Usb device. */
extern USBD_DescriptorsTypeDef FS_Desc;
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_DESC__C__ */
@@ -0,0 +1,274 @@
/*!
* \file msc_flash.c
*
* \brief Target fatfs flash implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "msc_flash.h"
/*------------------------------------------------------------------------------------
Local Variables
-------------------------------------------
-----------------------------------------*/
uint8_t spim_init = false;
#define FLASH_SECTOR_ALIGN(address) \
((uint32_t)(address) & ~(FAT_FLASH_SECTOR_SIZE - 1))
#define FLASH_SECTOR_OFFSET(address) \
((uint32_t)(address) & (FAT_FLASH_SECTOR_SIZE - 1))
static uint8_t dataBuffer[FAT_FLASH_SECTOR_SIZE] = {0};
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------
-----------------------------------------*/
/**
* @brief FatFs flash read id
* @param void
* @retval uint32_t - id
*/
uint32_t Fat_Flash_ReadID(void)
{
uint32_t id = 0;
DEBUG("id\r");
if (XR_OK == spi_flash_rdid(XC_SPI0, (uint8_t *)&id)) {
DEBUG("read id :0x%08x\r\n", id);
return id;
}
return id;
}
/**
* @brief FatFs flash chip erase
* @param void
* @retval bool - true or false
*/
bool Fat_Flash_ChipErase(void)
{
uint32_t offset_cnt =
(FAT_FLASH_END_ADDR - FAT_FLASH_START_ADDR + 1) / FAT_FLASH_SECTOR_SIZE;
for (uint32_t i = 0; i < offset_cnt; i++) {
if (XR_OK !=
xc_spi_flash_erase_sector(XC_SPI0, FAT_FLASH_START_ADDR +
i * FAT_FLASH_SECTOR_SIZE))
return false;
}
return true;
}
/**
* @brief FatFs flash sector erase
* @param void
* @retval bool - true or false
*/
bool Fat_Flash_SectorErase(uint32_t address)
{
if (XR_OK == xc_spi_flash_erase_sector(XC_SPI0, address))
return true;
return false;
}
/**
* @brief FatFs flash write data
* @param void
* @retval bool - true or false
*/
bool Fat_Flash_WriteData(uint32_t address, uint8_t *buffer, uint16_t length)
{
uint16_t writeLen, pageOff;
while (length > 0) {
pageOff = FLASH_PAGE_SIZE - (address % FLASH_PAGE_SIZE);
writeLen = length > pageOff ? pageOff : length;
if (XR_OK == spi_write_bytes(XC_SPI0, address, buffer, writeLen)) {
length -= writeLen;
address += writeLen;
buffer += writeLen;
} else
return false;
}
return true;
}
/**
* @brief FatFs flash read data
* @param void
* @retval bool - true or false
*/
bool Fat_Flash_ReadData(uint32_t address, uint8_t *buffer, uint16_t length)
{
if (XR_OK == spi_flash_read(XC_SPI0, address, buffer, length))
return true;
return false;
}
/**
* @brief FatFs flash data are write in units of 512 bytes
* @param void
* @retval bool - true or false
*/
bool Fat_Flash_Write_512B(uint32_t address, uint8_t count, uint8_t *data)
{
uint32_t sectorAddress;
uint32_t sectorOffset;
address += FAT_FLASH_START_ADDR;
if (address >= FAT_FLASH_END_ADDR)
return false;
// count *= 2;
while (count > 0) {
sectorAddress = FLASH_SECTOR_ALIGN(address);
sectorOffset = FLASH_SECTOR_OFFSET(address);
Fat_Flash_ReadData(sectorAddress, dataBuffer, FAT_FLASH_SECTOR_SIZE);
Fat_Flash_SectorErase(address);
while (count > 0) {
memcpy(dataBuffer + sectorOffset, data, DISK_UNIT_SIZE);
data += DISK_UNIT_SIZE;
address += DISK_UNIT_SIZE;
count -= 1;
sectorOffset += DISK_UNIT_SIZE;
if ((sectorOffset & (FAT_FLASH_SECTOR_SIZE - 1)) == 0) {
break;
}
}
if (false == Fat_Flash_WriteData(sectorAddress, dataBuffer,
FAT_FLASH_SECTOR_SIZE))
return false;
}
return true;
}
/**
* @brief FatFs flash data are read in units of 512 bytes
* @param void
* @retval bool - true or false
*/
bool Fat_Flash_Read_512B(uint32_t address, uint8_t count, uint8_t *data)
{
address += FAT_FLASH_START_ADDR;
if (address >= FAT_FLASH_END_ADDR)
return false;
// count *= 2;
while (count--) {
if (true == Fat_Flash_ReadData(address, data, (DISK_UNIT_SIZE))) {
data += (DISK_UNIT_SIZE);
address += (DISK_UNIT_SIZE);
} else {
return false;
}
}
return true;
}
/*----------------------------- Disk Map -----------------------------------*/
/**
* @brief Disk init
* @param void
* @retval bool - true or false
*/
bool Disk_Init(void)
{
if (spim_init == false) {
SPI_Flash_Init();
spim_init = true;
}
return true;
}
/**
* @brief Disk erase
* @param void
* @retval bool - true or false
*/
bool Disk_Erase(void)
{
if (true == Fat_Flash_ChipErase())
return true;
return false;
}
/**
* @brief Disk unit size
* @param void
* @retval uint16_t - size
*/
uint16_t Disk_UnitSize(void) { return DISK_UNIT_SIZE; }
/**
* @brief Disk unit count
* @param void
* @retval uint32_t - count
*/
uint32_t Disk_UnitCount(void)
{
uint32_t count = 0;
count = (FAT_FLASH_END_ADDR - FAT_FLASH_START_ADDR + 1) /
FAT_FLASH_PAGE_SIZE / 2;
return count;
}
/**
* @brief Disk unit data read
* @param void
* @retval bool - true or false
*/
bool Disk_UnitRead(uint32_t unitAddr, uint16_t unitCount, uint8_t *data)
{
if (true == Fat_Flash_Read_512B(unitAddr * 512, unitCount, data))
return true;
return false;
}
/**
* @brief Disk unit data write
* @param void
* @retval bool - true or false
*/
bool Disk_UnitWrite(uint32_t unitAddr, uint16_t unitCount, uint8_t *data)
{
if (true == Fat_Flash_Write_512B(unitAddr * 512, unitCount, data))
return true;
return false;
}
/*--------------------------------------------------------------------------*/
@@ -0,0 +1,72 @@
/*!
* \file msc_flash.h
*
* \brief Target msc flash implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __MSC_FLASH_H__
#define __MSC_FLASH_H__
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "xc6xxx_hal_spi.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
#define FAT_FLASH_ID 0x12408500 //0x00136085
#define FAT_FLASH_PAGE_SIZE 256U
#define FAT_FLASH_SECTOR_SIZE 4096u
#define FAT_FLASH_START_ADDR 0x20000 //0x40000
#define FAT_FLASH_END_ADDR 0x40000 //0x7FFFF
#define DISK_UNIT_SIZE 512U
/*------------------------------------------------------------------------------------
Exported Functions
------------------------------------------- -----------------------------------------*/
uint32_t Fat_Flash_ReadID( void );
bool Disk_Init( void );
bool Disk_Erase( void );
uint16_t Disk_UnitSize( void );
uint32_t Disk_UnitCount( void );
bool Disk_UnitRead( uint32_t unitAddr, uint16_t unitCount, uint8_t *data );
bool Disk_UnitWrite( uint32_t unitAddr, uint16_t unitCount, uint8_t *data );
#ifdef __cplusplus
}
#endif
#endif /* __MAIN_H */
@@ -0,0 +1,71 @@
/*!
* \file usb_device.c
*
* \brief Target usb device implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usb_device.h"
#include "usbd_core.h"
#include "usbd_desc.h"
#include "usbd_msc.h"
#include "usbd_storage_if.h"
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
/* USB Device Core handle declaration. */
USBD_HandleTypeDef hUsbDeviceFS;
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
/**
* @brief This function handles USB On The Go FS global interrupt.
* @param void
* @retval void
*/
void USB_Handler(void) { HAL_PCD_IRQHandler(&hpcd_USB_OTG_FS); }
/**
* @brief Init USB device Library, add supported class and start the library
* @param void
* @retval void
*/
void USB_DEVICE_Init(void)
{
/* Init Device Library, add supported class and start the library. */
if (USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS) != USBD_OK) {
Error_Handler();
}
if (USBD_RegisterClass(&hUsbDeviceFS, &USBD_MSC) != USBD_OK) {
Error_Handler();
}
if (USBD_MSC_RegisterStorage(&hUsbDeviceFS,
&USBD_Storage_Interface_fops_FS) != USBD_OK) {
Error_Handler();
}
if (USBD_Start(&hUsbDeviceFS) != USBD_OK) {
Error_Handler();
}
}
@@ -0,0 +1,47 @@
/*!
* \file usb_device.h
*
* \brief Target usb device implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USB_DEVICE_H__
#define __USB_DEVICE_H__
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_def.h"
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
void USB_DEVICE_Init( void );
#ifdef __cplusplus
}
#endif
#endif /* __USB_DEVICE_H__ */
@@ -0,0 +1,358 @@
/*!
* \file usbd_desc.c
*
* \brief Target the USB device descriptors implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_desc.h"
#include "usbd_conf.h"
#include "usbd_core.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------
-----------------------------------------*/
/** @defgroup USBD_DESC_Private_Defines USBD_DESC_Private_Defines
* @brief Private defines.
* @{
*/
#define USBD_VID 0x0483 // 1155
#define USBD_LANGID_STRING 0x0409 // 1033
#define USBD_MANUFACTURER_STRING "XinChip" //"XinChip"
#define USBD_PID_FS 22314 // 17788
#define USBD_PRODUCT_STRING_FS "XinChip Mass Storage" //"XinChip Mass Storage"
#define USBD_CONFIGURATION_STRING_FS "MSC Config"
#define USBD_INTERFACE_STRING_FS "MSC Interface"
#define USB_SIZ_BOS_DESC 0x0C
/*------------------------------------------------------------------------------------
Func Prototypes
-------------------------------------------
-----------------------------------------*/
/** @defgroup USBD_DESC_Private_FunctionPrototypes
* USBD_DESC_Private_FunctionPrototypes
* @brief Private functions declaration.
* @{
*/
static void Get_SerialNum(void);
static void IntToUnicode(uint32_t value, uint8_t *pbuf, uint8_t len);
/** @defgroup USBD_DESC_Private_FunctionPrototypes
* USBD_DESC_Private_FunctionPrototypes
* @brief Private functions declaration for FS.
* @{
*/
uint8_t *USBD_FS_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *USBD_FS_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *USBD_FS_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length);
uint8_t *USBD_FS_ProductStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length);
uint8_t *USBD_FS_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *USBD_FS_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *USBD_FS_InterfaceStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length);
#if (USBD_LPM_ENABLED == 1)
uint8_t *USBD_FS_USR_BOSDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
#endif /* (USBD_LPM_ENABLED == 1) */
/*------------------------------------------------------------------------------------
Local Variables
-------------------------------------------------------------------------------------*/
/** @defgroup USBD_DESC_Private_Variables USBD_DESC_Private_Variables
* @brief Private variables.
* @{
*/
USBD_DescriptorsTypeDef FS_Desc = {USBD_FS_DeviceDescriptor,
USBD_FS_LangIDStrDescriptor,
USBD_FS_ManufacturerStrDescriptor,
USBD_FS_ProductStrDescriptor,
USBD_FS_SerialStrDescriptor,
USBD_FS_ConfigStrDescriptor,
USBD_FS_InterfaceStrDescriptor
#if (USBD_LPM_ENABLED == 1)
,
USBD_FS_USR_BOSDescriptor
#endif /* (USBD_LPM_ENABLED == 1) */
};
#if defined(__ICCARM__) /* IAR Compiler */
#pragma data_alignment = 4
#endif /* defined ( __ICCARM__ ) */
/** USB standard device descriptor. */
__ALIGN_BEGIN uint8_t USBD_FS_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END = {
0x12, /*bLength */
USB_DESC_TYPE_DEVICE, /*bDescriptorType*/
#if (USBD_LPM_ENABLED == 1)
0x01,
/*bcdUSB */ /* changed to USB version 2.01
in order to support LPM L1 suspend
resume test of USBCV3.0*/
#else
0x00, /*bcdUSB */
#endif /* (USBD_LPM_ENABLED == 1) */
0x02,
0x00, /*bDeviceClass*/
0x00, /*bDeviceSubClass*/
0x00, /*bDeviceProtocol*/
USB_MAX_EP0_SIZE, /*bMaxPacketSize*/
LOBYTE(USBD_VID), /*idVendor*/
HIBYTE(USBD_VID), /*idVendor*/
LOBYTE(USBD_PID_FS), /*idProduct*/
HIBYTE(USBD_PID_FS), /*idProduct*/
0x00, /*bcdDevice rel. 2.00*/
0x02,
USBD_IDX_MFC_STR, /*Index of manufacturer string*/
USBD_IDX_PRODUCT_STR, /*Index of product string*/
USBD_IDX_SERIAL_STR, /*Index of serial number string*/
USBD_MAX_NUM_CONFIGURATION /*bNumConfigurations*/
};
/* USB_DeviceDescriptor */
/** BOS descriptor. */
#if (USBD_LPM_ENABLED == 1)
#if defined(__ICCARM__) /* IAR Compiler */
#pragma data_alignment = 4
#endif /* defined ( __ICCARM__ ) */
__ALIGN_BEGIN uint8_t USBD_FS_BOSDesc[USB_SIZ_BOS_DESC] __ALIGN_END = {
0x5, USB_DESC_TYPE_BOS, 0xC, 0x0, 0x1, /* 1 device capability*/
/* device capability*/
0x7, USB_DEVICE_CAPABITY_TYPE, 0x2, 0x2, /* LPM capability bit set*/
0x0, 0x0, 0x0};
#endif /* (USBD_LPM_ENABLED == 1) */
/** @defgroup USBD_DESC_Private_Variables USBD_DESC_Private_Variables
* @brief Private variables.
* @{
*/
#if defined(__ICCARM__) /* IAR Compiler */
#pragma data_alignment = 4
#endif /* defined ( __ICCARM__ ) */
/** USB lang identifier descriptor. */
__ALIGN_BEGIN uint8_t USBD_LangIDDesc[USB_LEN_LANGID_STR_DESC] __ALIGN_END = {
USB_LEN_LANGID_STR_DESC, USB_DESC_TYPE_STRING, LOBYTE(USBD_LANGID_STRING),
HIBYTE(USBD_LANGID_STRING)};
#if defined(__ICCARM__) /* IAR Compiler */
#pragma data_alignment = 4
#endif /* defined ( __ICCARM__ ) */
/* Internal string descriptor. */
__ALIGN_BEGIN uint8_t USBD_StrDesc[USBD_MAX_STR_DESC_SIZ] __ALIGN_END;
#if defined(__ICCARM__) /*!< IAR Compiler */
#pragma data_alignment = 4
#endif
__ALIGN_BEGIN uint8_t USBD_StringSerial[USB_SIZ_STRING_SERIAL] __ALIGN_END = {
USB_SIZ_STRING_SERIAL,
USB_DESC_TYPE_STRING,
};
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
/**
* @brief Return the device descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
UNUSED(speed);
*length = sizeof(USBD_FS_DeviceDesc);
return USBD_FS_DeviceDesc;
}
/**
* @brief Return the LangID string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
UNUSED(speed);
*length = sizeof(USBD_LangIDDesc);
return USBD_LangIDDesc;
}
/**
* @brief Return the product string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
if (speed == 0) {
USBD_GetString((uint8_t *)USBD_PRODUCT_STRING_FS, USBD_StrDesc, length);
} else {
USBD_GetString((uint8_t *)USBD_PRODUCT_STRING_FS, USBD_StrDesc, length);
}
return USBD_StrDesc;
}
/**
* @brief Return the manufacturer string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length)
{
UNUSED(speed);
USBD_GetString((uint8_t *)USBD_MANUFACTURER_STRING, USBD_StrDesc, length);
return USBD_StrDesc;
}
/**
* @brief Return the serial number string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
UNUSED(speed);
*length = USB_SIZ_STRING_SERIAL;
/* Update the serial number string descriptor with the data from the unique
* ID */
Get_SerialNum();
/* USER CODE BEGIN USBD_FS_SerialStrDescriptor */
/* USER CODE END USBD_FS_SerialStrDescriptor */
return (uint8_t *)USBD_StringSerial;
}
/**
* @brief Return the configuration string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
if (speed == USBD_SPEED_HIGH) {
USBD_GetString((uint8_t *)USBD_CONFIGURATION_STRING_FS, USBD_StrDesc,
length);
} else {
USBD_GetString((uint8_t *)USBD_CONFIGURATION_STRING_FS, USBD_StrDesc,
length);
}
return USBD_StrDesc;
}
/**
* @brief Return the interface string descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_InterfaceStrDescriptor(USBD_SpeedTypeDef speed,
uint16_t *length)
{
if (speed == 0) {
USBD_GetString((uint8_t *)USBD_INTERFACE_STRING_FS, USBD_StrDesc,
length);
} else {
USBD_GetString((uint8_t *)USBD_INTERFACE_STRING_FS, USBD_StrDesc,
length);
}
return USBD_StrDesc;
}
#if (USBD_LPM_ENABLED == 1)
/**
* @brief Return the BOS descriptor
* @param speed : Current device speed
* @param length : Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_FS_USR_BOSDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
INFO("\n");
UNUSED(speed);
*length = sizeof(USBD_FS_BOSDesc);
return (uint8_t *)USBD_FS_BOSDesc;
}
#endif /* (USBD_LPM_ENABLED == 1) */
/**
* @brief Create the serial number string descriptor
* @param None
* @retval None
*/
static void Get_SerialNum(void)
{
uint32_t deviceserial0, deviceserial1; //, deviceserial2;
// deviceserial0 = *(uint32_t *) DEVICE_ID1;
// deviceserial1 = *(uint32_t *) DEVICE_ID2;
// deviceserial2 = *(uint32_t *) DEVICE_ID3;
deviceserial0 = 0x20220902; // 5177440; //0;//5177402;
deviceserial1 = 0x1A0000; // 1395675155; //0x001A0000;
// deviceserial2 = //540488500; //0;
// deviceserial0 += deviceserial2;
if (deviceserial0 != 0) {
IntToUnicode(deviceserial0, &USBD_StringSerial[2], 8);
IntToUnicode(deviceserial1, &USBD_StringSerial[18], 4);
}
}
/**
* @brief Convert Hex 32Bits value into char
* @param value: value to convert
* @param pbuf: pointer to the buffer
* @param len: buffer length
* @retval None
*/
static void IntToUnicode(uint32_t value, uint8_t *pbuf, uint8_t len)
{
uint8_t idx = 0;
for (idx = 0; idx < len; idx++) {
if (((value >> 28)) < 0xA) {
pbuf[2 * idx] = (value >> 28) + '0';
} else {
pbuf[2 * idx] = (value >> 28) + 'A' - 10;
}
value = value << 4;
pbuf[2 * idx + 1] = 0;
}
}
/**
* @}
*/
@@ -0,0 +1,70 @@
/*!
* \file usbd_desc.h
*
* \brief Target the USB device descriptors implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_DESC__C__
#define __USBD_DESC__C__
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_def.h"
/*------------------------------------------------------------------------------------
Macros
------------------------------------------- -----------------------------------------*/
/** @defgroup USBD_DESC_Exported_Constants USBD_DESC_Exported_Constants
* @brief Constants.
* @{
*/
#define DEVICE_ID1 (UID_BASE)
#define DEVICE_ID2 (UID_BASE + 0x4)
#define DEVICE_ID3 (UID_BASE + 0x8)
#define USB_SIZ_STRING_SERIAL 0x1A
/**
* @}
*/
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
/** Descriptor for the Usb device. */
extern USBD_DescriptorsTypeDef FS_Desc;
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_DESC__C__ */
@@ -0,0 +1,242 @@
/*!
* \file usbd_storage_if.c
*
* \brief Memory management layer.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_storage_if.h"
#include "msc_flash.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------
-----------------------------------------*/
/** @defgroup USBD_STORAGE_Private_Defines
* @brief Private defines.
* @{
*/
#define STORAGE_LUN_NBR 1
#define STORAGE_BLK_NBR 0x48
#define STORAGE_BLK_SIZ 0x200
/*------------------------------------------------------------------------------------
Consts
-------------------------------------------
-----------------------------------------*/
/* USER CODE BEGIN INQUIRY_DATA_FS */
/** USB Mass storage Standard Inquiry Data. */
const int8_t STORAGE_Inquirydata_FS[] = {
/* 36 */
/* LUN 0 */
0x00, 0x80, 0x02, 0x02, (STANDARD_INQUIRY_DATA_LEN - 5),
0x00, 0x00, 0x00, 'X', 'i',
'n', 'C', 'h', 'i', 'p',
' ', /* Manufacturer : 8 bytes */
'P', 'r', 'o', 'd', 'u',
'c', 't', ' ', /* Product : 16 Bytes */
' ', ' ', ' ', ' ', ' ',
' ', ' ', ' ', '0', '.',
'0', '1' /* Version : 4 Bytes */
};
/**
* @}
*/
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
/** @defgroup USBD_STORAGE_Exported_Variables
* @brief Public variables.
* @{
*/
extern USBD_HandleTypeDef hUsbDeviceFS;
/**
* @}
*/
/*------------------------------------------------------------------------------------
Func Prototype
-------------------------------------------------------------------------------------*/
/** @defgroup USBD_STORAGE_Private_FunctionPrototypes
* @brief Private functions declaration.
* @{
*/
static int8_t STORAGE_Init_FS(uint8_t lun);
static int8_t STORAGE_GetCapacity_FS(uint8_t lun, uint32_t *block_num,
uint16_t *block_size);
static int8_t STORAGE_IsReady_FS(uint8_t lun);
static int8_t STORAGE_IsWriteProtected_FS(uint8_t lun);
static int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr,
uint16_t blk_len);
static int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr,
uint16_t blk_len);
static int8_t STORAGE_GetMaxLun_FS(void);
/**
* @}
*/
USBD_StorageTypeDef USBD_Storage_Interface_fops_FS = {
STORAGE_Init_FS, STORAGE_GetCapacity_FS,
STORAGE_IsReady_FS, STORAGE_IsWriteProtected_FS,
STORAGE_Read_FS, STORAGE_Write_FS,
STORAGE_GetMaxLun_FS, (int8_t *)STORAGE_Inquirydata_FS};
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
/**
* @brief Initializes the storage unit (medium) over USB FS IP
* @param lun: Logical unit number.
* @retval USBD_OK if all operations are OK else USBD_FAIL
*/
int8_t STORAGE_Init_FS(uint8_t lun)
{
UNUSED(lun);
return (USBD_OK);
}
/**
* @brief Returns the medium capacity.
* @param lun: Logical unit number.
* @param block_num: Number of total block number.
* @param block_size: Block size.
* @retval USBD_OK if all operations are OK else USBD_FAIL
*/
int8_t STORAGE_GetCapacity_FS(uint8_t lun, uint32_t *block_num,
uint16_t *block_size)
{
UNUSED(lun);
#if STORAGE_NO_FLASH
// STORAGE_BLK_NBR;
// STORAGE_BLK_SIZ;
*block_num = STORAGE_BLK_NBR;
*block_size = STORAGE_BLK_SIZ;
#else
*block_num = Disk_UnitCount();
*block_size = Disk_UnitSize();
#endif
return (USBD_OK);
}
/**
* @brief Checks whether the medium is ready.
* @param lun: Logical unit number.
* @retval USBD_OK if all operations are OK else USBD_FAIL
*/
int8_t STORAGE_IsReady_FS(uint8_t lun)
{
UNUSED(lun);
return (USBD_OK);
}
/**
* @brief Checks whether the medium is write protected.
* @param lun: Logical unit number.
* @retval USBD_OK if all operations are OK else USBD_FAIL
*/
int8_t STORAGE_IsWriteProtected_FS(uint8_t lun)
{
UNUSED(lun);
return (USBD_OK);
}
/**
* @brief Reads data from the medium.
* @param lun: Logical unit number.
* @param buf: data buffer.
* @param blk_addr: Logical block address.
* @param blk_len: Blocks number.
* @retval USBD_OK if all operations are OK else USBD_FAIL
*/
int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr,
uint16_t blk_len)
{
UNUSED(lun);
#if STORAGE_NO_FLASH
UNUSED(buf);
UNUSED(blk_addr);
UNUSED(blk_len);
// memcpy(buf, temp + (blk_addr * STORAGE_BLK_SIZ), blk_len *
// STORAGE_BLK_SIZ);
#else
Disk_UnitRead(blk_addr, blk_len, buf);
#endif
return (USBD_OK);
}
/**
* @brief Writes data into the medium.
* @param lun: Logical unit number.
* @param buf: data buffer.
* @param blk_addr: Logical block address.
* @param blk_len: Blocks number.
* @retval USBD_OK if all operations are OK else USBD_FAIL
*/
int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr,
uint16_t blk_len)
{
UNUSED(lun);
#if STORAGE_NO_FLASH
UNUSED(buf);
UNUSED(blk_addr);
UNUSED(blk_len);
// memcpy(temp + (blk_addr * STORAGE_BLK_SIZ), buf, blk_len *
// STORAGE_BLK_SIZ);
#else
Disk_UnitWrite(blk_addr, blk_len, buf);
#endif
return (USBD_OK);
}
/**
* @brief Returns the Max Supported LUNs.
* @param None
* @retval Lun(s) number.
*/
int8_t STORAGE_GetMaxLun_FS(void) { return (STORAGE_LUN_NBR - 1); }
/**
* @}
*/
@@ -0,0 +1,73 @@
/*!
* \file usbd_storage_if.h
*
* \brief Header for usbd_storage_if.c file.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_STORAGE_IF_H__
#define __USBD_STORAGE_IF_H__
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_msc.h"
/*------------------------------------------------------------------------------------
Macros
------------------------------------------- -----------------------------------------*/
/** @defgroup USBD_STORAGE_Exported_Defines USBD_STORAGE_Exported_Defines
* @brief Defines.
* @{
*/
#define STORAGE_NO_FLASH 0U
/**
* @}
*/
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
/** @defgroup USBD_STORAGE_Exported_Variables USBD_STORAGE_Exported_Variables
* @brief Public variables.
* @{
*/
/** STORAGE Interface callback. */
extern USBD_StorageTypeDef USBD_Storage_Interface_fops_FS;
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_STORAGE_IF_H__ */
@@ -0,0 +1,766 @@
/*!
* \file usbd_cdc.c
*
* \brief This file provides the high layer firmware functions to manage the
* following functionalities of the USB CDC Class:
* - Initialization and Configuration of high and low layer
* - Enumeration as CDC Device (and enumeration for each implemented
* memory interface)
* - OUT/IN data transfer
* - Command IN transfer (class requests management)
* - Error management
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author MCD Application Team
*
* \author ( XinChip ) Alex-J
*
* @verbatim
*
* ===================================================================
* CDC Class Driver Description
* ===================================================================
* This driver manages the "Universal Serial Bus Class Definitions for
* Communications Devices Revision 1.2 November 16, 2007" and the sub-protocol
* specification of "Universal Serial Bus Communications Class Subclass
* Specification for PSTN Devices Revision 1.2 February 9, 2007" This driver
* implements the following aspects of the specification:
* - Device descriptor management
* - Configuration descriptor management
* - Enumeration as CDC device with 2 data endpoints (IN and OUT)
* and 1 command endpoint (IN)
* - Requests management (as described in section 6.2 in
* specification)
* - Abstract Control Model compliant
* - Union Functional collection (using 1 IN endpoint for control)
* - Data interface class
*
* These aspects may be enriched or modified for a specific user
* application.
*
* This driver doesn't implement the following aspects of the
* specification (but it is possible to manage these features with some
* modifications on this driver):
* - Any class-specific aspect relative to communication classes
* should be managed by user application.
* - All communication classes other than PSTN are not managed
*
* @endverbatim
*
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_cdc.h"
#include "usbd_ctlreq.h"
/*-----------------------------------------------------------------------------------
Func Prototype
------------------------------------------------------------------------------------*/
/** @defgroup USBD_CDC_Private_FunctionPrototypes
* @{
*/
static uint8_t USBD_CDC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
static uint8_t USBD_CDC_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
static uint8_t USBD_CDC_Setup(USBD_HandleTypeDef *pdev,
USBD_SetupReqTypedef *req);
static uint8_t USBD_CDC_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum);
static uint8_t USBD_CDC_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum);
static uint8_t USBD_CDC_EP0_RxReady(USBD_HandleTypeDef *pdev);
static uint8_t *USBD_CDC_GetFSCfgDesc(uint16_t *length);
static uint8_t *USBD_CDC_GetHSCfgDesc(uint16_t *length);
static uint8_t *USBD_CDC_GetOtherSpeedCfgDesc(uint16_t *length);
static uint8_t *USBD_CDC_GetOtherSpeedCfgDesc(uint16_t *length);
uint8_t *USBD_CDC_GetDeviceQualifierDescriptor(uint16_t *length);
/*------------------------------------------------------------------------------------
Local Variables
-------------------------------------------------------------------------------------*/
/* USB Standard Device Descriptor */
__ALIGN_BEGIN static uint8_t
USBD_CDC_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END = {
USB_LEN_DEV_QUALIFIER_DESC,
USB_DESC_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x01,
0x00,
};
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Variables
* @{
*/
/* CDC interface class callbacks structure */
USBD_ClassTypeDef USBD_CDC = {
USBD_CDC_Init,
USBD_CDC_DeInit,
USBD_CDC_Setup,
NULL, /* EP0_TxSent */
USBD_CDC_EP0_RxReady,
USBD_CDC_DataIn,
USBD_CDC_DataOut,
NULL,
NULL,
NULL,
USBD_CDC_GetHSCfgDesc,
USBD_CDC_GetFSCfgDesc,
USBD_CDC_GetOtherSpeedCfgDesc,
USBD_CDC_GetDeviceQualifierDescriptor,
};
/* USB CDC device Configuration Descriptor */
__ALIGN_BEGIN static uint8_t
USBD_CDC_CfgDesc[USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END = {
/* Configuration Descriptor */
0x09, /* bLength: Configuration Descriptor size */
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
USB_CDC_CONFIG_DESC_SIZ, /* wTotalLength */
0x00, 0x02, /* bNumInterfaces: 2 interfaces */
0x01, /* bConfigurationValue: Configuration value */
0x00, /* iConfiguration: Index of string descriptor
describing the configuration */
#if (USBD_SELF_POWERED == 1U)
0xC0, /* bmAttributes: Bus Powered according to user configuration */
#else
0x80, /* bmAttributes: Bus Powered according to user configuration */
#endif /* USBD_SELF_POWERED */
USBD_MAX_POWER, /* MaxPower (mA) */
/* Interface Descriptor */
0x09, /* bLength: Interface Descriptor size */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */
/* Interface descriptor type */
0x00, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x01, /* bNumEndpoints: One endpoint used */
0x02, /* bInterfaceClass: Communication Interface Class */
0x02, /* bInterfaceSubClass: Abstract Control Model */
0x01, /* bInterfaceProtocol: Common AT commands */
0x00, /* iInterface */
/* Header Functional Descriptor */
0x05, /* bLength: Endpoint Descriptor size */
0x24, /* bDescriptorType: CS_INTERFACE */
0x00, /* bDescriptorSubtype: Header Func Desc */
0x10, /* bcdCDC: spec release number */
0x01,
/* Call Management Functional Descriptor */
0x05, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x01, /* bDescriptorSubtype: Call Management Func Desc */
0x00, /* bmCapabilities: D0+D1 */
0x01, /* bDataInterface */
/* ACM Functional Descriptor */
0x04, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x02, /* bDescriptorSubtype: Abstract Control Management desc */
0x02, /* bmCapabilities */
/* Union Functional Descriptor */
0x05, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x06, /* bDescriptorSubtype: Union func desc */
0x00, /* bMasterInterface: Communication class interface */
0x01, /* bSlaveInterface0: Data Class Interface */
/* Endpoint 2 Descriptor */
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
CDC_CMD_EP, /* bEndpointAddress */
0x03, /* bmAttributes: Interrupt */
LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize */
HIBYTE(CDC_CMD_PACKET_SIZE), CDC_FS_BINTERVAL, /* bInterval */
/*---------------------------------------------------------------------------*/
/* Data class interface descriptor */
0x09, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */
0x01, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x02, /* bNumEndpoints: Two endpoints used */
0x0A, /* bInterfaceClass: CDC */
0x00, /* bInterfaceSubClass */
0x00, /* bInterfaceProtocol */
0x00, /* iInterface */
/* Endpoint OUT Descriptor */
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
CDC_OUT_EP, /* bEndpointAddress */
0x02, /* bmAttributes: Bulk */
LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize */
HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), CDC_FS_BINTERVAL, /* bInterval */
/* Endpoint IN Descriptor */
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
CDC_IN_EP, /* bEndpointAddress */
0x02, /* bmAttributes: Bulk */
LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize */
HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), CDC_FS_BINTERVAL, /* bInterval */
};
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
extern USBD_HandleTypeDef hUsbDeviceFS;
/**
* @}
*/
/*------------------------------------------------------------------------------------
Local Variables
-------------------------------------------------------------------------------------*/
static uint8_t CDCInEpAdd = CDC_IN_EP;
static uint8_t CDCOutEpAdd = CDC_OUT_EP;
static uint8_t CDCCmdEpAdd = CDC_CMD_EP;
/**
* @}
*/
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
/**
* @brief USBD_CDC_Init
* Initialize the CDC interface
* @param pdev: device instance
* @param cfgidx: Configuration index
* @retval status
*/
static uint8_t USBD_CDC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
UNUSED(cfgidx);
USBD_CDC_HandleTypeDef *hcdc;
hcdc =
(USBD_CDC_HandleTypeDef *)USBD_malloc(sizeof(USBD_CDC_HandleTypeDef));
if (hcdc == NULL) {
pdev->pClassDataCmsit[pdev->classId] = NULL;
return (uint8_t)USBD_EMEM;
}
(void)USBD_memset(hcdc, 0, sizeof(USBD_CDC_HandleTypeDef));
pdev->pClassDataCmsit[pdev->classId] = (void *)hcdc;
pdev->pClassData = pdev->pClassDataCmsit[pdev->classId];
/* Open EP IN */
(void)USBD_LL_OpenEP(pdev, CDCInEpAdd, USBD_EP_TYPE_BULK,
CDC_DATA_FS_IN_PACKET_SIZE);
pdev->ep_in[CDCInEpAdd & 0xFU].is_used = 1U;
/* Open EP OUT */
(void)USBD_LL_OpenEP(pdev, CDCOutEpAdd, USBD_EP_TYPE_BULK,
CDC_DATA_FS_OUT_PACKET_SIZE);
pdev->ep_out[CDCOutEpAdd & 0xFU].is_used = 1U;
/* Set bInterval for CMD Endpoint */
pdev->ep_in[CDCCmdEpAdd & 0xFU].bInterval = CDC_FS_BINTERVAL;
/* Open Command IN EP */
(void)USBD_LL_OpenEP(pdev, CDCCmdEpAdd, USBD_EP_TYPE_INTR,
CDC_CMD_PACKET_SIZE);
pdev->ep_in[CDCCmdEpAdd & 0xFU].is_used = 1U;
hcdc->RxBuffer = NULL;
/* Init physical Interface components */
((USBD_CDC_ItfTypeDef *)pdev->pUserData[pdev->classId])->Init();
/* Init Xfer states */
hcdc->TxState = 0U;
hcdc->RxState = 0U;
if (hcdc->RxBuffer == NULL) {
return (uint8_t)USBD_EMEM;
}
/* Prepare Out endpoint to receive next packet */
(void)USBD_LL_PrepareReceive(pdev, CDCOutEpAdd, hcdc->RxBuffer,
CDC_DATA_FS_OUT_PACKET_SIZE);
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_CDC_Init
* DeInitialize the CDC layer
* @param pdev: device instance
* @param cfgidx: Configuration index
* @retval status
*/
static uint8_t USBD_CDC_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
UNUSED(cfgidx);
/* Close EP IN */
(void)USBD_LL_CloseEP(pdev, CDCInEpAdd);
pdev->ep_in[CDCInEpAdd & 0xFU].is_used = 0U;
/* Close EP OUT */
(void)USBD_LL_CloseEP(pdev, CDCOutEpAdd);
pdev->ep_out[CDCOutEpAdd & 0xFU].is_used = 0U;
/* Close Command IN EP */
(void)USBD_LL_CloseEP(pdev, CDCCmdEpAdd);
pdev->ep_in[CDCCmdEpAdd & 0xFU].is_used = 0U;
pdev->ep_in[CDCCmdEpAdd & 0xFU].bInterval = 0U;
/* DeInit physical Interface components */
if (pdev->pClassDataCmsit[pdev->classId] != NULL) {
((USBD_CDC_ItfTypeDef *)pdev->pUserData[pdev->classId])->DeInit();
(void)USBD_free(pdev->pClassDataCmsit[pdev->classId]);
pdev->pClassDataCmsit[pdev->classId] = NULL;
pdev->pClassData = NULL;
}
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_CDC_Setup
* Handle the CDC specific requests
* @param pdev: instance
* @param req: usb requests
* @retval status
*/
static uint8_t USBD_CDC_Setup(USBD_HandleTypeDef *pdev,
USBD_SetupReqTypedef *req)
{
USBD_CDC_HandleTypeDef *hcdc =
(USBD_CDC_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
uint16_t len;
uint8_t ifalt = 0U;
uint16_t status_info = 0U;
USBD_StatusTypeDef ret = USBD_OK;
if (hcdc == NULL) {
return (uint8_t)USBD_FAIL;
}
switch (req->bmRequest & USB_REQ_TYPE_MASK) {
case USB_REQ_TYPE_CLASS:
if (req->wLength != 0U) {
if ((req->bmRequest & 0x80U) != 0U) {
((USBD_CDC_ItfTypeDef *)pdev->pUserData[pdev->classId])
->Control(req->bRequest, (uint8_t *)hcdc->data,
req->wLength);
len = MIN(CDC_REQ_MAX_DATA_SIZE, req->wLength);
(void)USBD_CtlSendData(pdev, (uint8_t *)hcdc->data, len);
} else {
hcdc->CmdOpCode = req->bRequest;
hcdc->CmdLength = (uint8_t)MIN(req->wLength, USB_MAX_EP0_SIZE);
(void)USBD_CtlPrepareRx(pdev, (uint8_t *)hcdc->data,
hcdc->CmdLength);
}
} else {
((USBD_CDC_ItfTypeDef *)pdev->pUserData[pdev->classId])
->Control(req->bRequest, (uint8_t *)req, 0U);
}
break;
case USB_REQ_TYPE_STANDARD:
switch (req->bRequest) {
case USB_REQ_GET_STATUS:
if (pdev->dev_state == USBD_STATE_CONFIGURED) {
(void)USBD_CtlSendData(pdev, (uint8_t *)&status_info, 2U);
} else {
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
}
break;
case USB_REQ_GET_INTERFACE:
if (pdev->dev_state == USBD_STATE_CONFIGURED) {
(void)USBD_CtlSendData(pdev, &ifalt, 1U);
} else {
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
}
break;
case USB_REQ_SET_INTERFACE:
if (pdev->dev_state != USBD_STATE_CONFIGURED) {
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
}
break;
case USB_REQ_CLEAR_FEATURE:
break;
default:
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
break;
}
break;
default:
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
break;
}
return (uint8_t)ret;
}
/**
* @brief USBD_CDC_DataIn
* Data sent on non-control IN endpoint
* @param pdev: device instance
* @param epnum: endpoint number
* @retval status
*/
static uint8_t USBD_CDC_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
USBD_CDC_HandleTypeDef *hcdc;
PCD_HandleTypeDef *hpcd = (PCD_HandleTypeDef *)pdev->pData;
if (pdev->pClassDataCmsit[pdev->classId] == NULL) {
return (uint8_t)USBD_FAIL;
}
hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
if ((pdev->ep_in[epnum & 0xFU].total_length > 0U) &&
((pdev->ep_in[epnum & 0xFU].total_length %
hpcd->IN_ep[epnum & 0xFU].maxpacket) == 0U)) {
/* Update the packet total length */
pdev->ep_in[epnum & 0xFU].total_length = 0U;
/* Send ZLP */
(void)USBD_LL_Transmit(pdev, epnum, NULL, 0U);
} else {
hcdc->TxState = 0U;
if (((USBD_CDC_ItfTypeDef *)pdev->pUserData[pdev->classId])
->TransmitCplt != NULL) {
((USBD_CDC_ItfTypeDef *)pdev->pUserData[pdev->classId])
->TransmitCplt(hcdc->TxBuffer, &hcdc->TxLength, epnum);
}
}
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_CDC_DataOut
* Data received on non-control Out endpoint
* @param pdev: device instance
* @param epnum: endpoint number
* @retval status
*/
static uint8_t USBD_CDC_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
USBD_CDC_HandleTypeDef *hcdc =
(USBD_CDC_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
if (pdev->pClassDataCmsit[pdev->classId] == NULL) {
return (uint8_t)USBD_FAIL;
}
/* Get the received data length */
hcdc->RxLength = USBD_LL_GetRxDataSize(pdev, epnum);
/* USB data will be immediately processed, this allow next USB traffic being
NAKed till the end of the application Xfer */
((USBD_CDC_ItfTypeDef *)pdev->pUserData[pdev->classId])
->Receive(hcdc->RxBuffer, &hcdc->RxLength);
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &hcdc->RxBuffer[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_CDC_EP0_RxReady
* Handle EP0 Rx Ready event
* @param pdev: device instance
* @retval status
*/
static uint8_t USBD_CDC_EP0_RxReady(USBD_HandleTypeDef *pdev)
{
USBD_CDC_HandleTypeDef *hcdc =
(USBD_CDC_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
if (hcdc == NULL) {
return (uint8_t)USBD_FAIL;
}
if ((pdev->pUserData[pdev->classId] != NULL) &&
(hcdc->CmdOpCode != 0xFFU)) {
((USBD_CDC_ItfTypeDef *)pdev->pUserData[pdev->classId])
->Control(hcdc->CmdOpCode, (uint8_t *)hcdc->data,
(uint16_t)hcdc->CmdLength);
hcdc->CmdOpCode = 0xFFU;
}
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_CDC_GetFSCfgDesc
* Return configuration descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_CDC_GetFSCfgDesc(uint16_t *length)
{
USBD_EpDescTypeDef *pEpCmdDesc =
USBD_GetEpDesc(USBD_CDC_CfgDesc, CDC_CMD_EP);
USBD_EpDescTypeDef *pEpOutDesc =
USBD_GetEpDesc(USBD_CDC_CfgDesc, CDC_OUT_EP);
USBD_EpDescTypeDef *pEpInDesc = USBD_GetEpDesc(USBD_CDC_CfgDesc, CDC_IN_EP);
if (pEpCmdDesc != NULL) {
pEpCmdDesc->bInterval = CDC_FS_BINTERVAL;
}
if (pEpOutDesc != NULL) {
pEpOutDesc->wMaxPacketSize = CDC_DATA_FS_MAX_PACKET_SIZE;
}
if (pEpInDesc != NULL) {
pEpInDesc->wMaxPacketSize = CDC_DATA_FS_MAX_PACKET_SIZE;
}
*length = (uint16_t)sizeof(USBD_CDC_CfgDesc);
return USBD_CDC_CfgDesc;
}
/**
* @brief USBD_CDC_GetHSCfgDesc
* Return configuration descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_CDC_GetHSCfgDesc(uint16_t *length)
{
// USBD_EpDescTypeDef *pEpCmdDesc = USBD_GetEpDesc(USBD_CDC_CfgDesc,
// CDC_CMD_EP); USBD_EpDescTypeDef *pEpOutDesc =
// USBD_GetEpDesc(USBD_CDC_CfgDesc, CDC_OUT_EP); USBD_EpDescTypeDef
// *pEpInDesc = USBD_GetEpDesc(USBD_CDC_CfgDesc, CDC_IN_EP);
// if (pEpCmdDesc != NULL)
// {
// pEpCmdDesc->bInterval = CDC_HS_BINTERVAL;
// }
// if (pEpOutDesc != NULL)
// {
// pEpOutDesc->wMaxPacketSize = CDC_DATA_HS_MAX_PACKET_SIZE;
// }
// if (pEpInDesc != NULL)
// {
// pEpInDesc->wMaxPacketSize = CDC_DATA_HS_MAX_PACKET_SIZE;
// }
// *length = (uint16_t)sizeof(USBD_CDC_CfgDesc);
return USBD_CDC_CfgDesc;
}
/**
* @brief USBD_CDC_GetOtherSpeedCfgDesc
* Return configuration descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_CDC_GetOtherSpeedCfgDesc(uint16_t *length)
{
USBD_EpDescTypeDef *pEpCmdDesc =
USBD_GetEpDesc(USBD_CDC_CfgDesc, CDC_CMD_EP);
USBD_EpDescTypeDef *pEpOutDesc =
USBD_GetEpDesc(USBD_CDC_CfgDesc, CDC_OUT_EP);
USBD_EpDescTypeDef *pEpInDesc = USBD_GetEpDesc(USBD_CDC_CfgDesc, CDC_IN_EP);
if (pEpCmdDesc != NULL) {
pEpCmdDesc->bInterval = CDC_FS_BINTERVAL;
}
if (pEpOutDesc != NULL) {
pEpOutDesc->wMaxPacketSize = CDC_DATA_FS_MAX_PACKET_SIZE;
}
if (pEpInDesc != NULL) {
pEpInDesc->wMaxPacketSize = CDC_DATA_FS_MAX_PACKET_SIZE;
}
*length = (uint16_t)sizeof(USBD_CDC_CfgDesc);
return USBD_CDC_CfgDesc;
}
/**
* @brief USBD_CDC_GetDeviceQualifierDescriptor
* return Device Qualifier descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
uint8_t *USBD_CDC_GetDeviceQualifierDescriptor(uint16_t *length)
{
*length = (uint16_t)sizeof(USBD_CDC_DeviceQualifierDesc);
return USBD_CDC_DeviceQualifierDesc;
}
/**
* @brief USBD_CDC_RegisterInterface
* @param pdev: device instance
* @param fops: CD Interface callback
* @retval status
*/
uint8_t USBD_CDC_RegisterInterface(USBD_HandleTypeDef *pdev,
USBD_CDC_ItfTypeDef *fops)
{
if (fops == NULL) {
return (uint8_t)USBD_FAIL;
}
pdev->pUserData[pdev->classId] = fops;
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_CDC_SetTxBuffer
* @param pdev: device instance
* @param pbuff: Tx Buffer
* @param length: Tx Buffer length
* @retval status
*/
uint8_t USBD_CDC_SetTxBuffer(USBD_HandleTypeDef *pdev, uint8_t *pbuff,
uint32_t length)
{
USBD_CDC_HandleTypeDef *hcdc =
(USBD_CDC_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
if (hcdc == NULL) {
return (uint8_t)USBD_FAIL;
}
hcdc->TxBuffer = pbuff;
hcdc->TxLength = length;
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_CDC_SetRxBuffer
* @param pdev: device instance
* @param pbuff: Rx Buffer
* @retval status
*/
uint8_t USBD_CDC_SetRxBuffer(USBD_HandleTypeDef *pdev, uint8_t *pbuff)
{
USBD_CDC_HandleTypeDef *hcdc =
(USBD_CDC_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
if (hcdc == NULL) {
return (uint8_t)USBD_FAIL;
}
hcdc->RxBuffer = pbuff;
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_CDC_TransmitPacket
* Transmit packet on IN endpoint
* @param pdev: device instance
* @retval status
*/
extern volatile uint32_t epnum_change;
uint8_t USBD_CDC_TransmitPacket(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
USBD_CDC_HandleTypeDef *hcdc =
(USBD_CDC_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
USBD_StatusTypeDef ret = USBD_BUSY;
if (pdev->pClassDataCmsit[pdev->classId] == NULL) {
return (uint8_t)USBD_FAIL;
}
if (hcdc->TxState == 0U) {
/* Tx Transfer in progress */
hcdc->TxState = 1U;
/* Update the packet total length */
pdev->ep_in[epnum & 0xFU].total_length = hcdc->TxLength;
epnum_change = (epnum & 0xFU);
/* Transmit next packet */
(void)USBD_LL_Transmit(pdev, epnum, hcdc->TxBuffer, hcdc->TxLength);
// /* Update the packet total length */
// pdev->ep_in[CDCInEpAdd & 0xFU].total_length = hcdc->TxLength;
// /* Transmit next packet */
// (void)USBD_LL_Transmit(pdev, CDCInEpAdd, hcdc->TxBuffer,
// hcdc->TxLength);
ret = USBD_OK;
}
return (uint8_t)ret;
}
/**
* @brief USBD_CDC_ReceivePacket
* prepare OUT Endpoint for reception
* @param pdev: device instance
* @retval status
*/
uint8_t USBD_CDC_ReceivePacket(USBD_HandleTypeDef *pdev)
{
USBD_CDC_HandleTypeDef *hcdc =
(USBD_CDC_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
if (pdev->pClassDataCmsit[pdev->classId] == NULL) {
return (uint8_t)USBD_FAIL;
}
/* Prepare Out endpoint to receive next packet */
(void)USBD_LL_PrepareReceive(pdev, CDCOutEpAdd, hcdc->RxBuffer,
CDC_DATA_FS_OUT_PACKET_SIZE);
return (uint8_t)USBD_OK;
}
@@ -0,0 +1,162 @@
/*!
* \file usbd_cdc.h
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author MCD Application Team
*
* \author ( XinChip ) Alex-J
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USB_CDC_H
#define __USB_CDC_H
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_ioreq.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
/** @defgroup usbd_cdc_Exported_Defines
* @{
*/
#ifndef CDC_IN_EP
#define CDC_IN_EP 0x81U /* EP1 for data IN */
#endif /* CDC_IN_EP */
#ifndef CDC_OUT_EP
#define CDC_OUT_EP 0x01U /* EP1 for data OUT */
#endif /* CDC_OUT_EP */
#ifndef CDC_CMD_EP
#define CDC_CMD_EP 0x82U /* EP2 for CDC commands */
#endif /* CDC_CMD_EP */
#ifndef CDC_FS_BINTERVAL
#define CDC_FS_BINTERVAL 0x10U
#endif /* CDC_FS_BINTERVAL */
/* CDC Endpoints parameters: you can fine tune these values depending on the needed baudrates and performance. */
#define CDC_DATA_FS_MAX_PACKET_SIZE 64U /* Endpoint IN & OUT Packet size */
#define CDC_CMD_PACKET_SIZE 8U /* Control Endpoint Packet size */
#define USB_CDC_CONFIG_DESC_SIZ 67U
#define CDC_DATA_FS_IN_PACKET_SIZE CDC_DATA_FS_MAX_PACKET_SIZE
#define CDC_DATA_FS_OUT_PACKET_SIZE CDC_DATA_FS_MAX_PACKET_SIZE
#define CDC_REQ_MAX_DATA_SIZE 0x7U
/*---------------------------------------------------------------------*/
/* CDC definitions */
/*---------------------------------------------------------------------*/
#define CDC_SEND_ENCAPSULATED_COMMAND 0x00U
#define CDC_GET_ENCAPSULATED_RESPONSE 0x01U
#define CDC_SET_COMM_FEATURE 0x02U
#define CDC_GET_COMM_FEATURE 0x03U
#define CDC_CLEAR_COMM_FEATURE 0x04U
#define CDC_SET_LINE_CODING 0x20U
#define CDC_GET_LINE_CODING 0x21U
#define CDC_SET_CONTROL_LINE_STATE 0x22U
#define CDC_SEND_BREAK 0x23U
/**
* @}
*/
/*------------------------------------------------------------------------------------
Typedef
-------------------------------------------------------------------------------------*/
/** @defgroup USBD_CORE_Exported_TypesDefinitions
* @{
*/
typedef struct
{
uint32_t bitrate;
uint8_t format;
uint8_t paritytype;
uint8_t datatype;
} USBD_CDC_LineCodingTypeDef;
typedef struct _USBD_CDC_Itf
{
int8_t (* Init)(void);
int8_t (* DeInit)(void);
int8_t (* Control)(uint8_t cmd, uint8_t *pbuf, uint16_t length);
int8_t (* Receive)(uint8_t *Buf, uint32_t *Len);
int8_t (* TransmitCplt)(uint8_t *Buf, uint32_t *Len, uint8_t epnum);
} USBD_CDC_ItfTypeDef;
typedef struct
{
uint32_t data[CDC_DATA_FS_MAX_PACKET_SIZE * 2U]; /* Force 32-bit alignment */
uint8_t CmdOpCode;
uint8_t CmdLength;
uint8_t *RxBuffer;
uint8_t *TxBuffer;
uint32_t RxLength;
uint32_t TxLength;
__IO uint32_t TxState;
__IO uint32_t RxState;
} USBD_CDC_HandleTypeDef;
/**
* @}
*/
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
/** @defgroup USBD_CORE_Exported_Variables
* @{
*/
extern USBD_ClassTypeDef USBD_CDC;
/**
* @}
*/
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
/** @defgroup USB_CORE_Exported_Functions
* @{
*/
uint8_t USBD_CDC_RegisterInterface(USBD_HandleTypeDef *pdev,
USBD_CDC_ItfTypeDef *fops);
uint8_t USBD_CDC_SetTxBuffer(USBD_HandleTypeDef *pdev, uint8_t *pbuff,
uint32_t length);
uint8_t USBD_CDC_SetRxBuffer(USBD_HandleTypeDef *pdev, uint8_t *pbuff);
uint8_t USBD_CDC_ReceivePacket(USBD_HandleTypeDef *pdev);
uint8_t USBD_CDC_TransmitPacket(USBD_HandleTypeDef *pdev, uint8_t epnum);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USB_CDC_H */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,270 @@
/*!
* \file usbd_hid.h
*
* \brief This file provides the HID core functions.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author MCD Application Team
*
* \author ( XinChip ) Alex-J
*
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USB_HID_H
#define __USB_HID_H
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_ioreq.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
/** @defgroup USBD_HID_Exported_Defines
* @{
*/
#if (HID_CLASS_MODE == HID_MOUSE) /* HID_MOUSE */
#define HID_EPIN_ADDR 0x81U
#define HID_EPIN_SIZE 0x04U
#define USB_HID_CONFIG_DESC_SIZ 34U
#elif (HID_CLASS_MODE == HID_KEYBOARD) /* HID_KEYBOARD */
#define HID_EP1_OUTPUT 0U
#define HID_EPIN_ADDR 0x81U
#define HID_EPIN_SIZE 0x08U
#define HID_EPOUT_ADDR 0x01U
#define HID_EPOUT_SIZE 0x01U
#if HID_EP1_OUTPUT
#define USB_HID_CONFIG_DESC_SIZ 41U
#else
#define USB_HID_CONFIG_DESC_SIZ 34U
#endif
#define USBD_HID_OUTREPORT_BUF_SIZE 1U
#elif (HID_CLASS_MODE == HID_CUSTOM) /* HID_CUSTOM */
#define HID_EPIN_ADDR 0x81U
#define HID_EPIN_SIZE 0x40U
#define HID_EPOUT_ADDR 0x01U
#define HID_EPOUT_SIZE 0x40U
#define USB_HID_CONFIG_DESC_SIZ 41U
#define USBD_HID_OUTREPORT_BUF_SIZE 0x40U
#elif ((HID_CLASS_MODE == (HID_MOUSE | HID_CUSTOM)) || \
(HID_CLASS_MODE == (HID_KEYBOARD | HID_CUSTOM)))/* (HID_MOUSE | HID_CUSTOM) */
#if ((HID_CLASS_MODE & HID_MOUSE) == HID_MOUSE)
#define HID_EPIN_ADDR 0x81U
#define HID_EPIN_SIZE 0x04U
#endif
#if ((HID_CLASS_MODE & HID_KEYBOARD) == HID_KEYBOARD)
#define HID_EPIN_ADDR 0x81U
#define HID_EPIN_SIZE 0x08U
#define HID_EPOUT_ADDR 0x01U
#define HID_EPOUT_SIZE 0x01U
#define USBD_HID_OUTREPORT_BUF_SIZE 1U
#endif
#define CUSTOM_HID_EPIN_ADDR 0x82U
#define CUSTOM_HID_EPIN_SIZE 0x40U
#define CUSTOM_HID_EPOUT_ADDR 0x02U
#define CUSTOM_HID_EPOUT_SIZE 0x40U
#define CUSTOM_HID_FS_BINTERVAL 0x5U
#define USBD_CUSTOMHID_OUTREPORT_BUF_SIZE 0x40U
#if ((HID_CLASS_MODE & HID_MOUSE) == HID_MOUSE)
#define USB_HID_CONFIG_DESC_SIZ 66U
#endif
#if ((HID_CLASS_MODE & HID_KEYBOARD) == HID_KEYBOARD)
#define USB_HID_CONFIG_DESC_SIZ 73U
#endif
#define HID_DATAIN_EPNUM (HID_EPIN_ADDR & 0x0FU)
#define CUSTOM_HID_DATAIN_EPNUM (CUSTOM_HID_EPIN_ADDR & 0x0FU)
#elif (HID_CLASS_MODE == (HID_KEYBOARD | HID_MOUSE))
#define HID_EP1IN_ADDR 0x81U
#define HID_EP1IN_SIZE 0x08U
#define HID_EP1OUT_ADDR 0x01U
#define HID_EP1OUT_SIZE 0x01U
#define USBD_HID_OUTREPORT_BUF_SIZE 1U
#define HID_EP2IN_ADDR 0x82U
#define HID_EP2IN_SIZE 0x04U
#define USB_HID_CONFIG_DESC_SIZ 66U
#define HID_DATAIN_EPNUM_1 (HID_EP1IN_ADDR & 0x0FU)
#define HID_DATAIN_EPNUM_2 (HID_EP2IN_ADDR & 0x0FU)
#endif
#define USB_HID_DESC_SIZ 9U
#define HID_MOUSE_REPORT_DESC_SIZE 74U
#define HID_KEYBOARD_REPORT_DESC_SIZE 63U
#define USBD_CUSTOM_REPORT_DESC_SIZE 34U//43U //39U//34U
#define HID_DESCRIPTOR_TYPE 0x21U
#define HID_REPORT_DESC 0x22U
#ifndef HID_HS_BINTERVAL
#define HID_HS_BINTERVAL 0x07U
#endif /* HID_HS_BINTERVAL */
#ifndef HID_FS_BINTERVAL
#if ((HID_CLASS_MODE== HID_MOUSE) || \
(HID_CLASS_MODE == HID_KEYBOARD))
#define HID_FS_BINTERVAL 0x01U
#else
#define HID_FS_BINTERVAL 0x01U
#endif
#endif /* HID_FS_BINTERVAL */
#define HID_REQ_SET_PROTOCOL 0x0BU
#define HID_REQ_GET_PROTOCOL 0x03U
#define HID_REQ_SET_IDLE 0x0AU
#define HID_REQ_GET_IDLE 0x02U
#define HID_REQ_SET_REPORT 0x09U
#define HID_REQ_GET_REPORT 0x01U
/**
* @}
*/
/*------------------------------------------------------------------------------------
Typedef
-------------------------------------------------------------------------------------*/
/** @defgroup USBD_CORE_Exported_TypesDefinitions
* @{
*/
typedef enum
{
HID_IDLE = 0,
HID_BUSY,
} HID_StateTypeDef;
#if (HID_CLASS_MODE == HID_MOUSE)
typedef struct
{
uint32_t Protocol;
uint32_t IdleState;
uint32_t AltSetting;
HID_StateTypeDef state;
} USBD_HID_HandleTypeDef;
#else
typedef struct
{
uint8_t Report_buf[USBD_HID_OUTREPORT_BUF_SIZE];
uint32_t Protocol;
uint32_t IdleState;
uint32_t AltSetting;
uint32_t IsReportAvailable;
HID_StateTypeDef state;
} USBD_HID_HandleTypeDef;
#endif
//#if ((HID_CLASS_MODE & HID_CUSTOM) == HID_CUSTOM)
///** @defgroup USBD_CORE_Exported_TypesDefinitions
// * @{
// */
//typedef enum
//{
// CUSTOM_HID_IDLE = 0U,
// CUSTOM_HID_BUSY,
//} CUSTOM_HID_StateTypeDef;
//typedef struct
//{
// uint8_t Report_buf[USBD_CUSTOMHID_OUTREPORT_BUF_SIZE];
// uint32_t Protocol;
// uint32_t IdleState;
// uint32_t AltSetting;
// uint32_t IsReportAvailable;
// CUSTOM_HID_StateTypeDef state;
//} USBD_CUSTOM_HID_HandleTypeDef;
//#endif
/*
* HID Class specification version 1.1
* 6.2.1 HID Descriptor
*/
typedef struct
{
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t bcdHID;
uint8_t bCountryCode;
uint8_t bNumDescriptors;
uint8_t bHIDDescriptorType;
uint16_t wItemLength;
} __PACKED USBD_HIDDescTypeDef;
/**
* @}
*/
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
extern USBD_ClassTypeDef USBD_HID;
#if (HID_CLASS_MODE == HID_KEYBOARD)
extern uint8_t Report_buff[1];
#endif
extern uint8_t DataOut_Finished;
/*------------------------------------------------------------------------------------
Global Functions
-------------------------------------------------------------------------------------*/
uint8_t USBD_HID_SendReport(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t *report, uint16_t len);
uint8_t USBD_HID_ReceivePacket(USBD_HandleTypeDef *pdev);
uint32_t USBD_HID_GetPollingInterval(USBD_HandleTypeDef *pdev);
#ifdef __cplusplus
}
#endif
#endif /* __USB_HID_H */
/**
* @}
*/
@@ -0,0 +1,275 @@
/*!
* \file usbd_hid.h
*
* \brief This file provides the HID core functions.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author MCD Application Team
*
* \author ( XinChip ) Alex-J
*
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USB_HID_H
#define __USB_HID_H
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_ioreq.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
/** @defgroup USBD_HID_Exported_Defines
* @{
*/
#if (HID_CLASS_MODE == (HID_KEYBOARD | HID_MOUSE))
#define HID_EP1IN_ADDR 0x81U
#define HID_EP1IN_SIZE 0x08U
#define HID_EP1OUT_ADDR 0x01U
#define HID_EP1OUT_SIZE 0x01U
#define USBD_HID_OUTREPORT_BUF_SIZE 1U
#define HID_EP2IN_ADDR 0x82U
#define HID_EP2IN_SIZE 0x04U
#define USB_HID_CONFIG_DESC_SIZ 66U
#define HID_DATAIN_EPNUM_1 (HID_EP1IN_ADDR & 0x0FU)
#define HID_DATAIN_EPNUM_2 (HID_EP2IN_ADDR & 0x0FU)
#endif
#if (HID_CLASS_MODE == (HID_MOUSE | HID_CUSTOM))
#define HID_EPIN_ADDR 0x81U
#define HID_EPIN_SIZE 0x04U
#define CUSTOM_HID_EPIN_ADDR 0x82U
#define CUSTOM_HID_EPIN_SIZE 0x40U
#define CUSTOM_HID_EPOUT_ADDR 0x02U
#define CUSTOM_HID_EPOUT_SIZE 0x40U
#define CUSTOM_HID_FS_BINTERVAL 0x5U
#define USBD_CUSTOMHID_OUTREPORT_BUF_SIZE 0x40U
#define HID_DATAIN_EPNUM (HID_EPIN_ADDR & 0x0FU)
#define CUSTOM_HID_DATAIN_EPNUM (CUSTOM_HID_EPIN_ADDR & 0x0FU)
#define USB_HID_CONFIG_DESC_SIZ 66U
#endif
#if (HID_CLASS_MODE == HID_DOUBLE_CUSTOM)
#define HID_EPIN_ADDR 0x81U
#define HID_EPIN_SIZE 0x40U
#define HID_EPOUT_ADDR 0x01U
#define HID_EPOUT_SIZE 0x40U
#define HID_EP2IN_ADDR 0x82U
#define HID_EP2IN_SIZE 0x40U
#define HID_EP2OUT_ADDR 0x02U
#define HID_EP2OUT_SIZE 0x40U
#define USB_HID_CONFIG_DESC_SIZ 73U
//#define USB_HID_DOUBLE_CUSTOM_CONFIG_DESC_SIZ 82U
#define USBD_HID_OUTREPORT_BUF_SIZE 0x40U
#define HID_DATAIN_EPNUM_1 (HID_EPIN_ADDR & 0x0FU)
#define HID_DATAIN_EPNUM_2 (HID_EP2IN_ADDR & 0x0FU)
#endif
#define USB_HID_DESC_SIZ 9U
#define HID_MOUSE_REPORT_DESC_SIZE 74U
#define HID_KEYBOARD_REPORT_DESC_SIZE 63U
#define USBD_CUSTOM_REPORT_DESC_SIZE 34U
#define HID_DESCRIPTOR_TYPE 0x21U
#define HID_REPORT_DESC 0x22U
#ifndef HID_HS_BINTERVAL
#define HID_HS_BINTERVAL 0x07U
#endif /* HID_HS_BINTERVAL */
#ifndef HID_FS_BINTERVAL
#define HID_FS_BINTERVAL 0x01U
#endif /* HID_FS_BINTERVAL */
#ifndef HID_FS_K_BINTERVAL
#define HID_FS_K_BINTERVAL 0x0AU
#endif /* HID_FS_BINTERVAL */
#ifndef HID_FS_M_BINTERVAL
#define HID_FS_M_BINTERVAL 0x01U
#endif /* HID_FS_BINTERVAL */
#define HID_REQ_SET_PROTOCOL 0x0BU
#define HID_REQ_GET_PROTOCOL 0x03U
#define HID_REQ_SET_IDLE 0x0AU
#define HID_REQ_GET_IDLE 0x02U
#define HID_REQ_SET_REPORT 0x09U
#define HID_REQ_GET_REPORT 0x01U
/**
* @}
*/
/*------------------------------------------------------------------------------------
Typedef
-------------------------------------------------------------------------------------*/
/** @defgroup USBD_CORE_Exported_TypesDefinitions
* @{
*/
typedef enum
{
HID_IDLE = 0,
HID_BUSY,
} HID_StateTypeDef;
#if ((HID_CLASS_MODE & HID_MOUSE) == HID_MOUSE)
typedef struct
{
uint32_t Protocol;
uint32_t IdleState;
uint32_t AltSetting;
HID_StateTypeDef state;
} USBD_HID_HandleTypeDef;
#endif
#if ((HID_CLASS_MODE & HID_CUSTOM) == HID_CUSTOM)
/** @defgroup USBD_CORE_Exported_TypesDefinitions
* @{
*/
typedef enum
{
CUSTOM_HID_IDLE = 0U,
CUSTOM_HID_BUSY,
} CUSTOM_HID_StateTypeDef;
typedef struct
{
uint8_t Report_buf[USBD_CUSTOMHID_OUTREPORT_BUF_SIZE];
uint32_t Protocol;
uint32_t IdleState;
uint32_t AltSetting;
uint32_t IsReportAvailable;
CUSTOM_HID_StateTypeDef state;
} USBD_CUSTOM_HID_HandleTypeDef;
#endif
#if (HID_CLASS_MODE == HID_DOUBLE_CUSTOM)
typedef struct
{
uint8_t Report_buf[USBD_HID_OUTREPORT_BUF_SIZE];
uint32_t Protocol;
uint32_t IdleState;
uint32_t AltSetting;
uint32_t IsReportAvailable;
HID_StateTypeDef state;
} USBD_HID_HandleTypeDef;
#endif
//#if ((HID_CLASS_MODE & HID_CUSTOM) == HID_CUSTOM)
///** @defgroup USBD_CORE_Exported_TypesDefinitions
// * @{
// */
//typedef enum
//{
// CUSTOM_HID_IDLE = 0U,
// CUSTOM_HID_BUSY,
//} CUSTOM_HID_StateTypeDef;
//typedef struct
//{
// uint8_t Report_buf[USBD_CUSTOMHID_OUTREPORT_BUF_SIZE];
// uint32_t Protocol;
// uint32_t IdleState;
// uint32_t AltSetting;
// uint32_t IsReportAvailable;
// CUSTOM_HID_StateTypeDef state;
//} USBD_CUSTOM_HID_HandleTypeDef;
//#endif
/*
* HID Class specification version 1.1
* 6.2.1 HID Descriptor
*/
typedef struct
{
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t bcdHID;
uint8_t bCountryCode;
uint8_t bNumDescriptors;
uint8_t bHIDDescriptorType;
uint16_t wItemLength;
} __PACKED USBD_HIDDescTypeDef;
/**
* @}
*/
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
extern USBD_ClassTypeDef USBD_HID;
#if ((HID_CLASS_MODE & HID_KEYBOARD) == HID_KEYBOARD)
extern uint8_t Report_buff[1];
#endif
/*------------------------------------------------------------------------------------
Global Functions
-------------------------------------------------------------------------------------*/
#if (HID_CLASS_MODE == (HID_MOUSE | HID_KEYBOARD))
uint8_t USBD_Mouse_HID_SendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len);
uint8_t USBD_Keyboard_HID_SendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len);
#elif (HID_CLASS_MODE == (HID_MOUSE | HID_CUSTOM))
uint8_t USBD_Mouse_HID_SendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len);
uint8_t USBD_Custom_HID_SendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len);
#elif (HID_CLASS_MODE == HID_DOUBLE_CUSTOM)
uint8_t USBD_Custom1_HID_SendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len);
uint8_t USBD_Custom2_HID_SendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len);
#endif
uint32_t USBD_HID_GetPollingInterval(USBD_HandleTypeDef *pdev);
#ifdef __cplusplus
}
#endif
#endif /* __USB_HID_H */
/**
* @}
*/
@@ -0,0 +1,493 @@
/*!
* \file usbd_msc.c
*
* \brief This file provides all the MSC core functions.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author MCD Application Team
*
* \author ( XinChip ) Alex-J
* @verbatim
*
* ===================================================================
* MSC Class Description
* ===================================================================
* This module manages the MSC class V1.0 following the "Universal
* Serial Bus Mass Storage Class (MSC) Bulk-Only Transport (BOT)
Version 1.0
* Sep. 31, 1999".
* This driver implements the following aspects of the specification:
* - Bulk-Only Transport protocol
* - Subclass : SCSI transparent command set (ref. SCSI Primary
Commands - 3 (SPC-3))
*
* @endverbatim
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_msc.h"
/*------------------------------------------------------------------------------------
Func Prototype
-------------------------------------------------------------------------------------*/
/** @defgroup MSC_CORE_Private_FunctionPrototypes
* @{
*/
uint8_t USBD_MSC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
uint8_t USBD_MSC_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
uint8_t USBD_MSC_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
uint8_t USBD_MSC_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum);
uint8_t USBD_MSC_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum);
uint8_t *USBD_MSC_GetHSCfgDesc(uint16_t *length);
uint8_t *USBD_MSC_GetFSCfgDesc(uint16_t *length);
uint8_t *USBD_MSC_GetOtherSpeedCfgDesc(uint16_t *length);
uint8_t *USBD_MSC_GetDeviceQualifierDescriptor(uint16_t *length);
/**
* @}
*/
/*------------------------------------------------------------------------------------
Local Variables
-------------------------------------------------------------------------------------*/
/** @defgroup MSC_CORE_Private_Variables
* @{
*/
USBD_ClassTypeDef USBD_MSC = {
USBD_MSC_Init,
USBD_MSC_DeInit,
USBD_MSC_Setup,
NULL, /*EP0_TxSent*/
NULL, /*EP0_RxReady*/
USBD_MSC_DataIn,
USBD_MSC_DataOut,
NULL, /*SOF */
NULL,
NULL,
USBD_MSC_GetHSCfgDesc,
USBD_MSC_GetFSCfgDesc,
USBD_MSC_GetOtherSpeedCfgDesc,
USBD_MSC_GetDeviceQualifierDescriptor,
};
/* USB Mass storage device Configuration Descriptor */
/* All Descriptors (Configuration, Interface, Endpoint, Class, Vendor */
__ALIGN_BEGIN static uint8_t
USBD_MSC_CfgDesc[USB_MSC_CONFIG_DESC_SIZ] __ALIGN_END = {
0x09, /* bLength: Configuration Descriptor size */
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
USB_MSC_CONFIG_DESC_SIZ,
0x00, 0x01, /* bNumInterfaces: 1 interface */
0x01, /* bConfigurationValue */
0x04, /* iConfiguration */
#if (USBD_SELF_POWERED == 1U)
0xC0, /* bmAttributes: Bus Powered according to user configuration */
#else
0x80, /* bmAttributes: Bus Powered according to user configuration */
#endif /* USBD_SELF_POWERED */
USBD_MAX_POWER, /* MaxPower (mA) */
/******************** Mass Storage interface ********************/
0x09, /* bLength: Interface Descriptor size */
0x04, /* bDescriptorType: */
0x00, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x02, /* bNumEndpoints */
0x08, /* bInterfaceClass: MSC Class */
0x06, /* bInterfaceSubClass : SCSI transparent*/
0x50, /* nInterfaceProtocol */
0x05, /* iInterface: */
/******************** Mass Storage Endpoints ********************/
0x07, /* Endpoint descriptor length = 7 */
0x05, /* Endpoint descriptor type */
MSC_EPIN_ADDR, /* Endpoint address (IN, address 1) */
0x02, /* Bulk endpoint type */
LOBYTE(MSC_MAX_FS_PACKET), HIBYTE(MSC_MAX_FS_PACKET),
0x00, /* Polling interval in milliseconds */
0x07, /* Endpoint descriptor length = 7 */
0x05, /* Endpoint descriptor type */
MSC_EPOUT_ADDR, /* Endpoint address (OUT, address 1) */
0x02, /* Bulk endpoint type */
LOBYTE(MSC_MAX_FS_PACKET), HIBYTE(MSC_MAX_FS_PACKET),
0x00 /* Polling interval in milliseconds */
};
/* USB Standard Device Descriptor */
__ALIGN_BEGIN static uint8_t
USBD_MSC_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END = {
USB_LEN_DEV_QUALIFIER_DESC,
USB_DESC_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
MSC_MAX_FS_PACKET,
0x01,
0x00,
};
uint8_t MSCInEpAdd = MSC_EPIN_ADDR;
uint8_t MSCOutEpAdd = MSC_EPOUT_ADDR;
/**
* @}
*/
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
/**
* @brief USBD_MSC_Init
* Initialize the mass storage configuration
* @param pdev: device instance
* @param cfgidx: configuration index
* @retval status
*/
uint8_t USBD_MSC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
UNUSED(cfgidx);
USBD_MSC_BOT_HandleTypeDef *hmsc;
hmsc = (USBD_MSC_BOT_HandleTypeDef *)USBD_malloc(
sizeof(USBD_MSC_BOT_HandleTypeDef));
if (hmsc == NULL) {
pdev->pClassDataCmsit[pdev->classId] = NULL;
return (uint8_t)USBD_EMEM;
}
pdev->pClassDataCmsit[pdev->classId] = (void *)hmsc;
pdev->pClassData = pdev->pClassDataCmsit[pdev->classId];
if (pdev->dev_speed == USBD_SPEED_HIGH) {
/* Open EP OUT */
(void)USBD_LL_OpenEP(pdev, MSCOutEpAdd, USBD_EP_TYPE_BULK,
MSC_MAX_HS_PACKET);
pdev->ep_out[MSCOutEpAdd & 0xFU].is_used = 1U;
/* Open EP IN */
(void)USBD_LL_OpenEP(pdev, MSCInEpAdd, USBD_EP_TYPE_BULK,
MSC_MAX_HS_PACKET);
pdev->ep_in[MSCInEpAdd & 0xFU].is_used = 1U;
} else {
/* Open EP OUT */
(void)USBD_LL_OpenEP(pdev, MSCOutEpAdd, USBD_EP_TYPE_BULK,
MSC_MAX_FS_PACKET);
pdev->ep_out[MSCOutEpAdd & 0xFU].is_used = 1U;
/* Open EP IN */
(void)USBD_LL_OpenEP(pdev, MSCInEpAdd, USBD_EP_TYPE_BULK,
MSC_MAX_FS_PACKET);
pdev->ep_in[MSCInEpAdd & 0xFU].is_used = 1U;
}
/* Init the BOT layer */
MSC_BOT_Init(pdev);
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_MSC_DeInit
* DeInitialize the mass storage configuration
* @param pdev: device instance
* @param cfgidx: configuration index
* @retval status
*/
uint8_t USBD_MSC_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
UNUSED(cfgidx);
/* Close MSC EPs */
(void)USBD_LL_CloseEP(pdev, MSCOutEpAdd);
pdev->ep_out[MSCOutEpAdd & 0xFU].is_used = 0U;
/* Close EP IN */
(void)USBD_LL_CloseEP(pdev, MSCInEpAdd);
pdev->ep_in[MSCInEpAdd & 0xFU].is_used = 0U;
/* Free MSC Class Resources */
if (pdev->pClassDataCmsit[pdev->classId] != NULL) {
/* De-Init the BOT layer */
MSC_BOT_DeInit(pdev);
(void)USBD_free(pdev->pClassDataCmsit[pdev->classId]);
pdev->pClassDataCmsit[pdev->classId] = NULL;
pdev->pClassData = NULL;
}
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_MSC_Setup
* Handle the MSC specific requests
* @param pdev: device instance
* @param req: USB request
* @retval status
*/
uint8_t USBD_MSC_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
{
USBD_MSC_BOT_HandleTypeDef *hmsc =
(USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
USBD_StatusTypeDef ret = USBD_OK;
uint16_t status_info = 0U;
if (hmsc == NULL) {
return (uint8_t)USBD_FAIL;
}
switch (req->bmRequest & USB_REQ_TYPE_MASK) {
/* Class request */
case USB_REQ_TYPE_CLASS:
switch (req->bRequest) {
case BOT_GET_MAX_LUN:
if ((req->wValue == 0U) && (req->wLength == 1U) &&
((req->bmRequest & 0x80U) == 0x80U)) {
hmsc->max_lun = (uint32_t)((USBD_StorageTypeDef *)
pdev->pUserData[pdev->classId])
->GetMaxLun();
(void)USBD_CtlSendData(pdev, (uint8_t *)&hmsc->max_lun, 1U);
} else {
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
}
break;
case BOT_RESET:
if ((req->wValue == 0U) && (req->wLength == 0U) &&
((req->bmRequest & 0x80U) != 0x80U)) {
MSC_BOT_Reset(pdev);
} else {
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
}
break;
default:
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
break;
}
break;
/* Interface & Endpoint request */
case USB_REQ_TYPE_STANDARD:
switch (req->bRequest) {
case USB_REQ_GET_STATUS:
if (pdev->dev_state == USBD_STATE_CONFIGURED) {
(void)USBD_CtlSendData(pdev, (uint8_t *)&status_info, 2U);
} else {
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
}
break;
case USB_REQ_GET_INTERFACE:
if (pdev->dev_state == USBD_STATE_CONFIGURED) {
(void)USBD_CtlSendData(pdev, (uint8_t *)&hmsc->interface, 1U);
} else {
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
}
break;
case USB_REQ_SET_INTERFACE:
if (pdev->dev_state == USBD_STATE_CONFIGURED) {
hmsc->interface = (uint8_t)(req->wValue);
} else {
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
}
break;
case USB_REQ_CLEAR_FEATURE:
if (pdev->dev_state == USBD_STATE_CONFIGURED) {
if (req->wValue == USB_FEATURE_EP_HALT) {
/* Flush the FIFO */
(void)USBD_LL_FlushEP(pdev, (uint8_t)req->wIndex);
/* Handle BOT error */
MSC_BOT_CplClrFeature(pdev, (uint8_t)req->wIndex);
}
}
break;
default:
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
break;
}
break;
default:
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
break;
}
return (uint8_t)ret;
}
/**
* @brief USBD_MSC_DataIn
* handle data IN Stage
* @param pdev: device instance
* @param epnum: endpoint index
* @retval status
*/
uint8_t USBD_MSC_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
MSC_BOT_DataIn(pdev, epnum);
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_MSC_DataOut
* handle data OUT Stage
* @param pdev: device instance
* @param epnum: endpoint index
* @retval status
*/
uint8_t USBD_MSC_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
MSC_BOT_DataOut(pdev, epnum);
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_MSC_GetHSCfgDesc
* return configuration descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
uint8_t *USBD_MSC_GetHSCfgDesc(uint16_t *length)
{
USBD_EpDescTypeDef *pEpInDesc =
USBD_GetEpDesc(USBD_MSC_CfgDesc, MSC_EPIN_ADDR);
USBD_EpDescTypeDef *pEpOutDesc =
USBD_GetEpDesc(USBD_MSC_CfgDesc, MSC_EPOUT_ADDR);
if (pEpInDesc != NULL) {
pEpInDesc->wMaxPacketSize = MSC_MAX_HS_PACKET;
}
if (pEpOutDesc != NULL) {
pEpOutDesc->wMaxPacketSize = MSC_MAX_HS_PACKET;
}
*length = (uint16_t)sizeof(USBD_MSC_CfgDesc);
return USBD_MSC_CfgDesc;
}
/**
* @brief USBD_MSC_GetFSCfgDesc
* return configuration descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
uint8_t *USBD_MSC_GetFSCfgDesc(uint16_t *length)
{
USBD_EpDescTypeDef *pEpInDesc =
USBD_GetEpDesc(USBD_MSC_CfgDesc, MSC_EPIN_ADDR);
USBD_EpDescTypeDef *pEpOutDesc =
USBD_GetEpDesc(USBD_MSC_CfgDesc, MSC_EPOUT_ADDR);
if (pEpInDesc != NULL) {
pEpInDesc->wMaxPacketSize = MSC_MAX_FS_PACKET;
}
if (pEpOutDesc != NULL) {
pEpOutDesc->wMaxPacketSize = MSC_MAX_FS_PACKET;
}
*length = (uint16_t)sizeof(USBD_MSC_CfgDesc);
return USBD_MSC_CfgDesc;
}
/**
* @brief USBD_MSC_GetOtherSpeedCfgDesc
* return other speed configuration descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
uint8_t *USBD_MSC_GetOtherSpeedCfgDesc(uint16_t *length)
{
USBD_EpDescTypeDef *pEpInDesc =
USBD_GetEpDesc(USBD_MSC_CfgDesc, MSC_EPIN_ADDR);
USBD_EpDescTypeDef *pEpOutDesc =
USBD_GetEpDesc(USBD_MSC_CfgDesc, MSC_EPOUT_ADDR);
if (pEpInDesc != NULL) {
pEpInDesc->wMaxPacketSize = MSC_MAX_FS_PACKET;
}
if (pEpOutDesc != NULL) {
pEpOutDesc->wMaxPacketSize = MSC_MAX_FS_PACKET;
}
*length = (uint16_t)sizeof(USBD_MSC_CfgDesc);
return USBD_MSC_CfgDesc;
}
/**
* @brief DeviceQualifierDescriptor
* return Device Qualifier descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
uint8_t *USBD_MSC_GetDeviceQualifierDescriptor(uint16_t *length)
{
*length = (uint16_t)sizeof(USBD_MSC_DeviceQualifierDesc);
return USBD_MSC_DeviceQualifierDesc;
}
/**
* @brief USBD_MSC_RegisterStorage
* @param fops: storage callback
* @retval status
*/
uint8_t USBD_MSC_RegisterStorage(USBD_HandleTypeDef *pdev,
USBD_StorageTypeDef *fops)
{
if (fops == NULL) {
return (uint8_t)USBD_FAIL;
}
pdev->pUserData[pdev->classId] = fops;
return (uint8_t)USBD_OK;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,134 @@
/*!
* \file usbd_msc.h
*
* \brief Header for the usbd_msc.c file
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author MCD Application Team
*
* \author ( XinChip ) Alex-J
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_MSC_H
#define __USBD_MSC_H
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_msc_bot.h"
#include "usbd_msc_scsi.h"
#include "usbd_ioreq.h"
/*------------------------------------------------------------------------------------
Macros
------------------------------------------- -----------------------------------------*/
/** @defgroup USBD_BOT_Exported_Defines
* @{
*/
/* MSC Class Config */
#ifndef MSC_MEDIA_PACKET
#define MSC_MEDIA_PACKET 512U
#endif /* MSC_MEDIA_PACKET */
#define MSC_MAX_FS_PACKET 0x40U
#define MSC_MAX_HS_PACKET 0x200U
#define BOT_GET_MAX_LUN 0xFE
#define BOT_RESET 0xFF
#define USB_MSC_CONFIG_DESC_SIZ 32
#ifndef MSC_EPIN_ADDR
#define MSC_EPIN_ADDR 0x81U
#endif /* MSC_EPIN_ADDR */
#ifndef MSC_EPOUT_ADDR
#define MSC_EPOUT_ADDR 0x01U
#endif /* MSC_EPOUT_ADDR */
/**
* @}
*/
/*------------------------------------------------------------------------------------
Typedef
------------------------------------------------------------------------------------*/
/** @defgroup USB_CORE_Exported_Types
* @{
*/
typedef struct _USBD_STORAGE
{
int8_t (* Init)(uint8_t lun);
int8_t (* GetCapacity)(uint8_t lun, uint32_t *block_num, uint16_t *block_size);
int8_t (* IsReady)(uint8_t lun);
int8_t (* IsWriteProtected)(uint8_t lun);
int8_t (* Read)(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
int8_t (* Write)(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
int8_t (* GetMaxLun)(void);
int8_t *pInquiry;
} USBD_StorageTypeDef;
typedef struct
{
uint32_t max_lun;
uint32_t interface;
uint8_t bot_state;
uint8_t bot_status;
uint32_t bot_data_length;
uint8_t bot_data[MSC_MEDIA_PACKET];
USBD_MSC_BOT_CBWTypeDef cbw;
USBD_MSC_BOT_CSWTypeDef csw;
USBD_SCSI_SenseTypeDef scsi_sense [SENSE_LIST_DEEPTH];
uint8_t scsi_sense_head;
uint8_t scsi_sense_tail;
uint8_t scsi_medium_state;
uint16_t scsi_blk_size;
uint32_t scsi_blk_nbr;
uint32_t scsi_blk_addr;
uint32_t scsi_blk_len;
} USBD_MSC_BOT_HandleTypeDef;
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
/* Structure for MSC process */
extern USBD_ClassTypeDef USBD_MSC;
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
uint8_t USBD_MSC_RegisterStorage(USBD_HandleTypeDef *pdev,
USBD_StorageTypeDef *fops);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_MSC_H */
@@ -0,0 +1,381 @@
/*!
* \file usbd_msc_bot.c
*
* \brief This file provides all the BOT protocol core functions.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author MCD Application Team
*
* \author ( XinChip ) Alex-J
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_msc_bot.h"
#include "usbd_ioreq.h"
#include "usbd_msc.h"
#include "usbd_msc_scsi.h"
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
extern uint8_t MSCInEpAdd;
extern uint8_t MSCOutEpAdd;
/**
* @}
*/
/*------------------------------------------------------------------------------------
Func Prototype
-------------------------------------------------------------------------------------*/
/** @defgroup MSC_BOT_Private_FunctionPrototypes
* @{
*/
static void MSC_BOT_SendData(USBD_HandleTypeDef *pdev, uint8_t *pbuf,
uint32_t len);
static void MSC_BOT_CBW_Decode(USBD_HandleTypeDef *pdev);
static void MSC_BOT_Abort(USBD_HandleTypeDef *pdev);
/**
* @}
*/
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
/**
* @brief MSC_BOT_Init
* Initialize the BOT Process
* @param pdev: device instance
* @retval None
*/
void MSC_BOT_Init(USBD_HandleTypeDef *pdev)
{
USBD_MSC_BOT_HandleTypeDef *hmsc =
(USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
if (hmsc == NULL) {
return;
}
hmsc->bot_state = USBD_BOT_IDLE;
hmsc->bot_status = USBD_BOT_STATUS_NORMAL;
hmsc->scsi_sense_tail = 0U;
hmsc->scsi_sense_head = 0U;
hmsc->scsi_medium_state = SCSI_MEDIUM_UNLOCKED;
((USBD_StorageTypeDef *)pdev->pUserData[pdev->classId])->Init(0U);
(void)USBD_LL_FlushEP(pdev, MSCOutEpAdd);
(void)USBD_LL_FlushEP(pdev, MSCInEpAdd);
/* Prepare EP to Receive First BOT Cmd */
(void)USBD_LL_PrepareReceive(pdev, MSCOutEpAdd, (uint8_t *)&hmsc->cbw,
USBD_BOT_CBW_LENGTH);
}
/**
* @brief MSC_BOT_Reset
* Reset the BOT Machine
* @param pdev: device instance
* @retval None
*/
void MSC_BOT_Reset(USBD_HandleTypeDef *pdev)
{
USBD_MSC_BOT_HandleTypeDef *hmsc =
(USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
if (hmsc == NULL) {
return;
}
hmsc->bot_state = USBD_BOT_IDLE;
hmsc->bot_status = USBD_BOT_STATUS_RECOVERY;
(void)USBD_LL_ClearStallEP(pdev, MSCInEpAdd);
(void)USBD_LL_ClearStallEP(pdev, MSCOutEpAdd);
/* Prepare EP to Receive First BOT Cmd */
(void)USBD_LL_PrepareReceive(pdev, MSCOutEpAdd, (uint8_t *)&hmsc->cbw,
USBD_BOT_CBW_LENGTH);
}
/**
* @brief MSC_BOT_DeInit
* DeInitialize the BOT Machine
* @param pdev: device instance
* @retval None
*/
void MSC_BOT_DeInit(USBD_HandleTypeDef *pdev)
{
USBD_MSC_BOT_HandleTypeDef *hmsc =
(USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
if (hmsc != NULL) {
hmsc->bot_state = USBD_BOT_IDLE;
}
}
/**
* @brief MSC_BOT_DataIn
* Handle BOT IN data stage
* @param pdev: device instance
* @param epnum: endpoint index
* @retval None
*/
void MSC_BOT_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
UNUSED(epnum);
USBD_MSC_BOT_HandleTypeDef *hmsc =
(USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
if (hmsc == NULL) {
return;
}
switch (hmsc->bot_state) {
case USBD_BOT_DATA_IN:
if (SCSI_ProcessCmd(pdev, hmsc->cbw.bLUN, &hmsc->cbw.CB[0]) < 0) {
MSC_BOT_SendCSW(pdev, USBD_CSW_CMD_FAILED);
}
break;
case USBD_BOT_SEND_DATA:
case USBD_BOT_LAST_DATA_IN:
MSC_BOT_SendCSW(pdev, USBD_CSW_CMD_PASSED);
break;
default:
break;
}
}
/**
* @brief MSC_BOT_DataOut
* Process MSC OUT data
* @param pdev: device instance
* @param epnum: endpoint index
* @retval None
*/
void MSC_BOT_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
UNUSED(epnum);
USBD_MSC_BOT_HandleTypeDef *hmsc =
(USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
if (hmsc == NULL) {
return;
}
switch (hmsc->bot_state) {
case USBD_BOT_IDLE:
MSC_BOT_CBW_Decode(pdev);
break;
case USBD_BOT_DATA_OUT:
if (SCSI_ProcessCmd(pdev, hmsc->cbw.bLUN, &hmsc->cbw.CB[0]) < 0) {
MSC_BOT_SendCSW(pdev, USBD_CSW_CMD_FAILED);
}
break;
default:
break;
}
}
/**
* @brief MSC_BOT_CBW_Decode
* Decode the CBW command and set the BOT state machine accordingly
* @param pdev: device instance
* @retval None
*/
static void MSC_BOT_CBW_Decode(USBD_HandleTypeDef *pdev)
{
USBD_MSC_BOT_HandleTypeDef *hmsc =
(USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
if (hmsc == NULL) {
return;
}
hmsc->csw.dTag = hmsc->cbw.dTag;
hmsc->csw.dDataResidue = hmsc->cbw.dDataLength;
if ((USBD_LL_GetRxDataSize(pdev, MSCOutEpAdd) != USBD_BOT_CBW_LENGTH) ||
(hmsc->cbw.dSignature != USBD_BOT_CBW_SIGNATURE) ||
(hmsc->cbw.bLUN > 1U) || (hmsc->cbw.bCBLength < 1U) ||
(hmsc->cbw.bCBLength > 16U)) {
SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB);
hmsc->bot_status = USBD_BOT_STATUS_ERROR;
MSC_BOT_Abort(pdev);
} else {
if (SCSI_ProcessCmd(pdev, hmsc->cbw.bLUN, &hmsc->cbw.CB[0]) < 0) {
// if (hmsc->bot_state == USBD_BOT_NO_DATA)
// {
// MSC_BOT_SendCSW(pdev, USBD_CSW_CMD_FAILED);
// }
// else
{
MSC_BOT_Abort(pdev);
}
}
/* Burst xfer handled internally */
else if ((hmsc->bot_state != USBD_BOT_DATA_IN) &&
(hmsc->bot_state != USBD_BOT_DATA_OUT) &&
(hmsc->bot_state != USBD_BOT_LAST_DATA_IN)) {
if (hmsc->bot_data_length > 0U) {
MSC_BOT_SendData(pdev, hmsc->bot_data, hmsc->bot_data_length);
} else if (hmsc->bot_data_length == 0U) {
MSC_BOT_SendCSW(pdev, USBD_CSW_CMD_PASSED);
} else {
MSC_BOT_Abort(pdev);
}
}
// else
// {
// return;
// }
}
}
/**
* @brief MSC_BOT_SendData
* Send the requested data
* @param pdev: device instance
* @param buf: pointer to data buffer
* @param len: Data Length
* @retval None
*/
static void MSC_BOT_SendData(USBD_HandleTypeDef *pdev, uint8_t *pbuf,
uint32_t len)
{
USBD_MSC_BOT_HandleTypeDef *hmsc =
(USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
uint32_t length;
if (hmsc == NULL) {
return;
}
length = MIN(hmsc->cbw.dDataLength, len);
hmsc->csw.dDataResidue -= len;
hmsc->csw.bStatus = USBD_CSW_CMD_PASSED;
hmsc->bot_state = USBD_BOT_SEND_DATA;
(void)USBD_LL_Transmit(pdev, MSCInEpAdd, pbuf, length);
}
/**
* @brief MSC_BOT_SendCSW
* Send the Command Status Wrapper
* @param pdev: device instance
* @param status : CSW status
* @retval None
*/
void MSC_BOT_SendCSW(USBD_HandleTypeDef *pdev, uint8_t CSW_Status)
{
USBD_MSC_BOT_HandleTypeDef *hmsc =
(USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
if (hmsc == NULL) {
return;
}
hmsc->csw.dSignature = USBD_BOT_CSW_SIGNATURE;
hmsc->csw.bStatus = CSW_Status;
hmsc->bot_state = USBD_BOT_IDLE;
(void)USBD_LL_Transmit(pdev, MSCInEpAdd, (uint8_t *)&hmsc->csw,
USBD_BOT_CSW_LENGTH);
/* Prepare EP to Receive next Cmd */
(void)USBD_LL_PrepareReceive(pdev, MSCOutEpAdd, (uint8_t *)&hmsc->cbw,
USBD_BOT_CBW_LENGTH);
}
/**
* @brief MSC_BOT_Abort
* Abort the current transfer
* @param pdev: device instance
* @retval status
*/
static void MSC_BOT_Abort(USBD_HandleTypeDef *pdev)
{
USBD_MSC_BOT_HandleTypeDef *hmsc =
(USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
if (hmsc == NULL) {
return;
}
if ((hmsc->cbw.bmFlags == 0U) && (hmsc->cbw.dDataLength != 0U) &&
(hmsc->bot_status == USBD_BOT_STATUS_NORMAL)) {
(void)USBD_LL_StallEP(pdev, MSCOutEpAdd);
}
(void)USBD_LL_StallEP(pdev, MSCInEpAdd);
if (hmsc->bot_status == USBD_BOT_STATUS_ERROR) {
(void)USBD_LL_StallEP(pdev, MSCInEpAdd);
(void)USBD_LL_StallEP(pdev, MSCOutEpAdd);
}
}
/**
* @brief MSC_BOT_CplClrFeature
* Complete the clear feature request
* @param pdev: device instance
* @param epnum: endpoint index
* @retval None
*/
void MSC_BOT_CplClrFeature(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
USBD_MSC_BOT_HandleTypeDef *hmsc =
(USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
if (hmsc == NULL) {
return;
}
if (hmsc->bot_status == USBD_BOT_STATUS_ERROR) /* Bad CBW Signature */
{
(void)USBD_LL_StallEP(pdev, MSCInEpAdd);
(void)USBD_LL_StallEP(pdev, MSCOutEpAdd);
} else if (((epnum & 0x80U) == 0x80U) &&
(hmsc->bot_status != USBD_BOT_STATUS_RECOVERY)) {
MSC_BOT_SendCSW(pdev, USBD_CSW_CMD_FAILED);
} else {
return;
}
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,138 @@
/*!
* \file usbd_msc_bot.h
*
* \brief Header for the usbd_msc_bot.c file.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author MCD Application Team
*
* \author ( XinChip ) Alex-J
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_MSC_BOT_H
#define __USBD_MSC_BOT_H
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_core.h"
/*------------------------------------------------------------------------------------
Macros
------------------------------------------- -----------------------------------------*/
/** @defgroup USBD_CORE_Exported_Defines
* @{
*/
#define USBD_BOT_IDLE 0U /* Idle state */
#define USBD_BOT_DATA_OUT 1U /* Data Out state */
#define USBD_BOT_DATA_IN 2U /* Data In state */
#define USBD_BOT_LAST_DATA_IN 3U /* Last Data In Last */
#define USBD_BOT_SEND_DATA 4U /* Send Immediate data */
#define USBD_BOT_NO_DATA 5U /* No data Stage */
#define USBD_BOT_CBW_SIGNATURE 0x43425355U
#define USBD_BOT_CSW_SIGNATURE 0x53425355U
#define USBD_BOT_CBW_LENGTH 31U
#define USBD_BOT_CSW_LENGTH 13U
#define USBD_BOT_MAX_DATA 256U
/* CSW Status Definitions */
#define USBD_CSW_CMD_PASSED 0x00U
#define USBD_CSW_CMD_FAILED 0x01U
#define USBD_CSW_PHASE_ERROR 0x02U
/* BOT Status */
#define USBD_BOT_STATUS_NORMAL 0U
#define USBD_BOT_STATUS_RECOVERY 1U
#define USBD_BOT_STATUS_ERROR 2U
#define USBD_DIR_IN 0U
#define USBD_DIR_OUT 1U
#define USBD_BOTH_DIR 2U
/**
* @}
*/
/*------------------------------------------------------------------------------------
Typedef
------------------------------------------- -----------------------------------------*/
/** @defgroup MSC_CORE_Private_TypesDefinitions
* @{
*/
typedef struct
{
uint32_t dSignature;
uint32_t dTag;
uint32_t dDataLength;
uint8_t bmFlags;
uint8_t bLUN;
uint8_t bCBLength;
uint8_t CB[16];
uint8_t ReservedForAlign;
} USBD_MSC_BOT_CBWTypeDef;
typedef struct
{
uint32_t dSignature;
uint32_t dTag;
uint32_t dDataResidue;
uint8_t bStatus;
uint8_t ReservedForAlign[3];
} USBD_MSC_BOT_CSWTypeDef;
/**
* @}
*/
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
/** @defgroup USBD_CORE_Exported_FunctionsPrototypes
* @{
*/
void MSC_BOT_Init(USBD_HandleTypeDef *pdev);
void MSC_BOT_Reset(USBD_HandleTypeDef *pdev);
void MSC_BOT_DeInit(USBD_HandleTypeDef *pdev);
void MSC_BOT_DataIn(USBD_HandleTypeDef *pdev,
uint8_t epnum);
void MSC_BOT_DataOut(USBD_HandleTypeDef *pdev,
uint8_t epnum);
void MSC_BOT_SendCSW(USBD_HandleTypeDef *pdev,
uint8_t CSW_Status);
void MSC_BOT_CplClrFeature(USBD_HandleTypeDef *pdev,
uint8_t epnum);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_MSC_BOT_H */
@@ -0,0 +1,58 @@
/*!
* \file usbd_msc_data.c
*
* \brief This file provides all the vital inquiry pages and sense data.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author MCD Application Team
*
* \author ( XinChip ) Alex-J
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_msc_data.h"
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
/* USB Mass storage Page 0 Inquiry Data */
uint8_t MSC_Page00_Inquiry_Data[LENGTH_INQUIRY_PAGE00] = {
0x00, 0x00, 0x00, (LENGTH_INQUIRY_PAGE00 - 4U),
0x00, 0x80
// 0x83 //alex revise
};
/* USB Mass storage VPD Page 0x80 Inquiry Data for Unit Serial Number */
uint8_t MSC_Page80_Inquiry_Data[LENGTH_INQUIRY_PAGE80] = {
0x00, 0x80, 0x00, LENGTH_INQUIRY_PAGE80,
0x20, /* Put Product Serial number */
0x20, 0x20, 0x20};
/* USB Mass storage sense 6 Data */
uint8_t MSC_Mode_Sense6_data[MODE_SENSE6_LEN] = {
0x22, 0x00, 0x00, 0x00, 0x08, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
/* USB Mass storage sense 10 Data */
uint8_t MSC_Mode_Sense10_data[MODE_SENSE10_LEN] = {
0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
/**
* @}
*/
@@ -0,0 +1,74 @@
/*!
* \file usbd_msc_data.h
*
* \brief Header for the usbd_msc_data.c file.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author MCD Application Team
*
* \author ( XinChip ) Alex-J
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_MSC_DATA_H
#define __USBD_MSC_DATA_H
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_conf.h"
/*------------------------------------------------------------------------------------
Macros
------------------------------------------- -----------------------------------------*/
/** @defgroup USB_INFO_Exported_Defines
* @{
*/
#define MODE_SENSE6_LEN 0x17U
#define MODE_SENSE10_LEN 0x1BU
#define LENGTH_INQUIRY_PAGE00 0x06U //0x07U//0x06U alex revise
#define LENGTH_INQUIRY_PAGE80 0x08U
#define LENGTH_FORMAT_CAPACITIES 0x14U
/**
* @}
*/
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
/** @defgroup USBD_INFO_Exported_Variables
* @{
*/
extern uint8_t MSC_Page00_Inquiry_Data[LENGTH_INQUIRY_PAGE00];
extern uint8_t MSC_Page80_Inquiry_Data[LENGTH_INQUIRY_PAGE80];
extern uint8_t MSC_Mode_Sense6_data[MODE_SENSE6_LEN];
extern uint8_t MSC_Mode_Sense10_data[MODE_SENSE10_LEN];
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_MSC_DATA_H */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,163 @@
/*!
* \file usbd_msc_scsi.h
*
* \brief Header for the usbd_msc_scsi.c file.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author MCD Application Team
*
* \author ( XinChip ) Alex-J
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_MSC_SCSI_H
#define __USBD_MSC_SCSI_H
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_def.h"
/*------------------------------------------------------------------------------------
Macros
------------------------------------------- -----------------------------------------*/
/** @defgroup USBD_SCSI_Exported_Defines
* @{
*/
#define SENSE_LIST_DEEPTH 4U
/* SCSI Commands */
#define SCSI_FORMAT_UNIT 0x04U
#define SCSI_INQUIRY 0x12U
#define SCSI_MODE_SELECT6 0x15U
#define SCSI_MODE_SELECT10 0x55U
#define SCSI_MODE_SENSE6 0x1AU
#define SCSI_MODE_SENSE10 0x5AU
#define SCSI_ALLOW_MEDIUM_REMOVAL 0x1EU
#define SCSI_READ6 0x08U
#define SCSI_READ10 0x28U
#define SCSI_READ12 0xA8U
#define SCSI_READ16 0x88U
#define SCSI_READ_CAPACITY10 0x25U
#define SCSI_READ_CAPACITY16 0x9EU
#define SCSI_REQUEST_SENSE 0x03U
#define SCSI_START_STOP_UNIT 0x1BU
#define SCSI_TEST_UNIT_READY 0x00U
#define SCSI_WRITE6 0x0AU
#define SCSI_WRITE10 0x2AU
#define SCSI_WRITE12 0xAAU
#define SCSI_WRITE16 0x8AU
#define SCSI_VERIFY10 0x2FU
#define SCSI_VERIFY12 0xAFU
#define SCSI_VERIFY16 0x8FU
#define SCSI_SEND_DIAGNOSTIC 0x1DU
#define SCSI_READ_FORMAT_CAPACITIES 0x23U
#define NO_SENSE 0U
#define RECOVERED_ERROR 1U
#define NOT_READY 2U
#define MEDIUM_ERROR 3U
#define HARDWARE_ERROR 4U
#define ILLEGAL_REQUEST 5U
#define UNIT_ATTENTION 6U
#define DATA_PROTECT 7U
#define BLANK_CHECK 8U
#define VENDOR_SPECIFIC 9U
#define COPY_ABORTED 10U
#define ABORTED_COMMAND 11U
#define VOLUME_OVERFLOW 13U
#define MISCOMPARE 14U
#define INVALID_CDB 0x20U
#define INVALID_FIELED_IN_COMMAND 0x24U
#define PARAMETER_LIST_LENGTH_ERROR 0x1AU
#define INVALID_FIELD_IN_PARAMETER_LIST 0x26U
#define ADDRESS_OUT_OF_RANGE 0x21U
#define MEDIUM_NOT_PRESENT 0x3AU
#define MEDIUM_HAVE_CHANGED 0x28U
#define WRITE_PROTECTED 0x27U
#define UNRECOVERED_READ_ERROR 0x11U
#define WRITE_FAULT 0x03U
#define READ_FORMAT_CAPACITY_DATA_LEN 0x0CU
#define READ_CAPACITY10_DATA_LEN 0x08U
#define REQUEST_SENSE_DATA_LEN 0x12U
#define STANDARD_INQUIRY_DATA_LEN 0x24U
#define BLKVFY 0x04U
#define SCSI_MEDIUM_UNLOCKED 0x00U
#define SCSI_MEDIUM_LOCKED 0x01U
#define SCSI_MEDIUM_EJECTED 0x02U
/**
* @}
*/
/*------------------------------------------------------------------------------------
Typedef
------------------------------------------- -----------------------------------------*/
/** @defgroup USBD_SCSI_Exported_TypesDefinitions
* @{
*/
typedef struct _SENSE_ITEM
{
uint8_t Skey;
union
{
struct _ASCs
{
uint8_t ASC;
uint8_t ASCQ;
} b;
uint8_t ASC;
uint8_t *pData;
} w;
} USBD_SCSI_SenseTypeDef;
/**
* @}
*/
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
/** @defgroup USBD_SCSI_Exported_FunctionsPrototype
* @{
*/
int8_t SCSI_ProcessCmd(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *cmd);
void SCSI_SenseCode(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t sKey,
uint8_t ASC);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_MSC_SCSI_H */
@@ -0,0 +1,732 @@
/*!
* \file usbd_core.c
*
* \brief This file provides all the USBD core functions.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author MCD Application Team
*
* \author ( XinChip ) Alex-J
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_core.h"
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
/**
* @brief USBD_Init
* Initializes the device stack and load the class driver
* @param pdev: device instance
* @param pdesc: Descriptor structure address
* @param id: Low level core index
* @retval None
*/
USBD_StatusTypeDef USBD_Init(USBD_HandleTypeDef *pdev,
USBD_DescriptorsTypeDef *pdesc, uint8_t id)
{
USBD_StatusTypeDef ret;
/* Check whether the USB Host handle is valid */
if (pdev == NULL) {
#if (USBD_DEBUG_LEVEL > 1U)
USBD_ErrLog("Invalid Device handle");
#endif /* (USBD_DEBUG_LEVEL > 1U) */
return USBD_FAIL;
}
/* Unlink previous class*/
pdev->pClass[0] = NULL;
pdev->pUserData[0] = NULL;
pdev->pConfDesc = NULL;
/* Assign USBD Descriptors */
if (pdesc != NULL) {
pdev->pDesc = pdesc;
}
/* Set Device initial State */
pdev->dev_state = USBD_STATE_DEFAULT;
pdev->id = id;
/* Initialize low level driver */
ret = USBD_LL_Init(pdev);
return ret;
}
/**
* @brief USBD_DeInit
* Re-Initialize the device library
* @param pdev: device instance
* @retval status: status
*/
USBD_StatusTypeDef USBD_DeInit(USBD_HandleTypeDef *pdev)
{
USBD_StatusTypeDef ret;
/* Disconnect the USB Device */
(void)USBD_LL_Stop(pdev);
/* Set Default State */
pdev->dev_state = USBD_STATE_DEFAULT;
/* Free Class Resources */
if (pdev->pClass[0] != NULL) {
pdev->pClass[0]->DeInit(pdev, (uint8_t)pdev->dev_config);
}
pdev->pUserData[0] = NULL;
/* Free Device descriptors resources */
pdev->pDesc = NULL;
pdev->pConfDesc = NULL;
/* DeInitialize low level driver */
ret = USBD_LL_DeInit(pdev);
return ret;
}
/**
* @brief USBD_RegisterClass
* Link class driver to Device Core.
* @param pDevice : Device Handle
* @param pclass: Class handle
* @retval USBD Status
*/
USBD_StatusTypeDef USBD_RegisterClass(USBD_HandleTypeDef *pdev,
USBD_ClassTypeDef *pclass)
{
uint16_t len = 0U;
if (pclass == NULL) {
#if (USBD_DEBUG_LEVEL > 1U)
USBD_ErrLog("Invalid Class handle");
#endif /* (USBD_DEBUG_LEVEL > 1U) */
return USBD_FAIL;
}
/* link the class to the USB Device handle */
pdev->pClass[0] = pclass;
/* Get Device Configuration Descriptor */
if (pdev->pClass[pdev->classId]->GetFSConfigDescriptor != NULL) {
pdev->pConfDesc =
(void *)pdev->pClass[pdev->classId]->GetFSConfigDescriptor(&len);
}
/* Increment the NumClasses */
pdev->NumClasses++;
return USBD_OK;
}
/**
* @brief USBD_Start
* Start the USB Device Core.
* @param pdev: Device Handle
* @retval USBD Status
*/
USBD_StatusTypeDef USBD_Start(USBD_HandleTypeDef *pdev)
{
/* Start the low level driver */
return USBD_LL_Start(pdev);
}
/**
* @brief USBD_Stop
* Stop the USB Device Core.
* @param pdev: Device Handle
* @retval USBD Status
*/
USBD_StatusTypeDef USBD_Stop(USBD_HandleTypeDef *pdev)
{
/* Disconnect USB Device */
(void)USBD_LL_Stop(pdev);
if (pdev->pClass[0] != NULL) {
(void)pdev->pClass[0]->DeInit(pdev, (uint8_t)pdev->dev_config);
}
return USBD_OK;
}
/**
* @brief USBD_RunTestMode
* Launch test mode process
* @param pdev: device instance
* @retval status
*/
USBD_StatusTypeDef USBD_RunTestMode(USBD_HandleTypeDef *pdev)
{
#ifdef USBD_HS_TESTMODE_ENABLE
USBD_StatusTypeDef ret;
/* Run USB HS test mode */
ret = USBD_LL_SetTestMode(pdev, pdev->dev_test_mode);
return ret;
#else
/* Prevent unused argument compilation warning */
UNUSED(pdev);
return USBD_OK;
#endif /* USBD_HS_TESTMODE_ENABLE */
}
/**
* @brief USBD_SetClassConfig
* Configure device and start the interface
* @param pdev: device instance
* @param cfgidx: configuration index
* @retval status
*/
USBD_StatusTypeDef USBD_SetClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
USBD_StatusTypeDef ret = USBD_OK;
if (pdev->pClass[0] != NULL) {
/* Set configuration and Start the Class */
ret = (USBD_StatusTypeDef)pdev->pClass[0]->Init(pdev, cfgidx);
}
return ret;
}
/**
* @brief USBD_ClrClassConfig
* Clear current configuration
* @param pdev: device instance
* @param cfgidx: configuration index
* @retval status: USBD_StatusTypeDef
*/
USBD_StatusTypeDef USBD_ClrClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
USBD_StatusTypeDef ret = USBD_OK;
/* Clear configuration and De-initialize the Class process */
if (pdev->pClass[0]->DeInit(pdev, cfgidx) != 0U) {
ret = USBD_FAIL;
}
return ret;
}
/**
* @brief USBD_LL_SetupStage
* Handle the setup stage
* @param pdev: device instance
* @retval status
*/
USBD_StatusTypeDef USBD_LL_SetupStage(USBD_HandleTypeDef *pdev, uint8_t *psetup)
{
USBD_StatusTypeDef ret;
USBD_ParseSetupRequest(&pdev->request, psetup);
pdev->ep0_state = USBD_EP0_SETUP;
pdev->ep0_data_len = pdev->request.wLength;
switch (pdev->request.bmRequest & 0x1FU) {
case USB_REQ_RECIPIENT_DEVICE:
ret = USBD_StdDevReq(pdev, &pdev->request);
break;
case USB_REQ_RECIPIENT_INTERFACE:
ret = USBD_StdItfReq(pdev, &pdev->request);
break;
case USB_REQ_RECIPIENT_ENDPOINT:
ret = USBD_StdEPReq(pdev, &pdev->request);
break;
default:
ret = USBD_LL_StallEP(pdev, (pdev->request.bmRequest & 0x80U));
break;
}
return ret;
}
/**
* @brief USBD_LL_DataOutStage
* Handle data OUT stage
* @param pdev: device instance
* @param epnum: endpoint index
* @param pdata: data pointer
* @retval status
*/
USBD_StatusTypeDef USBD_LL_DataOutStage(USBD_HandleTypeDef *pdev, uint8_t epnum,
uint8_t *pdata)
{
USBD_EndpointTypeDef *pep;
USBD_StatusTypeDef ret = USBD_OK;
uint8_t idx;
if (epnum == 0U) {
pep = &pdev->ep_out[0];
if (pdev->ep0_state == USBD_EP0_DATA_OUT) {
if (pep->rem_length > pep->maxpacket) {
pep->rem_length -= pep->maxpacket;
(void)USBD_CtlContinueRx(pdev, pdata,
MIN(pep->rem_length, pep->maxpacket));
} else {
// alex revise
/* Find the class ID relative to the current request */
switch (pdev->request.bmRequest & 0x1FU) {
case USB_REQ_RECIPIENT_DEVICE:
/* Device requests must be managed by the first instantiated
class (or duplicated by all classes for simplicity) */
idx = 0U;
break;
case USB_REQ_RECIPIENT_INTERFACE:
idx = USBD_CoreFindIF(pdev, LOBYTE(pdev->request.wIndex));
break;
case USB_REQ_RECIPIENT_ENDPOINT:
idx = USBD_CoreFindEP(pdev, LOBYTE(pdev->request.wIndex));
break;
default:
/* Back to the first class in case of doubt */
idx = 0U;
break;
}
if (idx < USBD_MAX_SUPPORTED_CLASS) {
/* Setup the class ID and route the request to the relative
* class function */
if (pdev->dev_state == USBD_STATE_CONFIGURED) {
if (pdev->pClass[idx]->EP0_RxReady != NULL) {
pdev->classId = idx;
pdev->pClass[idx]->EP0_RxReady(pdev);
}
}
}
(void)USBD_CtlSendStatus(pdev);
}
} else {
#if 0
if (pdev->ep0_state == USBD_EP0_STATUS_OUT)
{
/*
* STATUS PHASE completed, update ep0_state to idle
*/
pdev->ep0_state = USBD_EP0_IDLE;
(void)USBD_LL_StallEP(pdev, 0U);
}
#endif
}
} else {
/* Get the class index relative to this interface */
idx = USBD_CoreFindEP(pdev, (epnum & 0x7FU));
if (((uint16_t)idx != 0xFFU) && (idx < USBD_MAX_SUPPORTED_CLASS)) {
/* Call the class data out function to manage the request */
if (pdev->dev_state == USBD_STATE_CONFIGURED) {
if (pdev->pClass[idx]->DataOut != NULL) {
pdev->classId = idx;
ret = (USBD_StatusTypeDef)pdev->pClass[idx]->DataOut(pdev,
epnum);
}
}
if (ret != USBD_OK) {
return ret;
}
}
}
return USBD_OK;
}
/**
* @brief USBD_LL_DataInStage
* Handle data in stage
* @param pdev: device instance
* @param epnum: endpoint index
* @retval status
*/
USBD_StatusTypeDef USBD_LL_DataInStage(USBD_HandleTypeDef *pdev, uint8_t epnum,
uint8_t *pdata)
{
USBD_EndpointTypeDef *pep;
USBD_StatusTypeDef ret;
uint8_t idx;
if (epnum == 0U) {
pep = &pdev->ep_in[0];
if (pdev->ep0_state == USBD_EP0_DATA_IN) {
if (pep->rem_length > pep->maxpacket) {
pep->rem_length -= pep->maxpacket;
(void)USBD_CtlContinueSendData(pdev, pdata, pep->rem_length);
/* Prepare endpoint for premature end of transfer */
// (void)USBD_LL_PrepareReceive(pdev, 0U, NULL, 0U);
} else {
/* last packet is MPS multiple, so send ZLP packet */
if ((pep->total_length % pep->maxpacket == 0) &&
(pep->total_length >= pep->maxpacket) &&
(pep->total_length < pdev->ep0_data_len)) {
(void)USBD_CtlContinueSendData(pdev, NULL, 0U);
pdev->ep0_data_len = 0U;
/* Prepare endpoint for premature end of transfer */
// (void)USBD_LL_PrepareReceive(pdev, 0U, NULL,
// 0U);
} else {
// if (pdev->dev_state == USBD_STATE_CONFIGURED)
// {
// if (pdev->pClass[0]->EP0_TxSent != NULL)
// {
// pdev->classId = 0U;
// pdev->pClass[0]->EP0_TxSent(pdev);
// }
// }
// (void)USBD_LL_StallEP(pdev, 0x80U);
(void)USBD_CtlReceiveStatus(pdev);
}
}
} else {
#if 0
if ((pdev->ep0_state == USBD_EP0_STATUS_IN) ||
(pdev->ep0_state == USBD_EP0_IDLE))
{
(void)USBD_LL_StallEP(pdev, 0x80U);
}
#endif
}
if (pdev->dev_test_mode != 0U) {
(void)USBD_RunTestMode(pdev);
pdev->dev_test_mode = 0U;
}
} else {
/* Get the class index relative to this interface */
idx = USBD_CoreFindEP(pdev, ((uint8_t)epnum | 0x80U));
if (((uint16_t)idx != 0xFFU) && (idx < USBD_MAX_SUPPORTED_CLASS)) {
/* Call the class data out function to manage the request */
if (pdev->dev_state == USBD_STATE_CONFIGURED) {
if (pdev->pClass[idx]->DataIn != NULL) {
pdev->classId = idx;
ret = (USBD_StatusTypeDef)pdev->pClass[idx]->DataIn(pdev,
epnum);
if (ret != USBD_OK) {
return ret;
}
}
}
}
}
return USBD_OK;
}
/**
* @brief USBD_LL_Reset
* Handle Reset event
* @param pdev: device instance
* @retval status
*/
USBD_StatusTypeDef USBD_LL_Reset(USBD_HandleTypeDef *pdev)
{
USBD_StatusTypeDef ret = USBD_OK;
/* Upon Reset call user call back */
pdev->dev_state = USBD_STATE_DEFAULT;
pdev->ep0_state = USBD_EP0_IDLE;
pdev->dev_config = 0U;
pdev->dev_remote_wakeup = 0U;
pdev->dev_test_mode = 0U;
if (pdev->pClass[0] != NULL) {
if (pdev->pClass[0]->DeInit != NULL) {
if (pdev->pClass[0]->DeInit(pdev, (uint8_t)pdev->dev_config) !=
USBD_OK) {
ret = USBD_FAIL;
}
}
}
/* Open EP0 OUT */
(void)USBD_LL_OpenEP(pdev, 0x00U, USBD_EP_TYPE_CTRL, USB_MAX_EP0_SIZE);
pdev->ep_out[0x00U & 0xFU].is_used = 1U;
pdev->ep_out[0].maxpacket = USB_MAX_EP0_SIZE;
/* Open EP0 IN */
(void)USBD_LL_OpenEP(pdev, 0x80U, USBD_EP_TYPE_CTRL, USB_MAX_EP0_SIZE);
pdev->ep_in[0x80U & 0xFU].is_used = 1U;
pdev->ep_in[0].maxpacket = USB_MAX_EP0_SIZE;
return ret;
}
/**
* @brief USBD_LL_SetSpeed
* Handle Reset event
* @param pdev: device instance
* @retval status
*/
USBD_StatusTypeDef USBD_LL_SetSpeed(USBD_HandleTypeDef *pdev,
USBD_SpeedTypeDef speed)
{
pdev->dev_speed = speed;
return USBD_OK;
}
/**
* @brief USBD_LL_Suspend
* Handle Suspend event
* @param pdev: device instance
* @retval status
*/
USBD_StatusTypeDef USBD_LL_Suspend(USBD_HandleTypeDef *pdev)
{
pdev->dev_old_state = pdev->dev_state;
pdev->dev_state = USBD_STATE_SUSPENDED;
return USBD_OK;
}
/**
* @brief USBD_LL_Resume
* Handle Resume event
* @param pdev: device instance
* @retval status
*/
USBD_StatusTypeDef USBD_LL_Resume(USBD_HandleTypeDef *pdev)
{
if (pdev->dev_state == USBD_STATE_SUSPENDED) {
pdev->dev_state = pdev->dev_old_state;
}
return USBD_OK;
}
/**
* @brief USBD_LL_SOF
* Handle SOF event
* @param pdev: device instance
* @retval status
*/
USBD_StatusTypeDef USBD_LL_SOF(USBD_HandleTypeDef *pdev)
{
/* The SOF event can be distributed for all classes that support it */
if (pdev->dev_state == USBD_STATE_CONFIGURED) {
if (pdev->pClass[0] != NULL) {
if (pdev->pClass[0]->SOF != NULL) {
(void)pdev->pClass[0]->SOF(pdev);
}
}
}
return USBD_OK;
}
/**
* @brief USBD_LL_IsoINIncomplete
* Handle iso in incomplete event
* @param pdev: device instance
* @retval status
*/
USBD_StatusTypeDef USBD_LL_IsoINIncomplete(USBD_HandleTypeDef *pdev,
uint8_t epnum)
{
if (pdev->pClass[pdev->classId] == NULL) {
return USBD_FAIL;
}
if (pdev->dev_state == USBD_STATE_CONFIGURED) {
if (pdev->pClass[pdev->classId]->IsoINIncomplete != NULL) {
(void)pdev->pClass[pdev->classId]->IsoINIncomplete(pdev, epnum);
}
}
return USBD_OK;
}
/**
* @brief USBD_LL_IsoOUTIncomplete
* Handle iso out incomplete event
* @param pdev: device instance
* @retval status
*/
USBD_StatusTypeDef USBD_LL_IsoOUTIncomplete(USBD_HandleTypeDef *pdev,
uint8_t epnum)
{
if (pdev->pClass[pdev->classId] == NULL) {
return USBD_FAIL;
}
if (pdev->dev_state == USBD_STATE_CONFIGURED) {
if (pdev->pClass[pdev->classId]->IsoOUTIncomplete != NULL) {
(void)pdev->pClass[pdev->classId]->IsoOUTIncomplete(pdev, epnum);
}
}
return USBD_OK;
}
/**
* @brief USBD_LL_DevConnected
* Handle device connection event
* @param pdev: device instance
* @retval status
*/
USBD_StatusTypeDef USBD_LL_DevConnected(USBD_HandleTypeDef *pdev)
{
/* Prevent unused argument compilation warning */
UNUSED(pdev);
return USBD_OK;
}
/**
* @brief USBD_LL_DevDisconnected
* Handle device disconnection event
* @param pdev: device instance
* @retval status
*/
USBD_StatusTypeDef USBD_LL_DevDisconnected(USBD_HandleTypeDef *pdev)
{
USBD_StatusTypeDef ret = USBD_OK;
/* Free Class Resources */
pdev->dev_state = USBD_STATE_DEFAULT;
if (pdev->pClass[0] != NULL) {
if (pdev->pClass[0]->DeInit(pdev, (uint8_t)pdev->dev_config) != 0U) {
ret = USBD_FAIL;
}
}
return ret;
}
/**
* @brief USBD_CoreFindIF
* return the class index relative to the selected interface
* @param pdev: device instance
* @param index : selected interface number
* @retval index of the class using the selected interface number. OxFF if no
* class found.
*/
uint8_t USBD_CoreFindIF(USBD_HandleTypeDef *pdev, uint8_t index)
{
UNUSED(pdev);
UNUSED(index);
return 0x00U;
}
/**
* @brief USBD_CoreFindEP
* return the class index relative to the selected endpoint
* @param pdev: device instance
* @param index : selected endpoint number
* @retval index of the class using the selected endpoint number. 0xFF if no
* class found.
*/
uint8_t USBD_CoreFindEP(USBD_HandleTypeDef *pdev, uint8_t index)
{
UNUSED(pdev);
UNUSED(index);
return 0x00U;
}
/**
* @brief USBD_GetEpDesc
* This function return the Endpoint descriptor
* @param pdev: device instance
* @param pConfDesc: pointer to Bos descriptor
* @param EpAddr: endpoint address
* @retval pointer to video endpoint descriptor
*/
void *USBD_GetEpDesc(uint8_t *pConfDesc, uint8_t EpAddr)
{
USBD_DescHeaderTypeDef *pdesc = (USBD_DescHeaderTypeDef *)(void *)pConfDesc;
USBD_ConfigDescTypeDef *desc = (USBD_ConfigDescTypeDef *)(void *)pConfDesc;
USBD_EpDescTypeDef *pEpDesc = NULL;
uint16_t ptr;
if (desc->wTotalLength > desc->bLength) {
ptr = desc->bLength;
while (ptr < desc->wTotalLength) {
pdesc = USBD_GetNextDesc((uint8_t *)pdesc, &ptr);
if (pdesc->bDescriptorType == USB_DESC_TYPE_ENDPOINT) {
pEpDesc = (USBD_EpDescTypeDef *)(void *)pdesc;
if (pEpDesc->bEndpointAddress == EpAddr) {
break;
} else {
pEpDesc = NULL;
}
}
}
}
return (void *)pEpDesc;
}
/**
* @brief USBD_GetNextDesc
* This function return the next descriptor header
* @param buf: Buffer where the descriptor is available
* @param ptr: data pointer inside the descriptor
* @retval next header
*/
USBD_DescHeaderTypeDef *USBD_GetNextDesc(uint8_t *pbuf, uint16_t *ptr)
{
USBD_DescHeaderTypeDef *pnext = (USBD_DescHeaderTypeDef *)(void *)pbuf;
*ptr += pnext->bLength;
pnext = (USBD_DescHeaderTypeDef *)(void *)(pbuf + pnext->bLength);
return (pnext);
}
/**
* @}
*/
@@ -0,0 +1,130 @@
/*!
* \file usbd_core.h
*
* \brief Header file for usbd_core.c file.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author MCD Application Team
*
* \author ( XinChip ) Alex-J
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_CORE_H
#define __USBD_CORE_H
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_conf.h"
#include "usbd_def.h"
#include "usbd_ioreq.h"
#include "usbd_ctlreq.h"
/*------------------------------------------------------------------------------------
Macros
------------------------------------------- -----------------------------------------*/
/** @defgroup USBD_CORE_Exported_Variables
* @{
*/
#define USBD_SOF USBD_LL_SOF
/**
* @}
*/
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
/** @defgroup USBD_CORE_Exported_FunctionsPrototype
* @{
*/
USBD_StatusTypeDef USBD_Init(USBD_HandleTypeDef *pdev, USBD_DescriptorsTypeDef *pdesc, uint8_t id);
USBD_StatusTypeDef USBD_DeInit(USBD_HandleTypeDef *pdev);
USBD_StatusTypeDef USBD_Start(USBD_HandleTypeDef *pdev);
USBD_StatusTypeDef USBD_Stop(USBD_HandleTypeDef *pdev);
USBD_StatusTypeDef USBD_RegisterClass(USBD_HandleTypeDef *pdev, USBD_ClassTypeDef *pclass);
uint8_t USBD_CoreFindIF(USBD_HandleTypeDef *pdev, uint8_t index);
uint8_t USBD_CoreFindEP(USBD_HandleTypeDef *pdev, uint8_t index);
USBD_StatusTypeDef USBD_RunTestMode(USBD_HandleTypeDef *pdev);
USBD_StatusTypeDef USBD_SetClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
USBD_StatusTypeDef USBD_ClrClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
USBD_StatusTypeDef USBD_LL_SetupStage(USBD_HandleTypeDef *pdev, uint8_t *psetup);
USBD_StatusTypeDef USBD_LL_DataOutStage(USBD_HandleTypeDef *pdev, uint8_t epnum, uint8_t *pdata);
USBD_StatusTypeDef USBD_LL_DataInStage(USBD_HandleTypeDef *pdev, uint8_t epnum, uint8_t *pdata);
USBD_StatusTypeDef USBD_LL_Reset(USBD_HandleTypeDef *pdev);
USBD_StatusTypeDef USBD_LL_SetSpeed(USBD_HandleTypeDef *pdev, USBD_SpeedTypeDef speed);
USBD_StatusTypeDef USBD_LL_Suspend(USBD_HandleTypeDef *pdev);
USBD_StatusTypeDef USBD_LL_Resume(USBD_HandleTypeDef *pdev);
USBD_StatusTypeDef USBD_LL_SOF(USBD_HandleTypeDef *pdev);
USBD_StatusTypeDef USBD_LL_IsoINIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum);
USBD_StatusTypeDef USBD_LL_IsoOUTIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum);
USBD_StatusTypeDef USBD_LL_DevConnected(USBD_HandleTypeDef *pdev);
USBD_StatusTypeDef USBD_LL_DevDisconnected(USBD_HandleTypeDef *pdev);
/* USBD Low Level Driver */
USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev);
USBD_StatusTypeDef USBD_LL_DeInit(USBD_HandleTypeDef *pdev);
USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev);
USBD_StatusTypeDef USBD_LL_Stop(USBD_HandleTypeDef *pdev);
USBD_StatusTypeDef USBD_LL_OpenEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr,
uint8_t ep_type, uint16_t ep_mps);
USBD_StatusTypeDef USBD_LL_CloseEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr);
USBD_StatusTypeDef USBD_LL_FlushEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr);
USBD_StatusTypeDef USBD_LL_StallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr);
USBD_StatusTypeDef USBD_LL_ClearStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr);
USBD_StatusTypeDef USBD_LL_SetUSBAddress(USBD_HandleTypeDef *pdev, uint8_t dev_addr);
USBD_StatusTypeDef USBD_LL_Transmit(USBD_HandleTypeDef *pdev, uint8_t ep_addr,
uint8_t *pbuf, uint32_t size);
USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev, uint8_t ep_addr,
uint8_t *pbuf, uint32_t size);
#ifdef USBD_HS_TESTMODE_ENABLE
USBD_StatusTypeDef USBD_LL_SetTestMode(USBD_HandleTypeDef *pdev, uint8_t testmode);
#endif /* USBD_HS_TESTMODE_ENABLE */
uint8_t USBD_LL_IsStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr);
uint32_t USBD_LL_GetRxDataSize(USBD_HandleTypeDef *pdev, uint8_t ep_addr);
void USBD_LL_Delay(uint32_t Delay);
void *USBD_GetEpDesc(uint8_t *pConfDesc, uint8_t EpAddr);
USBD_DescHeaderTypeDef *USBD_GetNextDesc(uint8_t *pbuf, uint16_t *ptr);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_CORE_H */
@@ -0,0 +1,886 @@
/*!
* \file usbd_ctlreq.c
*
* \brief This file provides the standard USB requests following chapter 9.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author MCD Application Team
*
* \author ( XinChip ) Alex-J
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_ctlreq.h"
#include "usbd_ioreq.h"
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
// volatile uint32_t rec_type = 0;
/*------------------------------------------------------------------------------------
Func Prototype
-------------------------------------------------------------------------------------*/
/** @defgroup USBD_REQ_Private_FunctionPrototypes
* @{
*/
static void USBD_GetDescriptor(USBD_HandleTypeDef *pdev,
USBD_SetupReqTypedef *req);
static void USBD_SetAddress(USBD_HandleTypeDef *pdev,
USBD_SetupReqTypedef *req);
static USBD_StatusTypeDef USBD_SetConfig(USBD_HandleTypeDef *pdev,
USBD_SetupReqTypedef *req);
static void USBD_GetConfig(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
static void USBD_GetStatus(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
static void USBD_SetFeature(USBD_HandleTypeDef *pdev,
USBD_SetupReqTypedef *req);
static void USBD_ClrFeature(USBD_HandleTypeDef *pdev,
USBD_SetupReqTypedef *req);
static uint8_t USBD_GetLen(uint8_t *buf);
/**
* @}
*/
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
/**
* @brief USBD_StdDevReq
* Handle standard usb device requests
* @param pdev: device instance
* @param req: usb request
* @retval status
*/
USBD_StatusTypeDef USBD_StdDevReq(USBD_HandleTypeDef *pdev,
USBD_SetupReqTypedef *req)
{
USBD_StatusTypeDef ret = USBD_OK;
switch (req->bmRequest & USB_REQ_TYPE_MASK) {
case USB_REQ_TYPE_CLASS:
case USB_REQ_TYPE_VENDOR:
ret = (USBD_StatusTypeDef)pdev->pClass[pdev->classId]->Setup(pdev, req);
break;
case USB_REQ_TYPE_STANDARD:
switch (req->bRequest) {
case USB_REQ_GET_DESCRIPTOR:
USBD_GetDescriptor(pdev, req);
break;
case USB_REQ_SET_ADDRESS:
USBD_SetAddress(pdev, req);
break;
case USB_REQ_SET_CONFIGURATION:
ret = USBD_SetConfig(pdev, req);
break;
case USB_REQ_GET_CONFIGURATION:
USBD_GetConfig(pdev, req);
break;
case USB_REQ_GET_STATUS:
USBD_GetStatus(pdev, req);
break;
case USB_REQ_SET_FEATURE:
USBD_SetFeature(pdev, req);
break;
case USB_REQ_CLEAR_FEATURE:
USBD_ClrFeature(pdev, req);
break;
default:
USBD_CtlError(pdev, req);
break;
}
break;
default:
USBD_CtlError(pdev, req);
break;
}
return ret;
}
/**
* @brief USBD_StdItfReq
* Handle standard usb interface requests
* @param pdev: device instance
* @param req: usb request
* @retval status
*/
USBD_StatusTypeDef USBD_StdItfReq(USBD_HandleTypeDef *pdev,
USBD_SetupReqTypedef *req)
{
USBD_StatusTypeDef ret = USBD_OK;
uint8_t idx;
switch (req->bmRequest & USB_REQ_TYPE_MASK) {
case USB_REQ_TYPE_CLASS:
case USB_REQ_TYPE_VENDOR:
case USB_REQ_TYPE_STANDARD:
switch (pdev->dev_state) {
case USBD_STATE_DEFAULT:
case USBD_STATE_ADDRESSED:
case USBD_STATE_CONFIGURED:
if (LOBYTE(req->wIndex) <= USBD_MAX_NUM_INTERFACES) {
/* Get the class index relative to this interface */
idx = USBD_CoreFindIF(pdev, LOBYTE(req->wIndex));
if (((uint8_t)idx != 0xFFU) &&
(idx < USBD_MAX_SUPPORTED_CLASS)) {
/* Call the class data out function to manage the request */
if (pdev->pClass[idx]->Setup != NULL) {
pdev->classId = idx;
ret = (USBD_StatusTypeDef)(pdev->pClass[idx]->Setup(
pdev, req));
} else {
/* should never reach this condition */
ret = USBD_FAIL;
}
} else {
/* No relative interface found */
ret = USBD_FAIL;
}
if ((req->wLength == 0U) && (ret == USBD_OK)) {
(void)USBD_CtlSendStatus(pdev);
}
} else {
USBD_CtlError(pdev, req);
}
break;
default:
USBD_CtlError(pdev, req);
break;
}
break;
default:
USBD_CtlError(pdev, req);
break;
}
return ret;
}
/**
* @brief USBD_StdEPReq
* Handle standard usb endpoint requests
* @param pdev: device instance
* @param req: usb request
* @retval status
*/
USBD_StatusTypeDef USBD_StdEPReq(USBD_HandleTypeDef *pdev,
USBD_SetupReqTypedef *req)
{
USBD_EndpointTypeDef *pep;
uint8_t ep_addr;
uint8_t idx;
USBD_StatusTypeDef ret = USBD_OK;
ep_addr = LOBYTE(req->wIndex);
switch (req->bmRequest & USB_REQ_TYPE_MASK) {
case USB_REQ_TYPE_CLASS:
case USB_REQ_TYPE_VENDOR:
/* Get the class index relative to this endpoint */
idx = USBD_CoreFindEP(pdev, ep_addr);
if (((uint8_t)idx != 0xFFU) && (idx < USBD_MAX_SUPPORTED_CLASS)) {
pdev->classId = idx;
/* Call the class data out function to manage the request */
if (pdev->pClass[idx]->Setup != NULL) {
ret = (USBD_StatusTypeDef)pdev->pClass[idx]->Setup(pdev, req);
}
}
break;
case USB_REQ_TYPE_STANDARD:
switch (req->bRequest) {
case USB_REQ_SET_FEATURE:
switch (pdev->dev_state) {
case USBD_STATE_ADDRESSED:
if ((ep_addr != 0x00U) && (ep_addr != 0x80U)) {
(void)USBD_LL_StallEP(pdev, ep_addr);
(void)USBD_LL_StallEP(pdev, 0x80U);
} else {
USBD_CtlError(pdev, req);
}
break;
case USBD_STATE_CONFIGURED:
if (req->wValue == USB_FEATURE_EP_HALT) {
if ((ep_addr != 0x00U) && (ep_addr != 0x80U) &&
(req->wLength == 0x00U)) {
(void)USBD_LL_StallEP(pdev, ep_addr);
}
}
(void)USBD_CtlSendStatus(pdev);
break;
default:
USBD_CtlError(pdev, req);
break;
}
break;
case USB_REQ_CLEAR_FEATURE:
switch (pdev->dev_state) {
case USBD_STATE_ADDRESSED:
if ((ep_addr != 0x00U) && (ep_addr != 0x80U)) {
(void)USBD_LL_StallEP(pdev, ep_addr);
(void)USBD_LL_StallEP(pdev, 0x80U);
} else {
USBD_CtlError(pdev, req);
}
break;
case USBD_STATE_CONFIGURED:
if (req->wValue == USB_FEATURE_EP_HALT) {
if ((ep_addr & 0x7FU) != 0x00U) {
(void)USBD_LL_ClearStallEP(pdev, ep_addr);
}
(void)USBD_CtlSendStatus(pdev);
/* Get the class index relative to this interface */
idx = USBD_CoreFindEP(pdev, ep_addr);
if (((uint8_t)idx != 0xFFU) &&
(idx < USBD_MAX_SUPPORTED_CLASS)) {
pdev->classId = idx;
/* Call the class data out function to manage the
* request */
if (pdev->pClass[idx]->Setup != NULL) {
ret = (USBD_StatusTypeDef)(pdev->pClass[idx]->Setup(
pdev, req));
}
}
}
break;
default:
USBD_CtlError(pdev, req);
break;
}
break;
case USB_REQ_GET_STATUS:
switch (pdev->dev_state) {
case USBD_STATE_ADDRESSED:
if ((ep_addr != 0x00U) && (ep_addr != 0x80U)) {
USBD_CtlError(pdev, req);
break;
}
pep = ((ep_addr & 0x80U) == 0x80U)
? &pdev->ep_in[ep_addr & 0x7FU]
: &pdev->ep_out[ep_addr & 0x7FU];
pep->status = 0x0000U;
(void)USBD_CtlSendData(pdev, (uint8_t *)&pep->status, 2U);
break;
case USBD_STATE_CONFIGURED:
if ((ep_addr & 0x80U) == 0x80U) {
if (pdev->ep_in[ep_addr & 0xFU].is_used == 0U) {
USBD_CtlError(pdev, req);
break;
}
} else {
if (pdev->ep_out[ep_addr & 0xFU].is_used == 0U) {
USBD_CtlError(pdev, req);
break;
}
}
pep = ((ep_addr & 0x80U) == 0x80U)
? &pdev->ep_in[ep_addr & 0x7FU]
: &pdev->ep_out[ep_addr & 0x7FU];
if ((ep_addr == 0x00U) || (ep_addr == 0x80U)) {
pep->status = 0x0000U;
} else if (USBD_LL_IsStallEP(pdev, ep_addr) != 0U) {
pep->status = 0x0001U;
} else {
pep->status = 0x0000U;
}
(void)USBD_CtlSendData(pdev, (uint8_t *)&pep->status, 2U);
break;
default:
USBD_CtlError(pdev, req);
break;
}
break;
default:
USBD_CtlError(pdev, req);
break;
}
break;
default:
USBD_CtlError(pdev, req);
break;
}
return ret;
}
/**
* @brief USBD_GetDescriptor
* Handle Get Descriptor requests
* @param pdev: device instance
* @param req: usb request
* @retval status
*/
static void USBD_GetDescriptor(USBD_HandleTypeDef *pdev,
USBD_SetupReqTypedef *req)
{
uint16_t len = 0U;
uint8_t *pbuf = NULL;
uint8_t err = 0U;
switch (req->wValue >> 8) {
#if ((USBD_LPM_ENABLED == 1U) || (USBD_CLASS_BOS_ENABLED == 1U))
case USB_DESC_TYPE_BOS:
if (pdev->pDesc->GetBOSDescriptor != NULL) {
pbuf = pdev->pDesc->GetBOSDescriptor(pdev->dev_speed, &len);
} else {
USBD_CtlError(pdev, req);
err++;
}
break;
#endif /* (USBD_LPM_ENABLED == 1U) || (USBD_CLASS_BOS_ENABLED == 1U) */
case USB_DESC_TYPE_DEVICE:
pbuf = pdev->pDesc->GetDeviceDescriptor(pdev->dev_speed, &len);
// rec_type = DESC_TYPE_DEVICE;
if ((req->wLength == 64) || (pdev->dev_state == USBD_STATE_DEFAULT)) {
// len = 8;
}
break;
case USB_DESC_TYPE_CONFIGURATION:
// if (pdev->dev_speed == USBD_SPEED_HIGH)
// {
// pbuf = (uint8_t
// *)pdev->pClass[0]->GetHSConfigDescriptor(&len); pbuf[1] =
// USB_DESC_TYPE_CONFIGURATION;
// }
// else
{
pbuf = (uint8_t *)pdev->pClass[0]->GetFSConfigDescriptor(&len);
// rec_type = DESC_TYPE_CONFIGURATION;
pbuf[1] = USB_DESC_TYPE_CONFIGURATION;
}
break;
case USB_DESC_TYPE_STRING:
switch ((uint8_t)(req->wValue)) {
case USBD_IDX_LANGID_STR:
if (pdev->pDesc->GetLangIDStrDescriptor != NULL) {
pbuf =
pdev->pDesc->GetLangIDStrDescriptor(pdev->dev_speed, &len);
// rec_type = DESC_TYPE_LANGID_STR;
} else {
USBD_CtlError(pdev, req);
err++;
}
break;
case USBD_IDX_MFC_STR:
if (pdev->pDesc->GetManufacturerStrDescriptor != NULL) {
pbuf = pdev->pDesc->GetManufacturerStrDescriptor(
pdev->dev_speed, &len);
// rec_type = DESC_TYPE_MFC_STR;
} else {
USBD_CtlError(pdev, req);
err++;
}
break;
case USBD_IDX_PRODUCT_STR:
if (pdev->pDesc->GetProductStrDescriptor != NULL) {
pbuf =
pdev->pDesc->GetProductStrDescriptor(pdev->dev_speed, &len);
// rec_type = DESC_TYPE_PRODUCT_STR;
} else {
USBD_CtlError(pdev, req);
err++;
}
break;
case USBD_IDX_SERIAL_STR:
if (pdev->pDesc->GetSerialStrDescriptor != NULL) {
pbuf =
pdev->pDesc->GetSerialStrDescriptor(pdev->dev_speed, &len);
// rec_type = DESC_TYPE_SERIAL_STR;
} else {
USBD_CtlError(pdev, req);
err++;
}
break;
case USBD_IDX_CONFIG_STR:
if (pdev->pDesc->GetConfigurationStrDescriptor != NULL) {
pbuf = pdev->pDesc->GetConfigurationStrDescriptor(
pdev->dev_speed, &len);
// rec_type = DESC_TYPE_CONFIG_STR;
} else {
USBD_CtlError(pdev, req);
err++;
}
break;
case USBD_IDX_INTERFACE_STR:
if (pdev->pDesc->GetInterfaceStrDescriptor != NULL) {
pbuf = pdev->pDesc->GetInterfaceStrDescriptor(pdev->dev_speed,
&len);
// rec_type = DESC_TYPE_INTERFACE_STR;
} else {
USBD_CtlError(pdev, req);
err++;
}
break;
default:
#if (USBD_SUPPORT_USER_STRING_DESC == 1U)
pbuf = NULL;
for (uint32_t idx = 0U; (idx < pdev->NumClasses); idx++) {
if (pdev->pClass[idx]->GetUsrStrDescriptor != NULL) {
pdev->classId = idx;
pbuf = pdev->pClass[idx]->GetUsrStrDescriptor(
pdev, LOBYTE(req->wValue), &len);
if (pbuf == NULL) /* This means that no class recognized the
string index */
{
continue;
} else {
break;
}
}
}
#endif /* USBD_SUPPORT_USER_STRING_DESC */
#if (USBD_CLASS_USER_STRING_DESC == 1U)
if (pdev->pDesc->GetUserStrDescriptor != NULL) {
pbuf = pdev->pDesc->GetUserStrDescriptor(pdev->dev_speed,
(req->wValue), &len);
} else {
USBD_CtlError(pdev, req);
err++;
}
#endif /* USBD_SUPPORT_USER_STRING_DESC */
#if ((USBD_CLASS_USER_STRING_DESC == 0U) && \
(USBD_SUPPORT_USER_STRING_DESC == 0U))
USBD_CtlError(pdev, req);
err++;
#endif /* (USBD_CLASS_USER_STRING_DESC == 0U) && \
(USBD_SUPPORT_USER_STRING_DESC == 0U) */
break;
}
break;
case USB_DESC_TYPE_DEVICE_QUALIFIER:
if (pdev->dev_speed == USBD_SPEED_HIGH) {
pbuf =
(uint8_t *)pdev->pClass[0]->GetDeviceQualifierDescriptor(&len);
// rec_type = DESC_TYPE_DEVICE_QUALIFIER;
} else {
USBD_CtlError(pdev, req);
err++;
}
break;
case USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION:
if (pdev->dev_speed == USBD_SPEED_HIGH) {
pbuf =
(uint8_t *)pdev->pClass[0]->GetOtherSpeedConfigDescriptor(&len);
// rec_type = DESC_TYPE_OTHER_SPEED_CONFIGURATION;
pbuf[1] = USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION;
} else {
USBD_CtlError(pdev, req);
err++;
}
break;
default:
USBD_CtlError(pdev, req);
err++;
break;
}
if (err != 0U) {
// (void)USBD_CtlSendData(pdev, NULL, 0);
return;
}
if (req->wLength != 0U) {
if (len != 0U) {
len = MIN(len, req->wLength);
(void)USBD_CtlSendData(pdev, pbuf, len);
}
// else
// {
// USBD_CtlError(pdev, req);
// }
}
// else
// {
// (void)USBD_CtlSendStatus(pdev);
// }
}
/**
* @brief USBD_SetAddress
* Set device address
* @param pdev: device instance
* @param req: usb request
* @retval status
*/
static void USBD_SetAddress(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
{
uint8_t dev_addr;
if ((req->wIndex == 0U) && (req->wLength == 0U) && (req->wValue < 128U)) {
dev_addr = (uint8_t)(req->wValue) & 0x7FU;
if (pdev->dev_state == USBD_STATE_CONFIGURED) {
USBD_CtlError(pdev, req);
} else {
pdev->dev_address = dev_addr;
(void)USBD_LL_SetUSBAddress(pdev, dev_addr);
(void)USBD_CtlSendStatus(pdev);
if (dev_addr != 0U) {
pdev->dev_state = USBD_STATE_ADDRESSED;
} else {
pdev->dev_state = USBD_STATE_DEFAULT;
}
}
} else {
USBD_CtlError(pdev, req);
}
}
/**
* @brief USBD_SetConfig
* Handle Set device configuration request
* @param pdev: device instance
* @param req: usb request
* @retval status
*/
static USBD_StatusTypeDef USBD_SetConfig(USBD_HandleTypeDef *pdev,
USBD_SetupReqTypedef *req)
{
USBD_StatusTypeDef ret = USBD_OK;
static uint8_t cfgidx;
cfgidx = (uint8_t)(req->wValue);
if (cfgidx > USBD_MAX_NUM_CONFIGURATION) {
USBD_CtlError(pdev, req);
return USBD_FAIL;
}
switch (pdev->dev_state) {
case USBD_STATE_ADDRESSED:
if (cfgidx != 0U) {
pdev->dev_config = cfgidx;
ret = USBD_SetClassConfig(pdev, cfgidx);
if (ret != USBD_OK) {
USBD_CtlError(pdev, req);
pdev->dev_state = USBD_STATE_ADDRESSED;
} else {
(void)USBD_CtlSendStatus(pdev);
pdev->dev_state = USBD_STATE_CONFIGURED;
}
} else {
(void)USBD_CtlSendStatus(pdev);
}
break;
case USBD_STATE_CONFIGURED:
if (cfgidx == 0U) {
pdev->dev_state = USBD_STATE_ADDRESSED;
pdev->dev_config = cfgidx;
(void)USBD_ClrClassConfig(pdev, cfgidx);
(void)USBD_CtlSendStatus(pdev);
} else if (cfgidx != pdev->dev_config) {
/* Clear old configuration */
(void)USBD_ClrClassConfig(pdev, (uint8_t)pdev->dev_config);
/* set new configuration */
pdev->dev_config = cfgidx;
ret = USBD_SetClassConfig(pdev, cfgidx);
if (ret != USBD_OK) {
USBD_CtlError(pdev, req);
(void)USBD_ClrClassConfig(pdev, (uint8_t)pdev->dev_config);
pdev->dev_state = USBD_STATE_ADDRESSED;
} else {
(void)USBD_CtlSendStatus(pdev);
}
} else {
(void)USBD_CtlSendStatus(pdev);
}
break;
default:
USBD_CtlError(pdev, req);
(void)USBD_ClrClassConfig(pdev, cfgidx);
ret = USBD_FAIL;
break;
}
return ret;
}
/**
* @brief USBD_GetConfig
* Handle Get device configuration request
* @param pdev: device instance
* @param req: usb request
* @retval status
*/
static void USBD_GetConfig(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
{
if (req->wLength != 1U) {
USBD_CtlError(pdev, req);
} else {
switch (pdev->dev_state) {
case USBD_STATE_DEFAULT:
case USBD_STATE_ADDRESSED:
pdev->dev_default_config = 0U;
(void)USBD_CtlSendData(pdev, (uint8_t *)&pdev->dev_default_config,
1U);
break;
case USBD_STATE_CONFIGURED:
(void)USBD_CtlSendData(pdev, (uint8_t *)&pdev->dev_config, 1U);
break;
default:
USBD_CtlError(pdev, req);
break;
}
}
}
/**
* @brief USBD_GetStatus
* Handle Get Status request
* @param pdev: device instance
* @param req: usb request
* @retval status
*/
static void USBD_GetStatus(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
{
switch (pdev->dev_state) {
case USBD_STATE_DEFAULT:
case USBD_STATE_ADDRESSED:
case USBD_STATE_CONFIGURED:
if (req->wLength != 0x2U) {
USBD_CtlError(pdev, req);
break;
}
#if (USBD_SELF_POWERED == 1U)
pdev->dev_config_status = USB_CONFIG_SELF_POWERED;
#else
pdev->dev_config_status = 0U;
#endif /* USBD_SELF_POWERED */
if (pdev->dev_remote_wakeup != 0U) {
pdev->dev_config_status |= USB_CONFIG_REMOTE_WAKEUP;
}
(void)USBD_CtlSendData(pdev, (uint8_t *)&pdev->dev_config_status, 2U);
break;
default:
USBD_CtlError(pdev, req);
break;
}
}
/**
* @brief USBD_SetFeature
* Handle Set device feature request
* @param pdev: device instance
* @param req: usb request
* @retval status
*/
static void USBD_SetFeature(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
{
if (req->wValue == USB_FEATURE_REMOTE_WAKEUP) {
pdev->dev_remote_wakeup = 1U;
(void)USBD_CtlSendStatus(pdev);
} else if (req->wValue == USB_FEATURE_TEST_MODE) {
pdev->dev_test_mode = req->wIndex >> 8;
(void)USBD_CtlSendStatus(pdev);
} else {
USBD_CtlError(pdev, req);
}
}
/**
* @brief USBD_ClrFeature
* Handle clear device feature request
* @param pdev: device instance
* @param req: usb request
* @retval status
*/
static void USBD_ClrFeature(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
{
switch (pdev->dev_state) {
case USBD_STATE_DEFAULT:
case USBD_STATE_ADDRESSED:
case USBD_STATE_CONFIGURED:
if (req->wValue == USB_FEATURE_REMOTE_WAKEUP) {
pdev->dev_remote_wakeup = 0U;
(void)USBD_CtlSendStatus(pdev);
}
break;
default:
USBD_CtlError(pdev, req);
break;
}
}
/**
* @brief USBD_ParseSetupRequest
* Copy buffer into setup structure
* @param pdev: device instance
* @param req: usb request
* @retval None
*/
void USBD_ParseSetupRequest(USBD_SetupReqTypedef *req, uint8_t *pdata)
{
uint8_t *pbuff = pdata;
req->bmRequest = *(uint8_t *)(pbuff);
pbuff++;
req->bRequest = *(uint8_t *)(pbuff);
pbuff++;
req->wValue = SWAPBYTE(pbuff);
pbuff++;
pbuff++;
req->wIndex = SWAPBYTE(pbuff);
pbuff++;
pbuff++;
req->wLength = SWAPBYTE(pbuff);
}
/**
* @brief USBD_CtlError
* Handle USB low level Error
* @param pdev: device instance
* @param req: usb request
* @retval None
*/
void USBD_CtlError(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
{
UNUSED(req);
(void)USBD_LL_StallEP(pdev, 0x80U);
(void)USBD_LL_StallEP(pdev, 0U);
// alex revise
(void)USB_EP0_OutStart(pdev->pData, 0, NULL);
// DEBUG("USBD_CtlError\r\n");
// DEBUG("TODO: \r\n");
// DEBUG("\r\n");
}
/**
* @brief USBD_GetString
* Convert Ascii string into unicode one
* @param desc : descriptor buffer
* @param unicode : Formatted string buffer (unicode)
* @param len : descriptor length
* @retval None
*/
void USBD_GetString(uint8_t *desc, uint8_t *unicode, uint16_t *len)
{
uint8_t idx = 0U;
uint8_t *pdesc;
if (desc == NULL) {
return;
}
pdesc = desc;
*len = ((uint16_t)USBD_GetLen(pdesc) * 2U) + 2U;
unicode[idx] = *(uint8_t *)len;
idx++;
unicode[idx] = USB_DESC_TYPE_STRING;
idx++;
while (*pdesc != (uint8_t)'\0') {
unicode[idx] = *pdesc;
pdesc++;
idx++;
unicode[idx] = 0U;
idx++;
}
}
/**
* @brief USBD_GetLen
* return the string length
* @param buf : pointer to the ascii string buffer
* @retval string length
*/
static uint8_t USBD_GetLen(uint8_t *buf)
{
uint8_t len = 0U;
uint8_t *pbuff = buf;
while (*pbuff != (uint8_t)'\0') {
len++;
pbuff++;
}
return len;
}
/**
* @}
*/
@@ -0,0 +1,58 @@
/*!
* \file usbd_ctlreq.h
*
* \brief Header file for the usbd_req.c file
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author MCD Application Team
*
* \author ( XinChip ) Alex-J
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USB_REQUEST_H
#define __USB_REQUEST_H
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_def.h"
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
USBD_StatusTypeDef USBD_StdDevReq(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
USBD_StatusTypeDef USBD_StdItfReq(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
USBD_StatusTypeDef USBD_StdEPReq(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
void USBD_CtlError(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
void USBD_ParseSetupRequest(USBD_SetupReqTypedef *req, uint8_t *pdata);
void USBD_GetString(uint8_t *desc, uint8_t *unicode, uint16_t *len);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USB_REQUEST_H */
@@ -0,0 +1,428 @@
/*!
* \file usbd_def.h
*
* \brief General defines for the usb device library
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author MCD Application Team
*
* \author ( XinChip ) Alex-J
*/
#ifndef __USBD_DEF_H
#define __USBD_DEF_H
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "xc_hal_pcd_np.h"
#include "usbd_conf.h"
/*------------------------------------------------------------------------------------
Macros
------------------------------------------- -----------------------------------------*/
/** @defgroup USB_DEF_Exported_Defines
* @{
*/
#if USB_HID
#define HID_MOUSE 0x01
#define HID_KEYBOARD 0x02
#define HID_CUSTOM 0x04
#define HID_DOUBLE_CUSTOM 0X08
#endif
#if USB_SINGLE_DEVICE
//#define HID_CLASS_MODE HID_MOUSE
#elif USB_COMPOSITE_DEVICE
#endif
#ifndef NULL
#define NULL 0U
#endif /* NULL */
#ifndef USBD_MAX_NUM_CONFIGURATION
#define USBD_MAX_NUM_CONFIGURATION 1U
#endif /* USBD_MAX_NUM_CONFIGURATION */
#ifndef USBD_MAX_SUPPORTED_CLASS
#define USBD_MAX_SUPPORTED_CLASS 1U
#endif /* USBD_MAX_SUPPORTED_CLASS */
#ifndef USBD_MAX_CLASS_ENDPOINTS
#define USBD_MAX_CLASS_ENDPOINTS 5U
#endif /* USBD_MAX_CLASS_ENDPOINTS */
#ifndef USBD_MAX_CLASS_INTERFACES
#define USBD_MAX_CLASS_INTERFACES 5U
#endif /* USBD_MAX_CLASS_INTERFACES */
#ifndef USBD_LPM_ENABLED
#define USBD_LPM_ENABLED 0U
#endif /* USBD_LPM_ENABLED */
#ifndef USBD_SELF_POWERED
#define USBD_SELF_POWERED 1U
#endif /*USBD_SELF_POWERED */
#ifndef USBD_MAX_POWER
#define USBD_MAX_POWER 0x32U /* 100 mA */
#endif /* USBD_MAX_POWER */
#ifndef USBD_SUPPORT_USER_STRING_DESC
#define USBD_SUPPORT_USER_STRING_DESC 0U
#endif /* USBD_SUPPORT_USER_STRING_DESC */
#ifndef USBD_CLASS_USER_STRING_DESC
#define USBD_CLASS_USER_STRING_DESC 0U
#endif /* USBD_CLASS_USER_STRING_DESC */
#define USB_LEN_DEV_QUALIFIER_DESC 0x0AU
#define USB_LEN_DEV_DESC 0x12U
#define USB_LEN_CFG_DESC 0x09U
#define USB_LEN_IF_DESC 0x09U
#define USB_LEN_EP_DESC 0x07U
#define USB_LEN_OTG_DESC 0x03U
#define USB_LEN_LANGID_STR_DESC 0x04U
#define USB_LEN_OTHER_SPEED_DESC_SIZ 0x09U
#define USBD_IDX_LANGID_STR 0x00U
#define USBD_IDX_MFC_STR 0x01U
#define USBD_IDX_PRODUCT_STR 0x02U
#define USBD_IDX_SERIAL_STR 0x03U
#define USBD_IDX_CONFIG_STR 0x04U
#define USBD_IDX_INTERFACE_STR 0x05U
#define USB_REQ_TYPE_STANDARD 0x00U
#define USB_REQ_TYPE_CLASS 0x20U
#define USB_REQ_TYPE_VENDOR 0x40U
#define USB_REQ_TYPE_MASK 0x60U
#define USB_REQ_RECIPIENT_DEVICE 0x00U
#define USB_REQ_RECIPIENT_INTERFACE 0x01U
#define USB_REQ_RECIPIENT_ENDPOINT 0x02U
#define USB_REQ_RECIPIENT_MASK 0x03U
#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
#define USB_DESC_TYPE_DEVICE 0x01U
#define USB_DESC_TYPE_CONFIGURATION 0x02U
#define USB_DESC_TYPE_STRING 0x03U
#define USB_DESC_TYPE_INTERFACE 0x04U
#define USB_DESC_TYPE_ENDPOINT 0x05U
#define USB_DESC_TYPE_DEVICE_QUALIFIER 0x06U
#define USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION 0x07U
#define USB_DESC_TYPE_IAD 0x0BU
#define USB_DESC_TYPE_BOS 0x0FU
#define USB_CONFIG_REMOTE_WAKEUP 0x02U
#define USB_CONFIG_SELF_POWERED 0x01U
#define USB_FEATURE_EP_HALT 0x00U
#define USB_FEATURE_REMOTE_WAKEUP 0x01U
#define USB_FEATURE_TEST_MODE 0x02U
#define USB_DEVICE_CAPABITY_TYPE 0x10U
#define USB_CONF_DESC_SIZE 0x09U
#define USB_IF_DESC_SIZE 0x09U
#define USB_EP_DESC_SIZE 0x07U
#define USB_IAD_DESC_SIZE 0x08U
#define USB_HS_MAX_PACKET_SIZE 512U
#define USB_FS_MAX_PACKET_SIZE 64U
#define USB_MAX_EP0_SIZE 64U
/* Device Status */
#define USBD_STATE_DEFAULT 0x01U
#define USBD_STATE_ADDRESSED 0x02U
#define USBD_STATE_CONFIGURED 0x03U
#define USBD_STATE_SUSPENDED 0x04U
/* EP0 State */
#define USBD_EP0_IDLE 0x00U
#define USBD_EP0_SETUP 0x01U
#define USBD_EP0_DATA_IN 0x02U
#define USBD_EP0_DATA_OUT 0x03U
#define USBD_EP0_STATUS_IN 0x04U
#define USBD_EP0_STATUS_OUT 0x05U
#define USBD_EP0_STALL 0x06U
#define USBD_EP_TYPE_CTRL 0x00U
#define USBD_EP_TYPE_ISOC 0x01U
#define USBD_EP_TYPE_BULK 0x02U
#define USBD_EP_TYPE_INTR 0x03U
#ifndef LOBYTE
#define LOBYTE(x) ((uint8_t)((x) & 0x00FFU))
#endif /* LOBYTE */
#ifndef HIBYTE
#define HIBYTE(x) ((uint8_t)(((x) & 0xFF00U) >> 8U))
#endif /* HIBYTE */
#ifndef MIN
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#endif /* MIN */
#ifndef MAX
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#endif /* MAX */
/*------------------------------------------------------------------------------------
Typedef
------------------------------------------------------------------------------------*/
//typedef enum
//{
// RESET = 0U,
// SET = !RESET
//} FlagStatus, ITStatus;
typedef enum
{
F_DISABLE = 0U,
F_ENABLE = !F_DISABLE
} FunctionalState;
typedef enum
{
SUCCESS = 0U,
ERROR = !SUCCESS
} ErrorStatus;
typedef enum
{
DESC_TYPE_DEVICE = 1,
DESC_TYPE_CONFIGURATION,
DESC_TYPE_LANGID_STR,
DESC_TYPE_MFC_STR,
DESC_TYPE_PRODUCT_STR,
DESC_TYPE_SERIAL_STR,
DESC_TYPE_CONFIG_STR,
DESC_TYPE_INTERFACE_STR,
DESC_TYPE_DEVICE_QUALIFIER,
DESC_TYPE_OTHER_SPEED_CONFIGURATION
} eDescriptor_Idx;
/** @defgroup USBD_DEF_Exported_TypesDefinitions
* @{
*/
typedef struct usb_setup_req
{
uint8_t bmRequest;
uint8_t bRequest;
uint16_t wValue;
uint16_t wIndex;
uint16_t wLength;
} USBD_SetupReqTypedef;
typedef struct
{
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t wTotalLength;
uint8_t bNumInterfaces;
uint8_t bConfigurationValue;
uint8_t iConfiguration;
uint8_t bmAttributes;
uint8_t bMaxPower;
} __PACKED USBD_ConfigDescTypeDef;
typedef struct
{
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t wTotalLength;
uint8_t bNumDeviceCaps;
} USBD_BosDescTypeDef;
typedef struct
{
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bEndpointAddress;
uint8_t bmAttributes;
uint16_t wMaxPacketSize;
uint8_t bInterval;
} __PACKED USBD_EpDescTypeDef;
typedef struct
{
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubType;
} USBD_DescHeaderTypeDef;
struct _USBD_HandleTypeDef;
typedef struct _Device_cb
{
uint8_t (*Init)(struct _USBD_HandleTypeDef *pdev, uint8_t cfgidx);
uint8_t (*DeInit)(struct _USBD_HandleTypeDef *pdev, uint8_t cfgidx);
/* Control Endpoints*/
uint8_t (*Setup)(struct _USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
uint8_t (*EP0_TxSent)(struct _USBD_HandleTypeDef *pdev);
uint8_t (*EP0_RxReady)(struct _USBD_HandleTypeDef *pdev);
/* Class Specific Endpoints*/
uint8_t (*DataIn)(struct _USBD_HandleTypeDef *pdev, uint8_t epnum);
uint8_t (*DataOut)(struct _USBD_HandleTypeDef *pdev, uint8_t epnum);
uint8_t (*SOF)(struct _USBD_HandleTypeDef *pdev);
uint8_t (*IsoINIncomplete)(struct _USBD_HandleTypeDef *pdev, uint8_t epnum);
uint8_t (*IsoOUTIncomplete)(struct _USBD_HandleTypeDef *pdev, uint8_t epnum);
uint8_t *(*GetHSConfigDescriptor)(uint16_t *length);
uint8_t *(*GetFSConfigDescriptor)(uint16_t *length);
uint8_t *(*GetOtherSpeedConfigDescriptor)(uint16_t *length);
uint8_t *(*GetDeviceQualifierDescriptor)(uint16_t *length);
#if (USBD_SUPPORT_USER_STRING_DESC == 1U)
uint8_t *(*GetUsrStrDescriptor)(struct _USBD_HandleTypeDef *pdev, uint8_t index, uint16_t *length);
#endif /* USBD_SUPPORT_USER_STRING_DESC */
} USBD_ClassTypeDef;
/* Following USB Device Speed */
typedef enum
{
USBD_SPEED_HIGH = 0U,
USBD_SPEED_FULL = 1U,
USBD_SPEED_LOW = 2U,
} USBD_SpeedTypeDef;
/* Following USB Device status */
typedef enum
{
USBD_OK = 0U,
USBD_BUSY,
USBD_EMEM,
USBD_FAIL,
} USBD_StatusTypeDef;
/* USB Device descriptors structure */
typedef struct
{
uint8_t *(*GetDeviceDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *(*GetLangIDStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *(*GetManufacturerStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *(*GetProductStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *(*GetSerialStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *(*GetConfigurationStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *(*GetInterfaceStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
#if (USBD_CLASS_USER_STRING_DESC == 1)
uint8_t *(*GetUserStrDescriptor)(USBD_SpeedTypeDef speed, uint8_t idx, uint16_t *length);
#endif /* USBD_CLASS_USER_STRING_DESC */
#if ((USBD_LPM_ENABLED == 1U) || (USBD_CLASS_BOS_ENABLED == 1))
uint8_t *(*GetBOSDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
#endif /* (USBD_LPM_ENABLED == 1U) || (USBD_CLASS_BOS_ENABLED == 1) */
} USBD_DescriptorsTypeDef;
/* USB Device handle structure */
typedef struct
{
uint32_t status;
uint32_t total_length;
uint32_t rem_length;
uint32_t maxpacket;
uint16_t is_used;
uint16_t bInterval;
} USBD_EndpointTypeDef;
/* USB Device handle structure */
typedef struct _USBD_HandleTypeDef
{
uint8_t id;
uint32_t dev_config;
uint32_t dev_default_config;
uint32_t dev_config_status;
USBD_SpeedTypeDef dev_speed;
USBD_EndpointTypeDef ep_in[16];
USBD_EndpointTypeDef ep_out[16];
__IO uint32_t ep0_state;
uint32_t ep0_data_len;
__IO uint8_t dev_state;
__IO uint8_t dev_old_state;
uint8_t dev_address;
uint8_t dev_connection_status;
uint8_t dev_test_mode;
uint32_t dev_remote_wakeup;
uint8_t ConfIdx;
USBD_SetupReqTypedef request;
USBD_DescriptorsTypeDef *pDesc;
USBD_ClassTypeDef *pClass[USBD_MAX_SUPPORTED_CLASS];
void *pClassData;
void *pClassDataCmsit[USBD_MAX_SUPPORTED_CLASS];
void *pUserData[USBD_MAX_SUPPORTED_CLASS];
void *pData;
void *pBosDesc;
void *pConfDesc;
uint32_t classId;
uint32_t NumClasses;
} USBD_HandleTypeDef;
/* USB Device endpoint direction */
typedef enum
{
OUT = 0x00,
IN = 0x80,
} USBD_EPDirectionTypeDef;
typedef enum
{
NETWORK_CONNECTION = 0x00,
RESPONSE_AVAILABLE = 0x01,
CONNECTION_SPEED_CHANGE = 0x2A
} USBD_CDC_NotifCodeTypeDef;
/**
* @}
*/
/** @defgroup USBD_DEF_Exported_Macros
* @{
*/
__STATIC_INLINE uint16_t SWAPBYTE(uint8_t *addr)
{
uint16_t _SwapVal, _Byte1, _Byte2;
uint8_t *_pbuff = addr;
_Byte1 = *(uint8_t *)_pbuff;
_pbuff++;
_Byte2 = *(uint8_t *)_pbuff;
_SwapVal = (_Byte2 << 8) | _Byte1;
return _SwapVal;
}
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
extern PCD_HandleTypeDef hpcd_USB_OTG_FS;
#endif /* __USBD_DEF_H */
@@ -0,0 +1,172 @@
/*!
* \file usbd_ioreq.c
*
* \brief This file provides the IO requests APIs for control endpoints.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author MCD Application Team
*
* \author ( XinChip ) Alex-J
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_ioreq.h"
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
/**
* @brief USBD_CtlSendData
* send data on the ctl pipe
* @param pdev: device instance
* @param buff: pointer to data buffer
* @param len: length of data to be sent
* @retval status
*/
USBD_StatusTypeDef USBD_CtlSendData(USBD_HandleTypeDef *pdev, uint8_t *pbuf,
uint32_t len)
{
/* Set EP0 State */
pdev->ep0_state = USBD_EP0_DATA_IN;
pdev->ep_in[0].total_length = len;
pdev->ep_in[0].rem_length = len;
/* Start the transfer */
(void)USBD_LL_Transmit(pdev, 0x00U, pbuf, len);
return USBD_OK;
}
/**
* @brief USBD_CtlContinueSendData
* continue sending data on the ctl pipe
* @param pdev: device instance
* @param buff: pointer to data buffer
* @param len: length of data to be sent
* @retval status
*/
USBD_StatusTypeDef USBD_CtlContinueSendData(USBD_HandleTypeDef *pdev,
uint8_t *pbuf, uint32_t len)
{
/* Start the next transfer */
(void)USBD_LL_Transmit(pdev, 0x00U, pbuf, len);
return USBD_OK;
}
/**
* @brief USBD_CtlPrepareRx
* receive data on the ctl pipe
* @param pdev: device instance
* @param buff: pointer to data buffer
* @param len: length of data to be received
* @retval status
*/
USBD_StatusTypeDef USBD_CtlPrepareRx(USBD_HandleTypeDef *pdev, uint8_t *pbuf,
uint32_t len)
{
/* Set EP0 State */
pdev->ep0_state = USBD_EP0_DATA_OUT;
pdev->ep_out[0].total_length = len;
pdev->ep_out[0].rem_length = len;
/* Start the transfer */
(void)USBD_LL_PrepareReceive(pdev, 0U, pbuf, len);
return USBD_OK;
}
/**
* @brief USBD_CtlContinueRx
* continue receive data on the ctl pipe
* @param pdev: device instance
* @param buff: pointer to data buffer
* @param len: length of data to be received
* @retval status
*/
USBD_StatusTypeDef USBD_CtlContinueRx(USBD_HandleTypeDef *pdev, uint8_t *pbuf,
uint32_t len)
{
(void)USBD_LL_PrepareReceive(pdev, 0U, pbuf, len);
return USBD_OK;
}
/**
* @brief USBD_CtlSendStatus
* send zero lzngth packet on the ctl pipe
* @param pdev: device instance
* @retval status
*/
USBD_StatusTypeDef USBD_CtlSendStatus(USBD_HandleTypeDef *pdev)
{
/* Set EP0 State */
pdev->ep0_state = USBD_EP0_STATUS_IN;
/* Start the transfer */
(void)USBD_LL_Transmit(pdev, 0x00U, NULL, 0U);
// alex revise
(void)USB_EP0_OutStart(pdev->pData, 0, NULL);
return USBD_OK;
}
/**
* @brief USBD_CtlReceiveStatus
* receive zero lzngth packet on the ctl pipe
* @param pdev: device instance
* @retval status
*/
USBD_StatusTypeDef USBD_CtlReceiveStatus(USBD_HandleTypeDef *pdev)
{
/* Set EP0 State */
pdev->ep0_state = USBD_EP0_STATUS_OUT;
/* Start the transfer */
(void)USBD_LL_PrepareReceive(pdev, 0U, NULL, 0U);
(void)USB_EP0_OutStart(pdev->pData, 0, NULL);
return USBD_OK;
}
/**
* @brief USBD_GetRxCount
* returns the received data length
* @param pdev: device instance
* @param ep_addr: endpoint address
* @retval Rx Data blength
*/
uint32_t USBD_GetRxCount(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
return USBD_LL_GetRxDataSize(pdev, ep_addr);
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,69 @@
/*!
* \file usbd_ioreq.h
*
* \brief Header file for the usbd_ioreq.c file.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author MCD Application Team
*
* \author ( XinChip ) Alex-J
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_IOREQ_H
#define __USBD_IOREQ_H
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_def.h"
#include "usbd_core.h"
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
USBD_StatusTypeDef USBD_CtlSendData(USBD_HandleTypeDef *pdev,
uint8_t *pbuf, uint32_t len);
USBD_StatusTypeDef USBD_CtlContinueSendData(USBD_HandleTypeDef *pdev,
uint8_t *pbuf, uint32_t len);
USBD_StatusTypeDef USBD_CtlPrepareRx(USBD_HandleTypeDef *pdev,
uint8_t *pbuf, uint32_t len);
USBD_StatusTypeDef USBD_CtlContinueRx(USBD_HandleTypeDef *pdev,
uint8_t *pbuf, uint32_t len);
USBD_StatusTypeDef USBD_CtlSendStatus(USBD_HandleTypeDef *pdev);
USBD_StatusTypeDef USBD_CtlReceiveStatus(USBD_HandleTypeDef *pdev);
uint32_t USBD_GetRxCount(USBD_HandleTypeDef *pdev, uint8_t ep_addr);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_IOREQ_H */
@@ -0,0 +1,593 @@
/*!
* \file usbd_conf.c
*
* \brief This file implements the board support package for the USB device
* library
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "usbd_core.h"
#include "usbd_def.h"
#include "xc_hal_usb.h"
#if USB_MSC
#include "usbd_msc.h"
#elif USB_HID
#include "usbd_hid.h"
#elif USB_CDC
#include "usbd_cdc.h"
#endif
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
PCD_HandleTypeDef hpcd_USB_OTG_FS;
/*------------------------------------------------------------------------------------
Func Prototypes
------------------------------------------------------------------------------------*/
void Error_Handler(void);
USBD_StatusTypeDef USBD_Get_USB_Status(HAL_StatusTypeDef hal_status);
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state
*/
__disable_irq();
while (1) {
}
/* USER CODE END Error_Handler_Debug */
}
/*******************************************************************************
LL Driver Callbacks (PCD -> USB Device Library)
*******************************************************************************/
/* MSP Init */
void HAL_PCD_MspInit(PCD_HandleTypeDef *pcdHandle)
{
USB_Phy_Init();
USB_Phy_Enable();
USB_Current_Ctrl(0);
// NVIC_SetPriority(USB_IRQn, 0); // MSC mode do not SET!!!!
USB_Phy_DP_Oprt(PULL_UP);
// HAL_Delay(100); // for(int i = 0; i < 0x455000*2; i++);
NVIC_EnableIRQ(USB_IRQn);
}
/* MSP DeInit */
void HAL_PCD_MspDeInit(PCD_HandleTypeDef *pcdHandle) { USB_Phy_Deinit(); }
/**
* @brief Setup stage callback
* @param hpcd: PCD handle
* @retval None
*/
void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
{
USBD_LL_SetupStage((USBD_HandleTypeDef *)hpcd->pData,
(uint8_t *)hpcd->Setup);
}
/**
* @brief Data Out stage callback.
* @param hpcd: PCD handle
* @param epnum: Endpoint number
* @retval None
*/
void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
{
USBD_LL_DataOutStage((USBD_HandleTypeDef *)hpcd->pData, epnum,
hpcd->OUT_ep[epnum].xfer_buff);
}
/**
* @brief Data In stage callback.
* @param hpcd: PCD handle
* @param epnum: Endpoint number
* @retval None
*/
void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
{
USBD_LL_DataInStage((USBD_HandleTypeDef *)hpcd->pData, epnum,
hpcd->IN_ep[epnum].xfer_buff);
}
/**
* @brief SOF callback.
* @param hpcd: PCD handle
* @retval None
*/
void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
{
USBD_LL_SOF((USBD_HandleTypeDef *)hpcd->pData);
}
/**
* @brief Reset callback.
* @param hpcd: PCD handle
* @retval None
*/
void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
{
USBD_SpeedTypeDef speed = USBD_SPEED_FULL;
// if ( hpcd->Init.speed == PCD_SPEED_HIGH)
// {
// speed = USBD_SPEED_HIGH;
// }
if (hpcd->Init.speed == PCD_SPEED_FULL) {
speed = USBD_SPEED_FULL;
} else {
Error_Handler();
}
/* Set Speed. */
USBD_LL_SetSpeed((USBD_HandleTypeDef *)hpcd->pData, speed);
/* Reset Device. */
USBD_LL_Reset((USBD_HandleTypeDef *)hpcd->pData);
}
/**
* @brief Suspend callback.
* When Low power mode is enabled the debug cannot be used (IAR, Keil doesn't
* support it)
* @param hpcd: PCD handle
* @retval None
*/
void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
{
/* Inform USB library that core enters in suspend Mode. */
USBD_LL_Suspend((USBD_HandleTypeDef *)hpcd->pData);
__HAL_PCD_GATE_PHYCLOCK(hpcd);
/* Enter in STOP mode. */
/* USER CODE BEGIN 2 */
if (hpcd->Init.low_power_enable) {
/* Set SLEEPDEEP bit and SleepOnExit of Cortex System Control Register.
*/
SCB->SCR |= (uint32_t)((uint32_t)(SCB_SCR_SLEEPDEEP_Msk |
SCB_SCR_SLEEPONEXIT_Msk));
}
/* USER CODE END 2 */
}
/**
* @brief Resume callback.
* When Low power mode is enabled the debug cannot be used (IAR, Keil doesn't
* support it)
* @param hpcd: PCD handle
* @retval None
*/
void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
{
/* USER CODE BEGIN 3 */
/* USER CODE END 3 */
USBD_LL_Resume((USBD_HandleTypeDef *)hpcd->pData);
}
/**
* @brief ISOOUTIncomplete callback.
* @param hpcd: PCD handle
* @param epnum: Endpoint number
* @retval None
*/
void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
{
USBD_LL_IsoOUTIncomplete((USBD_HandleTypeDef *)hpcd->pData, epnum);
}
/**
* @brief ISOINIncomplete callback.
* @param hpcd: PCD handle
* @param epnum: Endpoint number
* @retval None
*/
void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
{
USBD_LL_IsoINIncomplete((USBD_HandleTypeDef *)hpcd->pData, epnum);
}
/**
* @brief Connect callback.
* @param hpcd: PCD handle
* @retval None
*/
void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
{
USBD_LL_DevConnected((USBD_HandleTypeDef *)hpcd->pData);
}
/**
* @brief Disconnect callback.
* @param hpcd: PCD handle
* @retval None
*/
void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
{
USBD_LL_DevDisconnected((USBD_HandleTypeDef *)hpcd->pData);
}
/*******************************************************************************
LL Driver Interface (USB Device Library --> PCD)
*******************************************************************************/
/**
* @brief Initializes the low level portion of the device driver.
* @param pdev: Device handle
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev)
{
/* Init USB Ip. */
if (pdev->id == DEVICE_FS) {
/* Link the driver to the stack. */
hpcd_USB_OTG_FS.pData = pdev;
pdev->pData = &hpcd_USB_OTG_FS;
hpcd_USB_OTG_FS.Instance = XC_USB_OTG_FS;
hpcd_USB_OTG_FS.Init.dev_endpoints = 2; // 4;
hpcd_USB_OTG_FS.Init.speed = PCD_SPEED_FULL;
hpcd_USB_OTG_FS.Init.dma_enable = F_DISABLE;
hpcd_USB_OTG_FS.Init.phy_itface = PCD_PHY_EMBEDDED;
hpcd_USB_OTG_FS.Init.Sof_enable = F_DISABLE;
hpcd_USB_OTG_FS.Init.low_power_enable = F_DISABLE;
hpcd_USB_OTG_FS.Init.lpm_enable = F_DISABLE;
hpcd_USB_OTG_FS.Init.vbus_sensing_enable = F_DISABLE;
hpcd_USB_OTG_FS.Init.use_dedicated_ep1 = F_DISABLE;
if (HAL_PCD_Init(&hpcd_USB_OTG_FS) != HAL_OK) {
Error_Handler();
}
HAL_PCDEx_SetRxFiFo(&hpcd_USB_OTG_FS, 0x28);
HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 0, 0x10);
HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 1, 0x10);
}
return USBD_OK;
}
/**
* @brief De-Initializes the low level portion of the device driver.
* @param pdev: Device handle
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_DeInit(USBD_HandleTypeDef *pdev)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_DeInit(pdev->pData);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Starts the low level portion of the device driver.
* @param pdev: Device handle
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_Start(pdev->pData);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Stops the low level portion of the device driver.
* @param pdev: Device handle
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_Stop(USBD_HandleTypeDef *pdev)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_Stop(pdev->pData);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Opens an endpoint of the low level driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @param ep_type: Endpoint type
* @param ep_mps: Endpoint max packet size
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_OpenEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr,
uint8_t ep_type, uint16_t ep_mps)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_Open(pdev->pData, ep_addr, ep_mps, ep_type);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Closes an endpoint of the low level driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_CloseEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_Close(pdev->pData, ep_addr);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Flushes an endpoint of the Low Level Driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_FlushEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_Flush(pdev->pData, ep_addr);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Sets a Stall condition on an endpoint of the Low Level Driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_StallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_SetStall(pdev->pData, ep_addr);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Clears a Stall condition on an endpoint of the Low Level Driver.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_ClearStallEP(USBD_HandleTypeDef *pdev,
uint8_t ep_addr)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_ClrStall(pdev->pData, ep_addr);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Returns Stall condition.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval Stall (1: Yes, 0: No)
*/
uint8_t USBD_LL_IsStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
PCD_HandleTypeDef *hpcd = (PCD_HandleTypeDef *)pdev->pData;
if ((ep_addr & 0x80) == 0x80) {
return hpcd->IN_ep[ep_addr & 0x7F].is_stall;
} else {
return hpcd->OUT_ep[ep_addr & 0x7F].is_stall;
}
}
/**
* @brief Assigns a USB address to the device.
* @param pdev: Device handle
* @param dev_addr: Device address
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_SetUSBAddress(USBD_HandleTypeDef *pdev,
uint8_t dev_addr)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_SetAddress(pdev->pData, dev_addr);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Transmits data over an endpoint.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @param pbuf: Pointer to data to be sent
* @param size: Data size
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_Transmit(USBD_HandleTypeDef *pdev, uint8_t ep_addr,
uint8_t *pbuf, uint32_t size)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_Transmit(pdev->pData, ep_addr, pbuf, size);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Prepares an endpoint for reception.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @param pbuf: Pointer to data to be received
* @param size: Data size
* @retval USBD status
*/
USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev,
uint8_t ep_addr, uint8_t *pbuf,
uint32_t size)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_EP_Receive(pdev->pData, ep_addr, pbuf, size);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
/**
* @brief Returns the last transferred packet size.
* @param pdev: Device handle
* @param ep_addr: Endpoint number
* @retval Received Data Size
*/
uint32_t USBD_LL_GetRxDataSize(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
return HAL_PCD_EP_GetRxCount((PCD_HandleTypeDef *)pdev->pData, ep_addr);
}
#ifdef USBD_HS_TESTMODE_ENABLE
/**
* @brief Set High speed Test mode.
* @param pdev: Device handle
* @param testmode: test mode
* @retval USBD Status
*/
USBD_StatusTypeDef USBD_LL_SetTestMode(USBD_HandleTypeDef *pdev,
uint8_t testmode)
{
UNUSED(pdev);
UNUSED(testmode);
return USBD_OK;
}
#endif /* USBD_HS_TESTMODE_ENABLE */
/**
* @brief Static single allocation.
* @param size: Size of allocated memory
* @retval None
*/
void *USBD_static_malloc(uint32_t size)
{
#if USB_MSC
static uint32_t mem[(sizeof(USBD_MSC_BOT_HandleTypeDef) / 4) +
1]; /* On 32-bit boundary */
#elif USB_CDC
static uint32_t
mem[(sizeof(USBD_CDC_HandleTypeDef) / 4) + 1]; /* On 32-bit boundary */
#elif USB_HID
static uint32_t
mem[(sizeof(USBD_HID_HandleTypeDef) / 4) + 1]; /* On 32-bit boundary */
#else
static uint32_t mem[1];
#endif
return mem;
}
/**
* @brief Dummy memory free
* @param p: Pointer to allocated memory address
* @retval None
*/
void USBD_static_free(void *p) {}
/**
* @brief Delays routine for the USB Device Library.
* @param Delay: Delay in ms
* @retval None
*/
void USBD_LL_Delay(uint32_t Delay) { HAL_Delay(Delay); }
/**
* @brief Returns the USB status depending on the HAL status:
* @param hal_status: HAL status
* @retval USB status
*/
USBD_StatusTypeDef USBD_Get_USB_Status(HAL_StatusTypeDef hal_status)
{
USBD_StatusTypeDef usb_status = USBD_OK;
switch (hal_status) {
case HAL_OK:
usb_status = USBD_OK;
break;
case HAL_ERROR:
usb_status = USBD_FAIL;
break;
case HAL_BUSY:
usb_status = USBD_BUSY;
break;
case HAL_TIMEOUT:
usb_status = USBD_FAIL;
break;
default:
usb_status = USBD_FAIL;
break;
}
return usb_status;
}
@@ -0,0 +1,127 @@
/*!
* \file usbd_conf.h
*
* \brief Header for usbd_conf.c file.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_CONF__H
#define __USBD_CONF__H
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "usbd_def.h"
/*------------------------------------------------------------------------------------
Macros
------------------------------------------- -----------------------------------------*/
/** @defgroup USBD_CONF_Exported_Defines USBD_CONF_Exported_Defines
* @brief Defines for configuration of the Usb device.
* @{
*/
/*---------- -----------*/
#if USB_SINGLE_DEVICE
#define USBD_MAX_NUM_INTERFACES 1U
#elif USB_COMPOSITE_DEVICE
#define USBD_MAX_NUM_INTERFACES 2U
#endif
/*---------- -----------*/
#define USBD_MAX_NUM_CONFIGURATION 1U
/*---------- -----------*/
#define USBD_MAX_STR_DESC_SIZ 512U
/*---------- -----------*/
#define USBD_DEBUG_LEVEL 0U
/*---------- -----------*/
#define USBD_LPM_ENABLED 0U
/*---------- -----------*/
#define USBD_SELF_POWERED 1U
/*---------- -----------*/
#define MSC_MEDIA_PACKET 512U
/****************************************/
/* #define for FS and HS identification */
#define DEVICE_FS 0
//#define DEVICE_HS 1
/* Memory management macros make sure to use static memory allocation */
/** Alias for memory allocation. */
#define USBD_malloc (void *)USBD_static_malloc
/** Alias for memory release. */
#define USBD_free USBD_static_free
/** Alias for memory set. */
#define USBD_memset memset
/** Alias for memory copy. */
#define USBD_memcpy memcpy
/** Alias for delay. */
#define USBD_Delay HAL_Delay
/* DEBUG macros */
#if (USBD_DEBUG_LEVEL > 0)
#define USBD_UsrLog(...) DEBUG(__VA_ARGS__);\
DEBUG("\n");
#else
#define USBD_UsrLog(...)
#endif /* (USBD_DEBUG_LEVEL > 0U) */
#if (USBD_DEBUG_LEVEL > 1)
#define USBD_ErrLog(...) DEBUG("ERROR: ") ;\
DEBUG(__VA_ARGS__);\
DEBUG("\n");
#else
#define USBD_ErrLog(...)
#endif /* (USBD_DEBUG_LEVEL > 1U) */
#if (USBD_DEBUG_LEVEL > 2)
#define USBD_DbgLog(...) DEBUG("DEBUG : ") ;\
DEBUG(__VA_ARGS__);\
DEBUG("\n");
#else
#define USBD_DbgLog(...)
#endif /* (USBD_DEBUG_LEVEL > 2U) */
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
void *USBD_static_malloc(uint32_t size);
void USBD_static_free(void *p);
#ifdef __cplusplus
}
#endif
#endif /* __USBD_CONF__H__ */