1
0
Fork 0
mirror of https://github.com/betaflight/betaflight.git synced 2025-07-16 04:45:24 +03:00

Initiate APM32F40X MCU Support in Betaflight (#13709)

* Add APM32F4 driver libraries and USB middleware
* Remove all duplicated APM32 driver files and retaining only the APM32 LIB directory
This commit is contained in:
Morro 2024-06-28 13:03:34 +08:00 committed by GitHub
parent 2ff71b0a1f
commit 14bcc13150
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
258 changed files with 290932 additions and 0 deletions

View file

@ -0,0 +1,173 @@
/*!
* @file usbd_cdc.h
*
* @brief usb device cdc class handler header file
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Define to prevent recursive inclusion */
#ifndef _USBD_CDC_H_
#define _USBD_CDC_H_
/* Includes */
#include "usbd_core.h"
/** @addtogroup APM32_USB_Library
@{
*/
/** @addtogroup USBD_CDC_Class
@{
*/
/** @defgroup USBD_CDC_Macros Macros
@{
*/
#define USBD_CDC_FS_MP_SIZE 0x40
#define USBD_CDC_HS_MP_SIZE 0x200
#define USBD_CDC_CMD_MP_SIZE 0x08
#define USBD_CDC_DATA_MP_SIZE 0x07
#define USBD_CDC_CMD_EP_ADDR 0x82
#define USBD_CDC_DATA_IN_EP_ADDR 0x81
#define USBD_CDC_DATA_OUT_EP_ADDR 0x01
#define USBD_CDC_FS_INTERVAL 16
#define USBD_CDC_HS_INTERVAL 16
/**@} end of group USBD_CDC_Macros*/
/** @defgroup USBD_CDC_Enumerates Enumerates
@{
*/
/**
* @brief USB device CDC xfer status
*/
typedef enum
{
USBD_CDC_XFER_IDLE,
USBD_CDC_XFER_BUSY,
} USBD_CDC_XFER_STA_T;
/**
* @brief USB device CDC control status
*/
typedef enum
{
USBD_CDC_SEND_ENCAPSULATED_COMMAND = 0x00,
USBD_CDC_GET_ENCAPSULATED_RESPONSE = 0x01,
USBD_CDC_SET_COMM_FEATURE = 0x02,
USBD_CDC_GET_COMM_FEATURE = 0x03,
USBD_CDC_CLEAR_COMM_FEATURE = 0x04,
USBD_CDC_SET_LINE_CODING = 0x20,
USBD_CDC_GET_LINE_CODING = 0x21,
USBD_CDC_SET_CONTROL_LINE_STATE = 0x22,
USBD_CDC_SEND_BREAK = 0x23,
} USBD_CDC_CTRL_STA_T;
/**@} end of group USBD_CDC_Enumerates*/
/** @defgroup USBD_CDC_Structures Structures
@{
*/
/**
* @brief USB device CDC Line Coding Structure
*/
typedef struct
{
uint32_t baudRate;
uint8_t format;
uint8_t parityType;
uint8_t WordLen;
} USBD_CDC_LINE_CODING_T;
/**
* @brief USB device CDC interface handler
*/
typedef struct
{
const char* itfName;
USBD_STA_T (*ItfInit)(void);
USBD_STA_T (*ItfDeInit)(void);
USBD_STA_T (*ItfCtrl)(uint8_t command, uint8_t *buffer, uint16_t length);
USBD_STA_T (*ItfSend)(uint8_t *buffer, uint16_t length);
USBD_STA_T (*ItfSendEnd)(uint8_t epNum, uint8_t *buffer, uint32_t *length);
USBD_STA_T (*ItfReceive)(uint8_t *buffer, uint32_t *length);
USBD_STA_T (*ItfSOF)(void);
} USBD_CDC_INTERFACE_T;
/**
* @brief USB device CDC data handler
*/
typedef struct
{
__IO uint8_t state;
uint8_t *buffer;
uint32_t length;
} USBD_CDC_DATA_XFER_T;
/**
* @brief USB device CDC command handler
*/
typedef struct
{
uint8_t opcode;
uint8_t length;
} USBD_CDC_CMD_XFER_T;
/**
* @brief CDC information management
*/
typedef struct
{
uint8_t itf;
uint8_t epInAddr;
uint8_t epOutAddr;
uint8_t epCmdAddr;
USBD_CDC_DATA_XFER_T cdcTx;
USBD_CDC_DATA_XFER_T cdcRx;
uint32_t data[USBD_CDC_HS_MP_SIZE / 4];
USBD_CDC_CMD_XFER_T cdcCmd;
} USBD_CDC_INFO_T;
extern USBD_CLASS_T USBD_CDC_CLASS;
/**@} end of group USBD_CDC_Structures*/
/** @defgroup USBD_CDC_Functions Functions
@{
*/
USBD_STA_T USBD_CDC_TxPacket(USBD_INFO_T* usbInfo);
USBD_STA_T USBD_CDC_RxPacket(USBD_INFO_T* usbInfo);
uint8_t USBD_CDC_ReadInterval(USBD_INFO_T* usbInfo);
USBD_STA_T USBD_CDC_ConfigTxBuffer(USBD_INFO_T* usbInfo, uint8_t *buffer, uint32_t length);
USBD_STA_T USBD_CDC_ConfigRxBuffer(USBD_INFO_T* usbInfo, uint8_t *buffer);
USBD_STA_T USBD_CDC_RegisterItf(USBD_INFO_T* usbInfo, USBD_CDC_INTERFACE_T* itf);
/**@} end of group USBD_CDC_Functions */
/**@} end of group USBD_CDC_Class */
/**@} end of group APM32_USB_Library */
#endif

View file

@ -0,0 +1,663 @@
/*!
* @file usbd_cdc.c
*
* @brief usb device cdc class handler
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Includes */
#include "usbd_cdc.h"
#include "usbd_stdReq.h"
#include "usbd_dataXfer.h"
//#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/** @addtogroup APM32_USB_Library
@{
*/
/** @addtogroup USBD_CDC_Class
@{
*/
/** @defgroup USBD_CDC_Functions Functions
@{
*/
static USBD_STA_T USBD_CDC_ClassInitHandler(USBD_INFO_T* usbInfo, uint8_t cfgIndex);
static USBD_STA_T USBD_CDC_ClassDeInitHandler(USBD_INFO_T* usbInfo, uint8_t cfgIndex);
static USBD_STA_T USBD_CDC_SOFHandler(USBD_INFO_T* usbInfo);
static USBD_STA_T USBD_CDC_SetupHandler(USBD_INFO_T* usbInfo, USBD_REQ_SETUP_T* req);
static USBD_STA_T USBD_CDC_RxEP0Handler(USBD_INFO_T* usbInfo);
static USBD_STA_T USBD_CDC_DataInHandler(USBD_INFO_T* usbInfo, uint8_t epNum);
static USBD_STA_T USBD_CDC_DataOutHandler(USBD_INFO_T* usbInfo, uint8_t epNum);
/**@} end of group USBD_CDC_Functions */
/** @defgroup USBD_CDC_Structures Structures
@{
*/
/* CDC class handler */
USBD_CLASS_T USBD_CDC_CLASS =
{
/* Class handler */
"Class CDC",
NULL,
USBD_CDC_ClassInitHandler,
USBD_CDC_ClassDeInitHandler,
USBD_CDC_SOFHandler,
/* Control endpoint */
USBD_CDC_SetupHandler,
NULL,
USBD_CDC_RxEP0Handler,
/* Specific endpoint */
USBD_CDC_DataInHandler,
USBD_CDC_DataOutHandler,
NULL,
NULL,
};
/**@} end of group USBD_CDC_Structures*/
/** @defgroup USBD_CDC_Functions Functions
@{
*/
/*!
* @brief USB device CDC configuration handler
*
* @param usbInfo: usb device information
*
* @param cfgIndex: configuration index
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_CDC_ClassInitHandler(USBD_INFO_T* usbInfo, uint8_t cfgIndex)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_CDC_INFO_T* usbDevCDC;
UNUSED(cfgIndex);
/* Link class data */
usbInfo->devClass[usbInfo->classID]->classData = (USBD_CDC_INFO_T*)malloc(sizeof(USBD_CDC_INFO_T));
usbDevCDC = (USBD_CDC_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
memset(usbDevCDC, 0, sizeof(USBD_CDC_INFO_T));
USBD_USR_Debug("USBD_CDC_INFO_T size %d\r\n", sizeof(USBD_CDC_INFO_T));
if (usbDevCDC == NULL)
{
USBD_USR_LOG("usbDevCDC is NULL");
return USBD_FAIL;
}
usbDevCDC->epCmdAddr = USBD_CDC_CMD_EP_ADDR;
usbDevCDC->epInAddr = USBD_CDC_DATA_IN_EP_ADDR;
usbDevCDC->epOutAddr = USBD_CDC_DATA_OUT_EP_ADDR;
/* Open Command endpoint */
USBD_EP_OpenCallback(usbInfo, usbDevCDC->epCmdAddr, EP_TYPE_INTERRUPT, USBD_CDC_CMD_MP_SIZE);
usbInfo->devEpIn[usbDevCDC->epCmdAddr & 0x0F].useStatus = ENABLE;
/* Open Data endpoint */
switch (usbInfo->devSpeed)
{
case USBD_SPEED_FS:
USBD_EP_OpenCallback(usbInfo, usbDevCDC->epOutAddr, EP_TYPE_BULK, USBD_CDC_FS_MP_SIZE);
usbInfo->devEpOut[usbDevCDC->epOutAddr & 0x0F].useStatus = ENABLE;
USBD_EP_OpenCallback(usbInfo, usbDevCDC->epInAddr, EP_TYPE_BULK, USBD_CDC_FS_MP_SIZE);
usbInfo->devEpIn[usbDevCDC->epInAddr & 0x0F].useStatus = ENABLE;
usbInfo->devEpIn[usbDevCDC->epCmdAddr & 0x0F].interval = USBD_CDC_FS_INTERVAL;
break;
default:
USBD_EP_OpenCallback(usbInfo, usbDevCDC->epOutAddr, EP_TYPE_BULK, USBD_CDC_HS_MP_SIZE);
usbInfo->devEpOut[usbDevCDC->epOutAddr & 0x0F].useStatus = ENABLE;
USBD_EP_OpenCallback(usbInfo, usbDevCDC->epInAddr, EP_TYPE_BULK, USBD_CDC_HS_MP_SIZE);
usbInfo->devEpIn[usbDevCDC->epInAddr & 0x0F].useStatus = ENABLE;
usbInfo->devEpIn[usbDevCDC->epCmdAddr & 0x0F].interval = USBD_CDC_HS_INTERVAL;
break;
}
/* Interface Init */
usbDevCDC->cdcTx.buffer = NULL;
usbDevCDC->cdcRx.buffer = NULL;
usbDevCDC->cdcTx.state = USBD_CDC_XFER_IDLE;
usbDevCDC->cdcRx.state = USBD_CDC_XFER_IDLE;
((USBD_CDC_INTERFACE_T *)usbInfo->devClassUserData[usbInfo->classID])->ItfInit();
if(usbDevCDC->cdcRx.buffer == NULL)
{
USBD_USR_LOG("cdcRx buffer is NULL");
return USBD_FAIL;
}
switch (usbInfo->devSpeed)
{
case USBD_SPEED_FS:
USBD_EP_ReceiveCallback(usbInfo, usbDevCDC->epOutAddr, \
usbDevCDC->cdcRx.buffer, \
USBD_CDC_FS_MP_SIZE);
break;
default:
USBD_EP_ReceiveCallback(usbInfo, usbDevCDC->epOutAddr, \
usbDevCDC->cdcRx.buffer, \
USBD_CDC_HS_MP_SIZE);
break;
}
return usbStatus;
}
/*!
* @brief USB device CDC reset handler
*
* @param usbInfo: usb device information
*
* @param cfgIndex: configuration index
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_CDC_ClassDeInitHandler(USBD_INFO_T* usbInfo, uint8_t cfgIndex)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_CDC_INFO_T* usbDevCDC = (USBD_CDC_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
UNUSED(cfgIndex);
/* Close CDC EP */
USBD_EP_CloseCallback(usbInfo, usbDevCDC->epOutAddr);
usbInfo->devEpOut[usbDevCDC->epOutAddr & 0x0F].useStatus = DISABLE;
USBD_EP_CloseCallback(usbInfo, usbDevCDC->epInAddr);
usbInfo->devEpIn[usbDevCDC->epInAddr & 0x0F].useStatus = DISABLE;
USBD_EP_CloseCallback(usbInfo, usbDevCDC->epCmdAddr);
usbInfo->devEpIn[usbDevCDC->epCmdAddr & 0x0F].useStatus = DISABLE;
usbInfo->devEpIn[usbDevCDC->epCmdAddr & 0x0F].interval = 0;
if (usbInfo->devClass[usbInfo->classID]->classData != NULL)
{
if(((USBD_CDC_INTERFACE_T *)usbInfo->devClassUserData[usbInfo->classID])->ItfDeInit != NULL)
{
((USBD_CDC_INTERFACE_T *)usbInfo->devClassUserData[usbInfo->classID])->ItfDeInit();
}
free(usbInfo->devClass[usbInfo->classID]->classData);
usbInfo->devClass[usbInfo->classID]->classData = 0;
}
return usbStatus;
}
/*!
* @brief USB device CDC SOF handler
*
* @param usbInfo: usb device information
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_CDC_SOFHandler(USBD_INFO_T* usbInfo)
{
USBD_STA_T usbStatus = USBD_BUSY;
if(((USBD_CDC_INTERFACE_T *)usbInfo->devClassUserData[usbInfo->classID])->ItfSOF != NULL)
{
((USBD_CDC_INTERFACE_T *)usbInfo->devClassUserData[usbInfo->classID])->ItfSOF();
}
return usbStatus;
}
/*!
* @brief USB CDC device receive CTRL status
*
* @param usbInfo : usb handler information
*
* @param buffer : data buffer
*
* @param length : length of data
*
* @retval usb device status
*/
USBD_STA_T USBD_CDC_CtrlReceiveData(USBD_INFO_T* usbInfo, uint8_t *buffer, uint32_t length)
{
USBD_STA_T usbStatus = USBD_OK;
usbInfo->devEp0State = USBD_DEV_EP0_DATA_OUT;
usbInfo->devEpOut[USBD_EP_0].length = length;
usbInfo->devEpOut[USBD_EP_0].remainLen = length;
USBD_EP_ReceiveCallback(usbInfo, USBD_EP_0, buffer, length);
return usbStatus;
}
/*!
* @brief USB device CDC SETUP handler
*
* @param usbInfo: usb device information
*
* @param req: setup request
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_CDC_SetupHandler(USBD_INFO_T* usbInfo, USBD_REQ_SETUP_T* req)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_CDC_INFO_T* usbDevCDC = (USBD_CDC_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
uint8_t request;
uint8_t reqType;
uint16_t wLength = req->DATA_FIELD.wLength[0] | req->DATA_FIELD.wLength[1] << 8;
uint16_t status = 0x0000;
uint16_t length;
if (usbDevCDC == NULL)
{
return USBD_FAIL;
}
request = req->DATA_FIELD.bRequest;
reqType = req->DATA_FIELD.bmRequest.REQ_TYPE_B.type;
switch (reqType)
{
case USBD_REQ_TYPE_STANDARD:
switch (request)
{
case USBD_STD_GET_STATUS:
if (usbInfo->devState == USBD_DEV_CONFIGURE)
{
USBD_CtrlSendData(usbInfo, (uint8_t*)&status, 2);
}
else
{
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
}
break;
case USBD_STD_GET_INTERFACE:
if (usbInfo->devState == USBD_DEV_CONFIGURE)
{
usbDevCDC->itf = 0;
USBD_CtrlSendData(usbInfo, (uint8_t*)&usbDevCDC->itf, 1);
}
else
{
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
}
break;
case USBD_STD_SET_INTERFACE:
if (usbInfo->devState == USBD_DEV_CONFIGURE)
{
}
else
{
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
}
break;
case USBD_STD_CLEAR_FEATURE:
break;
default:
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
break;
}
break;
case USBD_REQ_TYPE_CLASS:
if(wLength)
{
if((usbInfo->reqSetup.DATA_FIELD.bmRequest.REQ_TYPE & 0x80) != 0)
{
((USBD_CDC_INTERFACE_T *)usbInfo->devClassUserData[usbInfo->classID])->ItfCtrl(request, \
(uint8_t *)usbDevCDC->data,
wLength);
length = USBD_CDC_DATA_MP_SIZE < wLength ? USBD_CDC_DATA_MP_SIZE : wLength;
USBD_CtrlSendData(usbInfo, (uint8_t *)usbDevCDC->data, length);
}
else
{
usbDevCDC->cdcCmd.opcode = request;
usbDevCDC->cdcCmd.length = wLength < USBD_EP0_PACKET_MAX_SIZE ? \
wLength : USBD_EP0_PACKET_MAX_SIZE;
USBD_CDC_CtrlReceiveData(usbInfo, (uint8_t *)usbDevCDC->data, usbDevCDC->cdcCmd.length);
}
}
else
{
((USBD_CDC_INTERFACE_T *)usbInfo->devClassUserData[usbInfo->classID])->ItfCtrl(request, \
(uint8_t *)req, \
0);
}
break;
case USBD_REQ_TYPE_VENDOR:
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
break;
default:
usbStatus = USBD_FAIL;
USBD_REQ_CtrlError(usbInfo, req);
break;
}
return usbStatus;
}
/*!
* @brief USB device CDC EP0 receive handler
*
* @param usbInfo: usb device information
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_CDC_RxEP0Handler(USBD_INFO_T* usbInfo)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_CDC_INFO_T* usbDevCDC = (USBD_CDC_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
if (usbDevCDC == NULL)
{
return USBD_FAIL;
}
if((usbInfo->devClassUserData[usbInfo->classID] != NULL) && (usbDevCDC->cdcCmd.opcode != 0xFF))
{
((USBD_CDC_INTERFACE_T *)usbInfo->devClassUserData[usbInfo->classID])->ItfCtrl(usbDevCDC->cdcCmd.opcode, \
(uint8_t *)usbDevCDC->data, \
(uint16_t)usbDevCDC->cdcCmd.length);
usbDevCDC->cdcCmd.opcode = 0xFF;
}
return usbStatus;
}
/*!
* @brief USB device CDC IN data handler
*
* @param usbInfo: usb device information
*
* @param epNum: endpoint number
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_CDC_DataInHandler(USBD_INFO_T* usbInfo, uint8_t epNum)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_CDC_INFO_T* usbDevCDC = (USBD_CDC_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
#if defined(USE_DAL_DRIVER)
PCD_HandleTypeDef* usbdh = (PCD_HandleTypeDef *)usbInfo->dataPoint;
#else
USBD_HANDLE_T* usbdh = (USBD_HANDLE_T *)usbInfo->dataPoint;
#endif /* USE_DAL_DRIVER */
if (usbdh == NULL)
{
return USBD_FAIL;
}
if (usbDevCDC == NULL)
{
return USBD_FAIL;
}
#if defined(USE_DAL_DRIVER)
if((usbInfo->devEpIn[epNum & 0x0F].length > 0) && \
(usbInfo->devEpIn[epNum & 0x0F].length % usbdh->IN_ep[epNum & 0x0F].maxpacket) == 0)
#else
if((usbInfo->devEpIn[epNum & 0x0F].length > 0) && \
(usbInfo->devEpIn[epNum & 0x0F].length % usbdh->epIN[epNum & 0x0F].mps) == 0)
#endif /* USE_DAL_DRIVER */
{
usbInfo->devEpIn[epNum & 0x0F].length = 0;
USBD_EP_TransferCallback(usbInfo, epNum, NULL, 0);
}
else
{
usbDevCDC->cdcTx.state = USBD_CDC_XFER_IDLE;
if(((USBD_CDC_INTERFACE_T *)usbInfo->devClassUserData[usbInfo->classID])->ItfSendEnd != NULL)
{
((USBD_CDC_INTERFACE_T *)usbInfo->devClassUserData[usbInfo->classID])->ItfSendEnd(epNum, \
usbDevCDC->cdcTx.buffer, \
&usbDevCDC->cdcTx.length);
}
}
return usbStatus;
}
/*!
* @brief USB device CDC OUT data handler
*
* @param usbInfo: usb device information
*
* @param epNum: endpoint number
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_CDC_DataOutHandler(USBD_INFO_T* usbInfo, uint8_t epNum)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_CDC_INFO_T* usbDevCDC = (USBD_CDC_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
if (usbDevCDC == NULL)
{
return USBD_FAIL;
}
usbDevCDC->cdcRx.length = USBD_EP_ReadRxDataLenCallback(usbInfo, epNum);
((USBD_CDC_INTERFACE_T *)usbInfo->devClassUserData[usbInfo->classID])->ItfReceive(usbDevCDC->cdcRx.buffer, \
&usbDevCDC->cdcRx.length);
return usbStatus;
}
/*!
* @brief USB device CDC configure TX buffer handler
*
* @param usbInfo: usb device information
*
* @param buffer: tx buffer
*
* @param length: tx buffer length
*
* @retval USB device operation status
*/
USBD_STA_T USBD_CDC_ConfigTxBuffer(USBD_INFO_T* usbInfo, uint8_t *buffer, uint32_t length)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_CDC_INFO_T* usbDevCDC = (USBD_CDC_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
if (usbDevCDC == NULL)
{
return USBD_FAIL;
}
usbDevCDC->cdcTx.buffer = buffer;
usbDevCDC->cdcTx.length = length;
return usbStatus;
}
/*!
* @brief USB device CDC configure RX buffer handler
*
* @param usbInfo: usb device information
*
* @param buffer: tx buffer
*
* @retval USB device operation status
*/
USBD_STA_T USBD_CDC_ConfigRxBuffer(USBD_INFO_T* usbInfo, uint8_t *buffer)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_CDC_INFO_T* usbDevCDC = (USBD_CDC_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
if (usbDevCDC == NULL)
{
return USBD_FAIL;
}
usbDevCDC->cdcRx.buffer = buffer;
return usbStatus;
}
/*!
* @brief USB device CDC register interface handler
*
* @param usbInfo: usb device information
*
* @param itf: interface handler
*
* @retval USB device operation status
*/
USBD_STA_T USBD_CDC_RegisterItf(USBD_INFO_T* usbInfo, USBD_CDC_INTERFACE_T* itf)
{
USBD_STA_T usbStatus = USBD_FAIL;
if (itf != NULL)
{
usbInfo->devClassUserData[usbInfo->classID] = itf;
usbStatus = USBD_OK;
}
return usbStatus;
}
/*!
* @brief USB device CDC transmit packet handler
*
* @param usbInfo: usb device information
*
* @retval USB device operation status
*/
USBD_STA_T USBD_CDC_TxPacket(USBD_INFO_T* usbInfo)
{
USBD_STA_T usbStatus = USBD_BUSY;
USBD_CDC_INFO_T* usbDevCDC = (USBD_CDC_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
if (usbDevCDC == NULL)
{
return USBD_FAIL;
}
if(usbDevCDC->cdcTx.state == USBD_CDC_XFER_IDLE)
{
usbDevCDC->cdcTx.state = USBD_CDC_XFER_BUSY;
usbInfo->devEpIn[usbDevCDC->epInAddr & 0x0F].length = usbDevCDC->cdcTx.length;
USBD_EP_TransferCallback(usbInfo, usbDevCDC->epInAddr, usbDevCDC->cdcTx.buffer, usbDevCDC->cdcTx.length);
usbStatus = USBD_OK;
}
return usbStatus;
}
/*!
* @brief USB device CDC receive packet handler
*
* @param usbInfo: usb device information
*
* @retval USB device operation status
*/
USBD_STA_T USBD_CDC_RxPacket(USBD_INFO_T* usbInfo)
{
USBD_STA_T usbStatus = USBD_BUSY;
USBD_CDC_INFO_T* usbDevCDC = (USBD_CDC_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
if (usbDevCDC == NULL)
{
return USBD_FAIL;
}
if(usbInfo->devSpeed == USBD_SPEED_HS)
{
USBD_EP_ReceiveCallback(usbInfo, usbDevCDC->epOutAddr, \
usbDevCDC->cdcRx.buffer, \
USBD_CDC_HS_MP_SIZE);
}
else
{
USBD_EP_ReceiveCallback(usbInfo, usbDevCDC->epOutAddr, \
usbDevCDC->cdcRx.buffer, \
USBD_CDC_FS_MP_SIZE);
}
return usbStatus;
}
/*!
* @brief USB device CDC read interval
*
* @param usbInfo: usb device information
*
* @retval usb interval
*/
uint8_t USBD_CDC_ReadInterval(USBD_INFO_T* usbInfo)
{
uint8_t interval;
if (usbInfo->devSpeed == USBD_SPEED_FS)
{
interval = USBD_CDC_FS_INTERVAL;
}
else
{
interval = USBD_CDC_HS_INTERVAL;
}
return interval;
}
/**@} end of group USBD_CDC_Functions */
/**@} end of group USBD_CDC_Class */
/**@} end of group APM32_USB_Library */

View file

@ -0,0 +1,228 @@
/*!
* @file usbd_composite_template.c
*
* @brief usb device composite class handler
*
* @version V1.0.0
*
* @date 2023-11-13
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Includes */
#include "usbd_composite.h"
#include "usbd_stdReq.h"
#include "usbd_dataXfer.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/** @addtogroup Examples
@{
*/
/** @addtogroup OTGD_Composite
@{
*/
/** @defgroup OTGD_Composite_Functions Functions
@{
*/
static USBD_STA_T USBD_Composite_ClassInitHandler(USBD_INFO_T* usbInfo, uint8_t cfgIndex);
static USBD_STA_T USBD_Composite_ClassDeInitHandler(USBD_INFO_T* usbInfo, uint8_t cfgIndex);
static USBD_STA_T USBD_Composite_SOFHandler(USBD_INFO_T* usbInfo);
static USBD_STA_T USBD_Composite_SetupHandler(USBD_INFO_T* usbInfo, USBD_REQ_SETUP_T* req);
static USBD_STA_T USBD_Composite_RxEP0Handler(USBD_INFO_T* usbInfo);
static USBD_STA_T USBD_Composite_DataInHandler(USBD_INFO_T* usbInfo, uint8_t epNum);
static USBD_STA_T USBD_Composite_DataOutHandler(USBD_INFO_T* usbInfo, uint8_t epNum);
/**@} end of group OTGD_Composite_Functions */
/** @defgroup OTGD_Composite_Structures Structures
@{
*/
/* Composite class handler */
USBD_CLASS_T USBD_COMPOSITE_CLASS =
{
/* Class handler */
"Class Composite",
NULL,
USBD_Composite_ClassInitHandler,
USBD_Composite_ClassDeInitHandler,
USBD_Composite_SOFHandler,
/* Control endpoint */
USBD_Composite_SetupHandler,
NULL,
USBD_Composite_RxEP0Handler,
/* Specific endpoint */
USBD_Composite_DataInHandler,
USBD_Composite_DataOutHandler,
NULL,
NULL,
};
/**@} end of group OTGD_Composite_Structures*/
/** @defgroup OTGD_Composite_Functions Functions
@{
*/
/*!
* @brief USB device composite init
*
* @param usbInfo: usb device information
*
* @param itf1: class interface 1
*
* @param itf2: class interface 2
*
* @retval USB device operation status
*/
USBD_STA_T USBD_Composite_Init(USBD_INFO_T* usbInfo, void* itf1, void* itf2)
{
USBD_STA_T usbStatus = USBD_OK;
return usbStatus;
}
/*!
* @brief USB device composite de-init
*
* @param usbInfo: usb device information
*
* @retval USB device operation status
*/
USBD_STA_T USBD_Composite_Deinit(USBD_INFO_T* usbInfo)
{
USBD_STA_T usbStatus = USBD_OK;
return usbStatus;
}
/*!
* @brief USB device composite configuration handler
*
* @param usbInfo: usb device information
*
* @param cfgIndex: configuration index
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_Composite_ClassInitHandler(USBD_INFO_T* usbInfo, uint8_t cfgIndex)
{
USBD_STA_T usbStatus = USBD_OK;
return usbStatus;
}
/*!
* @brief USB device composite reset handler
*
* @param usbInfo: usb device information
*
* @param cfgIndex: configuration index
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_Composite_ClassDeInitHandler(USBD_INFO_T* usbInfo, uint8_t cfgIndex)
{
USBD_STA_T usbStatus = USBD_OK;
return usbStatus;
}
/*!
* @brief USB device composite SOF handler
*
* @param usbInfo: usb device information
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_Composite_SOFHandler(USBD_INFO_T* usbInfo)
{
USBD_STA_T usbStatus = USBD_BUSY;
return usbStatus;
}
/*!
* @brief USB device composite SETUP handler
*
* @param usbInfo: usb device information
*
* @param req: setup request
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_Composite_SetupHandler(USBD_INFO_T* usbInfo, USBD_REQ_SETUP_T* req)
{
USBD_STA_T usbStatus = USBD_OK;
return usbStatus;
}
/*!
* @brief USB device composite EP0 receive handler
*
* @param usbInfo: usb device information
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_Composite_RxEP0Handler(USBD_INFO_T* usbInfo)
{
USBD_STA_T usbStatus = USBD_OK;
return usbStatus;
}
/*!
* @brief USB device composite IN data handler
*
* @param usbInfo: usb device information
*
* @param epNum: endpoint number
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_Composite_DataInHandler(USBD_INFO_T* usbInfo, uint8_t epNum)
{
USBD_STA_T usbStatus = USBD_OK;
return usbStatus;
}
/*!
* @brief USB device composite OUT data handler
*
* @param usbInfo: usb device information
*
* @param epNum: endpoint number
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_Composite_DataOutHandler(USBD_INFO_T* usbInfo, uint8_t epNum)
{
USBD_STA_T usbStatus = USBD_OK;
return usbStatus;
}
/**@} end of group OTGD_Composite_Functions */
/**@} end of group OTGD_Composite */
/**@} end of group Examples */

View file

@ -0,0 +1,70 @@
/*!
* @file usbd_composite_template.h
*
* @brief usb device composite class handler header file
*
* @version V1.0.0
*
* @date 2023-11-13
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Define to prevent recursive inclusion */
#ifndef _USBD_COMPOSITE_H_
#define _USBD_COMPOSITE_H_
#ifdef __cplusplus
extern "C" {
#endif
/* Includes */
#include "usbd_core.h"
/** @addtogroup Examples
@{
*/
/** @addtogroup OTGD_Composite
@{
*/
/** @defgroup OTGD_Composite_Macros Macros
@{
*/
/**@} end of group OTGD_Composite_Macros*/
/** @defgroup OTGD_Composite_Structures Structures
@{
*/
extern USBD_CLASS_T USBD_COMPOSITE_CLASS;
/**@} end of group OTGD_Composite_Structures*/
/** @defgroup OTGD_Composite_Functions Functions
@{
*/
USBD_STA_T USBD_Composite_Init(USBD_INFO_T* usbInfo, void* itf1, void* itf2);
USBD_STA_T USBD_Composite_Deinit(USBD_INFO_T* usbInfo);
/**@} end of group OTGD_Composite_Functions */
/**@} end of group OTGD_Composite */
/**@} end of group Examples */
#ifdef __cplusplus
}
#endif
#endif /* _USBD_COMPOSITE_H_ */

View file

@ -0,0 +1,374 @@
/*!
* @file usbd_hid.h
*
* @brief usb device hid class handler header file
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Define to prevent recursive inclusion */
#ifndef _USBD_CUSTOM_HID_H_
#define _USBD_CUSTOM_HID_H_
/* Includes */
#include "usbd_core.h"
/** @addtogroup APM32_USB_Library
@{
*/
/** @addtogroup USBD_CUSTOM_HID_Class
@{
*/
/** @defgroup USBD_CUSTOM_HID_Macros Macros
@{
*/
#define USBD_CUSTOM_HID_REPORT_DESC_SIZE 63
#define USBD_CUSTOM_HID_DESC_SIZE 9
#define USBD_CUSTOM_HID_FS_INTERVAL 10
#define USBD_CUSTOM_HID_HS_INTERVAL 7
#define USBD_CUSTOM_HID_IN_EP_ADDR 0x81
#define USBD_CUSTOM_HID_IN_EP_SIZE 0x04
#define USBD_CUSTOM_HID_OUT_EP_ADDR 0x01
#define USBD_CUSTOM_HID_OUT_EP_SIZE 0x04
#define USBD_CUSTOM_HID_FS_MP_SIZE 0x40
#define USBD_CLASS_SET_IDLE 0x0A
#define USBD_CLASS_GET_IDLE 0x02
#define USBD_CLASS_SET_REPORT 0x09
#define USBD_CLASS_GET_REPORT 0x01
#define USBD_CLASS_SET_PROTOCOL 0x0B
#define USBD_CLASS_GET_PROTOCOL 0x03
/**@} end of group USBD_CUSTOM_HID_Macros*/
/** @defgroup USBD_CUSTOM_HID_Enumerates Enumerates
@{
*/
/**
* @brief HID state type
*/
typedef enum
{
USBD_CUSTOM_HID_IDLE,
USBD_CUSTOM_HID_BUSY,
} USBD_CUSTOM_HID_STATE_T;
/**
* @brief HID keyboard value
*/
typedef enum
{
KEYBOARD_NONE,
KEYBOARD_ERROR_ROLL_OVER,
KEYBOARD_POST_FAIL,
KEYBOARD_ERROR_UNDEFINED,
KEYBOARD_A,
KEYBOARD_B,
KEYBOARD_C,
KEYBOARD_D,
KEYBOARD_E,
KEYBOARD_F,
KEYBOARD_G,
KEYBOARD_H,
KEYBOARD_I,
KEYBOARD_J,
KEYBOARD_K,
KEYBOARD_L,
KEYBOARD_M,
KEYBOARD_N,
KEYBOARD_O,
KEYBOARD_P,
KEYBOARD_Q,
KEYBOARD_R,
KEYBOARD_S,
KEYBOARD_T,
KEYBOARD_U,
KEYBOARD_V,
KEYBOARD_W,
KEYBOARD_X,
KEYBOARD_Y,
KEYBOARD_Z,
KEYBOARD_1_EXCLAMATION,
KEYBOARD_2_AT,
KEYBOARD_3_NUMBER_SIGN,
KEYBOARD_4_DOLLAR,
KEYBOARD_5_PERCENT,
KEYBOARD_6_CARET,
KEYBOARD_7_AMPERSAND,
KEYBOARD_8_ASTERISK,
KEYBOARD_9_OPARENTHESIS,
KEYBOARD_10_CPARENTHESIS,
KEYBOARD_ENTER,
KEYBOARD_ESCAPE,
KEYBOARD_BACKSPACE,
KEYBOARD_TAB,
KEYBOARD_SPACEBAR,
KEYBOARD_MINUS_UNDERSCORE,
KEYBOARD_EQUAL_PLUS,
KEYBOARD_OBRACKET_AND_OBRACE,
KEYBOARD_CBRACKET_AND_CBRACE,
KEYBOARD_BACKSLASH_VERTICAL_BAR,
KEYBOARD_NONUS_NUMBER_SIGN_TILDE,
KEYBOARD_SEMICOLON_COLON,
KEYBOARD_SINGLE_AND_DOUBLE_QUOTE,
KEYBOARD_GRAVE_ACCENT_AND_TILDE,
KEYBOARD_COMMA_AND_LESS,
KEYBOARD_DOT_GREATER,
KEYBOARD_SLASH_QUESTION,
KEYBOARD_CAPS_LOCK,
KEYBOARD_F1,
KEYBOARD_F2,
KEYBOARD_F3,
KEYBOARD_F4,
KEYBOARD_F5,
KEYBOARD_F6,
KEYBOARD_F7,
KEYBOARD_F8,
KEYBOARD_F9,
KEYBOARD_F10,
KEYBOARD_F11,
KEYBOARD_F12,
KEYBOARD_PRINTSCREEN,
KEYBOARD_SCROLL_LOCK,
KEYBOARD_PAUSE,
KEYBOARD_INSERT,
KEYBOARD_HOME,
KEYBOARD_PAGEUP,
KEYBOARD_DELETE,
KEYBOARD_END1,
KEYBOARD_PAGEDOWN,
KEYBOARD_RIGHTARROW,
KEYBOARD_LEFTARROW,
KEYBOARD_DOWNARROW,
KEYBOARD_UPARROW,
KEYBOARD_KEYBOARDPAD_NUM_LOCK_AND_CLEAR,
KEYBOARD_KEYBOARDPAD_SLASH,
KEYBOARD_KEYBOARDPAD_ASTERIKS,
KEYBOARD_KEYBOARDPAD_MINUS,
KEYBOARD_KEYBOARDPAD_PLUS,
KEYBOARD_KEYBOARDPAD_ENTER,
KEYBOARD_KEYBOARDPAD_1_END,
KEYBOARD_KEYBOARDPAD_2_DOWN_ARROW,
KEYBOARD_KEYBOARDPAD_3_PAGEDN,
KEYBOARD_KEYBOARDPAD_4_LEFT_ARROW,
KEYBOARD_KEYBOARDPAD_5,
KEYBOARD_KEYBOARDPAD_6_RIGHT_ARROW,
KEYBOARD_KEYBOARDPAD_7_HOME,
KEYBOARD_KEYBOARDPAD_8_UP_ARROW,
KEYBOARD_KEYBOARDPAD_9_PAGEUP,
KEYBOARD_KEYBOARDPAD_0_INSERT,
KEYBOARD_KEYBOARDPAD_DECIMAL_SEPARATOR_DELETE,
KEYBOARD_NONUS_BACK_SLASH_VERTICAL_BAR,
KEYBOARD_APPLICATION,
KEYBOARD_POWER,
KEYBOARD_KEYBOARDPAD_EQUAL,
KEYBOARD_F13,
KEYBOARD_F14,
KEYBOARD_F15,
KEYBOARD_F16,
KEYBOARD_F17,
KEYBOARD_F18,
KEYBOARD_F19,
KEYBOARD_F20,
KEYBOARD_F21,
KEYBOARD_F22,
KEYBOARD_F23,
KEYBOARD_F24,
KEYBOARD_EXECUTE,
KEYBOARD_HELP,
KEYBOARD_MENU,
KEYBOARD_SELECT,
KEYBOARD_STOP,
KEYBOARD_AGAIN,
KEYBOARD_UNDO,
KEYBOARD_CUT,
KEYBOARD_COPY,
KEYBOARD_PASTE,
KEYBOARD_FIND,
KEYBOARD_MUTE,
KEYBOARD_VOLUME_UP,
KEYBOARD_VOLUME_DOWN,
KEYBOARD_LOCKING_CAPS_LOCK,
KEYBOARD_LOCKING_NUM_LOCK,
KEYBOARD_LOCKING_SCROLL_LOCK,
KEYBOARD_KEYBOARDPAD_COMMA,
KEYBOARD_KEYBOARDPAD_EQUAL_SIGN,
KEYBOARD_INTERNATIONAL1,
KEYBOARD_INTERNATIONAL2,
KEYBOARD_INTERNATIONAL3,
KEYBOARD_INTERNATIONAL4,
KEYBOARD_INTERNATIONAL5,
KEYBOARD_INTERNATIONAL6,
KEYBOARD_INTERNATIONAL7,
KEYBOARD_INTERNATIONAL8,
KEYBOARD_INTERNATIONAL9,
KEYBOARD_LANG1,
KEYBOARD_LANG2,
KEYBOARD_LANG3,
KEYBOARD_LANG4,
KEYBOARD_LANG5,
KEYBOARD_LANG6,
KEYBOARD_LANG7,
KEYBOARD_LANG8,
KEYBOARD_LANG9,
KEYBOARD_ALTERNATE_ERASE,
KEYBOARD_SYSREQ,
KEYBOARD_CANCEL,
KEYBOARD_CLEAR,
KEYBOARD_PRIOR,
KEYBOARD_RETURN,
KEYBOARD_SEPARATOR,
KEYBOARD_OUT,
KEYBOARD_OPER,
KEYBOARD_CLEAR_AGAIN,
KEYBOARD_CRSEL,
KEYBOARD_EXSEL,
KEYBOARD_RESERVED1,
KEYBOARD_RESERVED2,
KEYBOARD_RESERVED3,
KEYBOARD_RESERVED4,
KEYBOARD_RESERVED5,
KEYBOARD_RESERVED6,
KEYBOARD_RESERVED7,
KEYBOARD_RESERVED8,
KEYBOARD_RESERVED9,
KEYBOARD_RESERVED10,
KEYBOARD_RESERVED11,
KEYBOARD_KEYBOARDPAD_00,
KEYBOARD_KEYBOARDPAD_000,
KEYBOARD_THOUSANDS_SEPARATOR,
KEYBOARD_DECIMAL_SEPARATOR,
KEYBOARD_CURRENCY_UNIT,
KEYBOARD_CURRENCY_SUB_UNIT,
KEYBOARD_KEYBOARDPAD_OPARENTHESIS,
KEYBOARD_KEYBOARDPAD_CPARENTHESIS,
KEYBOARD_KEYBOARDPAD_OBRACE,
KEYBOARD_KEYBOARDPAD_CBRACE,
KEYBOARD_KEYBOARDPAD_TAB,
KEYBOARD_KEYBOARDPAD_BACKSPACE,
KEYBOARD_KEYBOARDPAD_A,
KEYBOARD_KEYBOARDPAD_B,
KEYBOARD_KEYBOARDPAD_C,
KEYBOARD_KEYBOARDPAD_D,
KEYBOARD_KEYBOARDPAD_E,
KEYBOARD_KEYBOARDPAD_F,
KEYBOARD_KEYBOARDPAD_XOR,
KEYBOARD_KEYBOARDPAD_CARET,
KEYBOARD_KEYBOARDPAD_PERCENT,
KEYBOARD_KEYBOARDPAD_LESS,
KEYBOARD_KEYBOARDPAD_GREATER,
KEYBOARD_KEYBOARDPAD_AMPERSAND,
KEYBOARD_KEYBOARDPAD_LOGICAL_AND,
KEYBOARD_KEYBOARDPAD_VERTICAL_BAR,
KEYBOARD_KEYBOARDPAD_LOGIACL_OR,
KEYBOARD_KEYBOARDPAD_COLON,
KEYBOARD_KEYBOARDPAD_NUMBER_SIGN,
KEYBOARD_KEYBOARDPAD_SPACE,
KEYBOARD_KEYBOARDPAD_AT,
KEYBOARD_KEYBOARDPAD_EXCLAMATION_MARK,
KEYBOARD_KEYBOARDPAD_MEMORY_STORE,
KEYBOARD_KEYBOARDPAD_MEMORY_RECALL,
KEYBOARD_KEYBOARDPAD_MEMORY_CLEAR,
KEYBOARD_KEYBOARDPAD_MEMORY_ADD,
KEYBOARD_KEYBOARDPAD_MEMORY_SUBTRACT,
KEYBOARD_KEYBOARDPAD_MEMORY_MULTIPLY,
KEYBOARD_KEYBOARDPAD_MEMORY_DIVIDE,
KEYBOARD_KEYBOARDPAD_PLUSMINUS,
KEYBOARD_KEYBOARDPAD_CLEAR,
KEYBOARD_KEYBOARDPAD_CLEAR_ENTRY,
KEYBOARD_KEYBOARDPAD_BINARY,
KEYBOARD_KEYBOARDPAD_OCTAL,
KEYBOARD_KEYBOARDPAD_DECIMAL,
KEYBOARD_KEYBOARDPAD_HEXADECIMAL,
KEYBOARD_RESERVED12,
KEYBOARD_RESERVED13,
KEYBOARD_LEFTCONTROL,
KEYBOARD_LEFTSHIFT,
KEYBOARD_LEFTALT,
KEYBOARD_LEFT_GUI,
KEYBOARD_RIGHTCONTROL,
KEYBOARD_RIGHTSHIFT,
KEYBOARD_RIGHTALT,
KEYBOARD_RIGHT_GUI,
} USBH_HID_KEYBOARD_VALUE_T;
/**@} end of group USBD_CUSTOM_HID_Enumerates*/
/** @defgroup USBD_CUSTOM_HID_Structures Structures
@{
*/
/**
* @brief USB device Custom HID interface handler
*/
typedef struct
{
const char* itfName;
uint8_t *report;
USBD_STA_T (*ItfInit)(void);
USBD_STA_T (*ItfDeInit)(void);
USBD_STA_T (*ItfSend)(uint8_t *buffer, uint8_t length);
USBD_STA_T (*ItfReceive)(uint8_t *buffer, uint8_t *length);
} USBD_CUSTOM_HID_INTERFACE_T;
/**
* @brief CUSTOM HID information management
*/
typedef struct
{
uint8_t state;
uint8_t epInAddr;
uint8_t epOutAddr;
uint8_t reportSize;
uint8_t report[USBD_CUSTOM_HID_OUT_EP_SIZE];
uint8_t getReport;
uint8_t altSettingStatus;
uint8_t idleStatus;
uint8_t protocol;
} USBD_CUSTOM_HID_INFO_T;
extern USBD_CLASS_T USBD_CUSTOM_HID_CLASS;
/**@} end of group USBD_CUSTOM_HID_Structures*/
/** @defgroup USBD_CUSTOM_HID_Functions Functions
@{
*/
uint8_t USBD_CUSTOM_HID_ReadInterval(USBD_INFO_T* usbInfo);
USBD_STA_T USBD_CUSTOM_HID_TxReport(USBD_INFO_T* usbInfo, uint8_t* report, uint16_t length);
USBD_STA_T USBD_CUSTOM_HID_RxPacket(USBD_INFO_T* usbInfo);
USBD_STA_T USBD_CUSTOM_HID_RegisterItf(USBD_INFO_T* usbInfo, USBD_CUSTOM_HID_INTERFACE_T* itf);
/**@} end of group USBD_CUSTOM_HID_Functions */
/**@} end of group USBD_CUSTOM_HID_Class */
/**@} end of group APM32_USB_Library */
#endif

View file

@ -0,0 +1,644 @@
/*!
* @file usbd_customhid.c
*
* @brief usb device custom hid class handler
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Includes */
#include "usbd_customhid.h"
#include "usbd_stdReq.h"
#include "usbd_dataXfer.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/** @addtogroup APM32_USB_Library
@{
*/
/** @addtogroup USBD_CUSTOM_HID_Class
@{
*/
/** @defgroup USBD_CUSTOM_HID_Functions Functions
@{
*/
static USBD_STA_T USBD_CUSTOM_HID_ClassInitHandler(USBD_INFO_T* usbInfo, uint8_t cfgIndex);
static USBD_STA_T USBD_CUSTOM_HID_ClassDeInitHandler(USBD_INFO_T* usbInfo, uint8_t cfgIndex);
static USBD_STA_T USBD_CUSTOM_HID_SOFHandler(USBD_INFO_T* usbInfo);
static USBD_STA_T USBD_CUSTOM_HID_SetupHandler(USBD_INFO_T* usbInfo, USBD_REQ_SETUP_T* req);
static USBD_STA_T USBD_CUSTOM_HID_RxEP0Handler(USBD_INFO_T* usbInfo);
static USBD_STA_T USBD_CUSTOM_HID_DataInHandler(USBD_INFO_T* usbInfo, uint8_t epNum);
static USBD_STA_T USBD_CUSTOM_HID_DataOutHandler(USBD_INFO_T* usbInfo, uint8_t epNum);
static USBD_DESC_INFO_T USBD_CUSTOM_HID_ReportDescHandler(USBD_INFO_T* usbInfo);
static USBD_DESC_INFO_T USBD_CUSTOM_HID_DescHandler(uint8_t usbSpeed);
/**@} end of group USBD_CUSTOM_HID_Functions */
/** @defgroup USBD_CUSTOM_HID_Structures Structures
@{
*/
/* CUSTOM HID class handler */
USBD_CLASS_T USBD_CUSTOM_HID_CLASS =
{
/* Class handler */
"Class custom HID",
NULL,
USBD_CUSTOM_HID_ClassInitHandler,
USBD_CUSTOM_HID_ClassDeInitHandler,
USBD_CUSTOM_HID_SOFHandler,
/* Control endpoint */
USBD_CUSTOM_HID_SetupHandler,
NULL,
USBD_CUSTOM_HID_RxEP0Handler,
/* Specific endpoint */
USBD_CUSTOM_HID_DataInHandler,
USBD_CUSTOM_HID_DataOutHandler,
NULL,
NULL,
};
/**@} end of group USBD_CUSTOM_HID_Structures*/
/** @defgroup USBD_CUSTOM_HID_Variables Variables
@{
*/
/**
* @brief HID descriptor
*/
uint8_t USBD_HIDDesc[USBD_CUSTOM_HID_DESC_SIZE] =
{
/* bLength */
0x09,
/* bDescriptorType: HID */
USBD_DESC_HID,
/* bcdHID */
0x11, 0x01,
/* bCountryCode */
0x00,
/* bNumDescriptors */
0x01,
/* bDescriptorType */
USBD_DESC_HID_REPORT,
/* wItemLength */
USBD_CUSTOM_HID_REPORT_DESC_SIZE & 0xFF, USBD_CUSTOM_HID_REPORT_DESC_SIZE >> 8,
};
/**@} end of group USBD_CUSTOM_HID_Variables*/
/** @defgroup USBD_CUSTOM_HID_Functions Functions
@{
*/
/*!
* @brief USB device CUSTOM HID configuration handler
*
* @param usbInfo: usb device information
*
* @param cfgIndex: configuration index
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_CUSTOM_HID_ClassInitHandler(USBD_INFO_T* usbInfo, uint8_t cfgIndex)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_CUSTOM_HID_INFO_T* usbDevHID;
/* Link class data */
usbInfo->devClass[usbInfo->classID]->classData = (USBD_CUSTOM_HID_INFO_T*)malloc(sizeof(USBD_CUSTOM_HID_INFO_T));
usbDevHID = (USBD_CUSTOM_HID_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
memset(usbDevHID, 0, sizeof(USBD_CUSTOM_HID_INFO_T));
USBD_USR_Debug("USBD_CUSTOM_HID_INFO_T size %d\r\n", sizeof(USBD_CUSTOM_HID_INFO_T));
if (usbDevHID == NULL)
{
USBD_USR_LOG("usbDevHID is NULL");
return USBD_FAIL;
}
usbDevHID->epInAddr = USBD_CUSTOM_HID_IN_EP_ADDR;
usbDevHID->epOutAddr = USBD_CUSTOM_HID_OUT_EP_ADDR;
if (usbInfo->devSpeed == USBD_SPEED_FS)
{
usbInfo->devEpIn[usbDevHID->epInAddr & 0x0F].interval = USBD_CUSTOM_HID_FS_INTERVAL;
usbInfo->devEpOut[usbDevHID->epOutAddr & 0x0F].interval = USBD_CUSTOM_HID_FS_INTERVAL;
}
else
{
usbInfo->devEpIn[usbDevHID->epInAddr & 0x0F].interval = USBD_CUSTOM_HID_HS_INTERVAL;
usbInfo->devEpOut[usbDevHID->epOutAddr & 0x0F].interval = USBD_CUSTOM_HID_HS_INTERVAL;
}
/* Open endpoint */
USBD_EP_OpenCallback(usbInfo, usbDevHID->epInAddr, EP_TYPE_INTERRUPT, USBD_CUSTOM_HID_IN_EP_SIZE);
usbInfo->devEpIn[usbDevHID->epInAddr & 0x0F].useStatus = ENABLE;
USBD_EP_OpenCallback(usbInfo, usbDevHID->epOutAddr, EP_TYPE_INTERRUPT, USBD_CUSTOM_HID_OUT_EP_SIZE);
usbInfo->devEpOut[usbDevHID->epOutAddr & 0x0F].useStatus = ENABLE;
((USBD_CUSTOM_HID_INTERFACE_T *)usbInfo->devClassUserData[usbInfo->classID])->ItfInit();
USBD_EP_ReceiveCallback(usbInfo, usbDevHID->epOutAddr, \
usbDevHID->report, \
USBD_CUSTOM_HID_OUT_EP_SIZE);
usbDevHID->state = USBD_CUSTOM_HID_IDLE;
return usbStatus;
}
/*!
* @brief USB device CUSTOM HID reset handler
*
* @param usbInfo: usb device information
*
* @param cfgIndex: configuration index
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_CUSTOM_HID_ClassDeInitHandler(USBD_INFO_T* usbInfo, uint8_t cfgIndex)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_CUSTOM_HID_INFO_T* usbDevHID = (USBD_CUSTOM_HID_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
/* Close HID EP */
USBD_EP_CloseCallback(usbInfo, usbDevHID->epInAddr);
usbInfo->devEpIn[usbDevHID->epInAddr & 0x0F].interval = 0;
usbInfo->devEpIn[usbDevHID->epInAddr & 0x0F].useStatus = DISABLE;
USBD_EP_CloseCallback(usbInfo, usbDevHID->epOutAddr);
usbInfo->devEpOut[usbDevHID->epOutAddr & 0x0F].useStatus = DISABLE;
if (usbInfo->devClass[usbInfo->classID]->classData != NULL)
{
if(((USBD_CUSTOM_HID_INTERFACE_T *)usbInfo->devClassUserData[usbInfo->classID])->ItfDeInit != NULL)
{
((USBD_CUSTOM_HID_INTERFACE_T *)usbInfo->devClassUserData[usbInfo->classID])->ItfDeInit();
}
free(usbInfo->devClass[usbInfo->classID]->classData);
usbInfo->devClass[usbInfo->classID]->classData = 0;
}
return usbStatus;
}
/*!
* @brief USB device CUSTOM HID SOF handler
*
* @param usbInfo: usb device information
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_CUSTOM_HID_SOFHandler(USBD_INFO_T* usbInfo)
{
USBD_STA_T usbStatus = USBD_BUSY;
return usbStatus;
}
/*!
* @brief USB CUSTOM HID device receive CTRL status
*
* @param usbInfo : usb handler information
*
* @param buffer : data buffer
*
* @param length : length of data
*
* @retval usb device status
*/
USBD_STA_T USBD_CUSTOM_HID_CtrlReceiveData(USBD_INFO_T* usbInfo, uint8_t *buffer, uint32_t length)
{
USBD_STA_T usbStatus = USBD_OK;
usbInfo->devEp0State = USBD_DEV_EP0_DATA_OUT;
usbInfo->devEpOut[USBD_EP_0].length = length;
usbInfo->devEpOut[USBD_EP_0].remainLen = length;
USBD_EP_ReceiveCallback(usbInfo, USBD_EP_0, buffer, length);
return usbStatus;
}
/*!
* @brief USB device CUSTOM HID SETUP handler
*
* @param usbInfo: usb device information
*
* @param req: setup request
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_CUSTOM_HID_SetupHandler(USBD_INFO_T* usbInfo, USBD_REQ_SETUP_T* req)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_CUSTOM_HID_INFO_T* usbDevHID = (USBD_CUSTOM_HID_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
USBD_DESC_INFO_T descInfo;
uint8_t request;
uint8_t reqType;
uint16_t wValue = req->DATA_FIELD.wValue[0] | req->DATA_FIELD.wValue[1] << 8;
uint16_t wLength = req->DATA_FIELD.wLength[0] | req->DATA_FIELD.wLength[1] << 8;
uint16_t status = 0x0000;
if (usbDevHID == NULL)
{
USBD_USR_LOG("usbDevHID is NULL");
return USBD_FAIL;
}
request = req->DATA_FIELD.bRequest;
reqType = usbInfo->reqSetup.DATA_FIELD.bmRequest.REQ_TYPE_B.type;
switch (reqType)
{
case USBD_REQ_TYPE_STANDARD:
switch (request)
{
/* HID descriptor */
case USBD_STD_GET_DESCRIPTOR:
switch (req->DATA_FIELD.wValue[1])
{
case USBD_DESC_HID_REPORT:
descInfo = USBD_CUSTOM_HID_ReportDescHandler(usbInfo);
descInfo.size = descInfo.size < wLength ? descInfo.size : wLength;
break;
case USBD_DESC_HID:
descInfo = USBD_CUSTOM_HID_DescHandler(usbInfo->devSpeed);
descInfo.size = descInfo.size < wLength ? descInfo.size : wLength;
break;
default:
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
break;
}
if (descInfo.desc != NULL)
{
USBD_CtrlSendData(usbInfo, descInfo.desc, descInfo.size);
}
break;
case USBD_STD_GET_STATUS:
if (usbInfo->devState == USBD_DEV_CONFIGURE)
{
USBD_CtrlSendData(usbInfo, (uint8_t*)&status, 2);
}
else
{
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
}
break;
case USBD_STD_GET_INTERFACE:
if (usbInfo->devState == USBD_DEV_CONFIGURE)
{
USBD_CtrlSendData(usbInfo, (uint8_t*)&usbDevHID->altSettingStatus, 1);
}
else
{
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
}
break;
case USBD_STD_SET_INTERFACE:
if (usbInfo->devState == USBD_DEV_CONFIGURE)
{
usbDevHID->altSettingStatus = wValue;
}
else
{
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
}
break;
case USBD_STD_CLEAR_FEATURE:
break;
default:
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
break;
}
break;
case USBD_REQ_TYPE_CLASS:
switch (request)
{
case USBD_CLASS_SET_IDLE:
usbDevHID->idleStatus = req->DATA_FIELD.wValue[1];
break;
case USBD_CLASS_GET_IDLE:
USBD_CtrlSendData(usbInfo, (uint8_t*)&usbDevHID->idleStatus, 1);
break;
case USBD_CLASS_SET_PROTOCOL:
usbDevHID->protocol = req->DATA_FIELD.wValue[0];
break;
case USBD_CLASS_GET_PROTOCOL:
USBD_CtrlSendData(usbInfo, (uint8_t*)&usbDevHID->protocol, 1);
break;
case USBD_CLASS_SET_REPORT:
if (wLength < USBD_CUSTOM_HID_OUT_EP_SIZE)
{
USBD_CUSTOM_HID_CtrlReceiveData(usbInfo, usbDevHID->report, wLength);
usbDevHID->reportSize = wLength;
}
else
{
USBD_CUSTOM_HID_CtrlReceiveData(usbInfo, usbDevHID->report, USBD_CUSTOM_HID_OUT_EP_SIZE);
usbDevHID->reportSize = USBD_CUSTOM_HID_OUT_EP_SIZE;
}
usbDevHID->getReport = 1;
break;
default:
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
break;
}
break;
case USBD_REQ_TYPE_VENDOR:
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
break;
default:
usbStatus = USBD_FAIL;
USBD_REQ_CtrlError(usbInfo, req);
break;
}
return usbStatus;
}
/*!
* @brief USB device CUSTOM HID EP0 receive handler
*
* @param usbInfo: usb device information
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_CUSTOM_HID_RxEP0Handler(USBD_INFO_T* usbInfo)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_CUSTOM_HID_INFO_T* usbDevHID = (USBD_CUSTOM_HID_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
if (usbDevHID == NULL)
{
return USBD_FAIL;
}
if((usbInfo->devClassUserData[usbInfo->classID] != NULL) && (usbDevHID->getReport == 1))
{
((USBD_CUSTOM_HID_INTERFACE_T *)usbInfo->devClassUserData[usbInfo->classID])->ItfReceive(usbDevHID->report, \
&usbDevHID->reportSize);
usbDevHID->getReport = 0;
}
return usbStatus;
}
/*!
* @brief USB device CUSTOM HID IN data handler
*
* @param usbInfo: usb device information
*
* @param epNum: endpoint number
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_CUSTOM_HID_DataInHandler(USBD_INFO_T* usbInfo, uint8_t epNum)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_CUSTOM_HID_INFO_T* usbDevHID = (USBD_CUSTOM_HID_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
if (usbDevHID == NULL)
{
return USBD_FAIL;
}
usbDevHID->state = USBD_CUSTOM_HID_IDLE;
return usbStatus;
}
/*!
* @brief USB device CUSTOM HID OUT data handler
*
* @param usbInfo: usb device information
*
* @param epNum: endpoint number
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_CUSTOM_HID_DataOutHandler(USBD_INFO_T* usbInfo, uint8_t epNum)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_CUSTOM_HID_INFO_T* usbDevHID = (USBD_CUSTOM_HID_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
if (usbDevHID == NULL)
{
return USBD_FAIL;
}
usbDevHID->reportSize = USBD_EP_ReadRxDataLenCallback(usbInfo, epNum);
((USBD_CUSTOM_HID_INTERFACE_T *)usbInfo->devClassUserData[usbInfo->classID])->ItfReceive(usbDevHID->report, \
&usbDevHID->reportSize);
return usbStatus;
}
/*!
* @brief USB device CUSTOM HID report descriptor
*
* @param usbSpeed : usb speed
*
* @retval usb descriptor information
*/
static USBD_DESC_INFO_T USBD_CUSTOM_HID_ReportDescHandler(USBD_INFO_T* usbInfo)
{
USBD_DESC_INFO_T descInfo;
descInfo.desc = (uint8_t*)(((USBD_CUSTOM_HID_INTERFACE_T*)usbInfo->devClassUserData[usbInfo->classID])->report);
descInfo.size = USBD_CUSTOM_HID_REPORT_DESC_SIZE;
return descInfo;
}
/*!
* @brief USB device CUSTOM HID descriptor
*
* @param usbSpeed : usb speed
*
* @retval usb descriptor information
*/
static USBD_DESC_INFO_T USBD_CUSTOM_HID_DescHandler(uint8_t usbSpeed)
{
USBD_DESC_INFO_T descInfo;
descInfo.desc = USBD_HIDDesc;
descInfo.size = sizeof(USBD_HIDDesc);
return descInfo;
}
/*!
* @brief USB device CUSTOM HID send report descriptor
*
* @param usbInfo: usb device information
*
* @param report: report buffer
*
* @param length: report data length
*
* @retval usb descriptor information
*/
USBD_STA_T USBD_CUSTOM_HID_TxReport(USBD_INFO_T* usbInfo, uint8_t* report, uint16_t length)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_CUSTOM_HID_INFO_T* usbDevHID = (USBD_CUSTOM_HID_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
if (usbDevHID == NULL)
{
return USBD_FAIL;
}
switch (usbInfo->devState)
{
case USBD_DEV_CONFIGURE:
if (usbDevHID->state == USBD_CUSTOM_HID_IDLE)
{
usbDevHID->state = USBD_CUSTOM_HID_BUSY;
USBD_EP_TransferCallback(usbInfo, usbDevHID->epInAddr, report, length);
}
break;
default:
break;
}
return usbStatus;
}
/*!
* @brief USB device CUSTOM HID receive packet handler
*
* @param usbInfo: usb device information
*
* @retval USB device operation status
*/
USBD_STA_T USBD_CUSTOM_HID_RxPacket(USBD_INFO_T* usbInfo)
{
USBD_STA_T usbStatus = USBD_BUSY;
USBD_CUSTOM_HID_INFO_T* usbDevHID = (USBD_CUSTOM_HID_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
if (usbDevHID == NULL)
{
return USBD_FAIL;
}
if(usbInfo->devSpeed == USBD_SPEED_HS)
{
USBD_EP_ReceiveCallback(usbInfo, usbDevHID->epOutAddr, \
usbDevHID->report, \
USBD_CUSTOM_HID_OUT_EP_SIZE);
}
else
{
USBD_EP_ReceiveCallback(usbInfo, usbDevHID->epOutAddr, \
usbDevHID->report, \
USBD_CUSTOM_HID_OUT_EP_SIZE);
}
return usbStatus;
}
/*!
* @brief USB device CUSTOM HID read interval
*
* @param usbInfo: usb device information
*
* @retval usb interval
*/
uint8_t USBD_CUSTOM_HID_ReadInterval(USBD_INFO_T* usbInfo)
{
uint8_t interval;
if (usbInfo->devSpeed == USBD_SPEED_FS)
{
interval = USBD_CUSTOM_HID_FS_INTERVAL;
}
else
{
interval = ((1 << (USBD_CUSTOM_HID_FS_INTERVAL - 1)) / 8);
}
return interval;
}
/*!
* @brief USB device CUSTOM HID register interface handler
*
* @param usbInfo: usb device information
*
* @param itf: interface handler
*
* @retval USB device operation status
*/
USBD_STA_T USBD_CUSTOM_HID_RegisterItf(USBD_INFO_T* usbInfo, USBD_CUSTOM_HID_INTERFACE_T* itf)
{
USBD_STA_T usbStatus = USBD_FAIL;
if (itf != NULL)
{
usbInfo->devClassUserData[usbInfo->classID] = itf;
usbStatus = USBD_OK;
}
return usbStatus;
}
/**@} end of group USBD_CUSTOM_HID_Functions */
/**@} end of group USBD_CUSTOM_HID_Class */
/**@} end of group APM32_USB_Library */

View file

@ -0,0 +1,350 @@
/*!
* @file usbd_hid.h
*
* @brief usb device hid class handler header file
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Define to prevent recursive inclusion */
#ifndef _USBD_HID_H_
#define _USBD_HID_H_
/* Includes */
#include "usbd_core.h"
/** @addtogroup APM32_USB_Library
@{
*/
/** @addtogroup USBD_HID_Class
@{
*/
/** @defgroup USBD_HID_Macros Macros
@{
*/
#define USBD_HID_MOUSE_REPORT_DESC_SIZE 74
#define USBD_HID_KEYBOARD_REPORT_DESC_SIZE 63
#define USBD_HID_DESC_SIZE 9
#define USBD_HID_FS_INTERVAL 10
#define USBD_HID_HS_INTERVAL 7
#define USBD_HID_IN_EP_ADDR 0x81
#define USBD_HID_IN_EP_SIZE 0x04
#define USBD_HID_FS_MP_SIZE 0x40
#define USBD_CLASS_SET_IDLE 0x0A
#define USBD_CLASS_GET_IDLE 0x02
#define USBD_CLASS_SET_REPORT 0x09
#define USBD_CLASS_GET_REPORT 0x01
#define USBD_CLASS_SET_PROTOCOL 0x0B
#define USBD_CLASS_GET_PROTOCOL 0x03
/**@} end of group USBD_HID_Macros*/
/** @defgroup USBD_HID_Enumerates Enumerates
@{
*/
/**
* @brief HID state type
*/
typedef enum
{
USBD_HID_IDLE,
USBD_HID_BUSY,
} USBD_HID_STATE_T;
/**
* @brief HID keyboard value
*/
typedef enum
{
KEYBOARD_NONE,
KEYBOARD_ERROR_ROLL_OVER,
KEYBOARD_POST_FAIL,
KEYBOARD_ERROR_UNDEFINED,
KEYBOARD_A,
KEYBOARD_B,
KEYBOARD_C,
KEYBOARD_D,
KEYBOARD_E,
KEYBOARD_F,
KEYBOARD_G,
KEYBOARD_H,
KEYBOARD_I,
KEYBOARD_J,
KEYBOARD_K,
KEYBOARD_L,
KEYBOARD_M,
KEYBOARD_N,
KEYBOARD_O,
KEYBOARD_P,
KEYBOARD_Q,
KEYBOARD_R,
KEYBOARD_S,
KEYBOARD_T,
KEYBOARD_U,
KEYBOARD_V,
KEYBOARD_W,
KEYBOARD_X,
KEYBOARD_Y,
KEYBOARD_Z,
KEYBOARD_1_EXCLAMATION,
KEYBOARD_2_AT,
KEYBOARD_3_NUMBER_SIGN,
KEYBOARD_4_DOLLAR,
KEYBOARD_5_PERCENT,
KEYBOARD_6_CARET,
KEYBOARD_7_AMPERSAND,
KEYBOARD_8_ASTERISK,
KEYBOARD_9_OPARENTHESIS,
KEYBOARD_10_CPARENTHESIS,
KEYBOARD_ENTER,
KEYBOARD_ESCAPE,
KEYBOARD_BACKSPACE,
KEYBOARD_TAB,
KEYBOARD_SPACEBAR,
KEYBOARD_MINUS_UNDERSCORE,
KEYBOARD_EQUAL_PLUS,
KEYBOARD_OBRACKET_AND_OBRACE,
KEYBOARD_CBRACKET_AND_CBRACE,
KEYBOARD_BACKSLASH_VERTICAL_BAR,
KEYBOARD_NONUS_NUMBER_SIGN_TILDE,
KEYBOARD_SEMICOLON_COLON,
KEYBOARD_SINGLE_AND_DOUBLE_QUOTE,
KEYBOARD_GRAVE_ACCENT_AND_TILDE,
KEYBOARD_COMMA_AND_LESS,
KEYBOARD_DOT_GREATER,
KEYBOARD_SLASH_QUESTION,
KEYBOARD_CAPS_LOCK,
KEYBOARD_F1,
KEYBOARD_F2,
KEYBOARD_F3,
KEYBOARD_F4,
KEYBOARD_F5,
KEYBOARD_F6,
KEYBOARD_F7,
KEYBOARD_F8,
KEYBOARD_F9,
KEYBOARD_F10,
KEYBOARD_F11,
KEYBOARD_F12,
KEYBOARD_PRINTSCREEN,
KEYBOARD_SCROLL_LOCK,
KEYBOARD_PAUSE,
KEYBOARD_INSERT,
KEYBOARD_HOME,
KEYBOARD_PAGEUP,
KEYBOARD_DELETE,
KEYBOARD_END1,
KEYBOARD_PAGEDOWN,
KEYBOARD_RIGHTARROW,
KEYBOARD_LEFTARROW,
KEYBOARD_DOWNARROW,
KEYBOARD_UPARROW,
KEYBOARD_KEYBOARDPAD_NUM_LOCK_AND_CLEAR,
KEYBOARD_KEYBOARDPAD_SLASH,
KEYBOARD_KEYBOARDPAD_ASTERIKS,
KEYBOARD_KEYBOARDPAD_MINUS,
KEYBOARD_KEYBOARDPAD_PLUS,
KEYBOARD_KEYBOARDPAD_ENTER,
KEYBOARD_KEYBOARDPAD_1_END,
KEYBOARD_KEYBOARDPAD_2_DOWN_ARROW,
KEYBOARD_KEYBOARDPAD_3_PAGEDN,
KEYBOARD_KEYBOARDPAD_4_LEFT_ARROW,
KEYBOARD_KEYBOARDPAD_5,
KEYBOARD_KEYBOARDPAD_6_RIGHT_ARROW,
KEYBOARD_KEYBOARDPAD_7_HOME,
KEYBOARD_KEYBOARDPAD_8_UP_ARROW,
KEYBOARD_KEYBOARDPAD_9_PAGEUP,
KEYBOARD_KEYBOARDPAD_0_INSERT,
KEYBOARD_KEYBOARDPAD_DECIMAL_SEPARATOR_DELETE,
KEYBOARD_NONUS_BACK_SLASH_VERTICAL_BAR,
KEYBOARD_APPLICATION,
KEYBOARD_POWER,
KEYBOARD_KEYBOARDPAD_EQUAL,
KEYBOARD_F13,
KEYBOARD_F14,
KEYBOARD_F15,
KEYBOARD_F16,
KEYBOARD_F17,
KEYBOARD_F18,
KEYBOARD_F19,
KEYBOARD_F20,
KEYBOARD_F21,
KEYBOARD_F22,
KEYBOARD_F23,
KEYBOARD_F24,
KEYBOARD_EXECUTE,
KEYBOARD_HELP,
KEYBOARD_MENU,
KEYBOARD_SELECT,
KEYBOARD_STOP,
KEYBOARD_AGAIN,
KEYBOARD_UNDO,
KEYBOARD_CUT,
KEYBOARD_COPY,
KEYBOARD_PASTE,
KEYBOARD_FIND,
KEYBOARD_MUTE,
KEYBOARD_VOLUME_UP,
KEYBOARD_VOLUME_DOWN,
KEYBOARD_LOCKING_CAPS_LOCK,
KEYBOARD_LOCKING_NUM_LOCK,
KEYBOARD_LOCKING_SCROLL_LOCK,
KEYBOARD_KEYBOARDPAD_COMMA,
KEYBOARD_KEYBOARDPAD_EQUAL_SIGN,
KEYBOARD_INTERNATIONAL1,
KEYBOARD_INTERNATIONAL2,
KEYBOARD_INTERNATIONAL3,
KEYBOARD_INTERNATIONAL4,
KEYBOARD_INTERNATIONAL5,
KEYBOARD_INTERNATIONAL6,
KEYBOARD_INTERNATIONAL7,
KEYBOARD_INTERNATIONAL8,
KEYBOARD_INTERNATIONAL9,
KEYBOARD_LANG1,
KEYBOARD_LANG2,
KEYBOARD_LANG3,
KEYBOARD_LANG4,
KEYBOARD_LANG5,
KEYBOARD_LANG6,
KEYBOARD_LANG7,
KEYBOARD_LANG8,
KEYBOARD_LANG9,
KEYBOARD_ALTERNATE_ERASE,
KEYBOARD_SYSREQ,
KEYBOARD_CANCEL,
KEYBOARD_CLEAR,
KEYBOARD_PRIOR,
KEYBOARD_RETURN,
KEYBOARD_SEPARATOR,
KEYBOARD_OUT,
KEYBOARD_OPER,
KEYBOARD_CLEAR_AGAIN,
KEYBOARD_CRSEL,
KEYBOARD_EXSEL,
KEYBOARD_RESERVED1,
KEYBOARD_RESERVED2,
KEYBOARD_RESERVED3,
KEYBOARD_RESERVED4,
KEYBOARD_RESERVED5,
KEYBOARD_RESERVED6,
KEYBOARD_RESERVED7,
KEYBOARD_RESERVED8,
KEYBOARD_RESERVED9,
KEYBOARD_RESERVED10,
KEYBOARD_RESERVED11,
KEYBOARD_KEYBOARDPAD_00,
KEYBOARD_KEYBOARDPAD_000,
KEYBOARD_THOUSANDS_SEPARATOR,
KEYBOARD_DECIMAL_SEPARATOR,
KEYBOARD_CURRENCY_UNIT,
KEYBOARD_CURRENCY_SUB_UNIT,
KEYBOARD_KEYBOARDPAD_OPARENTHESIS,
KEYBOARD_KEYBOARDPAD_CPARENTHESIS,
KEYBOARD_KEYBOARDPAD_OBRACE,
KEYBOARD_KEYBOARDPAD_CBRACE,
KEYBOARD_KEYBOARDPAD_TAB,
KEYBOARD_KEYBOARDPAD_BACKSPACE,
KEYBOARD_KEYBOARDPAD_A,
KEYBOARD_KEYBOARDPAD_B,
KEYBOARD_KEYBOARDPAD_C,
KEYBOARD_KEYBOARDPAD_D,
KEYBOARD_KEYBOARDPAD_E,
KEYBOARD_KEYBOARDPAD_F,
KEYBOARD_KEYBOARDPAD_XOR,
KEYBOARD_KEYBOARDPAD_CARET,
KEYBOARD_KEYBOARDPAD_PERCENT,
KEYBOARD_KEYBOARDPAD_LESS,
KEYBOARD_KEYBOARDPAD_GREATER,
KEYBOARD_KEYBOARDPAD_AMPERSAND,
KEYBOARD_KEYBOARDPAD_LOGICAL_AND,
KEYBOARD_KEYBOARDPAD_VERTICAL_BAR,
KEYBOARD_KEYBOARDPAD_LOGIACL_OR,
KEYBOARD_KEYBOARDPAD_COLON,
KEYBOARD_KEYBOARDPAD_NUMBER_SIGN,
KEYBOARD_KEYBOARDPAD_SPACE,
KEYBOARD_KEYBOARDPAD_AT,
KEYBOARD_KEYBOARDPAD_EXCLAMATION_MARK,
KEYBOARD_KEYBOARDPAD_MEMORY_STORE,
KEYBOARD_KEYBOARDPAD_MEMORY_RECALL,
KEYBOARD_KEYBOARDPAD_MEMORY_CLEAR,
KEYBOARD_KEYBOARDPAD_MEMORY_ADD,
KEYBOARD_KEYBOARDPAD_MEMORY_SUBTRACT,
KEYBOARD_KEYBOARDPAD_MEMORY_MULTIPLY,
KEYBOARD_KEYBOARDPAD_MEMORY_DIVIDE,
KEYBOARD_KEYBOARDPAD_PLUSMINUS,
KEYBOARD_KEYBOARDPAD_CLEAR,
KEYBOARD_KEYBOARDPAD_CLEAR_ENTRY,
KEYBOARD_KEYBOARDPAD_BINARY,
KEYBOARD_KEYBOARDPAD_OCTAL,
KEYBOARD_KEYBOARDPAD_DECIMAL,
KEYBOARD_KEYBOARDPAD_HEXADECIMAL,
KEYBOARD_RESERVED12,
KEYBOARD_RESERVED13,
KEYBOARD_LEFTCONTROL,
KEYBOARD_LEFTSHIFT,
KEYBOARD_LEFTALT,
KEYBOARD_LEFT_GUI,
KEYBOARD_RIGHTCONTROL,
KEYBOARD_RIGHTSHIFT,
KEYBOARD_RIGHTALT,
KEYBOARD_RIGHT_GUI,
} USBH_HID_KEYBOARD_VALUE_T;
/**@} end of group USBD_HID_Enumerates*/
/** @defgroup USBD_HID_Structures Structures
@{
*/
/**
* @brief HID information management
*/
typedef struct
{
uint8_t state;
uint8_t epInAddr;
uint8_t altSettingStatus;
uint8_t idleStatus;
uint8_t protocol;
} USBD_HID_INFO_T;
extern USBD_CLASS_T USBD_HID_CLASS;
/**@} end of group USBD_HID_Structures*/
/** @defgroup USBD_HID_Functions Functions
@{
*/
uint8_t USBD_HID_ReadInterval(USBD_INFO_T* usbInfo);
USBD_STA_T USBD_HID_TxReport(USBD_INFO_T* usbInfo, uint8_t* report, uint16_t length);
/**@} end of group USBD_HID_Functions */
/**@} end of group USBD_HID_Class */
/**@} end of group APM32_USB_Library */
#endif

View file

@ -0,0 +1,523 @@
/*!
* @file usbd_hid.c
*
* @brief usb device hid class handler
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Includes */
#include "usbd_hid.h"
#include "usbd_stdReq.h"
#include "usbd_dataXfer.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/** @addtogroup APM32_USB_Library
@{
*/
/** @addtogroup USBD_HID_Class
@{
*/
/** @defgroup USBD_HID_Functions Functions
@{
*/
static USBD_STA_T USBD_HID_ClassInitHandler(USBD_INFO_T* usbInfo, uint8_t cfgIndex);
static USBD_STA_T USBD_HID_ClassDeInitHandler(USBD_INFO_T* usbInfo, uint8_t cfgIndex);
static USBD_STA_T USBD_HID_SOFHandler(USBD_INFO_T* usbInfo);
static USBD_STA_T USBD_HID_SetupHandler(USBD_INFO_T* usbInfo, USBD_REQ_SETUP_T* req);
static USBD_STA_T USBD_HID_DataInHandler(USBD_INFO_T* usbInfo, uint8_t epNum);
static USBD_DESC_INFO_T USBD_HID_ReportDescHandler(uint8_t usbSpeed);
static USBD_DESC_INFO_T USBD_HID_DescHandler(uint8_t usbSpeed);
/**@} end of group USBD_HID_Functions */
/** @defgroup USBD_HID_Structures Structures
@{
*/
/* HID class handler */
USBD_CLASS_T USBD_HID_CLASS =
{
/* Class handler */
"Class HID",
NULL,
USBD_HID_ClassInitHandler,
USBD_HID_ClassDeInitHandler,
USBD_HID_SOFHandler,
/* Control endpoint */
USBD_HID_SetupHandler,
NULL,
NULL,
/* Specific endpoint */
USBD_HID_DataInHandler,
NULL,
NULL,
NULL,
};
/**@} end of group USBD_HID_Structures*/
/** @defgroup USBD_HID_Variables Variables
@{
*/
/**
* @brief HID descriptor
*/
uint8_t USBD_HIDDesc[USBD_HID_DESC_SIZE] =
{
/* bLength */
0x09,
/* bDescriptorType: HID */
USBD_DESC_HID,
/* bcdHID */
0x11, 0x01,
/* bCountryCode */
0x00,
/* bNumDescriptors */
0x01,
/* bDescriptorType */
USBD_DESC_HID_REPORT,
/* wItemLength */
USBD_HID_MOUSE_REPORT_DESC_SIZE & 0xFF, USBD_HID_MOUSE_REPORT_DESC_SIZE >> 8,
};
/**
* @brief HID mouse report descriptor
*/
uint8_t USBD_HIDReportDesc[USBD_HID_MOUSE_REPORT_DESC_SIZE] =
{
0x05, 0x01, /* Usage Page (Generic Desktop Ctrls) */
0x09, 0x02, /* Usage (Mouse) */
0xA1, 0x01, /* Collection (Application) */
0x09, 0x01, /* Usage (Pointer) */
0xA1, 0x00, /* Collection (Physical) */
0x05, 0x09, /* Usage Page (Button) */
0x19, 0x01, /* Usage Minimum (0x01) */
0x29, 0x03, /* Usage Maximum (0x03) */
0x15, 0x00, /* Logical Minimum (0) */
0x25, 0x01, /* Logical Maximum (1) */
0x95, 0x03, /* Report Count (3) */
0x75, 0x01, /* Report Size (1) */
0x81, 0x02, /* Input (Data,Var,Abs) */
0x95, 0x01, /* Report Count (1) */
0x75, 0x05, /* Report Size (5) */
0x81, 0x01, /* Input (Const,Array,Abs) */
0x05, 0x01, /* Usage Page (Generic Desktop Ctrls) */
0x09, 0x30, /* Usage (X) */
0x09, 0x31, /* Usage (Y) */
0x09, 0x38, /* Usage (Wheel) */
0x15, 0x81, /* Logical Minimum (-127) */
0x25, 0x7F, /* Logical Maximum (127) */
0x75, 0x08, /* Report Size (8) */
0x95, 0x03, /* Report Count (3) */
0x81, 0x06, /* Input (Data,Var,Rel) */
0xC0, /* End Collection */
0x09, 0x3C, /* Usage (Motion Wakeup) */
0x05, 0xFF, /* Usage Page (Reserved 0xFF) */
0x09, 0x01, /* Usage (0x01) */
0x15, 0x00, /* Logical Minimum (0) */
0x25, 0x01, /* Logical Maximum (1) */
0x75, 0x01, /* Report Size (1) */
0x95, 0x02, /* Report Count (2) */
0xB1, 0x22, /* Feature (Data,Var,Abs,NoWrp) */
0x75, 0x06, /* Report Size (6) */
0x95, 0x01, /* Report Count (1) */
0xB1, 0x01, /* Feature (Const,Array,Abs,NoWrp) */
0xC0 /* End Collection */
};
/**@} end of group USBD_HID_Variables*/
/** @defgroup USBD_HID_Functions Functions
@{
*/
/*!
* @brief USB device HID configuration handler
*
* @param usbInfo: usb device information
*
* @param cfgIndex: configuration index
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_HID_ClassInitHandler(USBD_INFO_T* usbInfo, uint8_t cfgIndex)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_HID_INFO_T* usbDevHID;
/* Link class data */
usbInfo->devClass[usbInfo->classID]->classData = (USBD_HID_INFO_T*)malloc(sizeof(USBD_HID_INFO_T));
usbDevHID = (USBD_HID_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
memset(usbDevHID, 0, sizeof(USBD_HID_INFO_T));
USBD_USR_Debug("USBD_HID_INFO_T size %d\r\n", sizeof(USBD_HID_INFO_T));
if (usbDevHID == NULL)
{
USBD_USR_LOG("usbDevHID is NULL");
return USBD_FAIL;
}
usbDevHID->epInAddr = USBD_HID_IN_EP_ADDR;
if (usbInfo->devSpeed == USBD_SPEED_FS)
{
usbInfo->devEpIn[usbDevHID->epInAddr & 0x0F].interval = USBD_HID_FS_INTERVAL;
}
else
{
usbInfo->devEpIn[usbDevHID->epInAddr & 0x0F].interval = USBD_HID_HS_INTERVAL;
}
/* Open endpoint */
USBD_EP_OpenCallback(usbInfo, usbDevHID->epInAddr, EP_TYPE_INTERRUPT, USBD_HID_IN_EP_SIZE);
usbInfo->devEpIn[usbDevHID->epInAddr & 0x0F].useStatus = ENABLE;
usbDevHID->state = USBD_HID_IDLE;
return usbStatus;
}
/*!
* @brief USB device HID reset handler
*
* @param usbInfo: usb device information
*
* @param cfgIndex: configuration index
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_HID_ClassDeInitHandler(USBD_INFO_T* usbInfo, uint8_t cfgIndex)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_HID_INFO_T* usbDevHID = (USBD_HID_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
/* Close HID EP */
USBD_EP_CloseCallback(usbInfo, usbDevHID->epInAddr);
usbInfo->devEpIn[usbDevHID->epInAddr & 0x0F].interval = 0;
usbInfo->devEpIn[usbDevHID->epInAddr & 0x0F].useStatus = DISABLE;
if (usbInfo->devClass[usbInfo->classID]->classData != NULL)
{
free(usbInfo->devClass[usbInfo->classID]->classData);
usbInfo->devClass[usbInfo->classID]->classData = 0;
}
return usbStatus;
}
/*!
* @brief USB device HID SOF handler
*
* @param usbInfo: usb device information
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_HID_SOFHandler(USBD_INFO_T* usbInfo)
{
USBD_STA_T usbStatus = USBD_BUSY;
return usbStatus;
}
/*!
* @brief USB device HID SETUP handler
*
* @param usbInfo: usb device information
*
* @param req: setup request
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_HID_SetupHandler(USBD_INFO_T* usbInfo, USBD_REQ_SETUP_T* req)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_HID_INFO_T* usbDevHID = (USBD_HID_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
USBD_DESC_INFO_T descInfo;
uint8_t request;
uint8_t reqType;
uint16_t wValue = req->DATA_FIELD.wValue[0] | req->DATA_FIELD.wValue[1] << 8;
uint16_t wLength = req->DATA_FIELD.wLength[0] | req->DATA_FIELD.wLength[1] << 8;
uint16_t status = 0x0000;
if (usbDevHID == NULL)
{
USBD_USR_LOG("usbDevHID is NULL");
return USBD_FAIL;
}
request = req->DATA_FIELD.bRequest;
reqType = usbInfo->reqSetup.DATA_FIELD.bmRequest.REQ_TYPE_B.type;
switch (reqType)
{
case USBD_REQ_TYPE_STANDARD:
switch (request)
{
/* HID descriptor */
case USBD_STD_GET_DESCRIPTOR:
switch (req->DATA_FIELD.wValue[1])
{
case USBD_DESC_HID_REPORT:
descInfo = USBD_HID_ReportDescHandler(usbInfo->devSpeed);
descInfo.size = descInfo.size < wLength ? descInfo.size : wLength;
break;
case USBD_DESC_HID:
descInfo = USBD_HID_DescHandler(usbInfo->devSpeed);
descInfo.size = descInfo.size < wLength ? descInfo.size : wLength;
break;
default:
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
break;
}
if (descInfo.desc != NULL)
{
USBD_CtrlSendData(usbInfo, descInfo.desc, descInfo.size);
}
break;
case USBD_STD_GET_STATUS:
if (usbInfo->devState == USBD_DEV_CONFIGURE)
{
USBD_CtrlSendData(usbInfo, (uint8_t*)&status, 2);
}
else
{
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
}
break;
case USBD_STD_GET_INTERFACE:
if (usbInfo->devState == USBD_DEV_CONFIGURE)
{
USBD_CtrlSendData(usbInfo, (uint8_t*)&usbDevHID->altSettingStatus, 1);
}
else
{
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
}
break;
case USBD_STD_SET_INTERFACE:
if (usbInfo->devState == USBD_DEV_CONFIGURE)
{
usbDevHID->altSettingStatus = wValue;
}
else
{
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
}
break;
case USBD_STD_CLEAR_FEATURE:
break;
default:
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
break;
}
break;
case USBD_REQ_TYPE_CLASS:
switch (request)
{
case USBD_CLASS_SET_IDLE:
usbDevHID->idleStatus = req->DATA_FIELD.wValue[1];
break;
case USBD_CLASS_GET_IDLE:
USBD_CtrlSendData(usbInfo, (uint8_t*)&usbDevHID->idleStatus, 1);
break;
case USBD_CLASS_SET_PROTOCOL:
usbDevHID->protocol = req->DATA_FIELD.wValue[0];
break;
case USBD_CLASS_GET_PROTOCOL:
USBD_CtrlSendData(usbInfo, (uint8_t*)&usbDevHID->protocol, 1);
break;
default:
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
break;
}
break;
case USBD_REQ_TYPE_VENDOR:
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
break;
default:
usbStatus = USBD_FAIL;
USBD_REQ_CtrlError(usbInfo, req);
break;
}
return usbStatus;
}
/*!
* @brief USB device HID IN data handler
*
* @param usbInfo: usb device information
*
* @param epNum: endpoint number
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_HID_DataInHandler(USBD_INFO_T* usbInfo, uint8_t epNum)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_HID_INFO_T* usbDevHID = (USBD_HID_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
if (usbDevHID == NULL)
{
return USBD_FAIL;
}
usbDevHID->state = USBD_HID_IDLE;
return usbStatus;
}
/*!
* @brief USB device HID report descriptor
*
* @param usbSpeed : usb speed
*
* @retval usb descriptor information
*/
static USBD_DESC_INFO_T USBD_HID_ReportDescHandler(uint8_t usbSpeed)
{
USBD_DESC_INFO_T descInfo;
descInfo.desc = USBD_HIDReportDesc;
descInfo.size = sizeof(USBD_HIDReportDesc);
return descInfo;
}
/*!
* @brief USB device HID descriptor
*
* @param usbSpeed : usb speed
*
* @retval usb descriptor information
*/
static USBD_DESC_INFO_T USBD_HID_DescHandler(uint8_t usbSpeed)
{
USBD_DESC_INFO_T descInfo;
descInfo.desc = USBD_HIDDesc;
descInfo.size = sizeof(USBD_HIDDesc);
return descInfo;
}
/*!
* @brief USB device HID send report descriptor
*
* @param usbInfo: usb device information
*
* @param report: report buffer
*
* @param length: report data length
*
* @retval usb descriptor information
*/
USBD_STA_T USBD_HID_TxReport(USBD_INFO_T* usbInfo, uint8_t* report, uint16_t length)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_HID_INFO_T* usbDevHID = (USBD_HID_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
if (usbDevHID == NULL)
{
return USBD_FAIL;
}
switch (usbInfo->devState)
{
case USBD_DEV_CONFIGURE:
if (usbDevHID->state == USBD_HID_IDLE)
{
usbDevHID->state = USBD_HID_BUSY;
USBD_EP_TransferCallback(usbInfo, usbDevHID->epInAddr, report, length);
}
break;
default:
break;
}
return usbStatus;
}
/*!
* @brief USB device HID read interval
*
* @param usbInfo: usb device information
*
* @retval usb interval
*/
uint8_t USBD_HID_ReadInterval(USBD_INFO_T* usbInfo)
{
uint8_t interval;
if (usbInfo->devSpeed == USBD_SPEED_FS)
{
interval = USBD_HID_FS_INTERVAL;
}
else
{
interval = ((1 << (USBD_HID_HS_INTERVAL - 1)) / 8);
}
return interval;
}
/**@} end of group USBD_HID_Functions */
/**@} end of group USBD_HID_Class */
/**@} end of group APM32_USB_Library */

