summaryrefslogtreecommitdiff
path: root/Middlewares/ST/STM32_USB_Device_Library/Core
diff options
context:
space:
mode:
Diffstat (limited to 'Middlewares/ST/STM32_USB_Device_Library/Core')
-rwxr-xr-xMiddlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_core.h175
-rwxr-xr-xMiddlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ctlreq.h101
-rwxr-xr-xMiddlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_def.h524
-rwxr-xr-xMiddlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ioreq.h113
-rwxr-xr-xMiddlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c1221
-rwxr-xr-xMiddlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c1058
-rwxr-xr-xMiddlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c226
7 files changed, 3418 insertions, 0 deletions
diff --git a/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_core.h b/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_core.h
new file mode 100755
index 0000000..4672921
--- /dev/null
+++ b/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_core.h
@@ -0,0 +1,175 @@
+/**
+ ******************************************************************************
+ * @file usbd_core.h
+ * @author MCD Application Team
+ * @brief Header file for usbd_core.c file
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2015 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __USBD_CORE_H
+#define __USBD_CORE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbd_conf.h"
+#include "usbd_def.h"
+#include "usbd_ioreq.h"
+#include "usbd_ctlreq.h"
+
+/** @addtogroup STM32_USB_DEVICE_LIBRARY
+ * @{
+ */
+
+/** @defgroup USBD_CORE
+ * @brief This file is the Header file for usbd_core.c file
+ * @{
+ */
+
+
+/** @defgroup USBD_CORE_Exported_Defines
+ * @{
+ */
+#ifndef USBD_DEBUG_LEVEL
+#define USBD_DEBUG_LEVEL 0U
+#endif /* USBD_DEBUG_LEVEL */
+/**
+ * @}
+ */
+
+
+/** @defgroup USBD_CORE_Exported_TypesDefinitions
+ * @{
+ */
+
+
+/**
+ * @}
+ */
+
+
+
+/** @defgroup USBD_CORE_Exported_Macros
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+/** @defgroup USBD_CORE_Exported_Variables
+ * @{
+ */
+#define USBD_SOF USBD_LL_SOF
+/**
+ * @}
+ */
+
+/** @defgroup USBD_CORE_Exported_FunctionsPrototype
+ * @{
+ */
+USBD_StatusTypeDef USBD_Init(USBD_HandleTypeDef *pdev, USBD_DescriptorsTypeDef *pdesc, uint8_t id);
+USBD_StatusTypeDef USBD_DeInit(USBD_HandleTypeDef *pdev);
+USBD_StatusTypeDef USBD_Start(USBD_HandleTypeDef *pdev);
+USBD_StatusTypeDef USBD_Stop(USBD_HandleTypeDef *pdev);
+USBD_StatusTypeDef USBD_RegisterClass(USBD_HandleTypeDef *pdev, USBD_ClassTypeDef *pclass);
+#if (USBD_USER_REGISTER_CALLBACK == 1U)
+USBD_StatusTypeDef USBD_RegisterDevStateCallback(USBD_HandleTypeDef *pdev, USBD_DevStateCallbackTypeDef pUserCallback);
+#endif /* USBD_USER_REGISTER_CALLBACK */
+
+#ifdef USE_USBD_COMPOSITE
+USBD_StatusTypeDef USBD_RegisterClassComposite(USBD_HandleTypeDef *pdev, USBD_ClassTypeDef *pclass,
+ USBD_CompositeClassTypeDef classtype, uint8_t *EpAddr);
+
+USBD_StatusTypeDef USBD_UnRegisterClassComposite(USBD_HandleTypeDef *pdev);
+uint8_t USBD_CoreGetEPAdd(USBD_HandleTypeDef *pdev, uint8_t ep_dir, uint8_t ep_type, uint8_t ClassId);
+#endif /* USE_USBD_COMPOSITE */
+
+uint8_t USBD_CoreFindIF(USBD_HandleTypeDef *pdev, uint8_t index);
+uint8_t USBD_CoreFindEP(USBD_HandleTypeDef *pdev, uint8_t index);
+
+USBD_StatusTypeDef USBD_RunTestMode(USBD_HandleTypeDef *pdev);
+USBD_StatusTypeDef USBD_SetClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
+USBD_StatusTypeDef USBD_ClrClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
+
+USBD_StatusTypeDef USBD_LL_SetupStage(USBD_HandleTypeDef *pdev, uint8_t *psetup);
+USBD_StatusTypeDef USBD_LL_DataOutStage(USBD_HandleTypeDef *pdev, uint8_t epnum, uint8_t *pdata);
+USBD_StatusTypeDef USBD_LL_DataInStage(USBD_HandleTypeDef *pdev, uint8_t epnum, uint8_t *pdata);
+
+USBD_StatusTypeDef USBD_LL_Reset(USBD_HandleTypeDef *pdev);
+USBD_StatusTypeDef USBD_LL_SetSpeed(USBD_HandleTypeDef *pdev, USBD_SpeedTypeDef speed);
+USBD_StatusTypeDef USBD_LL_Suspend(USBD_HandleTypeDef *pdev);
+USBD_StatusTypeDef USBD_LL_Resume(USBD_HandleTypeDef *pdev);
+
+USBD_StatusTypeDef USBD_LL_SOF(USBD_HandleTypeDef *pdev);
+USBD_StatusTypeDef USBD_LL_IsoINIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum);
+USBD_StatusTypeDef USBD_LL_IsoOUTIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum);
+
+USBD_StatusTypeDef USBD_LL_DevConnected(USBD_HandleTypeDef *pdev);
+USBD_StatusTypeDef USBD_LL_DevDisconnected(USBD_HandleTypeDef *pdev);
+
+/* USBD Low Level Driver */
+USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev);
+USBD_StatusTypeDef USBD_LL_DeInit(USBD_HandleTypeDef *pdev);
+USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev);
+USBD_StatusTypeDef USBD_LL_Stop(USBD_HandleTypeDef *pdev);
+
+USBD_StatusTypeDef USBD_LL_OpenEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr,
+ uint8_t ep_type, uint16_t ep_mps);
+
+USBD_StatusTypeDef USBD_LL_CloseEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr);
+USBD_StatusTypeDef USBD_LL_FlushEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr);
+USBD_StatusTypeDef USBD_LL_StallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr);
+USBD_StatusTypeDef USBD_LL_ClearStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr);
+USBD_StatusTypeDef USBD_LL_SetUSBAddress(USBD_HandleTypeDef *pdev, uint8_t dev_addr);
+
+USBD_StatusTypeDef USBD_LL_Transmit(USBD_HandleTypeDef *pdev, uint8_t ep_addr,
+ uint8_t *pbuf, uint32_t size);
+
+USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev, uint8_t ep_addr,
+ uint8_t *pbuf, uint32_t size);
+
+#ifdef USBD_HS_TESTMODE_ENABLE
+USBD_StatusTypeDef USBD_LL_SetTestMode(USBD_HandleTypeDef *pdev, uint8_t testmode);
+#endif /* USBD_HS_TESTMODE_ENABLE */
+
+uint8_t USBD_LL_IsStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr);
+uint32_t USBD_LL_GetRxDataSize(USBD_HandleTypeDef *pdev, uint8_t ep_addr);
+
+void USBD_LL_Delay(uint32_t Delay);
+
+void *USBD_GetEpDesc(uint8_t *pConfDesc, uint8_t EpAddr);
+USBD_DescHeaderTypeDef *USBD_GetNextDesc(uint8_t *pbuf, uint16_t *ptr);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __USBD_CORE_H */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+
diff --git a/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ctlreq.h b/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ctlreq.h
new file mode 100755
index 0000000..6c45d6c
--- /dev/null
+++ b/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ctlreq.h
@@ -0,0 +1,101 @@
+/**
+ ******************************************************************************
+ * @file usbd_req.h
+ * @author MCD Application Team
+ * @brief Header file for the usbd_req.c file
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2015 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __USB_REQUEST_H
+#define __USB_REQUEST_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbd_def.h"
+
+
+/** @addtogroup STM32_USB_DEVICE_LIBRARY
+ * @{
+ */
+
+/** @defgroup USBD_REQ
+ * @brief header file for the usbd_req.c file
+ * @{
+ */
+
+/** @defgroup USBD_REQ_Exported_Defines
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+/** @defgroup USBD_REQ_Exported_Types
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+
+/** @defgroup USBD_REQ_Exported_Macros
+ * @{
+ */
+/**
+ * @}
+ */
+
+/** @defgroup USBD_REQ_Exported_Variables
+ * @{
+ */
+/**
+ * @}
+ */
+
+/** @defgroup USBD_REQ_Exported_FunctionsPrototype
+ * @{
+ */
+
+USBD_StatusTypeDef USBD_StdDevReq(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
+USBD_StatusTypeDef USBD_StdItfReq(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
+USBD_StatusTypeDef USBD_StdEPReq(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
+
+void USBD_CtlError(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
+void USBD_ParseSetupRequest(USBD_SetupReqTypedef *req, uint8_t *pdata);
+void USBD_GetString(uint8_t *desc, uint8_t *unicode, uint16_t *len);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __USB_REQUEST_H */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+
diff --git a/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_def.h b/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_def.h
new file mode 100755
index 0000000..5b2394e
--- /dev/null
+++ b/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_def.h
@@ -0,0 +1,524 @@
+/**
+ ******************************************************************************
+ * @file usbd_def.h
+ * @author MCD Application Team
+ * @brief General defines for the usb device library
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2015 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __USBD_DEF_H
+#define __USBD_DEF_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbd_conf.h"
+
+/** @addtogroup STM32_USBD_DEVICE_LIBRARY
+ * @{
+ */
+
+/** @defgroup USB_DEF
+ * @brief general defines for the usb device library file
+ * @{
+ */
+
+/** @defgroup USB_DEF_Exported_Defines
+ * @{
+ */
+
+#ifndef NULL
+#define NULL 0U
+#endif /* NULL */
+
+#ifndef USBD_MAX_NUM_INTERFACES
+#define USBD_MAX_NUM_INTERFACES 1U
+#endif /* USBD_MAX_NUM_CONFIGURATION */
+
+#ifndef USBD_MAX_NUM_CONFIGURATION
+#define USBD_MAX_NUM_CONFIGURATION 1U
+#endif /* USBD_MAX_NUM_CONFIGURATION */
+
+#ifdef USE_USBD_COMPOSITE
+#ifndef USBD_MAX_SUPPORTED_CLASS
+#define USBD_MAX_SUPPORTED_CLASS 4U
+#endif /* USBD_MAX_SUPPORTED_CLASS */
+#else
+#ifndef USBD_MAX_SUPPORTED_CLASS
+#define USBD_MAX_SUPPORTED_CLASS 1U
+#endif /* USBD_MAX_SUPPORTED_CLASS */
+#endif /* USE_USBD_COMPOSITE */
+
+#ifndef USBD_MAX_CLASS_ENDPOINTS
+#define USBD_MAX_CLASS_ENDPOINTS 5U
+#endif /* USBD_MAX_CLASS_ENDPOINTS */
+
+#ifndef USBD_MAX_CLASS_INTERFACES
+#define USBD_MAX_CLASS_INTERFACES 5U
+#endif /* USBD_MAX_CLASS_INTERFACES */
+
+#ifndef USBD_LPM_ENABLED
+#define USBD_LPM_ENABLED 0U
+#endif /* USBD_LPM_ENABLED */
+
+#ifndef USBD_SELF_POWERED
+#define USBD_SELF_POWERED 1U
+#endif /*USBD_SELF_POWERED */
+
+#ifndef USBD_MAX_POWER
+#define USBD_MAX_POWER 0x32U /* 100 mA */
+#endif /* USBD_MAX_POWER */
+
+#ifndef USBD_SUPPORT_USER_STRING_DESC
+#define USBD_SUPPORT_USER_STRING_DESC 0U
+#endif /* USBD_SUPPORT_USER_STRING_DESC */
+
+#ifndef USBD_CLASS_USER_STRING_DESC
+#define USBD_CLASS_USER_STRING_DESC 0U
+#endif /* USBD_CLASS_USER_STRING_DESC */
+
+#define USB_LEN_DEV_QUALIFIER_DESC 0x0AU
+#define USB_LEN_DEV_DESC 0x12U
+#define USB_LEN_CFG_DESC 0x09U
+#define USB_LEN_IF_DESC 0x09U
+#define USB_LEN_EP_DESC 0x07U
+#define USB_LEN_OTG_DESC 0x03U
+#define USB_LEN_LANGID_STR_DESC 0x04U
+#define USB_LEN_OTHER_SPEED_DESC_SIZ 0x09U
+
+#define USBD_IDX_LANGID_STR 0x00U
+#define USBD_IDX_MFC_STR 0x01U
+#define USBD_IDX_PRODUCT_STR 0x02U
+#define USBD_IDX_SERIAL_STR 0x03U
+#define USBD_IDX_CONFIG_STR 0x04U
+#define USBD_IDX_INTERFACE_STR 0x05U
+
+#define USB_REQ_TYPE_STANDARD 0x00U
+#define USB_REQ_TYPE_CLASS 0x20U
+#define USB_REQ_TYPE_VENDOR 0x40U
+#define USB_REQ_TYPE_MASK 0x60U
+
+#define USB_REQ_RECIPIENT_DEVICE 0x00U
+#define USB_REQ_RECIPIENT_INTERFACE 0x01U
+#define USB_REQ_RECIPIENT_ENDPOINT 0x02U
+#define USB_REQ_RECIPIENT_MASK 0x03U
+
+#define USB_REQ_GET_STATUS 0x00U
+#define USB_REQ_CLEAR_FEATURE 0x01U
+#define USB_REQ_SET_FEATURE 0x03U
+#define USB_REQ_SET_ADDRESS 0x05U
+#define USB_REQ_GET_DESCRIPTOR 0x06U
+#define USB_REQ_SET_DESCRIPTOR 0x07U
+#define USB_REQ_GET_CONFIGURATION 0x08U
+#define USB_REQ_SET_CONFIGURATION 0x09U
+#define USB_REQ_GET_INTERFACE 0x0AU
+#define USB_REQ_SET_INTERFACE 0x0BU
+#define USB_REQ_SYNCH_FRAME 0x0CU
+
+#define USB_DESC_TYPE_DEVICE 0x01U
+#define USB_DESC_TYPE_CONFIGURATION 0x02U
+#define USB_DESC_TYPE_STRING 0x03U
+#define USB_DESC_TYPE_INTERFACE 0x04U
+#define USB_DESC_TYPE_ENDPOINT 0x05U
+#define USB_DESC_TYPE_DEVICE_QUALIFIER 0x06U
+#define USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION 0x07U
+#define USB_DESC_TYPE_IAD 0x0BU
+#define USB_DESC_TYPE_BOS 0x0FU
+
+#define USB_CONFIG_REMOTE_WAKEUP 0x02U
+#define USB_CONFIG_SELF_POWERED 0x01U
+
+#define USB_FEATURE_EP_HALT 0x00U
+#define USB_FEATURE_REMOTE_WAKEUP 0x01U
+#define USB_FEATURE_TEST_MODE 0x02U
+
+#define USB_DEVICE_CAPABITY_TYPE 0x10U
+
+#define USB_CONF_DESC_SIZE 0x09U
+#define USB_IF_DESC_SIZE 0x09U
+#define USB_EP_DESC_SIZE 0x07U
+#define USB_IAD_DESC_SIZE 0x08U
+
+#define USB_HS_MAX_PACKET_SIZE 512U
+#define USB_FS_MAX_PACKET_SIZE 64U
+#define USB_MAX_EP0_SIZE 64U
+
+/* Device Status */
+#define USBD_STATE_DEFAULT 0x01U
+#define USBD_STATE_ADDRESSED 0x02U
+#define USBD_STATE_CONFIGURED 0x03U
+#define USBD_STATE_SUSPENDED 0x04U
+
+
+/* EP0 State */
+#define USBD_EP0_IDLE 0x00U
+#define USBD_EP0_SETUP 0x01U
+#define USBD_EP0_DATA_IN 0x02U
+#define USBD_EP0_DATA_OUT 0x03U
+#define USBD_EP0_STATUS_IN 0x04U
+#define USBD_EP0_STATUS_OUT 0x05U
+#define USBD_EP0_STALL 0x06U
+
+#define USBD_EP_TYPE_CTRL 0x00U
+#define USBD_EP_TYPE_ISOC 0x01U
+#define USBD_EP_TYPE_BULK 0x02U
+#define USBD_EP_TYPE_INTR 0x03U
+
+#ifdef USE_USBD_COMPOSITE
+#define USBD_EP_IN 0x80U
+#define USBD_EP_OUT 0x00U
+#define USBD_FUNC_DESCRIPTOR_TYPE 0x24U
+#define USBD_DESC_SUBTYPE_ACM 0x0FU
+#define USBD_DESC_ECM_BCD_LOW 0x00U
+#define USBD_DESC_ECM_BCD_HIGH 0x10U
+#endif /* USE_USBD_COMPOSITE */
+/**
+ * @}
+ */
+
+
+/** @defgroup USBD_DEF_Exported_TypesDefinitions
+ * @{
+ */
+
+typedef struct usb_setup_req
+{
+ uint8_t bmRequest;
+ uint8_t bRequest;
+ uint16_t wValue;
+ uint16_t wIndex;
+ uint16_t wLength;
+} USBD_SetupReqTypedef;
+
+typedef struct
+{
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint16_t wTotalLength;
+ uint8_t bNumInterfaces;
+ uint8_t bConfigurationValue;
+ uint8_t iConfiguration;
+ uint8_t bmAttributes;
+ uint8_t bMaxPower;
+} __PACKED USBD_ConfigDescTypeDef;
+
+typedef struct
+{
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint16_t wTotalLength;
+ uint8_t bNumDeviceCaps;
+} USBD_BosDescTypeDef;
+
+typedef struct
+{
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bEndpointAddress;
+ uint8_t bmAttributes;
+ uint16_t wMaxPacketSize;
+ uint8_t bInterval;
+} __PACKED USBD_EpDescTypeDef;
+
+typedef struct
+{
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubType;
+} USBD_DescHeaderTypeDef;
+
+struct _USBD_HandleTypeDef;
+
+typedef struct _Device_cb
+{
+ uint8_t (*Init)(struct _USBD_HandleTypeDef *pdev, uint8_t cfgidx);
+ uint8_t (*DeInit)(struct _USBD_HandleTypeDef *pdev, uint8_t cfgidx);
+ /* Control Endpoints*/
+ uint8_t (*Setup)(struct _USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
+ uint8_t (*EP0_TxSent)(struct _USBD_HandleTypeDef *pdev);
+ uint8_t (*EP0_RxReady)(struct _USBD_HandleTypeDef *pdev);
+ /* Class Specific Endpoints*/
+ uint8_t (*DataIn)(struct _USBD_HandleTypeDef *pdev, uint8_t epnum);
+ uint8_t (*DataOut)(struct _USBD_HandleTypeDef *pdev, uint8_t epnum);
+ uint8_t (*SOF)(struct _USBD_HandleTypeDef *pdev);
+ uint8_t (*IsoINIncomplete)(struct _USBD_HandleTypeDef *pdev, uint8_t epnum);
+ uint8_t (*IsoOUTIncomplete)(struct _USBD_HandleTypeDef *pdev, uint8_t epnum);
+
+ uint8_t *(*GetHSConfigDescriptor)(uint16_t *length);
+ uint8_t *(*GetFSConfigDescriptor)(uint16_t *length);
+ uint8_t *(*GetOtherSpeedConfigDescriptor)(uint16_t *length);
+ uint8_t *(*GetDeviceQualifierDescriptor)(uint16_t *length);
+#if (USBD_SUPPORT_USER_STRING_DESC == 1U)
+ uint8_t *(*GetUsrStrDescriptor)(struct _USBD_HandleTypeDef *pdev, uint8_t index, uint16_t *length);
+#endif /* USBD_SUPPORT_USER_STRING_DESC */
+
+} USBD_ClassTypeDef;
+
+/* Following USB Device Speed */
+typedef enum
+{
+ USBD_SPEED_HIGH = 0U,
+ USBD_SPEED_FULL = 1U,
+ USBD_SPEED_LOW = 2U,
+} USBD_SpeedTypeDef;
+
+/* Following USB Device status */
+typedef enum
+{
+ USBD_OK = 0U,
+ USBD_BUSY,
+ USBD_EMEM,
+ USBD_FAIL,
+} USBD_StatusTypeDef;
+
+/* USB Device descriptors structure */
+typedef struct
+{
+ uint8_t *(*GetDeviceDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
+ uint8_t *(*GetLangIDStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
+ uint8_t *(*GetManufacturerStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
+ uint8_t *(*GetProductStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
+ uint8_t *(*GetSerialStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
+ uint8_t *(*GetConfigurationStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
+ uint8_t *(*GetInterfaceStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
+#if (USBD_CLASS_USER_STRING_DESC == 1)
+ uint8_t *(*GetUserStrDescriptor)(USBD_SpeedTypeDef speed, uint8_t idx, uint16_t *length);
+#endif /* USBD_CLASS_USER_STRING_DESC */
+#if ((USBD_LPM_ENABLED == 1U) || (USBD_CLASS_BOS_ENABLED == 1))
+ uint8_t *(*GetBOSDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
+#endif /* (USBD_LPM_ENABLED == 1U) || (USBD_CLASS_BOS_ENABLED == 1) */
+} USBD_DescriptorsTypeDef;
+
+/* USB Device handle structure */
+typedef struct
+{
+ uint32_t total_length;
+ uint32_t rem_length;
+ uint32_t bInterval;
+ uint16_t maxpacket;
+ uint8_t status;
+ uint8_t is_used;
+ uint8_t *pbuffer;
+} USBD_EndpointTypeDef;
+
+#ifdef USE_USBD_COMPOSITE
+typedef enum
+{
+ CLASS_TYPE_NONE = 0,
+ CLASS_TYPE_HID = 1,
+ CLASS_TYPE_CDC = 2,
+ CLASS_TYPE_MSC = 3,
+ CLASS_TYPE_DFU = 4,
+ CLASS_TYPE_CHID = 5,
+ CLASS_TYPE_AUDIO = 6,
+ CLASS_TYPE_ECM = 7,
+ CLASS_TYPE_RNDIS = 8,
+ CLASS_TYPE_MTP = 9,
+ CLASS_TYPE_VIDEO = 10,
+ CLASS_TYPE_PRINTER = 11,
+ CLASS_TYPE_CCID = 12,
+} USBD_CompositeClassTypeDef;
+
+
+/* USB Device handle structure */
+typedef struct
+{
+ uint8_t add;
+ uint8_t type;
+ uint8_t size;
+ uint8_t is_used;
+} USBD_EPTypeDef;
+
+/* USB Device handle structure */
+typedef struct
+{
+ USBD_CompositeClassTypeDef ClassType;
+ uint32_t ClassId;
+ uint32_t Active;
+ uint32_t NumEps;
+ USBD_EPTypeDef Eps[USBD_MAX_CLASS_ENDPOINTS];
+ uint8_t *EpAdd;
+ uint32_t NumIf;
+ uint8_t Ifs[USBD_MAX_CLASS_INTERFACES];
+ uint32_t CurrPcktSze;
+} USBD_CompositeElementTypeDef;
+#endif /* USE_USBD_COMPOSITE */
+
+/* USB Device handle structure */
+typedef struct _USBD_HandleTypeDef
+{
+ uint8_t id;
+ uint32_t dev_config;
+ uint32_t dev_default_config;
+ uint32_t dev_config_status;
+ USBD_SpeedTypeDef dev_speed;
+ USBD_EndpointTypeDef ep_in[16];
+ USBD_EndpointTypeDef ep_out[16];
+ __IO uint32_t ep0_state;
+ uint32_t ep0_data_len;
+ __IO uint8_t dev_state;
+ __IO uint8_t dev_old_state;
+ uint8_t dev_address;
+ uint8_t dev_connection_status;
+ uint8_t dev_test_mode;
+ uint32_t dev_remote_wakeup;
+ uint8_t ConfIdx;
+
+ USBD_SetupReqTypedef request;
+ USBD_DescriptorsTypeDef *pDesc;
+ USBD_ClassTypeDef *pClass[USBD_MAX_SUPPORTED_CLASS];
+ void *pClassData;
+ void *pClassDataCmsit[USBD_MAX_SUPPORTED_CLASS];
+ void *pUserData[USBD_MAX_SUPPORTED_CLASS];
+ void *pData;
+ void *pBosDesc;
+ void *pConfDesc;
+ uint32_t classId;
+ uint32_t NumClasses;
+#ifdef USE_USBD_COMPOSITE
+ USBD_CompositeElementTypeDef tclasslist[USBD_MAX_SUPPORTED_CLASS];
+#endif /* USE_USBD_COMPOSITE */
+#if (USBD_USER_REGISTER_CALLBACK == 1U)
+ void (* DevStateCallback)(uint8_t dev_state, uint8_t cfgidx); /*!< User Notification callback */
+#endif /* USBD_USER_REGISTER_CALLBACK */
+} USBD_HandleTypeDef;
+
+#if (USBD_USER_REGISTER_CALLBACK == 1U)
+typedef void (*USBD_DevStateCallbackTypeDef)(uint8_t dev_state, uint8_t cfgidx); /*!< pointer to User callback function */
+#endif /* USBD_USER_REGISTER_CALLBACK */
+
+/* USB Device endpoint direction */
+typedef enum
+{
+ OUT = 0x00,
+ IN = 0x80,
+} USBD_EPDirectionTypeDef;
+
+typedef enum
+{
+ NETWORK_CONNECTION = 0x00,
+ RESPONSE_AVAILABLE = 0x01,
+ CONNECTION_SPEED_CHANGE = 0x2A
+} USBD_CDC_NotifCodeTypeDef;
+/**
+ * @}
+ */
+
+
+
+/** @defgroup USBD_DEF_Exported_Macros
+ * @{
+ */
+__STATIC_INLINE uint16_t SWAPBYTE(uint8_t *addr)
+{
+ uint16_t _SwapVal;
+ uint16_t _Byte1;
+ uint16_t _Byte2;
+ uint8_t *_pbuff = addr;
+
+ _Byte1 = *(uint8_t *)_pbuff;
+ _pbuff++;
+ _Byte2 = *(uint8_t *)_pbuff;
+
+ _SwapVal = (_Byte2 << 8) | _Byte1;
+
+ return _SwapVal;
+}
+
+#ifndef LOBYTE
+#define LOBYTE(x) ((uint8_t)((x) & 0x00FFU))
+#endif /* LOBYTE */
+
+#ifndef HIBYTE
+#define HIBYTE(x) ((uint8_t)(((x) & 0xFF00U) >> 8U))
+#endif /* HIBYTE */
+
+#ifndef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif /* MIN */
+
+#ifndef MAX
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#endif /* MAX */
+
+#if defined ( __GNUC__ )
+#ifndef __weak
+#define __weak __attribute__((weak))
+#endif /* __weak */
+#ifndef __packed
+#define __packed __attribute__((__packed__))
+#endif /* __packed */
+#endif /* __GNUC__ */
+
+
+/* In HS mode and when the DMA is used, all variables and data structures dealing
+ with the DMA during the transaction process should be 4-bytes aligned */
+
+#if defined ( __GNUC__ ) && !defined (__CC_ARM) /* GNU Compiler */
+#ifndef __ALIGN_END
+#define __ALIGN_END __attribute__ ((aligned (4U)))
+#endif /* __ALIGN_END */
+#ifndef __ALIGN_BEGIN
+#define __ALIGN_BEGIN
+#endif /* __ALIGN_BEGIN */
+#else
+#ifndef __ALIGN_END
+#define __ALIGN_END
+#endif /* __ALIGN_END */
+#ifndef __ALIGN_BEGIN
+#if defined (__CC_ARM) /* ARM Compiler */
+#define __ALIGN_BEGIN __align(4U)
+#elif defined (__ICCARM__) /* IAR Compiler */
+#define __ALIGN_BEGIN
+#endif /* __CC_ARM */
+#endif /* __ALIGN_BEGIN */
+#endif /* __GNUC__ */
+
+
+/**
+ * @}
+ */
+
+/** @defgroup USBD_DEF_Exported_Variables
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+/** @defgroup USBD_DEF_Exported_FunctionsPrototype
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __USBD_DEF_H */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
diff --git a/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ioreq.h b/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ioreq.h
new file mode 100755
index 0000000..15197b9
--- /dev/null
+++ b/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ioreq.h
@@ -0,0 +1,113 @@
+/**
+ ******************************************************************************
+ * @file usbd_ioreq.h
+ * @author MCD Application Team
+ * @brief Header file for the usbd_ioreq.c file
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2015 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __USBD_IOREQ_H
+#define __USBD_IOREQ_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbd_def.h"
+#include "usbd_core.h"
+
+/** @addtogroup STM32_USB_DEVICE_LIBRARY
+ * @{
+ */
+
+/** @defgroup USBD_IOREQ
+ * @brief header file for the usbd_ioreq.c file
+ * @{
+ */
+
+/** @defgroup USBD_IOREQ_Exported_Defines
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+/** @defgroup USBD_IOREQ_Exported_Types
+ * @{
+ */
+
+
+/**
+ * @}
+ */
+
+
+
+/** @defgroup USBD_IOREQ_Exported_Macros
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+/** @defgroup USBD_IOREQ_Exported_Variables
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+/** @defgroup USBD_IOREQ_Exported_FunctionsPrototype
+ * @{
+ */
+
+USBD_StatusTypeDef USBD_CtlSendData(USBD_HandleTypeDef *pdev,
+ uint8_t *pbuf, uint32_t len);
+
+USBD_StatusTypeDef USBD_CtlContinueSendData(USBD_HandleTypeDef *pdev,
+ uint8_t *pbuf, uint32_t len);
+
+USBD_StatusTypeDef USBD_CtlPrepareRx(USBD_HandleTypeDef *pdev,
+ uint8_t *pbuf, uint32_t len);
+
+USBD_StatusTypeDef USBD_CtlContinueRx(USBD_HandleTypeDef *pdev,
+ uint8_t *pbuf, uint32_t len);
+
+USBD_StatusTypeDef USBD_CtlSendStatus(USBD_HandleTypeDef *pdev);
+USBD_StatusTypeDef USBD_CtlReceiveStatus(USBD_HandleTypeDef *pdev);
+
+uint32_t USBD_GetRxCount(USBD_HandleTypeDef *pdev, uint8_t ep_addr);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __USBD_IOREQ_H */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
diff --git a/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c b/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c
new file mode 100755
index 0000000..bcf571e
--- /dev/null
+++ b/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c
@@ -0,0 +1,1221 @@
+/**
+ ******************************************************************************
+ * @file usbd_core.c
+ * @author MCD Application Team
+ * @brief This file provides all the USBD core functions.
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2015 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbd_core.h"
+
+#ifdef USE_USBD_COMPOSITE
+#include "usbd_composite_builder.h"
+#endif /* USE_USBD_COMPOSITE */
+
+/** @addtogroup STM32_USBD_DEVICE_LIBRARY
+ * @{
+ */
+
+
+/** @defgroup USBD_CORE
+ * @brief usbd core module
+ * @{
+ */
+
+/** @defgroup USBD_CORE_Private_TypesDefinitions
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup USBD_CORE_Private_Defines
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup USBD_CORE_Private_Macros
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup USBD_CORE_Private_FunctionPrototypes
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+/** @defgroup USBD_CORE_Private_Variables
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup USBD_CORE_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief USBD_Init
+ * Initialize the device stack and load the class driver
+ * @param pdev: device instance
+ * @param pdesc: Descriptor structure address
+ * @param id: Low level core index
+ * @retval status: USBD Status
+ */
+USBD_StatusTypeDef USBD_Init(USBD_HandleTypeDef *pdev,
+ USBD_DescriptorsTypeDef *pdesc, uint8_t id)
+{
+ USBD_StatusTypeDef ret;
+
+ /* Check whether the USB Host handle is valid */
+ if (pdev == NULL)
+ {
+#if (USBD_DEBUG_LEVEL > 1U)
+ USBD_ErrLog("Invalid Device handle");
+#endif /* (USBD_DEBUG_LEVEL > 1U) */
+ return USBD_FAIL;
+ }
+
+#ifdef USE_USBD_COMPOSITE
+ /* Parse the table of classes in use */
+ for (uint32_t i = 0; i < USBD_MAX_SUPPORTED_CLASS; i++)
+ {
+ /* Unlink previous class*/
+ pdev->pClass[i] = NULL;
+ pdev->pUserData[i] = NULL;
+
+ /* Set class as inactive */
+ pdev->tclasslist[i].Active = 0;
+ pdev->NumClasses = 0;
+ pdev->classId = 0;
+ }
+#else
+ /* Unlink previous class*/
+ pdev->pClass[0] = NULL;
+ pdev->pUserData[0] = NULL;
+#endif /* USE_USBD_COMPOSITE */
+
+ pdev->pConfDesc = NULL;
+
+ /* Assign USBD Descriptors */
+ if (pdesc != NULL)
+ {
+ pdev->pDesc = pdesc;
+ }
+
+ /* Set Device initial State */
+ pdev->dev_state = USBD_STATE_DEFAULT;
+ pdev->id = id;
+
+ /* Initialize low level driver */
+ ret = USBD_LL_Init(pdev);
+
+ return ret;
+}
+
+/**
+ * @brief USBD_DeInit
+ * De-Initialize the device library
+ * @param pdev: device instance
+ * @retval status: USBD Status
+ */
+USBD_StatusTypeDef USBD_DeInit(USBD_HandleTypeDef *pdev)
+{
+ USBD_StatusTypeDef ret;
+
+ /* Disconnect the USB Device */
+ (void)USBD_LL_Stop(pdev);
+
+ /* Set Default State */
+ pdev->dev_state = USBD_STATE_DEFAULT;
+
+#ifdef USE_USBD_COMPOSITE
+ /* Parse the table of classes in use */
+ for (uint32_t i = 0; i < USBD_MAX_SUPPORTED_CLASS; i++)
+ {
+ /* Check if current class is in use */
+ if ((pdev->tclasslist[i].Active) == 1U)
+ {
+ if (pdev->pClass[i] != NULL)
+ {
+ pdev->classId = i;
+ /* Free Class Resources */
+ pdev->pClass[i]->DeInit(pdev, (uint8_t)pdev->dev_config);
+ }
+ }
+ }
+#else
+ /* Free Class Resources */
+ if (pdev->pClass[0] != NULL)
+ {
+ pdev->pClass[0]->DeInit(pdev, (uint8_t)pdev->dev_config);
+ }
+
+ pdev->pUserData[0] = NULL;
+
+#endif /* USE_USBD_COMPOSITE */
+
+ /* Free Device descriptors resources */
+ pdev->pDesc = NULL;
+ pdev->pConfDesc = NULL;
+
+ /* DeInitialize low level driver */
+ ret = USBD_LL_DeInit(pdev);
+
+ return ret;
+}
+
+/**
+ * @brief USBD_RegisterClass
+ * Link class driver to Device Core.
+ * @param pdev: Device Handle
+ * @param pclass: Class handle
+ * @retval USBD Status
+ */
+USBD_StatusTypeDef USBD_RegisterClass(USBD_HandleTypeDef *pdev, USBD_ClassTypeDef *pclass)
+{
+ uint16_t len = 0U;
+
+ if (pclass == NULL)
+ {
+#if (USBD_DEBUG_LEVEL > 1U)
+ USBD_ErrLog("Invalid Class handle");
+#endif /* (USBD_DEBUG_LEVEL > 1U) */
+ return USBD_FAIL;
+ }
+
+ /* link the class to the USB Device handle */
+ pdev->pClass[0] = pclass;
+
+ /* Get Device Configuration Descriptor */
+#ifdef USE_USB_HS
+ if (pdev->pClass[pdev->classId]->GetHSConfigDescriptor != NULL)
+ {
+ pdev->pConfDesc = (void *)pdev->pClass[pdev->classId]->GetHSConfigDescriptor(&len);
+ }
+#else /* Default USE_USB_FS */
+ if (pdev->pClass[pdev->classId]->GetFSConfigDescriptor != NULL)
+ {
+ pdev->pConfDesc = (void *)pdev->pClass[pdev->classId]->GetFSConfigDescriptor(&len);
+ }
+#endif /* USE_USB_FS */
+
+ /* Increment the NumClasses */
+ pdev->NumClasses++;
+
+ return USBD_OK;
+}
+
+#ifdef USE_USBD_COMPOSITE
+/**
+ * @brief USBD_RegisterClassComposite
+ * Link class driver to Device Core.
+ * @param pdev : Device Handle
+ * @param pclass: Class handle
+ * @param classtype: Class type
+ * @param EpAddr: Endpoint Address handle
+ * @retval USBD Status
+ */
+USBD_StatusTypeDef USBD_RegisterClassComposite(USBD_HandleTypeDef *pdev, USBD_ClassTypeDef *pclass,
+ USBD_CompositeClassTypeDef classtype, uint8_t *EpAddr)
+{
+ USBD_StatusTypeDef ret = USBD_OK;
+ uint16_t len = 0U;
+
+ if ((pdev->classId < USBD_MAX_SUPPORTED_CLASS) && (pdev->NumClasses < USBD_MAX_SUPPORTED_CLASS))
+ {
+ if ((uint32_t)pclass != 0U)
+ {
+ /* Link the class to the USB Device handle */
+ pdev->pClass[pdev->classId] = pclass;
+ ret = USBD_OK;
+
+ pdev->tclasslist[pdev->classId].EpAdd = EpAddr;
+
+ /* Call the composite class builder */
+ (void)USBD_CMPSIT_AddClass(pdev, pclass, classtype, 0);
+
+ /* Increment the ClassId for the next occurrence */
+ pdev->classId ++;
+ pdev->NumClasses ++;
+ }
+ else
+ {
+#if (USBD_DEBUG_LEVEL > 1U)
+ USBD_ErrLog("Invalid Class handle");
+#endif /* (USBD_DEBUG_LEVEL > 1U) */
+ ret = USBD_FAIL;
+ }
+ }
+
+ if (ret == USBD_OK)
+ {
+ /* Get Device Configuration Descriptor */
+#ifdef USE_USB_HS
+ pdev->pConfDesc = USBD_CMPSIT.GetHSConfigDescriptor(&len);
+#else /* Default USE_USB_FS */
+ pdev->pConfDesc = USBD_CMPSIT.GetFSConfigDescriptor(&len);
+#endif /* USE_USB_FS */
+ }
+
+ return ret;
+}
+
+/**
+ * @brief USBD_UnRegisterClassComposite
+ * UnLink all composite class drivers from Device Core.
+ * @param pdev: Device Handle
+ * @retval USBD Status
+ */
+USBD_StatusTypeDef USBD_UnRegisterClassComposite(USBD_HandleTypeDef *pdev)
+{
+ USBD_StatusTypeDef ret = USBD_OK;
+ uint8_t idx1;
+ uint8_t idx2;
+
+ /* Unroll all activated classes */
+ for (idx1 = 0; idx1 < pdev->NumClasses; idx1++)
+ {
+ /* Check if the class correspond to the requested type and if it is active */
+ if (pdev->tclasslist[idx1].Active == 1U)
+ {
+ /* Set the new class ID */
+ pdev->classId = idx1;
+
+ /* Free resources used by the selected class */
+ if (pdev->pClass[pdev->classId] != NULL)
+ {
+ /* Free Class Resources */
+ if (pdev->pClass[pdev->classId]->DeInit(pdev, (uint8_t)pdev->dev_config) != 0U)
+ {
+#if (USBD_DEBUG_LEVEL > 1U)
+ USBD_ErrLog("Class DeInit didn't succeed!, can't unregister selected class");
+#endif /* (USBD_DEBUG_LEVEL > 1U) */
+
+ ret = USBD_FAIL;
+ }
+ }
+
+ /* Free the class pointer */
+ pdev->pClass[pdev->classId] = NULL;
+
+ /* Free the class location in classes table and reset its parameters to zero */
+ pdev->tclasslist[pdev->classId].ClassType = CLASS_TYPE_NONE;
+ pdev->tclasslist[pdev->classId].ClassId = 0U;
+ pdev->tclasslist[pdev->classId].Active = 0U;
+ pdev->tclasslist[pdev->classId].NumEps = 0U;
+ pdev->tclasslist[pdev->classId].NumIf = 0U;
+ pdev->tclasslist[pdev->classId].CurrPcktSze = 0U;
+
+ for (idx2 = 0U; idx2 < USBD_MAX_CLASS_ENDPOINTS; idx2++)
+ {
+ pdev->tclasslist[pdev->classId].Eps[idx2].add = 0U;
+ pdev->tclasslist[pdev->classId].Eps[idx2].type = 0U;
+ pdev->tclasslist[pdev->classId].Eps[idx2].size = 0U;
+ pdev->tclasslist[pdev->classId].Eps[idx2].is_used = 0U;
+ }
+
+ for (idx2 = 0U; idx2 < USBD_MAX_CLASS_INTERFACES; idx2++)
+ {
+ pdev->tclasslist[pdev->classId].Ifs[idx2] = 0U;
+ }
+ }
+ }
+
+ /* Reset the configuration descriptor */
+ (void)USBD_CMPST_ClearConfDesc(pdev);
+
+ /* Reset the class ID and number of classes */
+ pdev->classId = 0U;
+ pdev->NumClasses = 0U;
+
+ return ret;
+}
+#endif /* USE_USBD_COMPOSITE */
+
+#if (USBD_USER_REGISTER_CALLBACK == 1U)
+/**
+ * @brief USBD_RegisterDevStateCallback
+ * @param pdev : Device Handle
+ * @param pUserCallback: User Callback
+ * @retval USBD Status
+ */
+USBD_StatusTypeDef USBD_RegisterDevStateCallback(USBD_HandleTypeDef *pdev, USBD_DevStateCallbackTypeDef pUserCallback)
+{
+ pdev->DevStateCallback = pUserCallback;
+
+ return USBD_OK;
+}
+#endif /* USBD_USER_REGISTER_CALLBACK */
+
+/**
+ * @brief USBD_Start
+ * Start the USB Device Core.
+ * @param pdev: Device Handle
+ * @retval USBD Status
+ */
+USBD_StatusTypeDef USBD_Start(USBD_HandleTypeDef *pdev)
+{
+#ifdef USE_USBD_COMPOSITE
+ pdev->classId = 0U;
+#endif /* USE_USBD_COMPOSITE */
+
+ /* Start the low level driver */
+ return USBD_LL_Start(pdev);
+}
+
+/**
+ * @brief USBD_Stop
+ * Stop the USB Device Core.
+ * @param pdev: Device Handle
+ * @retval USBD Status
+ */
+USBD_StatusTypeDef USBD_Stop(USBD_HandleTypeDef *pdev)
+{
+ /* Disconnect USB Device */
+ (void)USBD_LL_Stop(pdev);
+
+ /* Free Class Resources */
+#ifdef USE_USBD_COMPOSITE
+ /* Parse the table of classes in use */
+ for (uint32_t i = 0U; i < USBD_MAX_SUPPORTED_CLASS; i++)
+ {
+ /* Check if current class is in use */
+ if ((pdev->tclasslist[i].Active) == 1U)
+ {
+ if (pdev->pClass[i] != NULL)
+ {
+ pdev->classId = i;
+ /* Free Class Resources */
+ (void)pdev->pClass[i]->DeInit(pdev, (uint8_t)pdev->dev_config);
+ }
+ }
+ }
+
+ /* Reset the class ID */
+ pdev->classId = 0U;
+#else
+ if (pdev->pClass[0] != NULL)
+ {
+ (void)pdev->pClass[0]->DeInit(pdev, (uint8_t)pdev->dev_config);
+ }
+#endif /* USE_USBD_COMPOSITE */
+
+ return USBD_OK;
+}
+
+/**
+ * @brief USBD_RunTestMode
+ * Launch test mode process
+ * @param pdev: device instance
+ * @retval status
+ */
+USBD_StatusTypeDef USBD_RunTestMode(USBD_HandleTypeDef *pdev)
+{
+#ifdef USBD_HS_TESTMODE_ENABLE
+ USBD_StatusTypeDef ret;
+
+ /* Run USB HS test mode */
+ ret = USBD_LL_SetTestMode(pdev, pdev->dev_test_mode);
+
+ return ret;
+#else
+ /* Prevent unused argument compilation warning */
+ UNUSED(pdev);
+
+ return USBD_OK;
+#endif /* USBD_HS_TESTMODE_ENABLE */
+}
+
+/**
+ * @brief USBD_SetClassConfig
+ * Configure device and start the interface
+ * @param pdev: device instance
+ * @param cfgidx: configuration index
+ * @retval status
+ */
+
+USBD_StatusTypeDef USBD_SetClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
+{
+ USBD_StatusTypeDef ret = USBD_OK;
+
+#ifdef USE_USBD_COMPOSITE
+ /* Parse the table of classes in use */
+ for (uint32_t i = 0U; i < USBD_MAX_SUPPORTED_CLASS; i++)
+ {
+ /* Check if current class is in use */
+ if ((pdev->tclasslist[i].Active) == 1U)
+ {
+ if (pdev->pClass[i] != NULL)
+ {
+ pdev->classId = i;
+ /* Set configuration and Start the Class*/
+ if (pdev->pClass[i]->Init(pdev, cfgidx) != 0U)
+ {
+ ret = USBD_FAIL;
+ }
+ }
+ }
+ }
+#else
+ if (pdev->pClass[0] != NULL)
+ {
+ /* Set configuration and Start the Class */
+ ret = (USBD_StatusTypeDef)pdev->pClass[0]->Init(pdev, cfgidx);
+ }
+#endif /* USE_USBD_COMPOSITE */
+
+ return ret;
+}
+
+/**
+ * @brief USBD_ClrClassConfig
+ * Clear current configuration
+ * @param pdev: device instance
+ * @param cfgidx: configuration index
+ * @retval status
+ */
+USBD_StatusTypeDef USBD_ClrClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
+{
+ USBD_StatusTypeDef ret = USBD_OK;
+
+#ifdef USE_USBD_COMPOSITE
+ /* Parse the table of classes in use */
+ for (uint32_t i = 0U; i < USBD_MAX_SUPPORTED_CLASS; i++)
+ {
+ /* Check if current class is in use */
+ if ((pdev->tclasslist[i].Active) == 1U)
+ {
+ if (pdev->pClass[i] != NULL)
+ {
+ pdev->classId = i;
+ /* Clear configuration and De-initialize the Class process */
+ if (pdev->pClass[i]->DeInit(pdev, cfgidx) != 0U)
+ {
+ ret = USBD_FAIL;
+ }
+ }
+ }
+ }
+#else
+ /* Clear configuration and De-initialize the Class process */
+ if (pdev->pClass[0]->DeInit(pdev, cfgidx) != 0U)
+ {
+ ret = USBD_FAIL;
+ }
+#endif /* USE_USBD_COMPOSITE */
+
+ return ret;
+}
+
+
+/**
+ * @brief USBD_LL_SetupStage
+ * Handle the setup stage
+ * @param pdev: device instance
+ * @param psetup: setup packet buffer pointer
+ * @retval status
+ */
+USBD_StatusTypeDef USBD_LL_SetupStage(USBD_HandleTypeDef *pdev, uint8_t *psetup)
+{
+ USBD_StatusTypeDef ret;
+
+ USBD_ParseSetupRequest(&pdev->request, psetup);
+
+ pdev->ep0_state = USBD_EP0_SETUP;
+
+ pdev->ep0_data_len = pdev->request.wLength;
+
+ switch (pdev->request.bmRequest & 0x1FU)
+ {
+ case USB_REQ_RECIPIENT_DEVICE:
+ ret = USBD_StdDevReq(pdev, &pdev->request);
+ break;
+
+ case USB_REQ_RECIPIENT_INTERFACE:
+ ret = USBD_StdItfReq(pdev, &pdev->request);
+ break;
+
+ case USB_REQ_RECIPIENT_ENDPOINT:
+ ret = USBD_StdEPReq(pdev, &pdev->request);
+ break;
+
+ default:
+ ret = USBD_LL_StallEP(pdev, (pdev->request.bmRequest & 0x80U));
+ break;
+ }
+
+ return ret;
+}
+
+/**
+ * @brief USBD_LL_DataOutStage
+ * Handle data OUT stage
+ * @param pdev: device instance
+ * @param epnum: endpoint index
+ * @param pdata: data pointer
+ * @retval status
+ */
+USBD_StatusTypeDef USBD_LL_DataOutStage(USBD_HandleTypeDef *pdev,
+ uint8_t epnum, uint8_t *pdata)
+{
+ USBD_EndpointTypeDef *pep;
+ USBD_StatusTypeDef ret = USBD_OK;
+ uint8_t idx;
+
+ UNUSED(pdata);
+
+ if (epnum == 0U)
+ {
+ pep = &pdev->ep_out[0];
+
+ if (pdev->ep0_state == USBD_EP0_DATA_OUT)
+ {
+ if (pep->rem_length > pep->maxpacket)
+ {
+ pep->rem_length -= pep->maxpacket;
+ pep->pbuffer += pep->maxpacket;
+
+ (void)USBD_CtlContinueRx(pdev, pep->pbuffer, MAX(pep->rem_length, pep->maxpacket));
+ }
+ else
+ {
+ /* Find the class ID relative to the current request */
+ switch (pdev->request.bmRequest & 0x1FU)
+ {
+ case USB_REQ_RECIPIENT_DEVICE:
+ /* Device requests must be managed by the first instantiated class
+ (or duplicated by all classes for simplicity) */
+ idx = 0U;
+ break;
+
+ case USB_REQ_RECIPIENT_INTERFACE:
+ idx = USBD_CoreFindIF(pdev, LOBYTE(pdev->request.wIndex));
+ break;
+
+ case USB_REQ_RECIPIENT_ENDPOINT:
+ idx = USBD_CoreFindEP(pdev, LOBYTE(pdev->request.wIndex));
+ break;
+
+ default:
+ /* Back to the first class in case of doubt */
+ idx = 0U;
+ break;
+ }
+
+ if (idx < USBD_MAX_SUPPORTED_CLASS)
+ {
+ /* Setup the class ID and route the request to the relative class function */
+ if (pdev->dev_state == USBD_STATE_CONFIGURED)
+ {
+ if (pdev->pClass[idx]->EP0_RxReady != NULL)
+ {
+ pdev->classId = idx;
+ pdev->pClass[idx]->EP0_RxReady(pdev);
+ }
+ }
+ }
+
+ (void)USBD_CtlSendStatus(pdev);
+ }
+ }
+ }
+ else
+ {
+ /* Get the class index relative to this interface */
+ idx = USBD_CoreFindEP(pdev, (epnum & 0x7FU));
+
+ if (((uint16_t)idx != 0xFFU) && (idx < USBD_MAX_SUPPORTED_CLASS))
+ {
+ /* Call the class data out function to manage the request */
+ if (pdev->dev_state == USBD_STATE_CONFIGURED)
+ {
+ if (pdev->pClass[idx]->DataOut != NULL)
+ {
+ pdev->classId = idx;
+ ret = (USBD_StatusTypeDef)pdev->pClass[idx]->DataOut(pdev, epnum);
+ }
+ }
+ if (ret != USBD_OK)
+ {
+ return ret;
+ }
+ }
+ }
+
+ return USBD_OK;
+}
+
+/**
+ * @brief USBD_LL_DataInStage
+ * Handle data in stage
+ * @param pdev: device instance
+ * @param epnum: endpoint index
+ * @param pdata: data pointer
+ * @retval status
+ */
+USBD_StatusTypeDef USBD_LL_DataInStage(USBD_HandleTypeDef *pdev,
+ uint8_t epnum, uint8_t *pdata)
+{
+ USBD_EndpointTypeDef *pep;
+ USBD_StatusTypeDef ret;
+ uint8_t idx;
+
+ UNUSED(pdata);
+
+ if (epnum == 0U)
+ {
+ pep = &pdev->ep_in[0];
+
+ if (pdev->ep0_state == USBD_EP0_DATA_IN)
+ {
+ if (pep->rem_length > pep->maxpacket)
+ {
+ pep->rem_length -= pep->maxpacket;
+ pep->pbuffer += pep->maxpacket;
+
+ (void)USBD_CtlContinueSendData(pdev, pep->pbuffer, pep->rem_length);
+
+ /* Prepare endpoint for premature end of transfer */
+ (void)USBD_LL_PrepareReceive(pdev, 0U, NULL, 0U);
+ }
+ else
+ {
+ /* last packet is MPS multiple, so send ZLP packet */
+ if ((pep->maxpacket == pep->rem_length) &&
+ (pep->total_length >= pep->maxpacket) &&
+ (pep->total_length < pdev->ep0_data_len))
+ {
+ (void)USBD_CtlContinueSendData(pdev, NULL, 0U);
+ pdev->ep0_data_len = 0U;
+
+ /* Prepare endpoint for premature end of transfer */
+ (void)USBD_LL_PrepareReceive(pdev, 0U, NULL, 0U);
+ }
+ else
+ {
+ if (pdev->dev_state == USBD_STATE_CONFIGURED)
+ {
+ if (pdev->pClass[0]->EP0_TxSent != NULL)
+ {
+ pdev->classId = 0U;
+ pdev->pClass[0]->EP0_TxSent(pdev);
+ }
+ }
+ (void)USBD_LL_StallEP(pdev, 0x80U);
+ (void)USBD_CtlReceiveStatus(pdev);
+ }
+ }
+ }
+
+ if (pdev->dev_test_mode != 0U)
+ {
+ (void)USBD_RunTestMode(pdev);
+ pdev->dev_test_mode = 0U;
+ }
+ }
+ else
+ {
+ /* Get the class index relative to this interface */
+ idx = USBD_CoreFindEP(pdev, ((uint8_t)epnum | 0x80U));
+
+ if (((uint16_t)idx != 0xFFU) && (idx < USBD_MAX_SUPPORTED_CLASS))
+ {
+ /* Call the class data out function to manage the request */
+ if (pdev->dev_state == USBD_STATE_CONFIGURED)
+ {
+ if (pdev->pClass[idx]->DataIn != NULL)
+ {
+ pdev->classId = idx;
+ ret = (USBD_StatusTypeDef)pdev->pClass[idx]->DataIn(pdev, epnum);
+
+ if (ret != USBD_OK)
+ {
+ return ret;
+ }
+ }
+ }
+ }
+ }
+
+ return USBD_OK;
+}
+
+/**
+ * @brief USBD_LL_Reset
+ * Handle Reset event
+ * @param pdev: device instance
+ * @retval status
+ */
+USBD_StatusTypeDef USBD_LL_Reset(USBD_HandleTypeDef *pdev)
+{
+ USBD_StatusTypeDef ret = USBD_OK;
+
+ /* Upon Reset call user call back */
+ pdev->dev_state = USBD_STATE_DEFAULT;
+ pdev->ep0_state = USBD_EP0_IDLE;
+ pdev->dev_config = 0U;
+ pdev->dev_remote_wakeup = 0U;
+ pdev->dev_test_mode = 0U;
+
+#ifdef USE_USBD_COMPOSITE
+ /* Parse the table of classes in use */
+ for (uint32_t i = 0U; i < USBD_MAX_SUPPORTED_CLASS; i++)
+ {
+ /* Check if current class is in use */
+ if ((pdev->tclasslist[i].Active) == 1U)
+ {
+ if (pdev->pClass[i] != NULL)
+ {
+ pdev->classId = i;
+ /* Clear configuration and De-initialize the Class process*/
+
+ if (pdev->pClass[i]->DeInit != NULL)
+ {
+ if (pdev->pClass[i]->DeInit(pdev, (uint8_t)pdev->dev_config) != USBD_OK)
+ {
+ ret = USBD_FAIL;
+ }
+ }
+ }
+ }
+ }
+#else
+
+ if (pdev->pClass[0] != NULL)
+ {
+ if (pdev->pClass[0]->DeInit != NULL)
+ {
+ if (pdev->pClass[0]->DeInit(pdev, (uint8_t)pdev->dev_config) != USBD_OK)
+ {
+ ret = USBD_FAIL;
+ }
+ }
+ }
+#endif /* USE_USBD_COMPOSITE */
+
+ /* Open EP0 OUT */
+ (void)USBD_LL_OpenEP(pdev, 0x00U, USBD_EP_TYPE_CTRL, USB_MAX_EP0_SIZE);
+ pdev->ep_out[0x00U & 0xFU].is_used = 1U;
+
+ pdev->ep_out[0].maxpacket = USB_MAX_EP0_SIZE;
+
+ /* Open EP0 IN */
+ (void)USBD_LL_OpenEP(pdev, 0x80U, USBD_EP_TYPE_CTRL, USB_MAX_EP0_SIZE);
+ pdev->ep_in[0x80U & 0xFU].is_used = 1U;
+
+ pdev->ep_in[0].maxpacket = USB_MAX_EP0_SIZE;
+
+ return ret;
+}
+
+/**
+ * @brief USBD_LL_SetSpeed
+ * Handle Reset event
+ * @param pdev: device instance
+ * @retval status
+ */
+USBD_StatusTypeDef USBD_LL_SetSpeed(USBD_HandleTypeDef *pdev,
+ USBD_SpeedTypeDef speed)
+{
+ pdev->dev_speed = speed;
+
+ return USBD_OK;
+}
+
+/**
+ * @brief USBD_LL_Suspend
+ * Handle Suspend event
+ * @param pdev: device instance
+ * @retval status
+ */
+USBD_StatusTypeDef USBD_LL_Suspend(USBD_HandleTypeDef *pdev)
+{
+ if (pdev->dev_state != USBD_STATE_SUSPENDED)
+ {
+ pdev->dev_old_state = pdev->dev_state;
+ }
+
+ pdev->dev_state = USBD_STATE_SUSPENDED;
+
+ return USBD_OK;
+}
+
+/**
+ * @brief USBD_LL_Resume
+ * Handle Resume event
+ * @param pdev: device instance
+ * @retval status
+ */
+USBD_StatusTypeDef USBD_LL_Resume(USBD_HandleTypeDef *pdev)
+{
+ if (pdev->dev_state == USBD_STATE_SUSPENDED)
+ {
+ pdev->dev_state = pdev->dev_old_state;
+ }
+
+ return USBD_OK;
+}
+
+/**
+ * @brief USBD_LL_SOF
+ * Handle SOF event
+ * @param pdev: device instance
+ * @retval status
+ */
+USBD_StatusTypeDef USBD_LL_SOF(USBD_HandleTypeDef *pdev)
+{
+ /* The SOF event can be distributed for all classes that support it */
+ if (pdev->dev_state == USBD_STATE_CONFIGURED)
+ {
+#ifdef USE_USBD_COMPOSITE
+ /* Parse the table of classes in use */
+ for (uint32_t i = 0; i < USBD_MAX_SUPPORTED_CLASS; i++)
+ {
+ /* Check if current class is in use */
+ if ((pdev->tclasslist[i].Active) == 1U)
+ {
+ if (pdev->pClass[i] != NULL)
+ {
+ if (pdev->pClass[i]->SOF != NULL)
+ {
+ pdev->classId = i;
+ (void)pdev->pClass[i]->SOF(pdev);
+ }
+ }
+ }
+ }
+#else
+ if (pdev->pClass[0] != NULL)
+ {
+ if (pdev->pClass[0]->SOF != NULL)
+ {
+ (void)pdev->pClass[0]->SOF(pdev);
+ }
+ }
+#endif /* USE_USBD_COMPOSITE */
+ }
+
+ return USBD_OK;
+}
+
+/**
+ * @brief USBD_LL_IsoINIncomplete
+ * Handle iso in incomplete event
+ * @param pdev: device instance
+ * @param epnum: Endpoint number
+ * @retval status
+ */
+USBD_StatusTypeDef USBD_LL_IsoINIncomplete(USBD_HandleTypeDef *pdev,
+ uint8_t epnum)
+{
+ if (pdev->pClass[pdev->classId] == NULL)
+ {
+ return USBD_FAIL;
+ }
+
+ if (pdev->dev_state == USBD_STATE_CONFIGURED)
+ {
+ if (pdev->pClass[pdev->classId]->IsoINIncomplete != NULL)
+ {
+ (void)pdev->pClass[pdev->classId]->IsoINIncomplete(pdev, epnum);
+ }
+ }
+
+ return USBD_OK;
+}
+
+/**
+ * @brief USBD_LL_IsoOUTIncomplete
+ * Handle iso out incomplete event
+ * @param pdev: device instance
+ * @param epnum: Endpoint number
+ * @retval status
+ */
+USBD_StatusTypeDef USBD_LL_IsoOUTIncomplete(USBD_HandleTypeDef *pdev,
+ uint8_t epnum)
+{
+ if (pdev->pClass[pdev->classId] == NULL)
+ {
+ return USBD_FAIL;
+ }
+
+ if (pdev->dev_state == USBD_STATE_CONFIGURED)
+ {
+ if (pdev->pClass[pdev->classId]->IsoOUTIncomplete != NULL)
+ {
+ (void)pdev->pClass[pdev->classId]->IsoOUTIncomplete(pdev, epnum);
+ }
+ }
+
+ return USBD_OK;
+}
+
+/**
+ * @brief USBD_LL_DevConnected
+ * Handle device connection event
+ * @param pdev: device instance
+ * @retval status
+ */
+USBD_StatusTypeDef USBD_LL_DevConnected(USBD_HandleTypeDef *pdev)
+{
+ /* Prevent unused argument compilation warning */
+ UNUSED(pdev);
+
+ return USBD_OK;
+}
+
+/**
+ * @brief USBD_LL_DevDisconnected
+ * Handle device disconnection event
+ * @param pdev: device instance
+ * @retval status
+ */
+USBD_StatusTypeDef USBD_LL_DevDisconnected(USBD_HandleTypeDef *pdev)
+{
+ USBD_StatusTypeDef ret = USBD_OK;
+
+ /* Free Class Resources */
+ pdev->dev_state = USBD_STATE_DEFAULT;
+
+#ifdef USE_USBD_COMPOSITE
+ /* Parse the table of classes in use */
+ for (uint32_t i = 0; i < USBD_MAX_SUPPORTED_CLASS; i++)
+ {
+ /* Check if current class is in use */
+ if ((pdev->tclasslist[i].Active) == 1U)
+ {
+ if (pdev->pClass[i] != NULL)
+ {
+ pdev->classId = i;
+ /* Clear configuration and De-initialize the Class process*/
+ if (pdev->pClass[i]->DeInit(pdev, (uint8_t)pdev->dev_config) != 0U)
+ {
+ ret = USBD_FAIL;
+ }
+ }
+ }
+ }
+#else
+ if (pdev->pClass[0] != NULL)
+ {
+ if (pdev->pClass[0]->DeInit(pdev, (uint8_t)pdev->dev_config) != 0U)
+ {
+ ret = USBD_FAIL;
+ }
+ }
+#endif /* USE_USBD_COMPOSITE */
+
+ return ret;
+}
+
+/**
+ * @brief USBD_CoreFindIF
+ * return the class index relative to the selected interface
+ * @param pdev: device instance
+ * @param index : selected interface number
+ * @retval index of the class using the selected interface number. OxFF if no class found.
+ */
+uint8_t USBD_CoreFindIF(USBD_HandleTypeDef *pdev, uint8_t index)
+{
+#ifdef USE_USBD_COMPOSITE
+ /* Parse the table of classes in use */
+ for (uint32_t i = 0U; i < USBD_MAX_SUPPORTED_CLASS; i++)
+ {
+ /* Check if current class is in use */
+ if ((pdev->tclasslist[i].Active) == 1U)
+ {
+ /* Parse all interfaces listed in the current class */
+ for (uint32_t j = 0U; j < pdev->tclasslist[i].NumIf; j++)
+ {
+ /* Check if requested Interface matches the current class interface */
+ if (pdev->tclasslist[i].Ifs[j] == index)
+ {
+ if (pdev->pClass[i]->Setup != NULL)
+ {
+ return (uint8_t)i;
+ }
+ }
+ }
+ }
+ }
+
+ return 0xFFU;
+#else
+ UNUSED(pdev);
+ UNUSED(index);
+
+ return 0x00U;
+#endif /* USE_USBD_COMPOSITE */
+}
+
+/**
+ * @brief USBD_CoreFindEP
+ * return the class index relative to the selected endpoint
+ * @param pdev: device instance
+ * @param index : selected endpoint number
+ * @retval index of the class using the selected endpoint number. 0xFF if no class found.
+ */
+uint8_t USBD_CoreFindEP(USBD_HandleTypeDef *pdev, uint8_t index)
+{
+#ifdef USE_USBD_COMPOSITE
+ /* Parse the table of classes in use */
+ for (uint32_t i = 0U; i < USBD_MAX_SUPPORTED_CLASS; i++)
+ {
+ /* Check if current class is in use */
+ if ((pdev->tclasslist[i].Active) == 1U)
+ {
+ /* Parse all endpoints listed in the current class */
+ for (uint32_t j = 0U; j < pdev->tclasslist[i].NumEps; j++)
+ {
+ /* Check if requested endpoint matches the current class endpoint */
+ if (pdev->tclasslist[i].Eps[j].add == index)
+ {
+ if (pdev->pClass[i]->Setup != NULL)
+ {
+ return (uint8_t)i;
+ }
+ }
+ }
+ }
+ }
+
+ return 0xFFU;
+#else
+ UNUSED(pdev);
+ UNUSED(index);
+
+ return 0x00U;
+#endif /* USE_USBD_COMPOSITE */
+}
+
+#ifdef USE_USBD_COMPOSITE
+/**
+ * @brief USBD_CoreGetEPAdd
+ * Get the endpoint address relative to a selected class
+ * @param pdev: device instance
+ * @param ep_dir: USBD_EP_IN or USBD_EP_OUT
+ * @param ep_type: USBD_EP_TYPE_CTRL, USBD_EP_TYPE_ISOC, USBD_EP_TYPE_BULK or USBD_EP_TYPE_INTR
+ * @param ClassId: The Class ID
+ * @retval Address of the selected endpoint or 0xFFU if no endpoint found.
+ */
+uint8_t USBD_CoreGetEPAdd(USBD_HandleTypeDef *pdev, uint8_t ep_dir, uint8_t ep_type, uint8_t ClassId)
+{
+ uint8_t idx;
+
+ /* Find the EP address in the selected class table */
+ for (idx = 0; idx < pdev->tclasslist[ClassId].NumEps; idx++)
+ {
+ if (((pdev->tclasslist[ClassId].Eps[idx].add & USBD_EP_IN) == ep_dir) && \
+ (pdev->tclasslist[ClassId].Eps[idx].type == ep_type) && \
+ (pdev->tclasslist[ClassId].Eps[idx].is_used != 0U))
+ {
+ return (pdev->tclasslist[ClassId].Eps[idx].add);
+ }
+ }
+
+ /* If reaching this point, then no endpoint was found */
+ return 0xFFU;
+}
+#endif /* USE_USBD_COMPOSITE */
+
+/**
+ * @brief USBD_GetEpDesc
+ * This function return the Endpoint descriptor
+ * @param pdev: device instance
+ * @param pConfDesc: pointer to Bos descriptor
+ * @param EpAddr: endpoint address
+ * @retval pointer to video endpoint descriptor
+ */
+void *USBD_GetEpDesc(uint8_t *pConfDesc, uint8_t EpAddr)
+{
+ USBD_DescHeaderTypeDef *pdesc = (USBD_DescHeaderTypeDef *)(void *)pConfDesc;
+ USBD_ConfigDescTypeDef *desc = (USBD_ConfigDescTypeDef *)(void *)pConfDesc;
+ USBD_EpDescTypeDef *pEpDesc = NULL;
+ uint16_t ptr;
+
+ if (desc->wTotalLength > desc->bLength)
+ {
+ ptr = desc->bLength;
+
+ while (ptr < desc->wTotalLength)
+ {
+ pdesc = USBD_GetNextDesc((uint8_t *)pdesc, &ptr);
+
+ if (pdesc->bDescriptorType == USB_DESC_TYPE_ENDPOINT)
+ {
+ pEpDesc = (USBD_EpDescTypeDef *)(void *)pdesc;
+
+ if (pEpDesc->bEndpointAddress == EpAddr)
+ {
+ break;
+ }
+ else
+ {
+ pEpDesc = NULL;
+ }
+ }
+ }
+ }
+
+ return (void *)pEpDesc;
+}
+
+/**
+ * @brief USBD_GetNextDesc
+ * This function return the next descriptor header
+ * @param buf: Buffer where the descriptor is available
+ * @param ptr: data pointer inside the descriptor
+ * @retval next header
+ */
+USBD_DescHeaderTypeDef *USBD_GetNextDesc(uint8_t *pbuf, uint16_t *ptr)
+{
+ USBD_DescHeaderTypeDef *pnext = (USBD_DescHeaderTypeDef *)(void *)pbuf;
+
+ *ptr += pnext->bLength;
+ pnext = (USBD_DescHeaderTypeDef *)(void *)(pbuf + pnext->bLength);
+
+ return (pnext);
+}
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
diff --git a/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c b/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c
new file mode 100755
index 0000000..814b810
--- /dev/null
+++ b/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c
@@ -0,0 +1,1058 @@
+/**
+ ******************************************************************************
+ * @file usbd_req.c
+ * @author MCD Application Team
+ * @brief This file provides the standard USB requests following chapter 9.
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2015 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbd_ctlreq.h"
+#include "usbd_ioreq.h"
+
+#ifdef USE_USBD_COMPOSITE
+#include "usbd_composite_builder.h"
+#endif /* USE_USBD_COMPOSITE */
+
+/** @addtogroup STM32_USBD_STATE_DEVICE_LIBRARY
+ * @{
+ */
+
+
+/** @defgroup USBD_REQ
+ * @brief USB standard requests module
+ * @{
+ */
+
+/** @defgroup USBD_REQ_Private_TypesDefinitions
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup USBD_REQ_Private_Defines
+ * @{
+ */
+#ifndef USBD_MAX_STR_DESC_SIZ
+#define USBD_MAX_STR_DESC_SIZ 64U
+#endif /* USBD_MAX_STR_DESC_SIZ */
+/**
+ * @}
+ */
+
+
+/** @defgroup USBD_REQ_Private_Macros
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup USBD_REQ_Private_Variables
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup USBD_REQ_Private_FunctionPrototypes
+ * @{
+ */
+static void USBD_GetDescriptor(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
+static void USBD_SetAddress(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
+static USBD_StatusTypeDef USBD_SetConfig(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
+static void USBD_GetConfig(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
+static void USBD_GetStatus(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
+static void USBD_SetFeature(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
+static void USBD_ClrFeature(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
+static uint8_t USBD_GetLen(uint8_t *buf);
+
+/**
+ * @}
+ */
+
+
+/** @defgroup USBD_REQ_Private_Functions
+ * @{
+ */
+
+
+/**
+ * @brief USBD_StdDevReq
+ * Handle standard usb device requests
+ * @param pdev: device instance
+ * @param req: usb request
+ * @retval status
+ */
+USBD_StatusTypeDef USBD_StdDevReq(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
+{
+ USBD_StatusTypeDef ret = USBD_OK;
+
+ switch (req->bmRequest & USB_REQ_TYPE_MASK)
+ {
+ case USB_REQ_TYPE_CLASS:
+ case USB_REQ_TYPE_VENDOR:
+ ret = (USBD_StatusTypeDef)pdev->pClass[pdev->classId]->Setup(pdev, req);
+ break;
+
+ case USB_REQ_TYPE_STANDARD:
+ switch (req->bRequest)
+ {
+ case USB_REQ_GET_DESCRIPTOR:
+ USBD_GetDescriptor(pdev, req);
+ break;
+
+ case USB_REQ_SET_ADDRESS:
+ USBD_SetAddress(pdev, req);
+ break;
+
+ case USB_REQ_SET_CONFIGURATION:
+ ret = USBD_SetConfig(pdev, req);
+ break;
+
+ case USB_REQ_GET_CONFIGURATION:
+ USBD_GetConfig(pdev, req);
+ break;
+
+ case USB_REQ_GET_STATUS:
+ USBD_GetStatus(pdev, req);
+ break;
+
+ case USB_REQ_SET_FEATURE:
+ USBD_SetFeature(pdev, req);
+ break;
+
+ case USB_REQ_CLEAR_FEATURE:
+ USBD_ClrFeature(pdev, req);
+ break;
+
+ default:
+ USBD_CtlError(pdev, req);
+ break;
+ }
+ break;
+
+ default:
+ USBD_CtlError(pdev, req);
+ break;
+ }
+
+ return ret;
+}
+
+/**
+ * @brief USBD_StdItfReq
+ * Handle standard usb interface requests
+ * @param pdev: device instance
+ * @param req: usb request
+ * @retval status
+ */
+USBD_StatusTypeDef USBD_StdItfReq(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
+{
+ USBD_StatusTypeDef ret = USBD_OK;
+ uint8_t idx;
+
+ switch (req->bmRequest & USB_REQ_TYPE_MASK)
+ {
+ case USB_REQ_TYPE_CLASS:
+ case USB_REQ_TYPE_VENDOR:
+ case USB_REQ_TYPE_STANDARD:
+ switch (pdev->dev_state)
+ {
+ case USBD_STATE_DEFAULT:
+ case USBD_STATE_ADDRESSED:
+ case USBD_STATE_CONFIGURED:
+
+ if (LOBYTE(req->wIndex) <= USBD_MAX_NUM_INTERFACES)
+ {
+ /* Get the class index relative to this interface */
+ idx = USBD_CoreFindIF(pdev, LOBYTE(req->wIndex));
+ if (((uint8_t)idx != 0xFFU) && (idx < USBD_MAX_SUPPORTED_CLASS))
+ {
+ /* Call the class data out function to manage the request */
+ if (pdev->pClass[idx]->Setup != NULL)
+ {
+ pdev->classId = idx;
+ ret = (USBD_StatusTypeDef)(pdev->pClass[idx]->Setup(pdev, req));
+ }
+ else
+ {
+ /* should never reach this condition */
+ ret = USBD_FAIL;
+ }
+ }
+ else
+ {
+ /* No relative interface found */
+ ret = USBD_FAIL;
+ }
+
+ if ((req->wLength == 0U) && (ret == USBD_OK))
+ {
+ (void)USBD_CtlSendStatus(pdev);
+ }
+ }
+ else
+ {
+ USBD_CtlError(pdev, req);
+ }
+ break;
+
+ default:
+ USBD_CtlError(pdev, req);
+ break;
+ }
+ break;
+
+ default:
+ USBD_CtlError(pdev, req);
+ break;
+ }
+
+ return ret;
+}
+
+/**
+ * @brief USBD_StdEPReq
+ * Handle standard usb endpoint requests
+ * @param pdev: device instance
+ * @param req: usb request
+ * @retval status
+ */
+USBD_StatusTypeDef USBD_StdEPReq(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
+{
+ USBD_EndpointTypeDef *pep;
+ uint8_t ep_addr;
+ uint8_t idx;
+ USBD_StatusTypeDef ret = USBD_OK;
+
+ ep_addr = LOBYTE(req->wIndex);
+
+ switch (req->bmRequest & USB_REQ_TYPE_MASK)
+ {
+ case USB_REQ_TYPE_CLASS:
+ case USB_REQ_TYPE_VENDOR:
+ /* Get the class index relative to this endpoint */
+ idx = USBD_CoreFindEP(pdev, ep_addr);
+ if (((uint8_t)idx != 0xFFU) && (idx < USBD_MAX_SUPPORTED_CLASS))
+ {
+ pdev->classId = idx;
+ /* Call the class data out function to manage the request */
+ if (pdev->pClass[idx]->Setup != NULL)
+ {
+ ret = (USBD_StatusTypeDef)pdev->pClass[idx]->Setup(pdev, req);
+ }
+ }
+ break;
+
+ case USB_REQ_TYPE_STANDARD:
+ switch (req->bRequest)
+ {
+ case USB_REQ_SET_FEATURE:
+ switch (pdev->dev_state)
+ {
+ case USBD_STATE_ADDRESSED:
+ if ((ep_addr != 0x00U) && (ep_addr != 0x80U))
+ {
+ (void)USBD_LL_StallEP(pdev, ep_addr);
+ (void)USBD_LL_StallEP(pdev, 0x80U);
+ }
+ else
+ {
+ USBD_CtlError(pdev, req);
+ }
+ break;
+
+ case USBD_STATE_CONFIGURED:
+ if (req->wValue == USB_FEATURE_EP_HALT)
+ {
+ if ((ep_addr != 0x00U) && (ep_addr != 0x80U) && (req->wLength == 0x00U))
+ {
+ (void)USBD_LL_StallEP(pdev, ep_addr);
+ }
+ }
+ (void)USBD_CtlSendStatus(pdev);
+
+ break;
+
+ default:
+ USBD_CtlError(pdev, req);
+ break;
+ }
+ break;
+
+ case USB_REQ_CLEAR_FEATURE:
+
+ switch (pdev->dev_state)
+ {
+ case USBD_STATE_ADDRESSED:
+ if ((ep_addr != 0x00U) && (ep_addr != 0x80U))
+ {
+ (void)USBD_LL_StallEP(pdev, ep_addr);
+ (void)USBD_LL_StallEP(pdev, 0x80U);
+ }
+ else
+ {
+ USBD_CtlError(pdev, req);
+ }
+ break;
+
+ case USBD_STATE_CONFIGURED:
+ if (req->wValue == USB_FEATURE_EP_HALT)
+ {
+ if ((ep_addr & 0x7FU) != 0x00U)
+ {
+ (void)USBD_LL_ClearStallEP(pdev, ep_addr);
+ }
+ (void)USBD_CtlSendStatus(pdev);
+
+ /* Get the class index relative to this interface */
+ idx = USBD_CoreFindEP(pdev, ep_addr);
+ if (((uint8_t)idx != 0xFFU) && (idx < USBD_MAX_SUPPORTED_CLASS))
+ {
+ pdev->classId = idx;
+ /* Call the class data out function to manage the request */
+ if (pdev->pClass[idx]->Setup != NULL)
+ {
+ ret = (USBD_StatusTypeDef)(pdev->pClass[idx]->Setup(pdev, req));
+ }
+ }
+ }
+ break;
+
+ default:
+ USBD_CtlError(pdev, req);
+ break;
+ }
+ break;
+
+ case USB_REQ_GET_STATUS:
+ switch (pdev->dev_state)
+ {
+ case USBD_STATE_ADDRESSED:
+ if ((ep_addr != 0x00U) && (ep_addr != 0x80U))
+ {
+ USBD_CtlError(pdev, req);
+ break;
+ }
+ pep = ((ep_addr & 0x80U) == 0x80U) ? &pdev->ep_in[ep_addr & 0x7FU] : \
+ &pdev->ep_out[ep_addr & 0x7FU];
+
+ pep->status = 0x0000U;
+
+ (void)USBD_CtlSendData(pdev, (uint8_t *)&pep->status, 2U);
+ break;
+
+ case USBD_STATE_CONFIGURED:
+ if ((ep_addr & 0x80U) == 0x80U)
+ {
+ if (pdev->ep_in[ep_addr & 0xFU].is_used == 0U)
+ {
+ USBD_CtlError(pdev, req);
+ break;
+ }
+ }
+ else
+ {
+ if (pdev->ep_out[ep_addr & 0xFU].is_used == 0U)
+ {
+ USBD_CtlError(pdev, req);
+ break;
+ }
+ }
+
+ pep = ((ep_addr & 0x80U) == 0x80U) ? &pdev->ep_in[ep_addr & 0x7FU] : \
+ &pdev->ep_out[ep_addr & 0x7FU];
+
+ if ((ep_addr == 0x00U) || (ep_addr == 0x80U))
+ {
+ pep->status = 0x0000U;
+ }
+ else if (USBD_LL_IsStallEP(pdev, ep_addr) != 0U)
+ {
+ pep->status = 0x0001U;
+ }
+ else
+ {
+ pep->status = 0x0000U;
+ }
+
+ (void)USBD_CtlSendData(pdev, (uint8_t *)&pep->status, 2U);
+ break;
+
+ default:
+ USBD_CtlError(pdev, req);
+ break;
+ }
+ break;
+
+ default:
+ USBD_CtlError(pdev, req);
+ break;
+ }
+ break;
+
+ default:
+ USBD_CtlError(pdev, req);
+ break;
+ }
+
+ return ret;
+}
+
+
+/**
+ * @brief USBD_GetDescriptor
+ * Handle Get Descriptor requests
+ * @param pdev: device instance
+ * @param req: usb request
+ * @retval None
+ */
+static void USBD_GetDescriptor(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
+{
+ uint16_t len = 0U;
+ uint8_t *pbuf = NULL;
+ uint8_t err = 0U;
+
+ switch (req->wValue >> 8)
+ {
+#if ((USBD_LPM_ENABLED == 1U) || (USBD_CLASS_BOS_ENABLED == 1U))
+ case USB_DESC_TYPE_BOS:
+ if (pdev->pDesc->GetBOSDescriptor != NULL)
+ {
+ pbuf = pdev->pDesc->GetBOSDescriptor(pdev->dev_speed, &len);
+ }
+ else
+ {
+ USBD_CtlError(pdev, req);
+ err++;
+ }
+ break;
+#endif /* (USBD_LPM_ENABLED == 1U) || (USBD_CLASS_BOS_ENABLED == 1U) */
+ case USB_DESC_TYPE_DEVICE:
+ pbuf = pdev->pDesc->GetDeviceDescriptor(pdev->dev_speed, &len);
+ break;
+
+ case USB_DESC_TYPE_CONFIGURATION:
+ if (pdev->dev_speed == USBD_SPEED_HIGH)
+ {
+#ifdef USE_USBD_COMPOSITE
+ if ((uint8_t)(pdev->NumClasses) > 0U)
+ {
+ pbuf = (uint8_t *)USBD_CMPSIT.GetHSConfigDescriptor(&len);
+ }
+ else
+#endif /* USE_USBD_COMPOSITE */
+ {
+ pbuf = (uint8_t *)pdev->pClass[0]->GetHSConfigDescriptor(&len);
+ }
+ pbuf[1] = USB_DESC_TYPE_CONFIGURATION;
+ }
+ else
+ {
+#ifdef USE_USBD_COMPOSITE
+ if ((uint8_t)(pdev->NumClasses) > 0U)
+ {
+ pbuf = (uint8_t *)USBD_CMPSIT.GetFSConfigDescriptor(&len);
+ }
+ else
+#endif /* USE_USBD_COMPOSITE */
+ {
+ pbuf = (uint8_t *)pdev->pClass[0]->GetFSConfigDescriptor(&len);
+ }
+ pbuf[1] = USB_DESC_TYPE_CONFIGURATION;
+ }
+ break;
+
+ case USB_DESC_TYPE_STRING:
+ switch ((uint8_t)(req->wValue))
+ {
+ case USBD_IDX_LANGID_STR:
+ if (pdev->pDesc->GetLangIDStrDescriptor != NULL)
+ {
+ pbuf = pdev->pDesc->GetLangIDStrDescriptor(pdev->dev_speed, &len);
+ }
+ else
+ {
+ USBD_CtlError(pdev, req);
+ err++;
+ }
+ break;
+
+ case USBD_IDX_MFC_STR:
+ if (pdev->pDesc->GetManufacturerStrDescriptor != NULL)
+ {
+ pbuf = pdev->pDesc->GetManufacturerStrDescriptor(pdev->dev_speed, &len);
+ }
+ else
+ {
+ USBD_CtlError(pdev, req);
+ err++;
+ }
+ break;
+
+ case USBD_IDX_PRODUCT_STR:
+ if (pdev->pDesc->GetProductStrDescriptor != NULL)
+ {
+ pbuf = pdev->pDesc->GetProductStrDescriptor(pdev->dev_speed, &len);
+ }
+ else
+ {
+ USBD_CtlError(pdev, req);
+ err++;
+ }
+ break;
+
+ case USBD_IDX_SERIAL_STR:
+ if (pdev->pDesc->GetSerialStrDescriptor != NULL)
+ {
+ pbuf = pdev->pDesc->GetSerialStrDescriptor(pdev->dev_speed, &len);
+ }
+ else
+ {
+ USBD_CtlError(pdev, req);
+ err++;
+ }
+ break;
+
+ case USBD_IDX_CONFIG_STR:
+ if (pdev->pDesc->GetConfigurationStrDescriptor != NULL)
+ {
+ pbuf = pdev->pDesc->GetConfigurationStrDescriptor(pdev->dev_speed, &len);
+ }
+ else
+ {
+ USBD_CtlError(pdev, req);
+ err++;
+ }
+ break;
+
+ case USBD_IDX_INTERFACE_STR:
+ if (pdev->pDesc->GetInterfaceStrDescriptor != NULL)
+ {
+ pbuf = pdev->pDesc->GetInterfaceStrDescriptor(pdev->dev_speed, &len);
+ }
+ else
+ {
+ USBD_CtlError(pdev, req);
+ err++;
+ }
+ break;
+
+ default:
+#if (USBD_SUPPORT_USER_STRING_DESC == 1U)
+ pbuf = NULL;
+
+ for (uint32_t idx = 0U; (idx < pdev->NumClasses); idx++)
+ {
+ if (pdev->pClass[idx]->GetUsrStrDescriptor != NULL)
+ {
+ pdev->classId = idx;
+ pbuf = pdev->pClass[idx]->GetUsrStrDescriptor(pdev, LOBYTE(req->wValue), &len);
+
+ if (pbuf == NULL) /* This means that no class recognized the string index */
+ {
+ continue;
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+#endif /* USBD_SUPPORT_USER_STRING_DESC */
+
+#if (USBD_CLASS_USER_STRING_DESC == 1U)
+ if (pdev->pDesc->GetUserStrDescriptor != NULL)
+ {
+ pbuf = pdev->pDesc->GetUserStrDescriptor(pdev->dev_speed, LOBYTE(req->wValue), &len);
+ }
+ else
+ {
+ USBD_CtlError(pdev, req);
+ err++;
+ }
+#endif /* USBD_SUPPORT_USER_STRING_DESC */
+
+#if ((USBD_CLASS_USER_STRING_DESC == 0U) && (USBD_SUPPORT_USER_STRING_DESC == 0U))
+ USBD_CtlError(pdev, req);
+ err++;
+#endif /* (USBD_CLASS_USER_STRING_DESC == 0U) && (USBD_SUPPORT_USER_STRING_DESC == 0U) */
+ break;
+ }
+ break;
+
+ case USB_DESC_TYPE_DEVICE_QUALIFIER:
+ if (pdev->dev_speed == USBD_SPEED_HIGH)
+ {
+#ifdef USE_USBD_COMPOSITE
+ if ((uint8_t)(pdev->NumClasses) > 0U)
+ {
+ pbuf = (uint8_t *)USBD_CMPSIT.GetDeviceQualifierDescriptor(&len);
+ }
+ else
+#endif /* USE_USBD_COMPOSITE */
+ {
+ pbuf = (uint8_t *)pdev->pClass[0]->GetDeviceQualifierDescriptor(&len);
+ }
+ }
+ else
+ {
+ USBD_CtlError(pdev, req);
+ err++;
+ }
+ break;
+
+ case USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION:
+ if (pdev->dev_speed == USBD_SPEED_HIGH)
+ {
+#ifdef USE_USBD_COMPOSITE
+ if ((uint8_t)(pdev->NumClasses) > 0U)
+ {
+ pbuf = (uint8_t *)USBD_CMPSIT.GetOtherSpeedConfigDescriptor(&len);
+ }
+ else
+#endif /* USE_USBD_COMPOSITE */
+ {
+ pbuf = (uint8_t *)pdev->pClass[0]->GetOtherSpeedConfigDescriptor(&len);
+ }
+ pbuf[1] = USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION;
+ }
+ else
+ {
+ USBD_CtlError(pdev, req);
+ err++;
+ }
+ break;
+
+ default:
+ USBD_CtlError(pdev, req);
+ err++;
+ break;
+ }
+
+ if (err != 0U)
+ {
+ return;
+ }
+
+ if (req->wLength != 0U)
+ {
+ if (len != 0U)
+ {
+ len = MIN(len, req->wLength);
+ (void)USBD_CtlSendData(pdev, pbuf, len);
+ }
+ else
+ {
+ USBD_CtlError(pdev, req);
+ }
+ }
+ else
+ {
+ (void)USBD_CtlSendStatus(pdev);
+ }
+}
+
+
+/**
+ * @brief USBD_SetAddress
+ * Set device address
+ * @param pdev: device instance
+ * @param req: usb request
+ * @retval None
+ */
+static void USBD_SetAddress(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
+{
+ uint8_t dev_addr;
+
+ if ((req->wIndex == 0U) && (req->wLength == 0U) && (req->wValue < 128U))
+ {
+ dev_addr = (uint8_t)(req->wValue) & 0x7FU;
+
+ if (pdev->dev_state == USBD_STATE_CONFIGURED)
+ {
+ USBD_CtlError(pdev, req);
+ }
+ else
+ {
+ pdev->dev_address = dev_addr;
+ (void)USBD_LL_SetUSBAddress(pdev, dev_addr);
+ (void)USBD_CtlSendStatus(pdev);
+
+ if (dev_addr != 0U)
+ {
+ pdev->dev_state = USBD_STATE_ADDRESSED;
+ }
+ else
+ {
+ pdev->dev_state = USBD_STATE_DEFAULT;
+ }
+ }
+ }
+ else
+ {
+ USBD_CtlError(pdev, req);
+ }
+}
+
+/**
+ * @brief USBD_SetConfig
+ * Handle Set device configuration request
+ * @param pdev: device instance
+ * @param req: usb request
+ * @retval status
+ */
+static USBD_StatusTypeDef USBD_SetConfig(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
+{
+ USBD_StatusTypeDef ret = USBD_OK;
+ static uint8_t cfgidx;
+
+ cfgidx = (uint8_t)(req->wValue);
+
+ if (cfgidx > USBD_MAX_NUM_CONFIGURATION)
+ {
+ USBD_CtlError(pdev, req);
+ return USBD_FAIL;
+ }
+
+ switch (pdev->dev_state)
+ {
+ case USBD_STATE_ADDRESSED:
+ if (cfgidx != 0U)
+ {
+ pdev->dev_config = cfgidx;
+
+ ret = USBD_SetClassConfig(pdev, cfgidx);
+
+ if (ret != USBD_OK)
+ {
+ USBD_CtlError(pdev, req);
+ pdev->dev_state = USBD_STATE_ADDRESSED;
+ }
+ else
+ {
+ (void)USBD_CtlSendStatus(pdev);
+ pdev->dev_state = USBD_STATE_CONFIGURED;
+
+#if (USBD_USER_REGISTER_CALLBACK == 1U)
+ if (pdev->DevStateCallback != NULL)
+ {
+ pdev->DevStateCallback(USBD_STATE_CONFIGURED, cfgidx);
+ }
+#endif /* USBD_USER_REGISTER_CALLBACK */
+ }
+ }
+ else
+ {
+ (void)USBD_CtlSendStatus(pdev);
+ }
+ break;
+
+ case USBD_STATE_CONFIGURED:
+ if (cfgidx == 0U)
+ {
+ pdev->dev_state = USBD_STATE_ADDRESSED;
+ pdev->dev_config = cfgidx;
+ (void)USBD_ClrClassConfig(pdev, cfgidx);
+ (void)USBD_CtlSendStatus(pdev);
+ }
+ else if (cfgidx != pdev->dev_config)
+ {
+ /* Clear old configuration */
+ (void)USBD_ClrClassConfig(pdev, (uint8_t)pdev->dev_config);
+
+ /* set new configuration */
+ pdev->dev_config = cfgidx;
+
+ ret = USBD_SetClassConfig(pdev, cfgidx);
+
+ if (ret != USBD_OK)
+ {
+ USBD_CtlError(pdev, req);
+ (void)USBD_ClrClassConfig(pdev, (uint8_t)pdev->dev_config);
+ pdev->dev_state = USBD_STATE_ADDRESSED;
+ }
+ else
+ {
+ (void)USBD_CtlSendStatus(pdev);
+ }
+ }
+ else
+ {
+ (void)USBD_CtlSendStatus(pdev);
+ }
+ break;
+
+ default:
+ USBD_CtlError(pdev, req);
+ (void)USBD_ClrClassConfig(pdev, cfgidx);
+ ret = USBD_FAIL;
+ break;
+ }
+
+ return ret;
+}
+
+/**
+ * @brief USBD_GetConfig
+ * Handle Get device configuration request
+ * @param pdev: device instance
+ * @param req: usb request
+ * @retval None
+ */
+static void USBD_GetConfig(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
+{
+ if (req->wLength != 1U)
+ {
+ USBD_CtlError(pdev, req);
+ }
+ else
+ {
+ switch (pdev->dev_state)
+ {
+ case USBD_STATE_DEFAULT:
+ case USBD_STATE_ADDRESSED:
+ pdev->dev_default_config = 0U;
+ (void)USBD_CtlSendData(pdev, (uint8_t *)&pdev->dev_default_config, 1U);
+ break;
+
+ case USBD_STATE_CONFIGURED:
+ (void)USBD_CtlSendData(pdev, (uint8_t *)&pdev->dev_config, 1U);
+ break;
+
+ default:
+ USBD_CtlError(pdev, req);
+ break;
+ }
+ }
+}
+
+/**
+ * @brief USBD_GetStatus
+ * Handle Get Status request
+ * @param pdev: device instance
+ * @param req: usb request
+ * @retval None
+ */
+static void USBD_GetStatus(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
+{
+ switch (pdev->dev_state)
+ {
+ case USBD_STATE_DEFAULT:
+ case USBD_STATE_ADDRESSED:
+ case USBD_STATE_CONFIGURED:
+ if (req->wLength != 0x2U)
+ {
+ USBD_CtlError(pdev, req);
+ break;
+ }
+
+#if (USBD_SELF_POWERED == 1U)
+ pdev->dev_config_status = USB_CONFIG_SELF_POWERED;
+#else
+ pdev->dev_config_status = 0U;
+#endif /* USBD_SELF_POWERED */
+
+ if (pdev->dev_remote_wakeup != 0U)
+ {
+ pdev->dev_config_status |= USB_CONFIG_REMOTE_WAKEUP;
+ }
+
+ (void)USBD_CtlSendData(pdev, (uint8_t *)&pdev->dev_config_status, 2U);
+ break;
+
+ default:
+ USBD_CtlError(pdev, req);
+ break;
+ }
+}
+
+
+/**
+ * @brief USBD_SetFeature
+ * Handle Set device feature request
+ * @param pdev: device instance
+ * @param req: usb request
+ * @retval None
+ */
+static void USBD_SetFeature(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
+{
+ if (req->wValue == USB_FEATURE_REMOTE_WAKEUP)
+ {
+ pdev->dev_remote_wakeup = 1U;
+ (void)USBD_CtlSendStatus(pdev);
+ }
+ else if (req->wValue == USB_FEATURE_TEST_MODE)
+ {
+ pdev->dev_test_mode = (uint8_t)(req->wIndex >> 8);
+ (void)USBD_CtlSendStatus(pdev);
+ }
+ else
+ {
+ USBD_CtlError(pdev, req);
+ }
+}
+
+
+/**
+ * @brief USBD_ClrFeature
+ * Handle clear device feature request
+ * @param pdev: device instance
+ * @param req: usb request
+ * @retval None
+ */
+static void USBD_ClrFeature(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
+{
+ switch (pdev->dev_state)
+ {
+ case USBD_STATE_DEFAULT:
+ case USBD_STATE_ADDRESSED:
+ case USBD_STATE_CONFIGURED:
+ if (req->wValue == USB_FEATURE_REMOTE_WAKEUP)
+ {
+ pdev->dev_remote_wakeup = 0U;
+ (void)USBD_CtlSendStatus(pdev);
+ }
+ break;
+
+ default:
+ USBD_CtlError(pdev, req);
+ break;
+ }
+}
+
+
+/**
+ * @brief USBD_ParseSetupRequest
+ * Copy buffer into setup structure
+ * @param req: usb request
+ * @param pdata: setup data pointer
+ * @retval None
+ */
+void USBD_ParseSetupRequest(USBD_SetupReqTypedef *req, uint8_t *pdata)
+{
+ uint8_t *pbuff = pdata;
+
+ req->bmRequest = *(uint8_t *)(pbuff);
+
+ pbuff++;
+ req->bRequest = *(uint8_t *)(pbuff);
+
+ pbuff++;
+ req->wValue = SWAPBYTE(pbuff);
+
+ pbuff++;
+ pbuff++;
+ req->wIndex = SWAPBYTE(pbuff);
+
+ pbuff++;
+ pbuff++;
+ req->wLength = SWAPBYTE(pbuff);
+}
+
+
+/**
+ * @brief USBD_CtlError
+ * Handle USB low level Error
+ * @param pdev: device instance
+ * @param req: usb request
+ * @retval None
+ */
+void USBD_CtlError(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
+{
+ UNUSED(req);
+
+ (void)USBD_LL_StallEP(pdev, 0x80U);
+ (void)USBD_LL_StallEP(pdev, 0U);
+}
+
+
+/**
+ * @brief USBD_GetString
+ * Convert Ascii string into unicode one
+ * @param desc : descriptor buffer
+ * @param unicode : Formatted string buffer (unicode)
+ * @param len : descriptor length
+ * @retval None
+ */
+void USBD_GetString(uint8_t *desc, uint8_t *unicode, uint16_t *len)
+{
+ uint8_t idx = 0U;
+ uint8_t *pdesc;
+
+ if (desc == NULL)
+ {
+ return;
+ }
+
+ pdesc = desc;
+ *len = MIN(USBD_MAX_STR_DESC_SIZ, ((uint16_t)USBD_GetLen(pdesc) * 2U) + 2U);
+
+ unicode[idx] = *(uint8_t *)len;
+ idx++;
+ unicode[idx] = USB_DESC_TYPE_STRING;
+ idx++;
+
+ while (*pdesc != (uint8_t)'\0')
+ {
+ unicode[idx] = *pdesc;
+ pdesc++;
+ idx++;
+
+ unicode[idx] = 0U;
+ idx++;
+ }
+}
+
+
+/**
+ * @brief USBD_GetLen
+ * return the string length
+ * @param buf : pointer to the ascii string buffer
+ * @retval string length
+ */
+static uint8_t USBD_GetLen(uint8_t *buf)
+{
+ uint8_t len = 0U;
+ uint8_t *pbuff = buf;
+
+ while (*pbuff != (uint8_t)'\0')
+ {
+ len++;
+ pbuff++;
+ }
+
+ return len;
+}
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
diff --git a/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c b/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c
new file mode 100755
index 0000000..2171398
--- /dev/null
+++ b/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c
@@ -0,0 +1,226 @@
+/**
+ ******************************************************************************
+ * @file usbd_ioreq.c
+ * @author MCD Application Team
+ * @brief This file provides the IO requests APIs for control endpoints.
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2015 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbd_ioreq.h"
+
+/** @addtogroup STM32_USB_DEVICE_LIBRARY
+ * @{
+ */
+
+
+/** @defgroup USBD_IOREQ
+ * @brief control I/O requests module
+ * @{
+ */
+
+/** @defgroup USBD_IOREQ_Private_TypesDefinitions
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+/** @defgroup USBD_IOREQ_Private_Defines
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup USBD_IOREQ_Private_Macros
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+/** @defgroup USBD_IOREQ_Private_Variables
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup USBD_IOREQ_Private_FunctionPrototypes
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+/** @defgroup USBD_IOREQ_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief USBD_CtlSendData
+ * send data on the ctl pipe
+ * @param pdev: device instance
+ * @param buff: pointer to data buffer
+ * @param len: length of data to be sent
+ * @retval status
+ */
+USBD_StatusTypeDef USBD_CtlSendData(USBD_HandleTypeDef *pdev,
+ uint8_t *pbuf, uint32_t len)
+{
+ /* Set EP0 State */
+ pdev->ep0_state = USBD_EP0_DATA_IN;
+ pdev->ep_in[0].total_length = len;
+ pdev->ep_in[0].pbuffer = pbuf;
+
+#ifdef USBD_AVOID_PACKET_SPLIT_MPS
+ pdev->ep_in[0].rem_length = 0U;
+#else
+ pdev->ep_in[0].rem_length = len;
+#endif /* USBD_AVOID_PACKET_SPLIT_MPS */
+
+ /* Start the transfer */
+ (void)USBD_LL_Transmit(pdev, 0x00U, pbuf, len);
+
+ return USBD_OK;
+}
+
+/**
+ * @brief USBD_CtlContinueSendData
+ * continue sending data on the ctl pipe
+ * @param pdev: device instance
+ * @param buff: pointer to data buffer
+ * @param len: length of data to be sent
+ * @retval status
+ */
+USBD_StatusTypeDef USBD_CtlContinueSendData(USBD_HandleTypeDef *pdev,
+ uint8_t *pbuf, uint32_t len)
+{
+ /* Start the next transfer */
+ (void)USBD_LL_Transmit(pdev, 0x00U, pbuf, len);
+
+ return USBD_OK;
+}
+
+/**
+ * @brief USBD_CtlPrepareRx
+ * receive data on the ctl pipe
+ * @param pdev: device instance
+ * @param buff: pointer to data buffer
+ * @param len: length of data to be received
+ * @retval status
+ */
+USBD_StatusTypeDef USBD_CtlPrepareRx(USBD_HandleTypeDef *pdev,
+ uint8_t *pbuf, uint32_t len)
+{
+ /* Set EP0 State */
+ pdev->ep0_state = USBD_EP0_DATA_OUT;
+ pdev->ep_out[0].total_length = len;
+ pdev->ep_out[0].pbuffer = pbuf;
+
+#ifdef USBD_AVOID_PACKET_SPLIT_MPS
+ pdev->ep_out[0].rem_length = 0U;
+#else
+ pdev->ep_out[0].rem_length = len;
+#endif /* USBD_AVOID_PACKET_SPLIT_MPS */
+
+ /* Start the transfer */
+ (void)USBD_LL_PrepareReceive(pdev, 0U, pbuf, len);
+
+ return USBD_OK;
+}
+
+/**
+ * @brief USBD_CtlContinueRx
+ * continue receive data on the ctl pipe
+ * @param pdev: device instance
+ * @param buff: pointer to data buffer
+ * @param len: length of data to be received
+ * @retval status
+ */
+USBD_StatusTypeDef USBD_CtlContinueRx(USBD_HandleTypeDef *pdev,
+ uint8_t *pbuf, uint32_t len)
+{
+ (void)USBD_LL_PrepareReceive(pdev, 0U, pbuf, len);
+
+ return USBD_OK;
+}
+
+/**
+ * @brief USBD_CtlSendStatus
+ * send zero lzngth packet on the ctl pipe
+ * @param pdev: device instance
+ * @retval status
+ */
+USBD_StatusTypeDef USBD_CtlSendStatus(USBD_HandleTypeDef *pdev)
+{
+ /* Set EP0 State */
+ pdev->ep0_state = USBD_EP0_STATUS_IN;
+
+ /* Start the transfer */
+ (void)USBD_LL_Transmit(pdev, 0x00U, NULL, 0U);
+
+ return USBD_OK;
+}
+
+/**
+ * @brief USBD_CtlReceiveStatus
+ * receive zero lzngth packet on the ctl pipe
+ * @param pdev: device instance
+ * @retval status
+ */
+USBD_StatusTypeDef USBD_CtlReceiveStatus(USBD_HandleTypeDef *pdev)
+{
+ /* Set EP0 State */
+ pdev->ep0_state = USBD_EP0_STATUS_OUT;
+
+ /* Start the transfer */
+ (void)USBD_LL_PrepareReceive(pdev, 0U, NULL, 0U);
+
+ return USBD_OK;
+}
+
+/**
+ * @brief USBD_GetRxCount
+ * returns the received data length
+ * @param pdev: device instance
+ * @param ep_addr: endpoint address
+ * @retval Rx Data blength
+ */
+uint32_t USBD_GetRxCount(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
+{
+ return USBD_LL_GetRxDataSize(pdev, ep_addr);
+}
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+