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:
parent
2ff71b0a1f
commit
14bcc13150
258 changed files with 290932 additions and 0 deletions
|
@ -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
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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_ */
|
|
@ -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
|
|
@ -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 */
|
|
@ -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
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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 */
|
|
@ -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 */
|
File diff suppressed because it is too large
Load diff
|
@ -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
|
|
@ -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 */
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
@ -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 */
|
|
@ -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 */
|
Loading…
Add table
Add a link
Reference in a new issue