View file

@ -0,0 +1,515 @@
/*!
* @file usbd_hid_keyboard.c
*
* @brief usb device hid class handler
*
* @version V1.0.0
*
* @date 2023-03-23
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Includes */
#include "usbd_hid.h"
#include "usbd_stdReq.h"
#include "usbd_dataXfer.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/** @addtogroup APM32_USB_Library
@{
*/
/** @addtogroup USBD_HID_Class
@{
*/
/** @defgroup USBD_HID_Keyboard_Functions Functions
@{
*/
static USBD_STA_T USBD_HID_ClassInitHandler(USBD_INFO_T* usbInfo, uint8_t cfgIndex);
static USBD_STA_T USBD_HID_ClassDeInitHandler(USBD_INFO_T* usbInfo, uint8_t cfgIndex);
static USBD_STA_T USBD_HID_SOFHandler(USBD_INFO_T* usbInfo);
static USBD_STA_T USBD_HID_SetupHandler(USBD_INFO_T* usbInfo, USBD_REQ_SETUP_T* req);
static USBD_STA_T USBD_HID_DataInHandler(USBD_INFO_T* usbInfo, uint8_t epNum);
static USBD_DESC_INFO_T USBD_HID_ReportDescHandler(uint8_t usbSpeed);
static USBD_DESC_INFO_T USBD_HID_DescHandler(uint8_t usbSpeed);
/**@} end of group USBD_HID_Keyboard_Functions */
/** @defgroup USBD_HID_Keyboard_Structures Structures
@{
*/
/* HID class handler */
USBD_CLASS_T USBD_HID_CLASS =
{
/* Class handler */
"Class HID",
NULL,
USBD_HID_ClassInitHandler,
USBD_HID_ClassDeInitHandler,
USBD_HID_SOFHandler,
/* Control endpoint */
USBD_HID_SetupHandler,
NULL,
NULL,
/* Specific endpoint */
USBD_HID_DataInHandler,
NULL,
NULL,
NULL,
};
/**@} end of group USBD_HID_Keyboard_Structures*/
/** @defgroup USBD_HID_Keyboard_Variables Variables
@{
*/
/**
* @brief HID descriptor
*/
uint8_t USBD_HIDDesc[USBD_HID_DESC_SIZE] =
{
/* bLength */
0x09,
/* bDescriptorType: HID */
USBD_DESC_HID,
/* bcdHID */
0x11, 0x01,
/* bCountryCode */
0x00,
/* bNumDescriptors */
0x01,
/* bDescriptorType */
USBD_DESC_HID_REPORT,
/* wItemLength */
USBD_HID_KEYBOARD_REPORT_DESC_SIZE & 0xFF, USBD_HID_KEYBOARD_REPORT_DESC_SIZE >> 8,
};
/**
* @brief HID keyboard report descriptor
*/
uint8_t USBD_HIDReportDesc[USBD_HID_KEYBOARD_REPORT_DESC_SIZE] =
{
0x05, 0x01, /* Usage Page (Generic Desktop Ctrls) */
0x09, 0x06, /* Usage (Keyboard) */
0xA1, 0x01, /* Collection (Application) */
0x05, 0x07, /* Usage Page (Keyboard) */
0x19, 0xE0, /* Usage Mininum (Keyboard LeftControl) */
0x29, 0xE7, /* Usage Maxinum (Keyboard Right GUI) */
0x15, 0x00, /* Logical Mininum (0) */
0x25, 0x01, /* Logical Maxinum (1) */
0x75, 0x01, /* Report Size (1) */
0x95, 0x08, /* Report Count (8) */
0x81, 0x02, /* Input (Data,Var,Abs) */
0x95, 0x01, /* Report Count (1) */
0x75, 0x08, /* Report Size (8) */
0x81, 0x03, /* Input (Cnst,Var,Abs) */
0x95, 0x05, /* Report Count (5) */
0x75, 0x01, /* Report Size (1) */
0x05, 0x08, /* Usage Page (LEDs) */
0x19, 0x01, /* Usage Mininum (Num Lock) */
0x29, 0x05, /* Usage Maxinum (Kana) */
0x91, 0x02, /* Output (Data,Var,Abs) */
0x95, 0x01, /* Report Count (1) */
0x75, 0x03, /* Report Size (3) */
0x91, 0x03, /* Output (Cnst,Var,Abs) */
0x95, 0x06, /* Report Count (6) */
0x75, 0x08, /* Report Size (8) */
0x15, 0x00, /* Logical Mininum (0) */
0x25, 0x65, /* Logical Maxinum (101) */
0x05, 0x07, /* Usage Page (Keyboard) */
0x19, 0x00, /* Usage Mininum (Reserved (no event indicated)) */
0x29, 0x65, /* Usage Maxinum (Keyboard Application) */
0x81, 0x00, /* Input (Data,Ary,Abs) */
0xC0 /* End Collection */
};
/**@} end of group USBD_HID_Keyboard_Variables*/
/** @defgroup USBD_HID_Keyboard_Functions Functions
@{
*/
/*!
* @brief USB device HID configuration handler
*
* @param usbInfo: usb device information
*
* @param cfgIndex: configuration index
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_HID_ClassInitHandler(USBD_INFO_T* usbInfo, uint8_t cfgIndex)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_HID_INFO_T* usbDevHID;
/* Link class data */
usbInfo->devClass[usbInfo->classID]->classData = (USBD_HID_INFO_T*)malloc(sizeof(USBD_HID_INFO_T));
usbDevHID = (USBD_HID_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
memset(usbDevHID, 0, sizeof(USBD_HID_INFO_T));
USBD_USR_Debug("USBD_HID_INFO_T size %d\r\n", sizeof(USBD_HID_INFO_T));
if (usbDevHID == NULL)
{
USBD_USR_LOG("usbDevHID is NULL");
return USBD_FAIL;
}
usbDevHID->epInAddr = USBD_HID_IN_EP_ADDR;
if (usbInfo->devSpeed == USBD_SPEED_FS)
{
usbInfo->devEpIn[usbDevHID->epInAddr & 0x0F].interval = USBD_HID_FS_INTERVAL;
}
else
{
usbInfo->devEpIn[usbDevHID->epInAddr & 0x0F].interval = USBD_HID_HS_INTERVAL;
}
/* Open endpoint */
USBD_EP_OpenCallback(usbInfo, usbDevHID->epInAddr, EP_TYPE_INTERRUPT, USBD_HID_IN_EP_SIZE);
usbInfo->devEpIn[usbDevHID->epInAddr & 0x0F].useStatus = ENABLE;
usbDevHID->state = USBD_HID_IDLE;
return usbStatus;
}
/*!
* @brief USB device HID reset handler
*
* @param usbInfo: usb device information
*
* @param cfgIndex: configuration index
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_HID_ClassDeInitHandler(USBD_INFO_T* usbInfo, uint8_t cfgIndex)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_HID_INFO_T* usbDevHID = (USBD_HID_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
/* Close HID EP */
USBD_EP_CloseCallback(usbInfo, usbDevHID->epInAddr);
usbInfo->devEpIn[usbDevHID->epInAddr & 0x0F].interval = 0;
usbInfo->devEpIn[usbDevHID->epInAddr & 0x0F].useStatus = DISABLE;
if (usbInfo->devClass[usbInfo->classID]->classData != NULL)
{
free(usbInfo->devClass[usbInfo->classID]->classData);
usbInfo->devClass[usbInfo->classID]->classData = 0;
}
return usbStatus;
}
/*!
* @brief USB device HID SOF handler
*
* @param usbInfo: usb device information
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_HID_SOFHandler(USBD_INFO_T* usbInfo)
{
USBD_STA_T usbStatus = USBD_BUSY;
return usbStatus;
}
/*!
* @brief USB device HID SETUP handler
*
* @param usbInfo: usb device information
*
* @param req: setup request
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_HID_SetupHandler(USBD_INFO_T* usbInfo, USBD_REQ_SETUP_T* req)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_HID_INFO_T* usbDevHID = (USBD_HID_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
USBD_DESC_INFO_T descInfo;
uint8_t request;
uint8_t reqType;
uint16_t wValue = req->DATA_FIELD.wValue[0] | req->DATA_FIELD.wValue[1] << 8;
uint16_t wLength = req->DATA_FIELD.wLength[0] | req->DATA_FIELD.wLength[1] << 8;
uint16_t status = 0x0000;
if (usbDevHID == NULL)
{
USBD_USR_LOG("usbDevHID is NULL");
return USBD_FAIL;
}
request = req->DATA_FIELD.bRequest;
reqType = usbInfo->reqSetup.DATA_FIELD.bmRequest.REQ_TYPE_B.type;
switch (reqType)
{
case USBD_REQ_TYPE_STANDARD:
switch (request)
{
/* HID descriptor */
case USBD_STD_GET_DESCRIPTOR:
switch (req->DATA_FIELD.wValue[1])
{
case USBD_DESC_HID_REPORT:
descInfo = USBD_HID_ReportDescHandler(usbInfo->devSpeed);
descInfo.size = descInfo.size < wLength ? descInfo.size : wLength;
break;
case USBD_DESC_HID:
descInfo = USBD_HID_DescHandler(usbInfo->devSpeed);
descInfo.size = descInfo.size < wLength ? descInfo.size : wLength;
break;
default:
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
break;
}
if (descInfo.desc != NULL)
{
USBD_CtrlSendData(usbInfo, descInfo.desc, descInfo.size);
}
break;
case USBD_STD_GET_STATUS:
if (usbInfo->devState == USBD_DEV_CONFIGURE)
{
USBD_CtrlSendData(usbInfo, (uint8_t*)&status, 2);
}
else
{
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
}
break;
case USBD_STD_GET_INTERFACE:
if (usbInfo->devState == USBD_DEV_CONFIGURE)
{
USBD_CtrlSendData(usbInfo, (uint8_t*)&usbDevHID->altSettingStatus, 1);
}
else
{
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
}
break;
case USBD_STD_SET_INTERFACE:
if (usbInfo->devState == USBD_DEV_CONFIGURE)
{
usbDevHID->altSettingStatus = wValue;
}
else
{
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
}
break;
case USBD_STD_CLEAR_FEATURE:
break;
default:
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
break;
}
break;
case USBD_REQ_TYPE_CLASS:
switch (request)
{
case USBD_CLASS_SET_IDLE:
usbDevHID->idleStatus = req->DATA_FIELD.wValue[1];
break;
case USBD_CLASS_GET_IDLE:
USBD_CtrlSendData(usbInfo, (uint8_t*)&usbDevHID->idleStatus, 1);
break;
case USBD_CLASS_SET_PROTOCOL:
usbDevHID->protocol = req->DATA_FIELD.wValue[0];
break;
case USBD_CLASS_GET_PROTOCOL:
USBD_CtrlSendData(usbInfo, (uint8_t*)&usbDevHID->protocol, 1);
break;
default:
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
break;
}
break;
case USBD_REQ_TYPE_VENDOR:
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
break;
default:
usbStatus = USBD_FAIL;
USBD_REQ_CtrlError(usbInfo, req);
break;
}
return usbStatus;
}
/*!
* @brief USB device HID IN data handler
*
* @param usbInfo: usb device information
*
* @param epNum: endpoint number
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_HID_DataInHandler(USBD_INFO_T* usbInfo, uint8_t epNum)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_HID_INFO_T* usbDevHID = (USBD_HID_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
if (usbDevHID == NULL)
{
return USBD_FAIL;
}
usbDevHID->state = USBD_HID_IDLE;
return usbStatus;
}
/*!
* @brief USB device HID report descriptor
*
* @param usbSpeed : usb speed
*
* @retval usb descriptor information
*/
static USBD_DESC_INFO_T USBD_HID_ReportDescHandler(uint8_t usbSpeed)
{
USBD_DESC_INFO_T descInfo;
descInfo.desc = USBD_HIDReportDesc;
descInfo.size = sizeof(USBD_HIDReportDesc);
return descInfo;
}
/*!
* @brief USB device HID descriptor
*
* @param usbSpeed : usb speed
*
* @retval usb descriptor information
*/
static USBD_DESC_INFO_T USBD_HID_DescHandler(uint8_t usbSpeed)
{
USBD_DESC_INFO_T descInfo;
descInfo.desc = USBD_HIDDesc;
descInfo.size = sizeof(USBD_HIDDesc);
return descInfo;
}
/*!
* @brief USB device HID send report descriptor
*
* @param usbInfo: usb device information
*
* @param report: report buffer
*
* @param length: report data length
*
* @retval usb descriptor information
*/
USBD_STA_T USBD_HID_TxReport(USBD_INFO_T* usbInfo, uint8_t* report, uint16_t length)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_HID_INFO_T* usbDevHID = (USBD_HID_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
if (usbDevHID == NULL)
{
return USBD_FAIL;
}
switch (usbInfo->devState)
{
case USBD_DEV_CONFIGURE:
if (usbDevHID->state == USBD_HID_IDLE)
{
usbDevHID->state = USBD_HID_BUSY;
USBD_EP_TransferCallback(usbInfo, usbDevHID->epInAddr, report, length);
}
break;
default:
break;
}
return usbStatus;
}
/*!
* @brief USB device HID read interval
*
* @param usbInfo: usb device information
*
* @retval usb interval
*/
uint8_t USBD_HID_ReadInterval(USBD_INFO_T* usbInfo)
{
uint8_t interval;
if (usbInfo->devSpeed == USBD_SPEED_FS)
{
interval = USBD_HID_FS_INTERVAL;
}
else
{
interval = ((1 << (USBD_HID_HS_INTERVAL - 1)) / 8);
}
return interval;
}
/**@} end of group USBD_HID_Keyboard_Functions */
/**@} end of group USBD_HID_Class */
/**@} end of group APM32_USB_Library */

