USB CDC library for MBED on STM32

Dependents:   PushToGo-F429

Revision:
0:7cf972f622d3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbd_cdc.c	Sun Sep 09 19:03:18 2018 +0000
@@ -0,0 +1,701 @@
+/**
+ ******************************************************************************
+ * @file    usbd_cdc.c
+ * @author  MCD Application Team
+ * @version V2.4.2
+ * @date    11-December-2015
+ * @brief   This file provides the high layer firmware functions to manage the
+ *          following functionalities of the USB CDC Class:
+ *           - Initialization and Configuration of high and low layer
+ *           - Enumeration as CDC Device (and enumeration for each implemented memory interface)
+ *           - OUT/IN data transfer
+ *           - Command IN transfer (class requests management)
+ *           - Error management
+ *
+ *  @verbatim
+ *
+ *          ===================================================================
+ *                                CDC Class Driver Description
+ *          ===================================================================
+ *           This driver manages the "Universal Serial Bus Class Definitions for Communications Devices
+ *           Revision 1.2 November 16, 2007" and the sub-protocol specification of "Universal Serial Bus
+ *           Communications Class Subclass Specification for PSTN Devices Revision 1.2 February 9, 2007"
+ *           This driver implements the following aspects of the specification:
+ *             - Device descriptor management
+ *             - Configuration descriptor management
+ *             - Enumeration as CDC device with 2 data endpoints (IN and OUT) and 1 command endpoint (IN)
+ *             - Requests management (as described in section 6.2 in specification)
+ *             - Abstract Control Model compliant
+ *             - Union Functional collection (using 1 IN endpoint for control)
+ *             - Data interface class
+ *
+ *           These aspects may be enriched or modified for a specific user application.
+ *
+ *            This driver doesn't implement the following aspects of the specification
+ *            (but it is possible to manage these features with some modifications on this driver):
+ *             - Any class-specific aspect relative to communication classes should be managed by user application.
+ *             - All communication classes other than PSTN are not managed
+ *
+ *  @endverbatim
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *        http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbd_cdc.h"
+#include "usbd_ctlreq.h"
+
+/** @addtogroup STM32_USB_DEVICE_LIBRARY
+ * @{
+ */
+
+/** @defgroup USBD_CDC 
+ * @brief usbd core module
+ * @{
+ */
+
+/** @defgroup USBD_CDC_Private_TypesDefinitions
+ * @{
+ */
+/**
+ * @}
+ */
+
+/** @defgroup USBD_CDC_Private_Defines
+ * @{
+ */
+/**
+ * @}
+ */
+
+/** @defgroup USBD_CDC_Private_Macros
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+/** @defgroup USBD_CDC_Private_FunctionPrototypes
+ * @{
+ */
+
+static uint8_t USBD_CDC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
+
+static uint8_t USBD_CDC_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
+
+static uint8_t USBD_CDC_Setup(USBD_HandleTypeDef *pdev,
+		USBD_SetupReqTypedef *req);
+
+static uint8_t USBD_CDC_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum);
+
+static uint8_t USBD_CDC_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum);
+
+static uint8_t USBD_CDC_EP0_RxReady(USBD_HandleTypeDef *pdev);
+
+static uint8_t *USBD_CDC_GetFSCfgDesc(uint16_t *length);
+
+static uint8_t *USBD_CDC_GetHSCfgDesc(uint16_t *length);
+
+static uint8_t *USBD_CDC_GetOtherSpeedCfgDesc(uint16_t *length);
+
+static uint8_t *USBD_CDC_GetOtherSpeedCfgDesc(uint16_t *length);
+
+uint8_t *USBD_CDC_GetDeviceQualifierDescriptor(uint16_t *length);
+
+/* USB Standard Device Descriptor */
+__ALIGN_BEGIN static uint8_t USBD_CDC_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END
+		=
+		{
+		USB_LEN_DEV_QUALIFIER_DESC,
+		USB_DESC_TYPE_DEVICE_QUALIFIER, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
+				0x01, 0x00, };
+
+/**
+ * @}
+ */
+
+/** @defgroup USBD_CDC_Private_Variables
+ * @{
+ */
+
+/* CDC interface class callbacks structure */
+USBD_ClassTypeDef USBD_CDC =
+{  USBD_CDC_Init, USBD_CDC_DeInit, USBD_CDC_Setup,
+NULL, /* EP0_TxSent, */
+USBD_CDC_EP0_RxReady, USBD_CDC_DataIn, USBD_CDC_DataOut,
+NULL,
+NULL,
+NULL, USBD_CDC_GetHSCfgDesc, USBD_CDC_GetFSCfgDesc,
+		USBD_CDC_GetOtherSpeedCfgDesc, USBD_CDC_GetDeviceQualifierDescriptor, };
+
+/* USB CDC device Configuration Descriptor */
+__ALIGN_BEGIN uint8_t USBD_CDC_CfgDesc[USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END =
+{
+
+//
+		/*Configuration Descriptor*/
+		0x09, /* bLength: Configuration Descriptor size */
+		USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
+		USB_CDC_CONFIG_DESC_SIZ, /* wTotalLength:no of returned bytes */
+		0x00, 0x02, /* bNumInterfaces: 2 interface */
+		0x01, /* bConfigurationValue: Configuration value */
+		0x00, /* iConfiguration: Index of string descriptor describing the configuration */
+		0xC0, /* bmAttributes: self powered */
+		0x32, /* MaxPower 0 mA */
+
+		/*---------------------------------------------------------------------------*/
+		// IAD to associate the two CDC interfaces
+		0x08,// bLength
+		0x0b,                   // bDescriptorType
+		0x00,                   // bFirstInterface
+		0x02,                   // bInterfaceCount
+		0x02,                   // bFunctionClass
+		0x02,                   // bFunctionSubClass
+		0,                      // bFunctionProtocol
+		0,                      // iFunction
+
+		/*Interface Descriptor */
+		0x09, /* bLength: Interface Descriptor size */
+		USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */
+		/* Interface descriptor type */
+		0x00, /* bInterfaceNumber: Number of Interface */
+		0x00, /* bAlternateSetting: Alternate setting */
+		0x01, /* bNumEndpoints: One endpoints used */
+		0x02, /* bInterfaceClass: Communication Interface Class */
+		0x02, /* bInterfaceSubClass: Abstract Control Model */
+		0x01, /* bInterfaceProtocol: Common AT commands */
+		0x00, /* iInterface: */
+
+		/*Header Functional Descriptor*/
+		0x05, /* bLength: Endpoint Descriptor size */
+		0x24, /* bDescriptorType: CS_INTERFACE */
+		0x00, /* bDescriptorSubtype: Header Func Desc */
+		0x10, /* bcdCDC: spec release number */
+		0x01,
+
+		/*Call Management Functional Descriptor*/
+		0x05, /* bFunctionLength */
+		0x24, /* bDescriptorType: CS_INTERFACE */
+		0x01, /* bDescriptorSubtype: Call Management Func Desc */
+		0x03, /* bmCapabilities: D0+D1 */
+		0x01, /* bDataInterface: 1 */
+
+		/*ACM Functional Descriptor*/
+		0x04, /* bFunctionLength */
+		0x24, /* bDescriptorType: CS_INTERFACE */
+		0x02, /* bDescriptorSubtype: Abstract Control Management desc */
+		0x02, /* bmCapabilities */
+
+		/*Union Functional Descriptor*/
+		0x05, /* bFunctionLength */
+		0x24, /* bDescriptorType: CS_INTERFACE */
+		0x06, /* bDescriptorSubtype: Union func desc */
+		0x00, /* bMasterInterface: Communication class interface */
+		0x01, /* bSlaveInterface0: Data Class Interface */
+
+		/*Endpoint 2 Descriptor*/
+		0x07, /* bLength: Endpoint Descriptor size */
+		USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
+		CDC_CMD_EP, /* bEndpointAddress */
+		0x03, /* bmAttributes: Interrupt */
+		LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: */
+		HIBYTE(CDC_CMD_PACKET_SIZE), 0x10, /* bInterval: */
+		/*---------------------------------------------------------------------------*/
+
+		/*Data class interface descriptor*/
+		0x09, /* bLength: Endpoint Descriptor size */
+		USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */
+		0x01, /* bInterfaceNumber: Number of Interface */
+		0x00, /* bAlternateSetting: Alternate setting */
+		0x02, /* bNumEndpoints: Two endpoints used */
+		0x0A, /* bInterfaceClass: CDC */
+		0x00, /* bInterfaceSubClass: */
+		0x00, /* bInterfaceProtocol: */
+		0x00, /* iInterface: */
+
+		/*Endpoint OUT Descriptor*/
+		0x07, /* bLength: Endpoint Descriptor size */
+		USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
+		CDC_OUT_EP, /* bEndpointAddress */
+		0x02, /* bmAttributes: Bulk */
+		LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */
+		HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), 0x00, /* bInterval: ignore for Bulk transfer */
+
+		/*Endpoint IN Descriptor*/
+		0x07, /* bLength: Endpoint Descriptor size */
+		USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
+		CDC_IN_EP, /* bEndpointAddress */
+		0x02, /* bmAttributes: Bulk */
+		LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */
+		HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), 0x00 /* bInterval: ignore for Bulk transfer */
+};
+
+/**
+ * @}
+ */
+
+/** @defgroup USBD_CDC_Private_Functions
+ * @{
+ */
+
+static USBD_CDC_HandleTypeDef usbd_cdc;
+
+/**
+ * @brief  USBD_CDC_Init
+ *         Initialize the CDC interface
+ * @param  pdev: device instance
+ * @param  cfgidx: Configuration index
+ * @retval status
+ */
+static uint8_t USBD_CDC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
+{
+	uint8_t ret = 0;
+	USBD_CDC_HandleTypeDef *hcdc;
+
+	if (pdev->dev_speed == USBD_SPEED_HIGH)
+	{
+		/* Open EP IN */
+		USBD_LL_OpenEP(pdev,
+		CDC_IN_EP,
+		USBD_EP_TYPE_BULK,
+		CDC_DATA_HS_IN_PACKET_SIZE);
+
+		/* Open EP OUT */
+		USBD_LL_OpenEP(pdev,
+		CDC_OUT_EP,
+		USBD_EP_TYPE_BULK,
+		CDC_DATA_HS_OUT_PACKET_SIZE);
+
+	}
+	else
+	{
+		/* Open EP IN */
+		USBD_LL_OpenEP(pdev,
+		CDC_IN_EP,
+		USBD_EP_TYPE_BULK,
+		CDC_DATA_FS_IN_PACKET_SIZE);
+
+		/* Open EP OUT */
+		USBD_LL_OpenEP(pdev,
+		CDC_OUT_EP,
+		USBD_EP_TYPE_BULK,
+		CDC_DATA_FS_OUT_PACKET_SIZE);
+	}
+	/* Open Command IN EP */
+	USBD_LL_OpenEP(pdev,
+	CDC_CMD_EP,
+	USBD_EP_TYPE_INTR,
+	CDC_CMD_PACKET_SIZE);
+
+//  pdev->pClassData = USBD_malloc(sizeof (USBD_CDC_HandleTypeDef));
+	pdev->pClassData = &usbd_cdc;
+
+	if (pdev->pClassData == NULL)
+	{
+		ret = 1;
+	}
+	else
+	{
+		hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData;
+
+		/* Init  physical Interface components */
+		((USBD_CDC_ItfTypeDef *) pdev->pUserData)->Init();
+
+		/* Init Xfer states */
+		hcdc->TxState = 0;
+		hcdc->RxState = 0;
+
+		if (pdev->dev_speed == USBD_SPEED_HIGH)
+		{
+			/* Prepare Out endpoint to receive next packet */
+			USBD_LL_PrepareReceive(pdev,
+			CDC_OUT_EP, hcdc->RxBuffer,
+			CDC_DATA_HS_OUT_PACKET_SIZE);
+		}
+		else
+		{
+			/* Prepare Out endpoint to receive next packet */
+			USBD_LL_PrepareReceive(pdev,
+			CDC_OUT_EP, hcdc->RxBuffer,
+			CDC_DATA_FS_OUT_PACKET_SIZE);
+		}
+
+	}
+	return ret;
+}
+
+/**
+ * @brief  USBD_CDC_Init
+ *         DeInitialize the CDC layer
+ * @param  pdev: device instance
+ * @param  cfgidx: Configuration index
+ * @retval status
+ */
+static uint8_t USBD_CDC_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
+{
+	uint8_t ret = 0;
+
+	/* Open EP IN */
+	USBD_LL_CloseEP(pdev,
+	CDC_IN_EP);
+
+	/* Open EP OUT */
+	USBD_LL_CloseEP(pdev,
+	CDC_OUT_EP);
+
+	/* Open Command IN EP */
+	USBD_LL_CloseEP(pdev,
+	CDC_CMD_EP);
+
+	/* DeInit  physical Interface components */
+	if (pdev->pClassData != NULL)
+	{
+		((USBD_CDC_ItfTypeDef *) pdev->pUserData)->DeInit();
+		//USBD_free(pdev->pClassData);
+		pdev->pClassData = NULL;
+	}
+
+	return ret;
+}
+
+/**
+ * @brief  USBD_CDC_Setup
+ *         Handle the CDC specific requests
+ * @param  pdev: instance
+ * @param  req: usb requests
+ * @retval status
+ */
+static uint8_t USBD_CDC_Setup(USBD_HandleTypeDef *pdev,
+		USBD_SetupReqTypedef *req)
+{
+	USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData;
+	static uint8_t ifalt = 0;
+
+	switch (req->bmRequest & USB_REQ_TYPE_MASK)
+	{
+	case USB_REQ_TYPE_CLASS:
+		if (req->wLength)
+		{
+			if (req->bmRequest & 0x80)
+			{
+				((USBD_CDC_ItfTypeDef *) pdev->pUserData)->Control(
+						req->bRequest, (uint8_t *) hcdc->data, req->wLength);
+				USBD_CtlSendData(pdev, (uint8_t *) hcdc->data, req->wLength);
+			}
+			else
+			{
+				hcdc->CmdOpCode = req->bRequest;
+				hcdc->CmdLength = req->wLength;
+
+				USBD_CtlPrepareRx(pdev, (uint8_t *) hcdc->data, req->wLength);
+			}
+
+		}
+		else
+		{
+			((USBD_CDC_ItfTypeDef *) pdev->pUserData)->Control(req->bRequest,
+					(uint8_t*) req, 0);
+		}
+		break;
+
+	case USB_REQ_TYPE_STANDARD:
+		switch (req->bRequest)
+		{
+		case USB_REQ_GET_INTERFACE:
+			USBD_CtlSendData(pdev, &ifalt, 1);
+			break;
+
+		case USB_REQ_SET_INTERFACE:
+			break;
+		}
+		break;
+
+	default:
+		break;
+	}
+	return USBD_OK;
+}
+
+/**
+ * @brief  USBD_CDC_DataIn
+ *         Data sent on non-control IN endpoint
+ * @param  pdev: device instance
+ * @param  epnum: endpoint number
+ * @retval status
+ */
+static uint8_t USBD_CDC_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum)
+{
+	USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData;
+
+	if (pdev->pClassData != NULL)
+	{
+
+		hcdc->TxState = 0;
+
+		((USBD_CDC_ItfTypeDef *) pdev->pUserData)->Transmitted(hcdc->TxBuffer,
+				hcdc->TxLength);
+
+		return USBD_OK;
+	}
+	else
+	{
+		return USBD_FAIL;
+	}
+}
+
+/**
+ * @brief  USBD_CDC_DataOut
+ *         Data received on non-control Out endpoint
+ * @param  pdev: device instance
+ * @param  epnum: endpoint number
+ * @retval status
+ */
+static uint8_t USBD_CDC_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum)
+{
+	USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData;
+
+	/* Get the received data length */
+	hcdc->RxLength = USBD_LL_GetRxDataSize(pdev, epnum);
+	hcdc->RxState = 0;
+
+	/* USB data will be immediately processed, this allow next USB traffic being
+	 NAKed till the end of the application Xfer */
+	if (pdev->pClassData != NULL)
+	{
+		((USBD_CDC_ItfTypeDef *) pdev->pUserData)->Received(hcdc->RxBuffer,
+				&hcdc->RxLength);
+
+		return USBD_OK;
+	}
+	else
+	{
+		return USBD_FAIL;
+	}
+}
+
+/**
+ * @brief  USBD_CDC_DataOut
+ *         Data received on non-control Out endpoint
+ * @param  pdev: device instance
+ * @param  epnum: endpoint number
+ * @retval status
+ */
+static uint8_t USBD_CDC_EP0_RxReady(USBD_HandleTypeDef *pdev)
+{
+	USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData;
+
+	if ((pdev->pUserData != NULL) && (hcdc->CmdOpCode != 0xFF))
+	{
+		((USBD_CDC_ItfTypeDef *) pdev->pUserData)->Control(hcdc->CmdOpCode,
+				(uint8_t *) hcdc->data, hcdc->CmdLength);
+		hcdc->CmdOpCode = 0xFF;
+
+	}
+	return USBD_OK;
+}
+
+/**
+ * @brief  USBD_CDC_GetFSCfgDesc
+ *         Return configuration descriptor
+ * @param  speed : current device speed
+ * @param  length : pointer data length
+ * @retval pointer to descriptor buffer
+ */
+static uint8_t *USBD_CDC_GetFSCfgDesc(uint16_t *length)
+{
+	*length = USB_CDC_CONFIG_DESC_SIZ;
+	return USBD_CDC_CfgDesc;
+}
+
+/**
+ * @brief  USBD_CDC_GetHSCfgDesc
+ *         Return configuration descriptor
+ * @param  speed : current device speed
+ * @param  length : pointer data length
+ * @retval pointer to descriptor buffer
+ */
+static uint8_t *USBD_CDC_GetHSCfgDesc(uint16_t *length)
+{
+	*length = USB_CDC_CONFIG_DESC_SIZ;
+	return USBD_CDC_CfgDesc;
+}
+
+/**
+ * @brief  USBD_CDC_GetCfgDesc
+ *         Return configuration descriptor
+ * @param  speed : current device speed
+ * @param  length : pointer data length
+ * @retval pointer to descriptor buffer
+ */
+static uint8_t *USBD_CDC_GetOtherSpeedCfgDesc(uint16_t *length)
+{
+	*length = USB_CDC_CONFIG_DESC_SIZ;
+	return USBD_CDC_CfgDesc;
+}
+
+/**
+ * @brief  DeviceQualifierDescriptor
+ *         return Device Qualifier descriptor
+ * @param  length : pointer data length
+ * @retval pointer to descriptor buffer
+ */
+uint8_t *USBD_CDC_GetDeviceQualifierDescriptor(uint16_t *length)
+{
+	*length = sizeof(USBD_CDC_DeviceQualifierDesc);
+	return USBD_CDC_DeviceQualifierDesc;
+}
+
+/**
+ * @brief  USBD_CDC_RegisterInterface
+ * @param  pdev: device instance
+ * @param  fops: CD  Interface callback
+ * @retval status
+ */
+uint8_t USBD_CDC_RegisterInterface(USBD_HandleTypeDef *pdev,
+		USBD_CDC_ItfTypeDef *fops)
+{
+	uint8_t ret = USBD_FAIL;
+
+	if (fops != NULL)
+	{
+		pdev->pUserData = fops;
+		ret = USBD_OK;
+	}
+
+	return ret;
+}
+
+/**
+ * @brief  USBD_CDC_SetTxBuffer
+ * @param  pdev: device instance
+ * @param  pbuff: Tx Buffer
+ * @retval status
+ */
+uint8_t USBD_CDC_SetTxBuffer(USBD_HandleTypeDef *pdev, uint8_t *pbuff,
+		uint16_t length)
+{
+	USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData;
+
+	hcdc->TxBuffer = pbuff;
+	hcdc->TxLength = length;
+
+	return USBD_OK;
+}
+
+/**
+ * @brief  USBD_CDC_SetRxBuffer
+ * @param  pdev: device instance
+ * @param  pbuff: Rx Buffer
+ * @retval status
+ */
+uint8_t USBD_CDC_SetRxBuffer(USBD_HandleTypeDef *pdev, uint8_t *pbuff)
+{
+	USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData;
+
+	hcdc->RxBuffer = pbuff;
+
+	return USBD_OK;
+}
+
+/**
+ * @brief  USBD_CDC_DataOut
+ *         Data received on non-control Out endpoint
+ * @param  pdev: device instance
+ * @param  epnum: endpoint number
+ * @retval status
+ */
+uint8_t USBD_CDC_TransmitPacket(USBD_HandleTypeDef *pdev)
+{
+	USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData;
+
+	if (pdev->pClassData != NULL)
+	{
+		if (hcdc->TxState == 0)
+		{
+			/* Tx Transfer in progress */
+			hcdc->TxState = 1;
+
+			/* Transmit next packet */
+			USBD_LL_Transmit(pdev,
+			CDC_IN_EP, hcdc->TxBuffer, hcdc->TxLength);
+
+			return USBD_OK;
+		}
+		else
+		{
+			return USBD_BUSY;
+		}
+	}
+	else
+	{
+		return USBD_FAIL;
+	}
+}
+
+/**
+ * @brief  USBD_CDC_ReceivePacket
+ *         prepare OUT Endpoint for reception
+ * @param  pdev: device instance
+ * @retval status
+ */
+uint8_t USBD_CDC_ReceivePacket(USBD_HandleTypeDef *pdev)
+{
+	USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData;
+
+	/* Suspend or Resume USB Out process */
+	if (pdev->pClassData != NULL)
+	{
+		hcdc->RxState = 1;
+		if (pdev->dev_speed == USBD_SPEED_HIGH)
+		{
+			/* Prepare Out endpoint to receive next packet */
+			USBD_LL_PrepareReceive(pdev,
+			CDC_OUT_EP, hcdc->RxBuffer,
+			CDC_DATA_HS_OUT_PACKET_SIZE);
+		}
+		else
+		{
+			/* Prepare Out endpoint to receive next packet */
+			USBD_LL_PrepareReceive(pdev,
+			CDC_OUT_EP, hcdc->RxBuffer,
+			CDC_DATA_FS_OUT_PACKET_SIZE);
+		}
+		return USBD_OK;
+	}
+	else
+	{
+		return USBD_FAIL;
+	}
+}
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+