View file

@ -0,0 +1,122 @@
/*!
* @file usbd_msc.h
*
* @brief usb device msc class handler header file
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Define to prevent recursive inclusion */
#ifndef _USBD_MSC_H_
#define _USBD_MSC_H_
/* Includes */
#include "usbd_core.h"
#include "usbd_msc_scsi.h"
#include "usbd_msc_bot.h"
/** @addtogroup APM32_USB_Library
@{
*/
/** @addtogroup USBD_MSC_Class
@{
*/
/** @defgroup USBD_MSC_Macros Macros
@{
*/
#define USBD_MSC_OUT_EP_ADDR 0x01
#define USBD_MSC_IN_EP_ADDR 0x81
#define USBD_MSC_FS_MP_SIZE 0x40
#define USBD_MSC_HS_MP_SIZE 0x200
#define USBD_CLASS_GET_MAX_LUN 0xFE
#define USBD_CLASS_BOT_RESET 0xFF
/**@} end of group USBD_MSC_Macros*/
/** @defgroup USBD_MSC_Structures Structures
@{
*/
/**
* @brief USB device storage handler
*/
typedef struct
{
const char* memoryName;
uint8_t* inquiryData;
uint8_t (*MemoryReadMaxLun)(void);
USBD_STA_T (*MemoryInit)(uint8_t lun);
USBD_STA_T (*MemoryReadCapacity)(uint8_t lun, uint32_t* blockNum, uint16_t* blockSize);
USBD_STA_T (*MemoryCheckReady)(uint8_t lun);
USBD_STA_T (*MemoryCheckWPR)(uint8_t lun);
USBD_STA_T (*MemoryReadData)(uint8_t lun, uint8_t* buffer, uint32_t blockAddr, uint16_t blockLength);
USBD_STA_T (*MemoryWriteData)(uint8_t lun, uint8_t* buffer, uint32_t blockAddr, uint16_t blockLength);
} USBD_MSC_MEMORY_T;
typedef struct
{
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;
/**
* @brief MSC information management
*/
typedef struct
{
uint8_t epInAddr;
uint8_t epOutAddr;
uint8_t maxLun;
uint8_t itf;
USBD_MSC_BOT_T* mscBot;
USBD_BOT_INFO_T usbDevBOT;
USBD_SCSI_INFO_T usbDevSCSI;
} USBD_MSC_INFO_T;
extern USBD_CLASS_T USBD_MSC_CLASS;
/**@} end of group USBD_MSC_Structures*/
/** @defgroup USBD_MSC_Functions Functions
@{
*/
USBD_STA_T USBD_MSC_RegisterMemory(USBD_INFO_T* usbInfo, USBD_MSC_MEMORY_T* memory);
/**@} end of group USBD_MSC_Functions */
/**@} end of group USBD_MSC_Class */
/**@} end of group APM32_USB_Library */
#endif

View file

@ -0,0 +1,218 @@
/*!
* @file usbd_msc_bot.h
*
* @brief usb device msc bot handler header file
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Define to prevent recursive inclusion */
#ifndef _USBD_MSC_BOT_H_
#define _USBD_MSC_BOT_H_
/* Includes */
#include "usbd_core.h"
/** @addtogroup APM32_USB_Library
@{
*/
/** @addtogroup USBD_MSC_Class
@{
*/
/** @defgroup USBD_MSC_Macros Macros
@{
*/
/* CBW parameter */
#define USBD_MSC_BOT_CBW_SIGNATURE (uint32_t)(0x43425355)
#define USBD_MSC_BOT_CBW_TAG (uint32_t)(0x20304050)
#define USBD_MSC_BOT_CBW_LEN 31
#define USBD_BOT_CBW_CB_LEN 16
#define USBD_LEN_CBW 10
/* CSW parameter */
#define USBD_MSC_BOT_CSW_SIGNATURE (uint32_t)(0x53425355)
#define USBD_MSC_BOT_CSW_LEN 13
#define USBD_LEN_CSW_MAX 63
#ifndef USBD_SUP_MSC_MEDIA_PACKET
#define USBD_SUP_MSC_MEDIA_PACKET 512U
#endif /* USBD_SUP_MSC_MEDIA_PACKET */
/**@} end of group USBD_MSC_Macros*/
/** @defgroup USBD_MSC_Enumerates Enumerates
@{
*/
/**
* @brief SCSI transmission state of BOT
*/
typedef enum
{
USBD_BOT_IDLE,
USBD_BOT_DATAOUT,
USBD_BOT_DATAIN,
USBD_BOT_DATAIN_LAST,
USBD_BOT_DATA_SEND,
USBD_BOT_NO_DATA,
} USBD_BOT_STATE_T;
/**
* @brief SCSI transmission status of BOT
*/
typedef enum
{
USBD_BOT_NORMAL,
USBD_BOT_RECOVERY,
USBD_BOT_ERR,
} USBD_BOT_STATUS_T;
/**
* @brief CSW status of BOT
*/
typedef enum
{
USBD_BOT_CSW_OK,
USBD_BOT_CSW_FAIL,
USBD_BOT_CSW_ERROR,
} USBD_BOT_CSW_STA_T;
/**@} end of group USBD_MSC_Enumerates*/
/** @defgroup USBD_MSC_Structures Structures
@{
*/
/**
* @brief USB device SCSI handler
*/
typedef struct
{
USBD_STA_T(*MemoryInit)(uint8_t lun);
USBD_STA_T(*MemoryReadCapacity)(uint8_t lun, uint32_t* blockNum, uint16_t* blockSize);
USBD_STA_T(*MemoryCheckReady)(uint8_t lun);
USBD_STA_T(*MemoryCheckWPR)(uint8_t lun);
USBD_STA_T(*MemoryReadData)(uint8_t lun, uint8_t* buffer, uint32_t blockAddr, uint16_t blockLength);
USBD_STA_T(*MemoryWriteData)(uint8_t lun, uint8_t* buffer, uint32_t blockAddr, uint16_t blockLength);
} USBD_MSC_SCSI_T;
/**
* @brief CBW flag
*/
typedef union
{
uint8_t CBW_Flag;
struct
{
uint8_t reserved : 7;
uint8_t dir : 1;
} CBW_FLAG_B;
} USBD_BOT_CBW_FLAG_T;
/**
* @brief Command Block Wrapper
*/
typedef union
{
struct
{
uint32_t dSignature;
uint32_t dTag;
uint32_t dDataXferLen;
USBD_BOT_CBW_FLAG_T bmFlags;
uint8_t bLUN;
uint8_t bCBLen;
uint8_t CB[16];
} DATA_FIELD;
uint8_t buffer[31];
} USBD_BOT_CBW_T;
/**
* @brief Command Status Wrapper
*/
typedef union
{
struct
{
uint32_t dSignature;
uint32_t dTag;
uint32_t dDataResidue;
uint8_t bStatus;
} DATA_FIELD;
uint8_t buffer[13];
} USBD_BOT_CSW_T;
/**
* @brief USB device BOT handler
*/
typedef struct
{
USBD_STA_T(*Init)(USBD_INFO_T* usbInfo);
USBD_STA_T(*DeInit)(USBD_INFO_T* usbInfo);
} USBD_MSC_BOT_T;
/**
* @brief BOT transmission parameter
*/
typedef struct
{
USBD_BOT_CBW_T CBW;
USBD_BOT_CSW_T CSW;
USBD_BOT_CSW_STA_T cswStatus;
uint8_t cbwStatus;
} USBD_BOT_CMDPACK_T;
/**
* @brief MSC BOT information
*/
typedef struct
{
uint8_t state;
uint8_t status;
USBD_BOT_CMDPACK_T cmdPack;
uint32_t dataLen;
uint8_t data[USBD_SUP_MSC_MEDIA_PACKET];
} USBD_BOT_INFO_T;
/**@} end of group USBD_MSC_Structures*/
/** @defgroup USBD_MSC_Functions Functions
@{
*/
USBD_STA_T USBD_MSC_BOT_Init(USBD_INFO_T* usbInfo);
USBD_STA_T USBD_MSC_BOT_DeInit(USBD_INFO_T* usbInfo);
USBD_STA_T USBD_MSC_BOT_Reset(USBD_INFO_T* usbInfo);
USBD_STA_T USBD_MSC_BOT_CBW_Decode(USBD_INFO_T* usbInfo);
USBD_STA_T USBD_MSC_BOT_ClearFeature(USBD_INFO_T* usbInfo, uint8_t epNum);
USBD_STA_T USBD_MSC_BOT_SendCSW(USBD_INFO_T* usbInfo, USBD_BOT_CSW_STA_T status);
/**@} end of group USBD_MSC_Functions */
/**@} end of group USBD_MSC_Class */
/**@} end of group APM32_USB_Library */
#endif

View file

@ -0,0 +1,190 @@
/*!
* @file usbd_msc_scsi.h
*
* @brief usb device msc scsi handler header file
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Define to prevent recursive inclusion */
#ifndef _USBD_MSC_SCSI_H_
#define _USBD_MSC_SCSI_H_
/* Includes */
#include "usbd_core.h"
/** @addtogroup APM32_USB_Library
@{
*/
/** @addtogroup USBD_MSC_Class
@{
*/
/** @defgroup USBD_MSC_Macros Macros
@{
*/
/* Length define of command */
#define USBD_LEN_STD_INQUIRY 36
#define USBD_LEN_STD_MODE_SENSE6 23
#define USBD_LEN_STD_MODE_SENSE10 27
#define USBD_LEN_STD_REQ_SENSE 18
#define USBD_SCSI_SENSE_LIST_NUMBER 4
#define USBD_LEN_INQUIRY_PAGE00 6
#define USBD_LEN_INQUIRY_PAGE80 8
#define STANDARD_INQUIRY_DATA_LEN USBD_LEN_STD_INQUIRY
/* SCSI Commands */
#define USBD_SCSI_CMD_FORMAT_UNIT ((uint8_t)0x04)
#define USBD_SCSI_CMD_INQUIRY ((uint8_t)0x12)
#define USBD_SCSI_CMD_SEND_DIAGNOSTIC ((uint8_t)0x1D)
#define USBD_SCSI_CMD_ALLOW_MEDIUM_REMOVAL ((uint8_t)0x1E)
#define USBD_SCSI_CMD_MODE_SELECT_6 ((uint8_t)0x15)
#define USBD_SCSI_CMD_MODE_SELECT_10 ((uint8_t)0x55)
#define USBD_SCSI_CMD_MODE_SENSE_6 ((uint8_t)0x1A)
#define USBD_SCSI_CMD_MODE_SENSE_10 ((uint8_t)0x5A)
#define USBD_SCSI_CMD_READ_FORMAT_CAPACITIES ((uint8_t)0x23)
#define USBD_SCSI_CMD_READ_CAPACITY ((uint8_t)0x25)
#define USBD_SCSI_CMD_READ_CAPACITY_16 ((uint8_t)0x9E)
#define USBD_SCSI_CMD_REQUEST_SENSE ((uint8_t)0x03)
#define USBD_SCSI_CMD_START_STOP_UNIT ((uint8_t)0x1B)
#define USBD_SCSI_CMD_TEST_UNIT_READY ((uint8_t)0x00)
#define USBD_SCSI_CMD_WRITE6 ((uint8_t)0x0A)
#define USBD_SCSI_CMD_WRITE10 ((uint8_t)0x2A)
#define USBD_SCSI_CMD_WRITE12 ((uint8_t)0xAA)
#define USBD_SCSI_CMD_WRITE16 ((uint8_t)0x8A)
#define USBD_SCSI_CMD_VERIFY_10 ((uint8_t)0x2F)
#define USBD_SCSI_CMD_VERIFY_12 ((uint8_t)0xAF)
#define USBD_SCSI_CMD_VERIFY_16 ((uint8_t)0x8F)
#define USBD_SCSI_CMD_READ_6 ((uint8_t)0x08)
#define USBD_SCSI_CMD_READ_10 ((uint8_t)0x28)
#define USBD_SCSI_CMD_READ_12 ((uint8_t)0xA8)
#define USBD_SCSI_CMD_READ_16 ((uint8_t)0x88)
/**@} end of group USBD_MSC_Macros*/
/** @defgroup USBD_MSC_Enumerates Enumerates
@{
*/
/**
* @brief MSC SCSI medium status
*/
typedef enum
{
USBD_SCSI_MEDIUM_UNLOCK,
USBD_SCSI_MEDIUM_LOCK,
USBD_SCSI_MEDIUM_EJECT,
} USBD_MEDIUM_STA_T;
/**
* @brief SCSI sense key type
*/
typedef enum
{
USBD_SCSI_SENSE_KEY_NO_SENSE = 0x00,
USBD_SCSI_SENSE_KEY_RECOVERED_ERROR,
USBD_SCSI_SENSE_KEY_NOT_READY,
USBD_SCSI_SENSE_KEY_MEDIUM_ERROR,
USBD_SCSI_SENSE_KEY_HARDWARE_ERROR,
USBD_SCSI_SENSE_KEY_ILLEGAL_REQUEST,
USBD_SCSI_SENSE_KEY_UNIT_ATTENTION,
USBD_SCSI_SENSE_KEY_DATA_PROTECT,
USBD_SCSI_SENSE_KEY_BLANK_CHECK,
USBD_SCSI_SENSE_KEY_VENDOR_SPECIFIC,
USBD_SCSI_SENSE_KEY_COPY_ABORTED,
USBD_SCSI_SENSE_KEY_ABORTED_COMMAND,
USBD_SCSI_SENSE_KEY_VOLUME_OVERFLOW = 0x0D,
USBD_SCSI_SENSE_KEY_MISCOMPARE = 0x0E,
} USBD_SCSI_SENSE_KEY_T;
/**
* @brief SCSI sense ASC type
*/
typedef enum
{
USBD_SCSI_ASC_WRITE_FAULT = 0x03,
USBD_SCSI_ASC_UNRECOVERED_READ_ERROR = 0x11,
USBD_SCSI_ASC_PARAMETER_LIST_LENGTH_ERROR = 0x1A,
USBD_SCSI_ASC_INVALID_CDB = 0x20,
USBD_SCSI_ASC_ADDRESS_OUT_OF_RANGE = 0x21,
USBD_SCSI_ASC_INVALID_FIELED_IN_COMMAND = 0x24,
USBD_SCSI_ASC_INVALID_FIELD_IN_PARAMETER_LIST = 0x26,
USBD_SCSI_ASC_WRITE_PROTECTED = 0x27,
USBD_SCSI_ASC_MEDIUM_HAVE_CHANGED = 0x28,
USBD_SCSI_ASC_MEDIUM_NOT_PRESENT = 0x3A,
} USBD_SCSI_SENSE_ASC_T;
/**@} end of group USBD_MSC_Enumerates*/
/** @defgroup USBD_MSC_Structures Structures
@{
*/
/**
* @brief MSC SCSI sense data type
*/
typedef struct
{
uint8_t Key;
uint8_t ASC;
uint8_t ASCQ;
} USBD_SCSI_SENSE_T;
/**
* @brief MSC SCSI information
*/
typedef struct
{
uint8_t senseHead;
uint8_t senseEnd;
uint8_t mediumState;
uint16_t blockSize;
uint32_t blockNum;
uint32_t blockAddr;
uint32_t blockLen;
USBD_SCSI_SENSE_T sense[USBD_SCSI_SENSE_LIST_NUMBER];
} USBD_SCSI_INFO_T;
/**@} end of group USBD_MSC_Structures*/
/** @defgroup USBD_MSC_Functions Functions
@{
*/
USBD_STA_T USBD_SCSI_Handle(USBD_INFO_T* usbInfo, uint8_t lun, uint8_t* command);
USBD_STA_T USBD_SCSI_CodeSense(USBD_INFO_T* usbInfo, uint8_t lun, uint8_t key, uint8_t asc, uint8_t ascq);
/**@} end of group USBD_MSC_Functions */
/**@} end of group USBD_MSC_Class */
/**@} end of group APM32_USB_Library */
#endif

View file

@ -0,0 +1,457 @@
/*!
* @file usbd_msc.c
*
* @brief usb device msc class handler
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Includes */
#include "usbd_msc.h"
#include "usbd_msc_bot.h"
#include "usbd_stdReq.h"
#include "usbd_dataXfer.h"
//#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/** @addtogroup APM32_USB_Library
@{
*/
/** @addtogroup USBD_MSC_Class
@{
*/
/** @defgroup USBD_MSC_Functions Functions
@{
*/
static USBD_STA_T USBD_MSC_ClassInitHandler(USBD_INFO_T* usbInfo, uint8_t cfgIndex);
static USBD_STA_T USBD_MSC_ClassDeInitHandler(USBD_INFO_T* usbInfo, uint8_t cfgIndex);
static USBD_STA_T USBD_MSC_SOFHandler(USBD_INFO_T* usbInfo);
static USBD_STA_T USBD_MSC_SetupHandler(USBD_INFO_T* usbInfo, USBD_REQ_SETUP_T* req);
static USBD_STA_T USBD_MSC_DataInHandler(USBD_INFO_T* usbInfo, uint8_t epNum);
static USBD_STA_T USBD_MSC_DataOutHandler(USBD_INFO_T* usbInfo, uint8_t epNum);
/**@} end of group USBD_MSC_Functions */
/** @defgroup USBD_MSC_Structures Structures
@{
*/
/* MSC class handler */
USBD_CLASS_T USBD_MSC_CLASS =
{
/* Class handler */
"Class MSC",
NULL,
USBD_MSC_ClassInitHandler,
USBD_MSC_ClassDeInitHandler,
USBD_MSC_SOFHandler,
/* Control endpoint */
USBD_MSC_SetupHandler,
NULL,
NULL,
/* Specific endpoint */
USBD_MSC_DataInHandler,
USBD_MSC_DataOutHandler,
NULL,
NULL,
};
/**@} end of group USBD_MSC_Structures*/
/** @defgroup USBD_MSC_Functions Functions
@{
*/
/*!
* @brief USB device MSC configuration handler
*
* @param usbInfo: usb device information
*
* @param cfgIndex: configuration index
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_MSC_ClassInitHandler(USBD_INFO_T* usbInfo, uint8_t cfgIndex)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_MSC_INFO_T* usbDevMSC;
UNUSED(cfgIndex);
/* Link class data */
usbInfo->devClass[usbInfo->classID]->classData = (USBD_MSC_INFO_T*)malloc(sizeof(USBD_MSC_INFO_T));
usbDevMSC = (USBD_MSC_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
memset(usbDevMSC, 0, sizeof(USBD_MSC_INFO_T));
USBD_USR_Debug("USBD_MSC_INFO_T size %d\r\n", sizeof(USBD_MSC_INFO_T));
if (usbDevMSC == NULL)
{
USBD_USR_LOG("usbDevMSC is NULL");
return USBD_FAIL;
}
usbDevMSC->epInAddr = USBD_MSC_IN_EP_ADDR;
usbDevMSC->epOutAddr = USBD_MSC_OUT_EP_ADDR;
/* Open endpoint */
switch (usbInfo->devSpeed)
{
case USBD_SPEED_FS:
USBD_EP_OpenCallback(usbInfo, usbDevMSC->epOutAddr, EP_TYPE_BULK, USBD_MSC_FS_MP_SIZE);
usbInfo->devEpOut[usbDevMSC->epOutAddr & 0x0F].useStatus = ENABLE;
USBD_EP_OpenCallback(usbInfo, usbDevMSC->epInAddr, EP_TYPE_BULK, USBD_MSC_FS_MP_SIZE);
usbInfo->devEpIn[usbDevMSC->epInAddr & 0x0F].useStatus = ENABLE;
break;
default:
USBD_EP_OpenCallback(usbInfo, usbDevMSC->epOutAddr, EP_TYPE_BULK, USBD_MSC_HS_MP_SIZE);
usbInfo->devEpOut[usbDevMSC->epOutAddr & 0x0F].useStatus = ENABLE;
USBD_EP_OpenCallback(usbInfo, usbDevMSC->epInAddr, EP_TYPE_BULK, USBD_MSC_HS_MP_SIZE);
usbInfo->devEpIn[usbDevMSC->epInAddr & 0x0F].useStatus = ENABLE;
break;
}
USBD_MSC_BOT_Init(usbInfo);
return usbStatus;
}
/*!
* @brief USB device MSC reset handler
*
* @param usbInfo: usb device information
*
* @param cfgIndex: configuration index
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_MSC_ClassDeInitHandler(USBD_INFO_T* usbInfo, uint8_t cfgIndex)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_MSC_INFO_T* usbDevMSC = (USBD_MSC_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
UNUSED(cfgIndex);
/* Close MSC EP */
USBD_EP_CloseCallback(usbInfo, usbDevMSC->epOutAddr);
usbInfo->devEpOut[usbDevMSC->epOutAddr & 0x0F].useStatus = DISABLE;
USBD_EP_CloseCallback(usbInfo, usbDevMSC->epInAddr);
usbInfo->devEpIn[usbDevMSC->epInAddr & 0x0F].useStatus = DISABLE;
if (usbInfo->devClassUserData[usbInfo->classID] != NULL)
{
USBD_MSC_BOT_DeInit(usbInfo);
}
if (usbInfo->devClass[usbInfo->classID]->classData != NULL)
{
free(usbInfo->devClass[usbInfo->classID]->classData);
usbInfo->devClass[usbInfo->classID]->classData = 0;
}
return usbStatus;
}
/*!
* @brief USB device MSC SOF handler
*
* @param usbInfo: usb device information
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_MSC_SOFHandler(USBD_INFO_T* usbInfo)
{
USBD_STA_T usbStatus = USBD_BUSY;
UNUSED(usbInfo);
return usbStatus;
}
/*!
* @brief USB device MSC SETUP handler
*
* @param usbInfo: usb device information
*
* @param req: setup request
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_MSC_SetupHandler(USBD_INFO_T* usbInfo, USBD_REQ_SETUP_T* req)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_MSC_INFO_T* usbDevMSC = (USBD_MSC_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
uint8_t request;
uint8_t reqType;
uint16_t wIndex = req->DATA_FIELD.wIndex[0] | req->DATA_FIELD.wIndex[1] << 8;
uint16_t wValue = req->DATA_FIELD.wValue[0] | req->DATA_FIELD.wValue[1] << 8;
uint16_t wLength = req->DATA_FIELD.wLength[0] | req->DATA_FIELD.wLength[1] << 8;
uint16_t status = 0x0000;
if (usbDevMSC == NULL)
{
return USBD_FAIL;
}
request = req->DATA_FIELD.bRequest;
reqType = req->DATA_FIELD.bmRequest.REQ_TYPE_B.type;
switch (reqType)
{
case USBD_REQ_TYPE_STANDARD:
switch (request)
{
case USBD_STD_GET_STATUS:
if (usbInfo->devState == USBD_DEV_CONFIGURE)
{
USBD_CtrlSendData(usbInfo, (uint8_t*)&status, 2);
}
else
{
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
}
break;
case USBD_STD_GET_INTERFACE:
if (usbInfo->devState == USBD_DEV_CONFIGURE)
{
USBD_CtrlSendData(usbInfo, (uint8_t*)&usbDevMSC->itf, 1);
}
else
{
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
}
break;
case USBD_STD_SET_INTERFACE:
if (usbInfo->devState == USBD_DEV_CONFIGURE)
{
usbDevMSC->itf = wValue;
}
else
{
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
}
break;
case USBD_STD_CLEAR_FEATURE:
if (usbInfo->devState == USBD_DEV_CONFIGURE)
{
if (wValue == USBD_FEATURE_SELECTOR_ENDPOINT_HALT)
{
USBD_EP_FlushCallback(usbInfo, wIndex);
/* BOT error */
USBD_MSC_BOT_ClearFeature(usbInfo, wIndex);
}
}
break;
default:
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
break;
}
break;
case USBD_REQ_TYPE_CLASS:
switch (request)
{
case USBD_CLASS_GET_MAX_LUN:
if ((req->DATA_FIELD.bmRequest.REQ_TYPE_B.dir == EP_DIR_IN) && \
(wValue == 0) && (wLength == 1))
{
usbDevMSC->maxLun = \
((USBD_MSC_MEMORY_T*)usbInfo->devClassUserData[usbInfo->classID])->MemoryReadMaxLun();
USBD_CtrlSendData(usbInfo, (uint8_t*)&usbDevMSC->maxLun, 1);
}
else
{
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
}
break;
case USBD_CLASS_BOT_RESET:
if ((req->DATA_FIELD.bmRequest.REQ_TYPE_B.dir == EP_DIR_OUT) && \
(wValue == 0) && (wLength == 0))
{
USBD_MSC_BOT_Reset(usbInfo);
}
else
{
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
}
break;
default:
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
break;
}
break;
case USBD_REQ_TYPE_VENDOR:
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
break;
default:
usbStatus = USBD_FAIL;
USBD_REQ_CtrlError(usbInfo, req);
break;
}
return usbStatus;
}
/*!
* @brief USB device MSC IN data handler
*
* @param usbInfo: usb device information
*
* @param epNum: endpoint number
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_MSC_DataInHandler(USBD_INFO_T* usbInfo, uint8_t epNum)
{
USBD_STA_T usbStatus = USBD_OK;
uint8_t reqStatus = USBD_BUSY;
USBD_MSC_INFO_T* usbDevMSC = (USBD_MSC_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
UNUSED(epNum);
if (usbDevMSC == NULL)
{
return USBD_FAIL;
}
switch (usbDevMSC->usbDevBOT.state)
{
case USBD_BOT_DATAIN:
reqStatus = USBD_SCSI_Handle(usbInfo, usbDevMSC->usbDevBOT.cmdPack.CBW.DATA_FIELD.bLUN, \
&usbDevMSC->usbDevBOT.cmdPack.CBW.DATA_FIELD.CB[0]);
if (reqStatus == USBD_FAIL)
{
USBD_MSC_BOT_SendCSW(usbInfo, USBD_BOT_CSW_FAIL);
}
break;
case USBD_BOT_DATAIN_LAST:
case USBD_BOT_DATA_SEND:
USBD_MSC_BOT_SendCSW(usbInfo, USBD_BOT_CSW_OK);
break;
default:
break;
}
return usbStatus;
}
/*!
* @brief USB device MSC OUT data handler
*
* @param usbInfo: usb device information
*
* @param epNum: endpoint number
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_MSC_DataOutHandler(USBD_INFO_T* usbInfo, uint8_t epNum)
{
USBD_STA_T usbStatus = USBD_OK;
uint8_t reqStatus = USBD_BUSY;
USBD_MSC_INFO_T* usbDevMSC = (USBD_MSC_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
UNUSED(epNum);
if (usbDevMSC == NULL)
{
return USBD_FAIL;
}
/* Handler BOT state */
switch (usbDevMSC->usbDevBOT.state)
{
case USBD_BOT_IDLE:
USBD_MSC_BOT_CBW_Decode(usbInfo);
break;
case USBD_BOT_DATAOUT:
reqStatus = USBD_SCSI_Handle(usbInfo, usbDevMSC->usbDevBOT.cmdPack.CBW.DATA_FIELD.bLUN, \
&usbDevMSC->usbDevBOT.cmdPack.CBW.DATA_FIELD.CB[0]);
if (reqStatus == USBD_FAIL)
{
USBD_MSC_BOT_SendCSW(usbInfo, USBD_BOT_CSW_FAIL);
}
break;
default:
break;
}
return usbStatus;
}
/*!
* @brief USB device MSC register memory handler
*
* @param usbInfo: usb device information
*
* @param memory: memory handler
*
* @retval USB device operation status
*/
USBD_STA_T USBD_MSC_RegisterMemory(USBD_INFO_T* usbInfo, USBD_MSC_MEMORY_T* memory)
{
USBD_STA_T usbStatus = USBD_FAIL;
if (memory != NULL)
{
usbInfo->devClassUserData[usbInfo->classID] = memory;
usbStatus = USBD_OK;
}
return usbStatus;
}
/**@} end of group USBD_MSC_Functions */
/**@} end of group USBD_MSC_Class */
/**@} end of group APM32_USB_Library */

View file

@ -0,0 +1,367 @@
/*!
* @file usbd_msc_bot.c
*
* @brief usb device msc bot handler
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Includes */
#include "usbd_msc_bot.h"
#include "usbd_msc.h"
#include "usbd_dataXfer.h"
/** @addtogroup APM32_USB_Library
@{
*/
/** @addtogroup USBD_MSC_Class
@{
*/
/** @defgroup USBD_MSC_Functions Functions
@{
*/
/*!
* @brief Init BOT of USB device MSC
*
* @param usbInfo : usb handler information
*
* @retval USB device operation status
*/
USBD_STA_T USBD_MSC_BOT_Init(USBD_INFO_T* usbInfo)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_MSC_INFO_T* usbDevMSC = (USBD_MSC_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
if (usbDevMSC == NULL)
{
return USBD_FAIL;
}
usbDevMSC->usbDevSCSI.senseHead = 0;
usbDevMSC->usbDevSCSI.senseEnd = 0;
usbDevMSC->usbDevSCSI.mediumState = USBD_SCSI_MEDIUM_UNLOCK;
/* Init USB device memory managment */
((USBD_MSC_MEMORY_T*)usbInfo->devClassUserData[usbInfo->classID])->MemoryInit(0);
usbDevMSC->usbDevBOT.state = USBD_BOT_IDLE;
usbDevMSC->usbDevBOT.status = USBD_BOT_NORMAL;
USBD_EP_FlushCallback(usbInfo, usbDevMSC->epInAddr);
USBD_EP_FlushCallback(usbInfo, usbDevMSC->epOutAddr);
USBD_EP_ReceiveCallback(usbInfo, usbDevMSC->epOutAddr, \
(uint8_t*)&usbDevMSC->usbDevBOT.cmdPack.CBW,
USBD_MSC_BOT_CBW_LEN);
return usbStatus;
}
/*!
* @brief De-init BOT of USB device MSC
*
* @param usbInfo : usb handler information
*
* @retval USB device operation status
*/
USBD_STA_T USBD_MSC_BOT_DeInit(USBD_INFO_T* usbInfo)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_MSC_INFO_T* usbDevMSC = (USBD_MSC_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
if (usbDevMSC == NULL)
{
return USBD_FAIL;
}
usbDevMSC->usbDevBOT.state = USBD_BOT_IDLE;
return usbStatus;
}
/*!
* @brief Reset BOT of USB device MSC
*
* @param usbInfo : usb handler information
*
* @retval USB device operation status
*/
USBD_STA_T USBD_MSC_BOT_Reset(USBD_INFO_T* usbInfo)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_MSC_INFO_T* usbDevMSC = (USBD_MSC_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
if (usbDevMSC == NULL)
{
return USBD_FAIL;
}
usbDevMSC->usbDevBOT.state = USBD_BOT_IDLE;
usbDevMSC->usbDevBOT.status = USBD_BOT_RECOVERY;
USBD_EP_ClearStallCallback(usbInfo, usbDevMSC->epInAddr);
USBD_EP_ClearStallCallback(usbInfo, usbDevMSC->epOutAddr);
USBD_EP_ReceiveCallback(usbInfo, usbDevMSC->epOutAddr, \
(uint8_t*)&usbDevMSC->usbDevBOT.cmdPack.CBW, \
USBD_MSC_BOT_CBW_LEN);
return usbStatus;
}
/*!
* @brief Abort BOT of USB device MSC
*
* @param usbInfo : usb handler information
*
* @retval USB device operation status
*/
USBD_STA_T USBD_MSC_BOT_Abort(USBD_INFO_T* usbInfo)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_MSC_INFO_T* usbDevMSC = (USBD_MSC_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
if (usbDevMSC == NULL)
{
return USBD_FAIL;
}
if ((usbDevMSC->usbDevBOT.cmdPack.CBW.DATA_FIELD.bmFlags.CBW_Flag == 0) && \
(usbDevMSC->usbDevBOT.cmdPack.CBW.DATA_FIELD.dDataXferLen != 0) && \
(usbDevMSC->usbDevBOT.status == USBD_BOT_NORMAL))
{
USBD_EP_StallCallback(usbInfo, usbDevMSC->epOutAddr);
}
USBD_EP_StallCallback(usbInfo, usbDevMSC->epInAddr);
if (usbDevMSC->usbDevBOT.status == USBD_BOT_ERR)
{
USBD_EP_StallCallback(usbInfo, usbDevMSC->epInAddr);
USBD_EP_StallCallback(usbInfo, usbDevMSC->epOutAddr);
}
return usbStatus;
}
/*!
* @brief Send CSW packet
*
* @param usbInfo : usb handler information
*
* @param status : CSW status
*
* @retval USB device operation status
*/
USBD_STA_T USBD_MSC_BOT_SendCSW(USBD_INFO_T* usbInfo, USBD_BOT_CSW_STA_T status)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_MSC_INFO_T* usbDevMSC = (USBD_MSC_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
if (usbDevMSC == NULL)
{
return USBD_FAIL;
}
usbDevMSC->usbDevBOT.cmdPack.CSW.DATA_FIELD.dSignature = USBD_MSC_BOT_CSW_SIGNATURE;
usbDevMSC->usbDevBOT.cmdPack.CSW.DATA_FIELD.bStatus = status;
usbDevMSC->usbDevBOT.state = USBD_BOT_IDLE;
USBD_EP_TransferCallback(usbInfo, usbDevMSC->epInAddr, \
(uint8_t*)&usbDevMSC->usbDevBOT.cmdPack.CSW, \
USBD_MSC_BOT_CSW_LEN);
USBD_EP_ReceiveCallback(usbInfo, usbDevMSC->epOutAddr, \
(uint8_t*)&usbDevMSC->usbDevBOT.cmdPack.CBW, \
USBD_MSC_BOT_CBW_LEN);
return usbStatus;
}
/*!
* @brief Send BOT data
*
* @param usbInfo : usb handler information
*
* @param buffer : data buffer
*
* @param length : data length
*
* @retval USB device operation status
*/
USBD_STA_T USBD_MSC_BOT_SendData(USBD_INFO_T* usbInfo, uint8_t* buffer, uint32_t length)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_MSC_INFO_T* usbDevMSC = (USBD_MSC_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
uint32_t lengthTemp;
if (usbDevMSC == NULL)
{
return USBD_FAIL;
}
lengthTemp = length;
if (usbDevMSC->usbDevBOT.cmdPack.CBW.DATA_FIELD.dDataXferLen < length)
{
lengthTemp = usbDevMSC->usbDevBOT.cmdPack.CBW.DATA_FIELD.dDataXferLen;
}
usbDevMSC->usbDevBOT.cmdPack.CSW.DATA_FIELD.dDataResidue -= length;
usbDevMSC->usbDevBOT.cmdPack.CSW.DATA_FIELD.bStatus = USBD_BOT_CSW_OK;
usbDevMSC->usbDevBOT.state = USBD_BOT_DATA_SEND;
USBD_EP_TransferCallback(usbInfo, usbDevMSC->epInAddr, buffer, lengthTemp);
return usbStatus;
}
/*!
* @brief Decode CBW packet
*
* @param usbInfo : usb handler information
*
* @retval USB device operation status
*/
USBD_STA_T USBD_MSC_BOT_CBW_Decode(USBD_INFO_T* usbInfo)
{
USBD_STA_T usbStatus = USBD_OK;
uint8_t reqStatus = USBD_BUSY;
USBD_MSC_INFO_T* usbDevMSC = (USBD_MSC_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
uint32_t lastRevDataLen;
if (usbDevMSC == NULL)
{
return USBD_FAIL;
}
usbDevMSC->usbDevBOT.cmdPack.CSW.DATA_FIELD.dTag = \
usbDevMSC->usbDevBOT.cmdPack.CBW.DATA_FIELD.dTag;
usbDevMSC->usbDevBOT.cmdPack.CSW.DATA_FIELD.dDataResidue = \
usbDevMSC->usbDevBOT.cmdPack.CBW.DATA_FIELD.dDataXferLen;
lastRevDataLen = USBD_EP_ReadRxDataLenCallback(usbInfo, usbDevMSC->epOutAddr);
if ((lastRevDataLen != USBD_MSC_BOT_CBW_LEN) || \
(usbDevMSC->usbDevBOT.cmdPack.CBW.DATA_FIELD.dSignature != USBD_MSC_BOT_CBW_SIGNATURE) || \
(usbDevMSC->usbDevBOT.cmdPack.CBW.DATA_FIELD.bLUN > 1) || \
(usbDevMSC->usbDevBOT.cmdPack.CBW.DATA_FIELD.bCBLen < 1) || \
(usbDevMSC->usbDevBOT.cmdPack.CBW.DATA_FIELD.bCBLen > 16))
{
USBD_SCSI_CodeSense(usbInfo, usbDevMSC->usbDevBOT.cmdPack.CBW.DATA_FIELD.bLUN, \
USBD_SCSI_SENSE_KEY_ILLEGAL_REQUEST, USBD_SCSI_ASC_INVALID_CDB, 0);
usbDevMSC->usbDevBOT.status = USBD_BOT_ERR;
USBD_MSC_BOT_Abort(usbInfo);
}
else
{
reqStatus = USBD_SCSI_Handle(usbInfo, usbDevMSC->usbDevBOT.cmdPack.CBW.DATA_FIELD.bLUN, \
&usbDevMSC->usbDevBOT.cmdPack.CBW.DATA_FIELD.CB[0]);
if (reqStatus == USBD_FAIL)
{
if (usbDevMSC->usbDevBOT.state == USBD_BOT_NO_DATA)
{
USBD_MSC_BOT_SendCSW(usbInfo, USBD_BOT_CSW_FAIL);
}
else
{
USBD_MSC_BOT_Abort(usbInfo);
}
}
else if ((usbDevMSC->usbDevBOT.state != USBD_BOT_DATAIN) && \
(usbDevMSC->usbDevBOT.state != USBD_BOT_DATAOUT) && \
(usbDevMSC->usbDevBOT.state != USBD_BOT_DATAIN_LAST))
{
if (usbDevMSC->usbDevBOT.dataLen == 0)
{
USBD_MSC_BOT_SendCSW(usbInfo, USBD_BOT_CSW_OK);
}
else if (usbDevMSC->usbDevBOT.dataLen > 0)
{
USBD_MSC_BOT_SendData(usbInfo, usbDevMSC->usbDevBOT.data, usbDevMSC->usbDevBOT.dataLen);
}
else
{
USBD_MSC_BOT_Abort(usbInfo);
}
}
else
{
return USBD_OK;
}
}
return usbStatus;
}
/*!
* @brief Clear feature BOT of USB device MSC
*
* @param usbInfo : usb handler information
*
* @param epNum : endpoint number
*
* @retval USB device operation status
*/
USBD_STA_T USBD_MSC_BOT_ClearFeature(USBD_INFO_T* usbInfo, uint8_t epNum)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_MSC_INFO_T* usbDevMSC = (USBD_MSC_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
if (usbDevMSC == NULL)
{
return USBD_FAIL;
}
switch (usbDevMSC->usbDevBOT.status)
{
/* CBW signature error */
case USBD_BOT_ERR:
USBD_EP_StallCallback(usbInfo, usbDevMSC->epInAddr);
USBD_EP_StallCallback(usbInfo, usbDevMSC->epOutAddr);
break;
case USBD_BOT_NORMAL:
if ((epNum & 0x80) == 0x80)
{
usbDevMSC->usbDevBOT.cmdPack.cswStatus = USBD_BOT_CSW_FAIL;
USBD_MSC_BOT_SendCSW(usbInfo, usbDevMSC->usbDevBOT.cmdPack.cswStatus);
}
break;
default:
break;
}
return usbStatus;
}
/**@} end of group USBD_MSC_Functions */
/**@} end of group USBD_MSC_Class */
/**@} end of group APM32_USB_Library */

View file

@ -0,0 +1,146 @@
/*!
* @file usbd_winusb.h
*
* @brief usb device winUSB class handler header file
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Define to prevent recursive inclusion */
#ifndef _USBD_WINUSB_H_
#define _USBD_WINUSB_H_
/* Includes */
#include "usbd_core.h"
/** @addtogroup APM32_USB_Library
@{
*/
/** @addtogroup USBD_WINUSB_Class
@{
*/
/** @defgroup USBD_WINUSB_Macros Macros
@{
*/
#define USBD_WINUSB_OS_FEATURE_DESC_SIZE 0x28
#define USBD_WINUSB_OS_PROPERTY_DESC_SIZE 0x8E
#define USBD_WINUSB_FS_MP_SIZE 0x40
#define USBD_WINUSB_HS_MP_SIZE 0x200
#define USBD_WINUSB_CMD_MP_SIZE 0x08
#define USBD_WINUSB_DATA_MP_SIZE 0x07
#define USBD_WINUSB_CMD_EP_ADDR 0x82
#define USBD_WINUSB_DATA_IN_EP_ADDR 0x81
#define USBD_WINUSB_DATA_OUT_EP_ADDR 0x01
#define USBD_WINUSB_FS_INTERVAL 16
#define USBD_WINUSB_HS_INTERVAL 16
/**@} end of group USBD_WINUSB_Macros*/
/** @defgroup USBD_WINUSB_Enumerates Enumerates
@{
*/
/**
* @brief USB device WINUSB xfer status
*/
typedef enum
{
USBD_WINUSB_XFER_IDLE,
USBD_WINUSB_XFER_BUSY,
} USBD_WINUSB_XFER_STA_T;
/**@} end of group USBD_WINUSB_Enumerates*/
/** @defgroup USBD_WINUSB_Structures Structures
@{
*/
/**
* @brief USB device WINUSB interface handler
*/
typedef struct
{
const char* itfName;
USBD_STA_T (*ItfInit)(void);
USBD_STA_T (*ItfDeInit)(void);
USBD_STA_T (*ItfCtrl)(uint8_t command, uint8_t *buffer, uint16_t length);
USBD_STA_T (*ItfSend)(uint8_t *buffer, uint16_t length);
USBD_STA_T (*ItfSendEnd)(uint8_t epNum, uint8_t *buffer, uint32_t *length);
USBD_STA_T (*ItfReceive)(uint8_t *buffer, uint32_t *length);
} USBD_WINUSB_INTERFACE_T;
/**
* @brief USB device WINUSB data handler
*/
typedef struct
{
__IO uint8_t state;
uint8_t *buffer;
uint32_t length;
} USBD_WINUSB_DATA_XFER_T;
/**
* @brief USB device WINUSB command handler
*/
typedef struct
{
uint8_t opcode;
uint8_t length;
} USBD_WINUSB_CMD_XFER_T;
/**
* @brief WINUSB information management
*/
typedef struct
{
uint8_t itf;
uint8_t epInAddr;
uint8_t epOutAddr;
USBD_WINUSB_DATA_XFER_T winusbTx;
USBD_WINUSB_DATA_XFER_T winusbRx;
uint32_t data[USBD_WINUSB_HS_MP_SIZE / 4];
} USBD_WINUSB_INFO_T;
extern USBD_CLASS_T USBD_WINUSB_CLASS;
/**@} end of group USBD_WINUSB_Structures*/
/** @defgroup USBD_WINUSB_Functions Functions
@{
*/
USBD_STA_T USBD_WINUSB_TxPacket(USBD_INFO_T* usbInfo);
USBD_STA_T USBD_WINUSB_RxPacket(USBD_INFO_T* usbInfo);
uint8_t USBD_WINUSB_ReadInterval(USBD_INFO_T* usbInfo);
USBD_STA_T USBD_WINUSB_ConfigTxBuffer(USBD_INFO_T* usbInfo, uint8_t *buffer, uint32_t length);
USBD_STA_T USBD_WINUSB_ConfigRxBuffer(USBD_INFO_T* usbInfo, uint8_t *buffer);
USBD_STA_T USBD_WINUSB_RegisterItf(USBD_INFO_T* usbInfo, USBD_WINUSB_INTERFACE_T* itf);
/**@} end of group USBD_WINUSB_Functions */
/**@} end of group USBD_WINUSB_Class */
/**@} end of group APM32_USB_Library */
#endif

View file

@ -0,0 +1,769 @@
/*!
* @file usbd_winusb.c
*
* @brief usb device winUSB class handler
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Includes */
#include "usbd_winusb.h"
#include "usbd_stdReq.h"
#include "usbd_dataXfer.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/** @addtogroup APM32_USB_Library
@{
*/
/** @addtogroup USBD_WINUSB_Class
@{
*/
/** @defgroup USBD_WINUSB_Functions Functions
@{
*/
static USBD_STA_T USBD_WINUSB_ClassInitHandler(USBD_INFO_T* usbInfo, uint8_t cfgIndex);
static USBD_STA_T USBD_WINUSB_ClassDeInitHandler(USBD_INFO_T* usbInfo, uint8_t cfgIndex);
static USBD_STA_T USBD_WINUSB_SOFHandler(USBD_INFO_T* usbInfo);
static USBD_STA_T USBD_WINUSB_SetupHandler(USBD_INFO_T* usbInfo, USBD_REQ_SETUP_T* req);
static USBD_STA_T USBD_WINUSB_DataInHandler(USBD_INFO_T* usbInfo, uint8_t epNum);
static USBD_STA_T USBD_WINUSB_DataOutHandler(USBD_INFO_T* usbInfo, uint8_t epNum);
/**@} end of group USBD_WINUSB_Functions */
/** @defgroup USBD_WINUSB_Structures Structures
@{
*/
/* WINUSB class handler */
USBD_CLASS_T USBD_WINUSB_CLASS =
{
/* Class handler */
"Class WINUSB",
NULL,
USBD_WINUSB_ClassInitHandler,
USBD_WINUSB_ClassDeInitHandler,
USBD_WINUSB_SOFHandler,
/* Control endpoint */
USBD_WINUSB_SetupHandler,
NULL,
NULL,
/* Specific endpoint */
USBD_WINUSB_DataInHandler,
USBD_WINUSB_DataOutHandler,
NULL,
NULL,
};
/**@} end of group USBD_WINUSB_Structures*/
/** @defgroup USBD_WINUSB_Variables Variables
@{
*/
/**
* @brief WinUSB OS feature descriptor
*/
uint8_t USBD_WinUsbOsFeatureDesc[USBD_WINUSB_OS_FEATURE_DESC_SIZE] =
{
/* dwLength */
0x28, 0x00, 0x00, 0x00,
/* bcdVersion */
0x00, 0x01,
/* wIndex extended compat ID descritor */
0x04, 0x00,
/* bCount */
0x01,
/* Reserved */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* WCID Function */
/* bFirstInterfaceNumber */
0x00,
/* bReserved */
0x00,
/* CID */
'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00,
/* Sub CID */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* Reserved */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
/* L"DeviceInterfaceGUID" : wIndex = 0x0005 */
/* L"{12345678-1234-1234-1234-123456789ABC}" */
uint8_t USBD_WinUsbOsPropertyDesc[USBD_WINUSB_OS_PROPERTY_DESC_SIZE] =
{
/* dwTotalSize = Header + All sections */
0x8E, 0x00, 0x00, 0x00,
/* bcdVersion */
0x00, 0x01,
/* wIndex */
0x05, 0x00,
/* bCount */
0x01, 0x00,
/* dwSize - this section */
0x84, 0x00, 0x00, 0x00,
/* dwPropertyDataType */
0x01, 0x00, 0x00, 0x00,
/* wPropertyNameLength */
0x28, 0x00,
/* WCHAR L"DeviceInterfaceGUID" */
'D', 0x00, 'e', 0x00,
'v', 0x00, 'i', 0x00,
'c', 0x00, 'e', 0x00,
'I', 0x00, 'n', 0x00,
't', 0x00, 'e', 0x00,
'r', 0x00, 'f', 0x00,
'a', 0x00, 'c', 0x00,
'e', 0x00, 'G', 0x00,
'U', 0x00, 'I', 0x00,
'D', 0x00, 0x00, 0x00,
/* dwPropertyDataLength : 78 Bytes = 0x0000004E */
0x4E, 0x00, 0x00, 0x00,
/* WCHAR : L"{12345678-1234-1234-1234-123456789ABC}" */
'{', 0x00, '1', 0x00,
'2', 0x00, '3', 0x00,
'4', 0x00, '5', 0x00,
'6', 0x00, '7', 0x00,
'8', 0x00, '-', 0x00,
'1', 0x00, '2', 0x00,
'3', 0x00, '4', 0x00,
'-', 0x00, '1', 0x00,
'2', 0x00, '3', 0x00,
'4', 0x00, '-', 0x00,
'1', 0x00, '2', 0x00,
'3', 0x00, '4', 0x00,
'-', 0x00, '1', 0x00,
'2', 0x00, '3', 0x00,
'4', 0x00, '5', 0x00,
'6', 0x00, '7', 0x00,
'8', 0x00, '9', 0x00,
'A', 0x00, 'B', 0x00,
'C', 0x00, '}', 0x00,
0x00, 0x00
};
/**@} end of group USBD_WINUSB_Variables*/
/** @defgroup USBD_WINUSB_Functions Functions
@{
*/
/*!
* @brief USB device WINUSB feature descriptor
*
* @param usbSpeed : usb speed
*
* @retval usb descriptor information
*/
static USBD_DESC_INFO_T USBD_WinUsbFeatureDescHandler(uint8_t usbSpeed)
{
USBD_DESC_INFO_T descInfo;
descInfo.desc = USBD_WinUsbOsFeatureDesc;
descInfo.size = sizeof(USBD_WinUsbOsFeatureDesc);
return descInfo;
}
/*!
* @brief USB device WINUSB property descriptor
*
* @param usbSpeed : usb speed
*
* @retval usb descriptor information
*/
static USBD_DESC_INFO_T USBD_WinUsbPropertyDescHandler(uint8_t usbSpeed)
{
USBD_DESC_INFO_T descInfo;
descInfo.desc = USBD_WinUsbOsPropertyDesc;
descInfo.size = sizeof(USBD_WinUsbOsPropertyDesc);
return descInfo;
}
/*!
* @brief USB device WINUSB configuration handler
*
* @param usbInfo: usb device information
*
* @param cfgIndex: configuration index
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_WINUSB_ClassInitHandler(USBD_INFO_T* usbInfo, uint8_t cfgIndex)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_WINUSB_INFO_T* usbDevWINUSB;
/* Link class data */
usbInfo->devClass[usbInfo->classID]->classData = (USBD_WINUSB_INFO_T*)malloc(sizeof(USBD_WINUSB_INFO_T));
usbDevWINUSB = (USBD_WINUSB_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
memset(usbDevWINUSB, 0, sizeof(USBD_WINUSB_INFO_T));
USBD_USR_Debug("USBD_WINUSB_INFO_T size %d\r\n", sizeof(USBD_WINUSB_INFO_T));
if (usbDevWINUSB == NULL)
{
USBD_USR_LOG("usbDevWINUSB is NULL");
return USBD_FAIL;
}
usbDevWINUSB->epInAddr = USBD_WINUSB_DATA_IN_EP_ADDR;
usbDevWINUSB->epOutAddr = USBD_WINUSB_DATA_OUT_EP_ADDR;
/* Open Data endpoint */
switch (usbInfo->devSpeed)
{
case USBD_SPEED_FS:
USBD_EP_OpenCallback(usbInfo, usbDevWINUSB->epOutAddr, EP_TYPE_BULK, USBD_WINUSB_FS_MP_SIZE);
usbInfo->devEpOut[usbDevWINUSB->epOutAddr & 0x0F].useStatus = ENABLE;
USBD_EP_OpenCallback(usbInfo, usbDevWINUSB->epInAddr, EP_TYPE_BULK, USBD_WINUSB_FS_MP_SIZE);
usbInfo->devEpIn[usbDevWINUSB->epInAddr & 0x0F].useStatus = ENABLE;
break;
default:
USBD_EP_OpenCallback(usbInfo, usbDevWINUSB->epOutAddr, EP_TYPE_BULK, USBD_WINUSB_HS_MP_SIZE);
usbInfo->devEpOut[usbDevWINUSB->epOutAddr & 0x0F].useStatus = ENABLE;
USBD_EP_OpenCallback(usbInfo, usbDevWINUSB->epInAddr, EP_TYPE_BULK, USBD_WINUSB_HS_MP_SIZE);
usbInfo->devEpIn[usbDevWINUSB->epInAddr & 0x0F].useStatus = ENABLE;
break;
}
/* Interface Init */
usbDevWINUSB->winusbTx.buffer = NULL;
usbDevWINUSB->winusbRx.buffer = NULL;
usbDevWINUSB->winusbTx.state = USBD_WINUSB_XFER_IDLE;
usbDevWINUSB->winusbRx.state = USBD_WINUSB_XFER_IDLE;
((USBD_WINUSB_INTERFACE_T *)usbInfo->devClassUserData[usbInfo->classID])->ItfInit();
if(usbDevWINUSB->winusbRx.buffer == NULL)
{
USBD_USR_LOG("winusbRx buffer is NULL");
return USBD_FAIL;
}
switch (usbInfo->devSpeed)
{
case USBD_SPEED_FS:
USBD_EP_ReceiveCallback(usbInfo, usbDevWINUSB->epOutAddr, \
usbDevWINUSB->winusbRx.buffer, \
USBD_WINUSB_FS_MP_SIZE);
break;
default:
USBD_EP_ReceiveCallback(usbInfo, usbDevWINUSB->epOutAddr, \
usbDevWINUSB->winusbRx.buffer, \
USBD_WINUSB_HS_MP_SIZE);
break;
}
return usbStatus;
}
/*!
* @brief USB device WINUSB reset handler
*
* @param usbInfo: usb device information
*
* @param cfgIndex: configuration index
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_WINUSB_ClassDeInitHandler(USBD_INFO_T* usbInfo, uint8_t cfgIndex)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_WINUSB_INFO_T* usbDevWINUSB = (USBD_WINUSB_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
/* Close WINUSB EP */
USBD_EP_CloseCallback(usbInfo, usbDevWINUSB->epOutAddr);
usbInfo->devEpOut[usbDevWINUSB->epOutAddr & 0x0F].useStatus = DISABLE;
USBD_EP_CloseCallback(usbInfo, usbDevWINUSB->epInAddr);
usbInfo->devEpIn[usbDevWINUSB->epInAddr & 0x0F].useStatus = DISABLE;
if (usbInfo->devClass[usbInfo->classID]->classData != NULL)
{
if(((USBD_WINUSB_INTERFACE_T *)usbInfo->devClassUserData[usbInfo->classID])->ItfDeInit != NULL)
{
((USBD_WINUSB_INTERFACE_T *)usbInfo->devClassUserData[usbInfo->classID])->ItfDeInit();
}
free(usbInfo->devClass[usbInfo->classID]->classData);
usbInfo->devClass[usbInfo->classID]->classData = 0;
}
return usbStatus;
}
/*!
* @brief USB device WINUSB SOF handler
*
* @param usbInfo: usb device information
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_WINUSB_SOFHandler(USBD_INFO_T* usbInfo)
{
USBD_STA_T usbStatus = USBD_BUSY;
return usbStatus;
}
/*!
* @brief USB WINUSB device receive CTRL status
*
* @param usbInfo : usb handler information
*
* @param buffer : data buffer
*
* @param length : length of data
*
* @retval usb device status
*/
USBD_STA_T USBD_WINUSB_CtrlReceiveData(USBD_INFO_T* usbInfo, uint8_t *buffer, uint32_t length)
{
USBD_STA_T usbStatus = USBD_OK;
usbInfo->devEp0State = USBD_DEV_EP0_DATA_OUT;
usbInfo->devEpOut[USBD_EP_0].length = length;
usbInfo->devEpOut[USBD_EP_0].remainLen = length;
USBD_EP_ReceiveCallback(usbInfo, USBD_EP_0, buffer, length);
return usbStatus;
}
/*!
* @brief USB device WINUSB SETUP handler
*
* @param usbInfo: usb device information
*
* @param req: setup request
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_WINUSB_SetupHandler(USBD_INFO_T* usbInfo, USBD_REQ_SETUP_T* req)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_WINUSB_INFO_T* usbDevWINUSB = (USBD_WINUSB_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
uint8_t request;
uint8_t reqType;
uint16_t wLength = req->DATA_FIELD.wLength[0] | req->DATA_FIELD.wLength[1] << 8;
uint16_t wIndex = req->DATA_FIELD.wIndex[0] | req->DATA_FIELD.wIndex[1] << 8;
uint16_t status = 0x0000;
uint16_t length;
USBD_DESC_INFO_T descInfo;
request = req->DATA_FIELD.bRequest;
reqType = usbInfo->reqSetup.DATA_FIELD.bmRequest.REQ_TYPE_B.type;
if(request != USBD_VEN_REQ_MS_CODE)
{
if (usbDevWINUSB == NULL)
{
return USBD_FAIL;
}
}
switch (reqType)
{
case USBD_REQ_TYPE_STANDARD:
switch (request)
{
case USBD_STD_GET_STATUS:
if (usbInfo->devState == USBD_DEV_CONFIGURE)
{
USBD_CtrlSendData(usbInfo, (uint8_t*)&status, 2);
}
else
{
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
}
break;
case USBD_STD_GET_INTERFACE:
if (usbInfo->devState == USBD_DEV_CONFIGURE)
{
usbDevWINUSB->itf = 0;
USBD_CtrlSendData(usbInfo, (uint8_t*)&usbDevWINUSB->itf, 1);
}
else
{
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
}
break;
case USBD_STD_SET_INTERFACE:
if (usbInfo->devState == USBD_DEV_CONFIGURE)
{
}
else
{
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
}
break;
case USBD_STD_CLEAR_FEATURE:
break;
default:
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
break;
}
break;
case USBD_REQ_TYPE_CLASS:
if(wLength)
{
if((usbInfo->reqSetup.DATA_FIELD.bmRequest.REQ_TYPE & 0x80) == 0x80)
{
((USBD_WINUSB_INTERFACE_T *)usbInfo->devClassUserData[usbInfo->classID])->ItfCtrl(request, \
(uint8_t *)usbDevWINUSB->data,
wLength);
length = USBD_WINUSB_DATA_MP_SIZE < wLength ? USBD_WINUSB_DATA_MP_SIZE : wLength;
USBD_CtrlSendData(usbInfo, (uint8_t *)usbDevWINUSB->data, length);
}
}
else
{
((USBD_WINUSB_INTERFACE_T *)usbInfo->devClassUserData[usbInfo->classID])->ItfCtrl(request, \
(uint8_t *)req, \
0);
}
break;
case USBD_REQ_TYPE_VENDOR:
switch (request)
{
case USBD_VEN_REQ_MS_CODE:
switch(wIndex)
{
case USBD_WINUSB_DESC_FEATURE:
descInfo = USBD_WinUsbFeatureDescHandler(usbInfo->devSpeed);
descInfo.size = descInfo.size < wLength ? descInfo.size : wLength;
break;
case USBD_WINUSB_DESC_PROPERTY:
descInfo = USBD_WinUsbPropertyDescHandler(usbInfo->devSpeed);
descInfo.size = descInfo.size < wLength ? descInfo.size : wLength;
break;
default:
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
break;
}
if (descInfo.desc != NULL)
{
USBD_CtrlSendData(usbInfo, descInfo.desc, descInfo.size);
}
break;
default:
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
break;
}
break;
default:
usbStatus = USBD_FAIL;
USBD_REQ_CtrlError(usbInfo, req);
break;
}
return usbStatus;
}
/*!
* @brief USB device WINUSB IN data handler
*
* @param usbInfo: usb device information
*
* @param epNum: endpoint number
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_WINUSB_DataInHandler(USBD_INFO_T* usbInfo, uint8_t epNum)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_WINUSB_INFO_T* usbDevWINUSB = (USBD_WINUSB_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
#if defined(USE_DAL_DRIVER)
PCD_HandleTypeDef* usbdh = (PCD_HandleTypeDef *)usbInfo->dataPoint;
#else
USBD_HANDLE_T* usbdh = (USBD_HANDLE_T *)usbInfo->dataPoint;
#endif /* USE_DAL_DRIVER */
if (usbdh == NULL)
{
return USBD_FAIL;
}
if (usbDevWINUSB == NULL)
{
return USBD_FAIL;
}
#if defined(USE_DAL_DRIVER)
if((usbInfo->devEpIn[epNum & 0x0F].length > 0) && \
(usbInfo->devEpIn[epNum & 0x0F].length % usbdh->IN_ep[epNum & 0x0F].maxpacket) == 0)
#else
if((usbInfo->devEpIn[epNum & 0x0F].length > 0) && \
(usbInfo->devEpIn[epNum & 0x0F].length % usbdh->epIN[epNum & 0x0F].mps) == 0)
#endif /* USE_DAL_DRIVER */
{
usbInfo->devEpIn[epNum & 0x0F].length = 0;
USBD_EP_TransferCallback(usbInfo, epNum, NULL, 0);
}
else
{
usbDevWINUSB->winusbTx.state = USBD_WINUSB_XFER_IDLE;
if(((USBD_WINUSB_INTERFACE_T *)usbInfo->devClassUserData[usbInfo->classID])->ItfSendEnd != NULL)
{
((USBD_WINUSB_INTERFACE_T *)usbInfo->devClassUserData[usbInfo->classID])->ItfSendEnd(epNum, \
usbDevWINUSB->winusbTx.buffer, \
&usbDevWINUSB->winusbTx.length);
}
}
return usbStatus;
}
/*!
* @brief USB device WINUSB OUT data handler
*
* @param usbInfo: usb device information
*
* @param epNum: endpoint number
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_WINUSB_DataOutHandler(USBD_INFO_T* usbInfo, uint8_t epNum)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_WINUSB_INFO_T* usbDevWINUSB = (USBD_WINUSB_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
if (usbDevWINUSB == NULL)
{
return USBD_FAIL;
}
usbDevWINUSB->winusbRx.length = USBD_EP_ReadRxDataLenCallback(usbInfo, epNum);
((USBD_WINUSB_INTERFACE_T *)usbInfo->devClassUserData[usbInfo->classID])->ItfReceive(usbDevWINUSB->winusbRx.buffer, \
&usbDevWINUSB->winusbRx.length);
return usbStatus;
}
/*!
* @brief USB device WINUSB configure TX buffer handler
*
* @param usbInfo: usb device information
*
* @param buffer: tx buffer
*
* @param length: tx buffer length
*
* @retval USB device operation status
*/
USBD_STA_T USBD_WINUSB_ConfigTxBuffer(USBD_INFO_T* usbInfo, uint8_t *buffer, uint32_t length)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_WINUSB_INFO_T* usbDevWINUSB = (USBD_WINUSB_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
if (usbDevWINUSB == NULL)
{
return USBD_FAIL;
}
usbDevWINUSB->winusbTx.buffer = buffer;
usbDevWINUSB->winusbTx.length = length;
return usbStatus;
}
/*!
* @brief USB device WINUSB configure RX buffer handler
*
* @param usbInfo: usb device information
*
* @param buffer: tx buffer
*
* @retval USB device operation status
*/
USBD_STA_T USBD_WINUSB_ConfigRxBuffer(USBD_INFO_T* usbInfo, uint8_t *buffer)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_WINUSB_INFO_T* usbDevWINUSB = (USBD_WINUSB_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
if (usbDevWINUSB == NULL)
{
return USBD_FAIL;
}
usbDevWINUSB->winusbRx.buffer = buffer;
return usbStatus;
}
/*!
* @brief USB device WINUSB register interface handler
*
* @param usbInfo: usb device information
*
* @param itf: interface handler
*
* @retval USB device operation status
*/
USBD_STA_T USBD_WINUSB_RegisterItf(USBD_INFO_T* usbInfo, USBD_WINUSB_INTERFACE_T* itf)
{
USBD_STA_T usbStatus = USBD_FAIL;
if (itf != NULL)
{
usbInfo->devClassUserData[usbInfo->classID] = itf;
usbStatus = USBD_OK;
}
return usbStatus;
}
/*!
* @brief USB device WINUSB transmit packet handler
*
* @param usbInfo: usb device information
*
* @retval USB device operation status
*/
USBD_STA_T USBD_WINUSB_TxPacket(USBD_INFO_T* usbInfo)
{
USBD_STA_T usbStatus = USBD_BUSY;
USBD_WINUSB_INFO_T* usbDevWINUSB = (USBD_WINUSB_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
if (usbDevWINUSB == NULL)
{
return USBD_FAIL;
}
if(usbDevWINUSB->winusbTx.state == USBD_WINUSB_XFER_IDLE)
{
usbDevWINUSB->winusbTx.state = USBD_WINUSB_XFER_BUSY;
usbInfo->devEpIn[usbDevWINUSB->epInAddr & 0x0F].length = usbDevWINUSB->winusbTx.length;
USBD_EP_TransferCallback(usbInfo, usbDevWINUSB->epInAddr, usbDevWINUSB->winusbTx.buffer, usbDevWINUSB->winusbTx.length);
usbStatus = USBD_OK;
}
return usbStatus;
}
/*!
* @brief USB device WINUSB receive packet handler
*
* @param usbInfo: usb device information
*
* @retval USB device operation status
*/
USBD_STA_T USBD_WINUSB_RxPacket(USBD_INFO_T* usbInfo)
{
USBD_STA_T usbStatus = USBD_BUSY;
USBD_WINUSB_INFO_T* usbDevWINUSB = (USBD_WINUSB_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
if (usbDevWINUSB == NULL)
{
return USBD_FAIL;
}
if(usbInfo->devSpeed == USBD_SPEED_HS)
{
USBD_EP_ReceiveCallback(usbInfo, usbDevWINUSB->epOutAddr, \
usbDevWINUSB->winusbRx.buffer, \
USBD_WINUSB_HS_MP_SIZE);
}
else
{
USBD_EP_ReceiveCallback(usbInfo, usbDevWINUSB->epOutAddr, \
usbDevWINUSB->winusbRx.buffer, \
USBD_WINUSB_FS_MP_SIZE);
}
return usbStatus;
}
/*!
* @brief USB device WINUSB read interval
*
* @param usbInfo: usb device information
*
* @retval usb interval
*/
uint8_t USBD_WINUSB_ReadInterval(USBD_INFO_T* usbInfo)
{
uint8_t interval;
if (usbInfo->devSpeed == USBD_SPEED_FS)
{
interval = USBD_WINUSB_FS_INTERVAL;
}
else
{
interval = USBD_WINUSB_HS_INTERVAL;
}
return interval;
}
/**@} end of group USBD_WINUSB_Functions */
/**@} end of group USBD_WINUSB_Class */
/**@} end of group APM32_USB_Library */

View file

@ -0,0 +1,389 @@
/*!
* @file usbd_config.h
*
* @brief usb device config header file
*
* @version V1.0.1
*
* @date 2023-03-27
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Define to prevent recursive inclusion */
#ifndef _USBD_CONFIG_H_
#define _USBD_CONFIG_H_
/* Includes */
#include "usbd_board.h"
//#include <stdio.h>
/** @addtogroup APM32_USB_Library
@{
*/
/** @addtogroup USBD_Core
@{
*/
/** @defgroup USBD_Core_Macros Macros
@{
*/
/*!< [31:16] APM32 USB Device Library main version V1.1.3*/
#define __APM32_USB_DEVICE_VERSION_MAIN (0x01) /*!< [31:24] main version */
#define __APM32_USB_DEVICE_VERSION_SUB1 (0x01) /*!< [23:16] sub1 version */
#define __APM32_USB_DEVICE_VERSION_SUB2 (0x03) /*!< [15:8] sub2 version */
#define __APM32_USB_DEVICE_VERSION_RC (0x00) /*!< [7:0] release candidate */
#define __APM32_USB_DEVICE_VERSION ((__APM32_USB_DEVICE_VERSION_MAIN << 24)\
|(__APM32_USB_DEVICE_VERSION_SUB1 << 16)\
|(__APM32_USB_DEVICE_VERSION_SUB2 << 8 )\
|(__APM32_USB_DEVICE_VERSION_RC))
#define USBD_DEVICE_DEFAULT_ADDRESS 0
#define USBD_EP0_PACKET_MAX_SIZE 64
/**@} end of group USBD_Core_Macros*/
/** @defgroup USBD_Core_Enumerates Enumerates
@{
*/
/**
* @brief USB device operation status
*/
typedef enum
{
USBD_OK,
USBD_BUSY,
USBD_FAIL,
} USBD_STA_T;
/**
* @brief USB device speed type
*/
typedef enum
{
USBD_SPEED_FS,
USBD_SPEED_HS,
} USBD_SPEED_T;
/**
* @brief USB device speed
*/
typedef enum
{
USBD_DEVICE_SPEED_HS,
USBD_DEVICE_SPEED_FS,
USBD_DEVICE_SPEED_LS
} USBD_DEVICE_SPEED_T;
/**
* @brief USB device state
*/
typedef enum
{
USBD_DEV_IDLE,
USBD_DEV_DEFAULT,
USBD_DEV_ADDRESS,
USBD_DEV_CONFIGURE,
USBD_DEV_SUSPEND,
} USBD_DEV_STA_T;
/**
* @brief USB device EP0 state
*/
typedef enum
{
USBD_DEV_EP0_IDLE,
USBD_DEV_EP0_SETUP,
USBD_DEV_EP0_DATA_IN,
USBD_DEV_EP0_DATA_OUT,
USBD_DEV_EP0_STATUS_IN,
USBD_DEV_EP0_STATUS_OUT,
USBD_DEV_EP0_STALL,
} USBD_DEV_EP0_STA_T;
/**
* @brief USB device request type
*/
typedef enum
{
USBD_REQ_TYPE_STANDARD = 0,
USBD_REQ_TYPE_CLASS,
USBD_REQ_TYPE_VENDOR,
USBD_REQ_TYPE_RESERVED
} USBD_DEV_REQ_TYPE_T;
/**
* @brief USB device feature request type
*/
typedef enum
{
USBD_FEATURE_SELECTOR_ENDPOINT_HALT,
USBD_FEATURE_REMOTE_WAKEUP,
USBD_FEATURE_TEST_MODE,
} USBD_REQ_FEATURE_T;
/**
* @brief USB device status configuration type
*/
typedef enum
{
USBD_CFG_NONE,
USBD_CFG_SELF_POWER,
USBD_CFG_REMOTE_WAKEUP,
} USBD_REQ_CFG_T;
/**
* @brief USB standard device standard requests type
*/
typedef enum
{
USBD_STD_GET_STATUS = 0,
USBD_STD_CLEAR_FEATURE = 1,
USBD_STD_RESERVED1 = 2,
USBD_STD_SET_FEATURE = 3,
USBD_STD_RESERVED2 = 4,
USBD_STD_SET_ADDRESS = 5,
USBD_STD_GET_DESCRIPTOR = 6,
USBD_STD_SET_DESCRIPTOR = 7,
USBD_STD_GET_CONFIGURATION = 8,
USBD_STD_SET_CONFIGURATION = 9,
USBD_STD_GET_INTERFACE = 10,
USBD_STD_SET_INTERFACE = 11,
USBD_STD_SYNCH_FRAME = 12,
USBD_STD_CNT, /* <! Request counter */
} USBD_STD_REQ_TYPE_T;
/**
* @brief USB device vendor requests type
*/
typedef enum
{
USBD_VEN_REQ_MS_CODE = 0xA0,
} USBD_VENDOR_REQ_TYPE_T;
/**
* @brief USB device winusb descriptor type
*/
typedef enum
{
USBD_WINUSB_DESC_FEATURE = 0x04,
USBD_WINUSB_DESC_PROPERTY = 0x05,
} USBD_WINUSB_DESC_TYPE_T;
/**
* @brief USB descriptor types
*/
typedef enum
{
USBD_DESC_DEVICE = 0x01,
USBD_DESC_CONFIGURATION = 0x02,
USBD_DESC_STRING = 0x03,
USBD_DESC_INTERFACE = 0x04,
USBD_DESC_ENDPOINT = 0x05,
USBD_DESC_DEVICE_QUALIFIER = 0x06,
USBD_DESC_OTHER_SPEED = 0x07,
USBD_DESC_INTERFACE_POWER = 0x08,
USBD_DESC_IAD = 0x0B,
USBD_DESC_BOS = 0x0F,
USBD_DESC_HID = 0x21,
USBD_DESC_HID_REPORT = 0x22,
USBD_DESC_HID_PHY = 0x23,
} USBD_DESC_TYPE_T;
/**
* @brief USB string descriptor types
*/
typedef enum
{
USBD_DESC_STR_LANGID,
USBD_DESC_STR_MFC,
USBD_DESC_STR_PRODUCT,
USBD_DESC_STR_SERIAL,
USBD_DESC_STR_CONFIG,
USBD_DESC_STR_INTERFACE,
USBD_DESC_STR_WINUSB_OS = 0xEE,
} USBD_DESC_STR_T;
/**
* @brief USB device request recipient
*/
typedef enum
{
USBD_RECIPIENT_DEVICE = 0,
USBD_RECIPIENT_INTERFACE,
USBD_RECIPIENT_ENDPOINT,
USBD_RECIPIENT_OTHER
} USBD_DEV_RECIPIENT_T;
/**@} end of group USBD_Core_Enumerates*/
/** @defgroup USBD_Core_Structures Structures
@{
*/
/**
* @brief USB device endpoint information
*/
typedef struct
{
uint32_t length;
uint32_t remainLen;
uint32_t status;
uint32_t mp;
uint16_t useStatus;
uint16_t interval;
} USBD_EP_INFO_T;
/**
* @brief USB device descriptor information
*/
typedef struct
{
uint8_t* desc;
uint8_t size;
} USBD_DESC_INFO_T;
struct _USBD_INFO_T;
/* Descriptor callback function type define */
typedef USBD_DESC_INFO_T(*USBD_DescCallback_T)(uint8_t usbSpeed);
/**
* @brief USB device descriptor structure
*/
typedef struct
{
const char* descName;
USBD_DescCallback_T deviceDescHandler;
USBD_DescCallback_T configDescHandler;
USBD_DescCallback_T configStrDescHandler;
USBD_DescCallback_T interfaceStrDescHandler;
USBD_DescCallback_T langIdStrDescHandler;
USBD_DescCallback_T manufacturerStrDescHandler;
USBD_DescCallback_T productStrDescHandler;
USBD_DescCallback_T serialStrDescHandler;
#if USBD_SUP_LPM
USBD_DescCallback_T bosDescHandler;
#endif
USBD_DescCallback_T winUsbOsStrDescHandler;
USBD_DescCallback_T otherSpeedConfigDescHandler;
USBD_DescCallback_T devQualifierDescHandler;
} USBD_DESC_T;
/**
* @brief USB request type
*/
typedef union
{
uint8_t REQ_TYPE;
struct
{
uint8_t recipient : 5;
uint8_t type : 2;
uint8_t dir : 1;
} REQ_TYPE_B;
} USBD_REQ_TYPE_T;
/**
* @brief USB device SETUP request
*/
typedef struct
{
union
{
uint8_t REQ_DATA[8];
struct
{
USBD_REQ_TYPE_T bmRequest;
uint8_t bRequest;
uint8_t wValue[2];
uint8_t wIndex[2];
uint8_t wLength[2];
} DATA_FIELD;
};
} USBD_REQ_SETUP_T;
/* Standard device request callback function type define */
typedef USBD_STA_T(*USBD_StdDevReqCallback_T)(struct _USBD_INFO_T* usbInfo, USBD_REQ_SETUP_T* req);
/**
* @brief USB device class handler
*/
typedef struct
{
/* Class handler */
const char* className;
void* classData;
USBD_STA_T(*ClassInitHandler)(struct _USBD_INFO_T* usbInfo, uint8_t cfgIndex);
USBD_STA_T(*ClassDeInitHandler)(struct _USBD_INFO_T* usbInfo, uint8_t cfgIndex);
USBD_STA_T(*ClassSofHandler)(struct _USBD_INFO_T* usbInfo);
/* Control endpoint */
USBD_STA_T(*ClassSetup)(struct _USBD_INFO_T* usbInfo, USBD_REQ_SETUP_T* req);
USBD_STA_T(*ClassTxEP0)(struct _USBD_INFO_T* usbInfo);
USBD_STA_T(*ClassRxEP0)(struct _USBD_INFO_T* usbInfo);
/* Specific endpoint */
USBD_STA_T(*ClassDataIn)(struct _USBD_INFO_T* usbInfo, uint8_t epNum);
USBD_STA_T(*ClassDataOut)(struct _USBD_INFO_T* usbInfo, uint8_t epNum);
USBD_STA_T(*ClassIsoOutIncomplete)(struct _USBD_INFO_T* usbInfo, uint8_t epNum);
USBD_STA_T(*ClassIsoInIncomplete)(struct _USBD_INFO_T* usbInfo, uint8_t epNum);
} USBD_CLASS_T;
/**
* @brief USB device information
*/
typedef struct _USBD_INFO_T
{
__IO uint8_t devState;
__IO uint8_t preDevState;
__IO uint8_t devEp0State;
uint32_t devEp0DataLen;
uint8_t devSpeed;
uint8_t devAddr;
USBD_DESC_T* devDesc;
USBD_CLASS_T* devClass[USBD_SUP_CLASS_MAX_NUM];
void* devClassUserData[USBD_SUP_CLASS_MAX_NUM];
uint32_t classID;
uint32_t classNum;
void* cfgDesc;
USBD_REQ_SETUP_T reqSetup;
uint32_t devCfg;
uint32_t devCfgStatus;
uint32_t devCfgDefault;
uint8_t devTestModeStatus;
uint32_t devRemoteWakeUpStatus;
USBD_EP_INFO_T devEpIn[16];
USBD_EP_INFO_T devEpOut[16];
void (*userCallback)(struct _USBD_INFO_T* usbInfo, uint8_t userStatus);
void* dataPoint;
} USBD_INFO_T;
/**@} end of group USBD_Core_Structures*/
/**@} end of group USBD_Core */
/**@} end of group APM32_USB_Library */
#endif

View file

@ -0,0 +1,109 @@
/*!
* @file usbd_core.h
*
* @brief USB device core function
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Define to prevent recursive inclusion */
#ifndef _USBD_CORE_H_
#define _USBD_CORE_H_
/* Includes */
#include "usbd_config.h"
/** @addtogroup APM32_USB_Library
@{
*/
/** @addtogroup USBD_Core
@{
*/
/** @defgroup USBD_Core_Enumerates Enumerates
@{
*/
/**
* @brief USB device user status
*/
typedef enum
{
USBD_USER_RESET = 1,
USBD_USER_RESUME,
USBD_USER_SUSPEND,
USBD_USER_CONNECT,
USBD_USER_DISCONNECT,
USBD_USER_ENUM_DONE,
USBD_USER_ERROR,
} USBD_USER_STATUS;
/**@} end of group USBD_Core_Enumerates*/
/** @defgroup USBD_Core_Functions Functions
@{
*/
USBD_STA_T USBD_Init(USBD_INFO_T* usbInfo, USBD_SPEED_T usbDevSpeed, \
USBD_DESC_T* usbDevDesc, \
USBD_CLASS_T* usbDevClass, \
void (*userCallbackFunc)(struct _USBD_INFO_T*, uint8_t));
USBD_STA_T USBD_DeInit(USBD_INFO_T* usbInfo);
void USBD_HardwareInit(USBD_INFO_T* usbInfo);
void USBD_HardwareReset(USBD_INFO_T* usbInfo);
USBD_STA_T USBD_SetSpeed(USBD_INFO_T* usbInfo, USBD_DEVICE_SPEED_T speed);
USBD_STA_T USBD_SetupStage(USBD_INFO_T* usbInfo, uint8_t* setup);
USBD_STA_T USBD_DataOutStage(USBD_INFO_T* usbInfo, uint8_t epNum, uint8_t* buffer);
USBD_STA_T USBD_DataInStage(USBD_INFO_T* usbInfo, uint8_t epNum, uint8_t* buffer);
USBD_STA_T USBD_Resume(USBD_INFO_T* usbInfo);
USBD_STA_T USBD_Suspend(USBD_INFO_T* usbInfo);
USBD_STA_T USBD_Reset(USBD_INFO_T* usbInfo);
USBD_STA_T USBD_HandleSOF(USBD_INFO_T* usbInfo);
USBD_STA_T USBD_IsoInInComplete(USBD_INFO_T* usbInfo, uint8_t epNum);
USBD_STA_T USBD_IsoOutInComplete(USBD_INFO_T* usbInfo, uint8_t epNum);
USBD_STA_T USBD_Connect(USBD_INFO_T* usbInfo);
USBD_STA_T USBD_Disconnect(USBD_INFO_T* usbInfo);
void USBD_StartCallback(USBD_INFO_T* usbInfo);
void USBD_StopCallback(USBD_INFO_T* usbInfo);
void USBD_StopDeviceCallback(USBD_INFO_T* usbInfo);
USBD_STA_T USBD_EP_StallCallback(USBD_INFO_T* usbInfo, uint8_t epAddr);
USBD_STA_T USBD_EP_ClearStallCallback(USBD_INFO_T* usbInfo, uint8_t epAddr);
uint8_t USBD_EP_ReadStallStatusCallback(USBD_INFO_T* usbInfo, uint8_t epAddr);
void USBD_EP_OpenCallback(USBD_INFO_T* usbInfo, uint8_t epAddr, \
uint8_t epType, uint16_t epMps);
void USBD_EP_CloseCallback(USBD_INFO_T* usbInfo, uint8_t epAddr);
uint32_t USBD_EP_ReadRxDataLenCallback(USBD_INFO_T* usbInfo, uint8_t epAddr);
USBD_STA_T USBD_EP_ReceiveCallback(USBD_INFO_T* usbInfo, uint8_t epAddr, \
uint8_t* buffer, uint32_t length);
USBD_STA_T USBD_EP_TransferCallback(USBD_INFO_T* usbInfo, uint8_t epAddr, \
uint8_t* buffer, uint32_t length);
USBD_STA_T USBD_EP_FlushCallback(USBD_INFO_T* usbInfo, uint8_t epAddr);
USBD_STA_T USBD_SetDevAddressCallback(USBD_INFO_T* usbInfo, uint8_t address);
/**@} end of group USBD_Core_Functions */
/**@} end of group USBD_Core */
/**@} end of group APM32_USB_Library */
#endif

View file

@ -0,0 +1,57 @@
/*!
* @file usbd_dataXfer.h
*
* @brief USB device input and output hander function head file
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Define to prevent recursive inclusion */
#ifndef _USBD_DATAXFER_H_
#define _USBD_DATAXFER_H_
/* Includes */
#include "usbd_core.h"
/** @addtogroup APM32_USB_Library
@{
*/
/** @addtogroup USBD_Core
@{
*/
/** @defgroup USBD_Core_Functions Functions
@{
*/
USBD_STA_T USBD_CtrlSendData(USBD_INFO_T* usbInfo, uint8_t* buffer, uint32_t length);
USBD_STA_T USBD_CtrlSendNextData(USBD_INFO_T* usbInfo, uint8_t* buffer, uint32_t length);
USBD_STA_T USBD_CtrlReceiveData(USBD_INFO_T* usbInfo, uint8_t* buffer, uint32_t length);
USBD_STA_T USBD_CtrlSendStatus(USBD_INFO_T* usbInfo);
USBD_STA_T USBD_CtrlReceiveStatus(USBD_INFO_T* usbInfo);
USBD_STA_T USBH_SetupReqParse(uint8_t* buffer, USBD_REQ_SETUP_T* req);
/**@} end of group USBD_Core_Functions */
/**@} end of group USBD_Core */
/**@} end of group APM32_USB_Library */
#endif

View file

@ -0,0 +1,59 @@
/*!
* @file usbd_stdReq.h
*
* @brief USB standard request process
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Define to prevent recursive inclusion */
#ifndef _USBD_STDREQ_H_
#define _USBD_STDREQ_H_
/* Includes */
#include "usbd_core.h"
/** @addtogroup APM32_USB_Library
@{
*/
/** @addtogroup USBD_Core
@{
*/
/** @defgroup USBD_Core_Structures Structures
@{
*/
extern USBD_StdDevReqCallback_T USBD_StdDevReqHandler[];
/**@} end of group USBD_Core_Structures*/
/** @defgroup USBD_Core_Functions Functions
@{
*/
USBD_STA_T USBD_REQ_CtrlError(USBD_INFO_T* usbInfo, USBD_REQ_SETUP_T* req);
/**@} end of group USBD_Core_Functions */
/**@} end of group USBD_Core */
/**@} end of group APM32_USB_Library */
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,173 @@
/*!
* @file usbd_dataXfer.c
*
* @brief USB device input and output hander function
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Includes */
#include "usbd_dataXfer.h"
/** @addtogroup APM32_USB_Library
@{
*/
/** @addtogroup USBD_Core
@{
*/
/** @defgroup USBD_Core_Functions Functions
@{
*/
/*!
* @brief Parse setup request
*
* @param buffer : parse buffer
*
* @param req : setup request data
*
* @retval usb device status
*/
USBD_STA_T USBH_SetupReqParse(uint8_t* buffer, USBD_REQ_SETUP_T* req)
{
USBD_STA_T usbStatus = USBD_OK;
/* bmRequestType */
req->REQ_DATA[0] = *(uint8_t*)(buffer + 0);
req->DATA_FIELD.bRequest = *(uint8_t*)(buffer + 1);
req->DATA_FIELD.wValue[0] = *(uint8_t*)(buffer + 2);
req->DATA_FIELD.wValue[1] = *(uint8_t*)(buffer + 3);
req->DATA_FIELD.wIndex[0] = *(uint8_t*)(buffer + 4);
req->DATA_FIELD.wIndex[1] = *(uint8_t*)(buffer + 5);
req->DATA_FIELD.wLength[0] = *(uint8_t*)(buffer + 6);
req->DATA_FIELD.wLength[1] = *(uint8_t*)(buffer + 7);
return usbStatus;
}
/*!
* @brief USB device continue receive CTRL data
*
* @param usbInfo : usb handler information
*
* @param buffer : data buffer
*
* @param length : length of data
*
* @retval usb device status
*/
USBD_STA_T USBD_CtrlReceiveData(USBD_INFO_T* usbInfo, uint8_t* buffer, uint32_t length)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_EP_ReceiveCallback(usbInfo, USBD_EP_0, buffer, length);
return usbStatus;
}
/*!
* @brief USB device send CTRL status
*
* @param usbInfo : usb handler information
*
* @retval usb device status
*/
USBD_STA_T USBD_CtrlSendStatus(USBD_INFO_T* usbInfo)
{
USBD_STA_T usbStatus = USBD_OK;
usbInfo->devEp0State = USBD_DEV_EP0_STATUS_IN;
USBD_EP_TransferCallback(usbInfo, USBD_EP_0, NULL, 0);
return usbStatus;
}
/*!
* @brief USB device receive CTRL status
*
* @param usbInfo : usb handler information
*
* @retval usb device status
*/
USBD_STA_T USBD_CtrlReceiveStatus(USBD_INFO_T* usbInfo)
{
USBD_STA_T usbStatus = USBD_OK;
usbInfo->devEp0State = USBD_DEV_EP0_STATUS_OUT;
USBD_EP_ReceiveCallback(usbInfo, USBD_EP_0, NULL, 0);
return usbStatus;
}
/*!
* @brief USB device send CTRL data
*
* @param usbInfo : usb handler information
*
* @param buffer : data buffer
*
* @param length : length of data
*
* @retval usb device status
*/
USBD_STA_T USBD_CtrlSendData(USBD_INFO_T* usbInfo, uint8_t* buffer, uint32_t length)
{
USBD_STA_T usbStatus = USBD_OK;
usbInfo->devEp0State = USBD_DEV_EP0_DATA_IN;
usbInfo->devEpIn[USBD_EP_0].length = length;
usbInfo->devEpIn[USBD_EP_0].remainLen = length;
USBD_EP_TransferCallback(usbInfo, USBD_EP_0, buffer, length);
return usbStatus;
}
/*!
* @brief USB device send next CTRL data
*
* @param usbInfo : usb handler information
*
* @param buffer : data buffer
*
* @param length : length of data
*
* @retval usb device status
*/
USBD_STA_T USBD_CtrlSendNextData(USBD_INFO_T* usbInfo, uint8_t* buffer, uint32_t length)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_EP_TransferCallback(usbInfo, USBD_EP_0, buffer, length);
return usbStatus;
}
/**@} end of group USBD_Core_Functions */
/**@} end of group USBD_Core */
/**@} end of group APM32_USB_Library */

View file

@ -0,0 +1,697 @@
/*!
* @file usbd_stdReq.c
*
* @brief USB standard request process
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Includes */
#include "usbd_stdReq.h"
#include "usbd_dataXfer.h"
/** @addtogroup APM32_USB_Library
@{
*/
/** @addtogroup USBD_Core
@{
*/
/** @defgroup USBD_Core_Functions Functions
@{
*/
static USBD_STA_T USBD_REQ_GetStatus(USBD_INFO_T* usbInfo, USBD_REQ_SETUP_T* req);
static USBD_STA_T USBD_REQ_ClearFeature(USBD_INFO_T* usbInfo, USBD_REQ_SETUP_T* req);
static USBD_STA_T USBD_REQ_SetFeature(USBD_INFO_T* usbInfo, USBD_REQ_SETUP_T* req);
static USBD_STA_T USBD_REQ_SetAddress(USBD_INFO_T* usbInfo, USBD_REQ_SETUP_T* req);
static USBD_STA_T USBD_REQ_GetDesc(USBD_INFO_T* usbInfo, USBD_REQ_SETUP_T* req);
static USBD_STA_T USBD_REQ_SetDesc(USBD_INFO_T* usbInfo, USBD_REQ_SETUP_T* req);
static USBD_STA_T USBD_REQ_GetCfg(USBD_INFO_T* usbInfo, USBD_REQ_SETUP_T* req);
static USBD_STA_T USBD_REQ_SetCfg(USBD_INFO_T* usbInfo, USBD_REQ_SETUP_T* req);
static USBD_STA_T USBD_REQ_GetItf(USBD_INFO_T* usbInfo, USBD_REQ_SETUP_T* req);
static USBD_STA_T USBD_REQ_SetItf(USBD_INFO_T* usbInfo, USBD_REQ_SETUP_T* req);
static USBD_STA_T USBD_REQ_SyncFrame(USBD_INFO_T* usbInfo, USBD_REQ_SETUP_T* req);
/**@} end of group USBD_Core_Functions */
/** @defgroup USBD_Core_Structures Structures
@{
*/
/* Standard device request function match with USBD_STD_REQ_TYPE_T */
USBD_StdDevReqCallback_T USBD_StdDevReqHandler[] =
{
USBD_REQ_GetStatus,
USBD_REQ_ClearFeature,
NULL,
USBD_REQ_SetFeature,
NULL,
USBD_REQ_SetAddress,
USBD_REQ_GetDesc,
USBD_REQ_SetDesc,
USBD_REQ_GetCfg,
USBD_REQ_SetCfg,
USBD_REQ_GetItf,
USBD_REQ_SetItf,
USBD_REQ_SyncFrame,
};
/**@} end of group USBD_Core_Structures*/
/** @defgroup USBD_Core_Functions Functions
@{
*/
/*!
* @brief USB device get status request
*
* @param usbInfo : usb handler information
*
* @param setup : setup data
*
* @retval usb device status
*/
static USBD_STA_T USBD_REQ_GetStatus(USBD_INFO_T* usbInfo, USBD_REQ_SETUP_T* req)
{
USBD_STA_T usbStatus = USBD_OK;
uint16_t wLength = req->DATA_FIELD.wLength[0] | req->DATA_FIELD.wLength[1] << 8;
switch (usbInfo->devState)
{
case USBD_DEV_DEFAULT:
case USBD_DEV_ADDRESS:
case USBD_DEV_CONFIGURE:
if (wLength != 0x02)
{
USBD_REQ_CtrlError(usbInfo, req);
break;
}
#if USBD_SUP_SELF_PWR
usbInfo->devCfgStatus = USBD_CFG_SELF_POWER;
#else
usbInfo->devCfgStatus = USBD_CFG_NONE;
#endif
if (usbInfo->devRemoteWakeUpStatus == ENABLE)
{
usbInfo->devCfgStatus |= USBD_CFG_REMOTE_WAKEUP;
}
USBD_CtrlSendData(usbInfo, (uint8_t*)&usbInfo->devCfgStatus, 2);
break;
default:
USBD_REQ_CtrlError(usbInfo, req);
break;
}
return usbStatus;
}
/*!
* @brief USB device clear feature request
*
* @param usbInfo : usb handler information
*
* @param setup : setup data
*
* @retval usb device status
*/
static USBD_STA_T USBD_REQ_ClearFeature(USBD_INFO_T* usbInfo, USBD_REQ_SETUP_T* req)
{
USBD_STA_T usbStatus = USBD_OK;
uint16_t wValue = req->DATA_FIELD.wValue[0] | req->DATA_FIELD.wValue[1] << 8;
switch (usbInfo->devState)
{
case USBD_DEV_DEFAULT:
case USBD_DEV_ADDRESS:
case USBD_DEV_CONFIGURE:
if (wValue == USBD_FEATURE_REMOTE_WAKEUP)
{
usbInfo->devRemoteWakeUpStatus = DISABLE;
USBD_CtrlSendStatus(usbInfo);
}
break;
default:
USBD_REQ_CtrlError(usbInfo, req);
break;
}
return usbStatus;
}
/*!
* @brief USB device set feature request
*
* @param usbInfo : usb handler information
*
* @param setup : setup data
*
* @retval usb device status
*/
static USBD_STA_T USBD_REQ_SetFeature(USBD_INFO_T* usbInfo, USBD_REQ_SETUP_T* req)
{
USBD_STA_T usbStatus = USBD_OK;
uint16_t wValue = req->DATA_FIELD.wValue[0] | req->DATA_FIELD.wValue[1] << 8;
switch (wValue)
{
case USBD_FEATURE_REMOTE_WAKEUP:
usbInfo->devRemoteWakeUpStatus = ENABLE;
USBD_CtrlSendStatus(usbInfo);
break;
case USBD_FEATURE_TEST_MODE:
usbInfo->devTestModeStatus = req->DATA_FIELD.wIndex[1];
USBD_CtrlSendStatus(usbInfo);
break;
default:
USBD_REQ_CtrlError(usbInfo, req);
break;
}
return usbStatus;
}
/*!
* @brief USB device set address request
*
* @param usbInfo : usb handler information
*
* @param setup : setup data
*
* @retval usb device status
*/
static USBD_STA_T USBD_REQ_SetAddress(USBD_INFO_T* usbInfo, USBD_REQ_SETUP_T* req)
{
USBD_STA_T usbStatus = USBD_OK;
uint16_t wIndex = req->DATA_FIELD.wIndex[0] | req->DATA_FIELD.wIndex[1] << 8;
uint16_t wLength = req->DATA_FIELD.wLength[0] | req->DATA_FIELD.wLength[1] << 8;
uint16_t wValue = req->DATA_FIELD.wValue[0] | req->DATA_FIELD.wValue[1] << 8;
uint8_t devAddr = wValue & 0x7F;
if ((wIndex == 0) && (wLength == 0) && (wValue < 0x80))
{
switch (usbInfo->devState)
{
case USBD_DEV_CONFIGURE:
USBD_REQ_CtrlError(usbInfo, req);
break;
default:
usbInfo->devAddr = devAddr;
USBD_SetDevAddressCallback(usbInfo, devAddr);
USBD_CtrlSendStatus(usbInfo);
if (devAddr)
{
usbInfo->devState = USBD_DEV_ADDRESS;
}
else
{
usbInfo->devState = USBD_DEV_DEFAULT;
}
break;
}
}
else
{
USBD_REQ_CtrlError(usbInfo, req);
}
return usbStatus;
}
/*!
* @brief USB device get descriptor request
*
* @param usbInfo : usb handler information
*
* @param setup : setup data
*
* @retval usb device status
*/
static USBD_STA_T USBD_REQ_GetDesc(USBD_INFO_T* usbInfo, USBD_REQ_SETUP_T* req)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_DESC_INFO_T descInfo;
uint8_t reqError = 0;
uint16_t wLength = req->DATA_FIELD.wLength[0] | req->DATA_FIELD.wLength[1] << 8;
switch (req->DATA_FIELD.wValue[1])
{
#if USBD_SUP_LPM
case USBD_DESC_BOS:
if (usbInfo->devDesc->bosDescHandler != NULL)
{
descInfo = usbInfo->devDesc->bosDescHandler(usbInfo->devSpeed);
}
else
{
USBD_REQ_CtrlError(usbInfo, req);
reqError++;
}
break;
#endif
case USBD_DESC_DEVICE:
descInfo = usbInfo->devDesc->deviceDescHandler(usbInfo->devSpeed);
break;
case USBD_DESC_CONFIGURATION:
descInfo = usbInfo->devDesc->configDescHandler(usbInfo->devSpeed);
break;
case USBD_DESC_STRING:
switch (req->DATA_FIELD.wValue[0])
{
case USBD_DESC_STR_LANGID:
if (usbInfo->devDesc->langIdStrDescHandler != NULL)
{
descInfo = usbInfo->devDesc->langIdStrDescHandler(usbInfo->devSpeed);
}
else
{
USBD_REQ_CtrlError(usbInfo, req);
reqError++;
}
break;
case USBD_DESC_STR_MFC:
if (usbInfo->devDesc->manufacturerStrDescHandler != NULL)
{
descInfo = usbInfo->devDesc->manufacturerStrDescHandler(usbInfo->devSpeed);
}
else
{
USBD_REQ_CtrlError(usbInfo, req);
reqError++;
}
break;
case USBD_DESC_STR_PRODUCT:
if (usbInfo->devDesc->productStrDescHandler != NULL)
{
descInfo = usbInfo->devDesc->productStrDescHandler(usbInfo->devSpeed);
}
else
{
USBD_REQ_CtrlError(usbInfo, req);
reqError++;
}
break;
case USBD_DESC_STR_SERIAL:
if (usbInfo->devDesc->serialStrDescHandler != NULL)
{
descInfo = usbInfo->devDesc->serialStrDescHandler(usbInfo->devSpeed);
}
else
{
USBD_REQ_CtrlError(usbInfo, req);
reqError++;
}
break;
case USBD_DESC_STR_CONFIG:
if (usbInfo->devDesc->configStrDescHandler != NULL)
{
descInfo = usbInfo->devDesc->configStrDescHandler(usbInfo->devSpeed);
}
else
{
USBD_REQ_CtrlError(usbInfo, req);
reqError++;
}
break;
case USBD_DESC_STR_INTERFACE:
if (usbInfo->devDesc->interfaceStrDescHandler != NULL)
{
descInfo = usbInfo->devDesc->interfaceStrDescHandler(usbInfo->devSpeed);
}
else
{
USBD_REQ_CtrlError(usbInfo, req);
reqError++;
}
break;
case USBD_DESC_STR_WINUSB_OS:
if (usbInfo->devDesc->winUsbOsStrDescHandler != NULL)
{
descInfo = usbInfo->devDesc->winUsbOsStrDescHandler(usbInfo->devSpeed);
}
else
{
USBD_REQ_CtrlError(usbInfo, req);
reqError++;
}
break;
default:
USBD_REQ_CtrlError(usbInfo, req);
reqError++;
break;
}
break;
case USBD_DESC_DEVICE_QUALIFIER:
if (usbInfo->devSpeed == USBD_SPEED_FS)
{
USBD_REQ_CtrlError(usbInfo, req);
reqError++;
}
else
{
descInfo = usbInfo->devDesc->devQualifierDescHandler(usbInfo->devSpeed);
}
break;
case USBD_DESC_OTHER_SPEED:
if (usbInfo->devSpeed == USBD_SPEED_FS)
{
USBD_REQ_CtrlError(usbInfo, req);
reqError++;
}
else
{
descInfo = usbInfo->devDesc->otherSpeedConfigDescHandler(usbInfo->devSpeed);
}
break;
default:
USBD_REQ_CtrlError(usbInfo, req);
reqError++;
break;
}
if (reqError)
{
usbStatus = USBD_FAIL;
return usbStatus;
}
if (wLength)
{
if (descInfo.size)
{
if (descInfo.size > wLength)
{
descInfo.size = wLength;
}
USBD_CtrlSendData(usbInfo, descInfo.desc, descInfo.size);
}
else
{
USBD_REQ_CtrlError(usbInfo, req);
}
}
else
{
USBD_CtrlSendStatus(usbInfo);
}
return usbStatus;
}
/*!
* @brief USB device set descriptor request
*
* @param usbInfo : usb handler information
*
* @param req : setup data
*
* @retval usb device status
*/
static USBD_STA_T USBD_REQ_SetDesc(USBD_INFO_T* usbInfo, USBD_REQ_SETUP_T* req)
{
USBD_STA_T usbStatus = USBD_OK;
UNUSED(usbInfo);
UNUSED(req);
return usbStatus;
}
/*!
* @brief USB device get configuration request
*
* @param usbInfo : usb handler information
*
* @param setup : setup data
*
* @retval usb device status
*/
static USBD_STA_T USBD_REQ_GetCfg(USBD_INFO_T* usbInfo, USBD_REQ_SETUP_T* req)
{
USBD_STA_T usbStatus = USBD_OK;
uint16_t wLength = req->DATA_FIELD.wLength[0] | req->DATA_FIELD.wLength[1] << 8;
if (wLength == 1)
{
switch (usbInfo->devState)
{
case USBD_DEV_DEFAULT:
case USBD_DEV_ADDRESS:
usbInfo->devCfgDefault = 0;
USBD_CtrlSendData(usbInfo, (uint8_t*)&usbInfo->devCfgDefault, 1);
break;
case USBD_DEV_CONFIGURE:
USBD_CtrlSendData(usbInfo, (uint8_t*)&usbInfo->devCfg, 1);
break;
default:
USBD_REQ_CtrlError(usbInfo, req);
break;
}
}
else
{
USBD_REQ_CtrlError(usbInfo, req);
}
return usbStatus;
}
/*!
* @brief USB device set configuration request
*
* @param usbInfo : usb handler information
*
* @param setup : setup data
*
* @retval usb device status
*/
static USBD_STA_T USBD_REQ_SetCfg(USBD_INFO_T* usbInfo, USBD_REQ_SETUP_T* req)
{
USBD_STA_T usbStatus = USBD_OK;
static uint8_t cfgIndex;
cfgIndex = req->DATA_FIELD.wValue[0];
if (cfgIndex > USBD_SUP_CONFIGURATION_MAX_NUM)
{
USBD_REQ_CtrlError(usbInfo, req);
return USBD_FAIL;
}
switch (usbInfo->devState)
{
case USBD_DEV_ADDRESS:
if (cfgIndex == 0)
{
USBD_CtrlSendStatus(usbInfo);
}
else
{
usbInfo->devCfg = cfgIndex;
/* Set class configuration */
if (usbInfo->devClass[0] != NULL)
{
usbStatus = usbInfo->devClass[0]->ClassInitHandler(usbInfo, cfgIndex);
}
if (usbStatus == USBD_OK)
{
USBD_CtrlSendStatus(usbInfo);
usbInfo->devState = USBD_DEV_CONFIGURE;
}
else
{
USBD_REQ_CtrlError(usbInfo, req);
usbInfo->devState = USBD_DEV_ADDRESS;
}
}
break;
case USBD_DEV_CONFIGURE:
if (cfgIndex == 0)
{
usbInfo->devState = USBD_DEV_ADDRESS;
usbInfo->devCfg = cfgIndex;
/* Clear class configuration */
usbInfo->devClass[0]->ClassDeInitHandler(usbInfo, cfgIndex);
USBD_CtrlSendStatus(usbInfo);
}
else if (cfgIndex != usbInfo->devCfg)
{
/* Clear old class configuration */
usbInfo->devClass[0]->ClassDeInitHandler(usbInfo, usbInfo->devCfg);
usbInfo->devCfg = cfgIndex;
/* Set class configuration */
if (usbInfo->devClass[0] != NULL)
{
usbStatus = usbInfo->devClass[0]->ClassInitHandler(usbInfo, cfgIndex);
}
if (usbStatus == USBD_OK)
{
USBD_CtrlSendStatus(usbInfo);
}
else
{
USBD_REQ_CtrlError(usbInfo, req);
/* Clear old class configuration */
usbInfo->devClass[0]->ClassDeInitHandler(usbInfo, usbInfo->devCfg);
usbInfo->devState = USBD_DEV_ADDRESS;
}
}
else
{
USBD_CtrlSendStatus(usbInfo);
}
break;
default:
USBD_REQ_CtrlError(usbInfo, req);
/* Clear class configuration */
if (usbInfo->devClass[0]->ClassDeInitHandler(usbInfo, cfgIndex) != USBD_OK)
{
usbStatus = USBD_FAIL;
}
break;
}
return usbStatus;
}
/*!
* @brief USB device get interface request
*
* @param usbInfo : usb handler information
*
* @param setup : setup data
*
* @retval usb device status
*/
static USBD_STA_T USBD_REQ_GetItf(USBD_INFO_T* usbInfo, USBD_REQ_SETUP_T* req)
{
USBD_STA_T usbStatus = USBD_OK;
UNUSED(usbInfo);
UNUSED(req);
return usbStatus;
}
/*!
* @brief USB device set interface request
*
* @param usbInfo : usb handler information
*
* @param setup : setup data
*
* @retval usb device status
*/
static USBD_STA_T USBD_REQ_SetItf(USBD_INFO_T* usbInfo, USBD_REQ_SETUP_T* req)
{
USBD_STA_T usbStatus = USBD_OK;
UNUSED(usbInfo);
UNUSED(req);
return usbStatus;
}
/*!
* @brief USB device sync frame request
*
* @param usbInfo : usb handler information
*
* @param setup : setup data
*
* @retval usb device status
*/
static USBD_STA_T USBD_REQ_SyncFrame(USBD_INFO_T* usbInfo, USBD_REQ_SETUP_T* req)
{
USBD_STA_T usbStatus = USBD_OK;
UNUSED(usbInfo);
UNUSED(req);
return usbStatus;
}
/*!
* @brief USB device control request error
*
* @param usbInfo : usb handler information
*
* @param setup : setup data
*
* @retval usb device status
*/
USBD_STA_T USBD_REQ_CtrlError(USBD_INFO_T* usbInfo, USBD_REQ_SETUP_T* req)
{
USBD_STA_T usbStatus = USBD_OK;
UNUSED(req);
USBD_EP_StallCallback(usbInfo, 0x80);
USBD_EP_StallCallback(usbInfo, 0x00);
return usbStatus;
}
/**@} end of group USBD_Core_Functions */
/**@} end of group USBD_Core */
/**@} end of group APM32_USB_Library */