This commit is contained in:
2025-08-31 19:53:50 -05:00
commit 652e2d358c
182 changed files with 232506 additions and 0 deletions

View File

@ -0,0 +1,446 @@
/**
******************************************************************************
* @file usbh_cdc.h
* @author MCD Application Team
* @brief This file contains all the prototypes for the usbh_cdc.c
******************************************************************************
* @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 ----------------------------------------------*/
#ifndef __USBH_CDC_H
#define __USBH_CDC_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbh_core.h"
/** @addtogroup USBH_LIB
* @{
*/
/** @addtogroup USBH_CLASS
* @{
*/
/** @addtogroup USBH_CDC_CLASS
* @{
*/
/** @defgroup USBH_CDC_CORE
* @brief This file is the Header file for usbh_core.c
* @{
*/
/*Communication Class codes*/
#define USB_CDC_CLASS 0x02U
#define COMMUNICATION_INTERFACE_CLASS_CODE 0x02U
/*Data Interface Class Codes*/
#define DATA_INTERFACE_CLASS_CODE 0x0AU
/*Communication sub class codes*/
#define RESERVED 0x00U
#define DIRECT_LINE_CONTROL_MODEL 0x01U
#define ABSTRACT_CONTROL_MODEL 0x02U
#define TELEPHONE_CONTROL_MODEL 0x03U
#define MULTICHANNEL_CONTROL_MODEL 0x04U
#define CAPI_CONTROL_MODEL 0x05U
#define ETHERNET_NETWORKING_CONTROL_MODEL 0x06U
#define ATM_NETWORKING_CONTROL_MODEL 0x07U
/*Communication Interface Class Control Protocol Codes*/
#define NO_CLASS_SPECIFIC_PROTOCOL_CODE 0x00U
#define COMMON_AT_COMMAND 0x01U
#define VENDOR_SPECIFIC 0xFFU
#define CS_INTERFACE 0x24U
#define CDC_PAGE_SIZE_64 0x40U
/*Class-Specific Request Codes*/
#define CDC_SEND_ENCAPSULATED_COMMAND 0x00U
#define CDC_GET_ENCAPSULATED_RESPONSE 0x01U
#define CDC_SET_COMM_FEATURE 0x02U
#define CDC_GET_COMM_FEATURE 0x03U
#define CDC_CLEAR_COMM_FEATURE 0x04U
#define CDC_SET_AUX_LINE_STATE 0x10U
#define CDC_SET_HOOK_STATE 0x11U
#define CDC_PULSE_SETUP 0x12U
#define CDC_SEND_PULSE 0x13U
#define CDC_SET_PULSE_TIME 0x14U
#define CDC_RING_AUX_JACK 0x15U
#define CDC_SET_LINE_CODING 0x20U
#define CDC_GET_LINE_CODING 0x21U
#define CDC_SET_CONTROL_LINE_STATE 0x22U
#define CDC_SEND_BREAK 0x23U
#define CDC_SET_RINGER_PARMS 0x30U
#define CDC_GET_RINGER_PARMS 0x31U
#define CDC_SET_OPERATION_PARMS 0x32U
#define CDC_GET_OPERATION_PARMS 0x33U
#define CDC_SET_LINE_PARMS 0x34U
#define CDC_GET_LINE_PARMS 0x35U
#define CDC_DIAL_DIGITS 0x36U
#define CDC_SET_UNIT_PARAMETER 0x37U
#define CDC_GET_UNIT_PARAMETER 0x38U
#define CDC_CLEAR_UNIT_PARAMETER 0x39U
#define CDC_GET_PROFILE 0x3AU
#define CDC_SET_ETHERNET_MULTICAST_FILTERS 0x40U
#define CDC_SET_ETHERNET_POWER_MANAGEMENT_PATTERN FILTER 0x41U
#define CDC_GET_ETHERNET_POWER_MANAGEMENT_PATTERN FILTER 0x42U
#define CDC_SET_ETHERNET_PACKET_FILTER 0x43U
#define CDC_GET_ETHERNET_STATISTIC 0x44U
#define CDC_SET_ATM_DATA_FORMAT 0x50U
#define CDC_GET_ATM_DEVICE_STATISTICS 0x51U
#define CDC_SET_ATM_DEFAULT_VC 0x52U
#define CDC_GET_ATM_VC_STATISTICS 0x53U
/* wValue for SetControlLineState*/
#define CDC_ACTIVATE_CARRIER_SIGNAL_RTS 0x0002U
#define CDC_DEACTIVATE_CARRIER_SIGNAL_RTS 0x0000U
#define CDC_ACTIVATE_SIGNAL_DTR 0x0001U
#define CDC_DEACTIVATE_SIGNAL_DTR 0x0000U
#define LINE_CODING_STRUCTURE_SIZE 0x07U
/**
* @}
*/
/** @defgroup USBH_CDC_CORE_Exported_Types
* @{
*/
/* States for CDC State Machine */
typedef enum
{
CDC_IDLE = 0U,
CDC_SEND_DATA,
CDC_SEND_DATA_WAIT,
CDC_RECEIVE_DATA,
CDC_RECEIVE_DATA_WAIT,
}
CDC_DataStateTypeDef;
typedef enum
{
CDC_IDLE_STATE = 0U,
CDC_SET_LINE_CODING_STATE,
CDC_GET_LAST_LINE_CODING_STATE,
CDC_TRANSFER_DATA,
CDC_ERROR_STATE,
}
CDC_StateTypeDef;
/*Line coding structure*/
typedef union _CDC_LineCodingStructure
{
uint8_t Array[LINE_CODING_STRUCTURE_SIZE];
struct
{
uint32_t dwDTERate; /*Data terminal rate, in bits per second*/
uint8_t bCharFormat; /*Stop bits
0 - 1 Stop bit
1 - 1.5 Stop bits
2 - 2 Stop bits*/
uint8_t bParityType; /* Parity
0 - None
1 - Odd
2 - Even
3 - Mark
4 - Space*/
uint8_t bDataBits; /* Data bits (5, 6, 7, 8 or 16). */
} b;
}
CDC_LineCodingTypeDef;
/* Header Functional Descriptor
--------------------------------------------------------------------------------
Offset| field | Size | Value | Description
------|---------------------|-------|------------|------------------------------
0 | bFunctionLength | 1 | number | Size of this descriptor.
1 | bDescriptorType | 1 | Constant | CS_INTERFACE (0x24)
2 | bDescriptorSubtype | 1 | Constant | Identifier (ID) of functional
| | | | descriptor.
3 | bcdCDC | 2 | |
| | | Number | USB Class Definitions for
| | | | Communication Devices Specification
| | | | release number in binary-coded
| | | | decimal
------|---------------------|-------|------------|------------------------------
*/
typedef struct _FunctionalDescriptorHeader
{
uint8_t bLength; /*Size of this descriptor.*/
uint8_t bDescriptorType; /*CS_INTERFACE (0x24)*/
uint8_t bDescriptorSubType; /* Header functional descriptor subtype as*/
uint16_t bcdCDC; /* USB Class Definitions for Communication
Devices Specification release number in
binary-coded decimal. */
}
CDC_HeaderFuncDesc_TypeDef;
/* Call Management Functional Descriptor
--------------------------------------------------------------------------------
Offset| field | Size | Value | Description
------|---------------------|-------|------------|------------------------------
0 | bFunctionLength | 1 | number | Size of this descriptor.
1 | bDescriptorType | 1 | Constant | CS_INTERFACE (0x24)
2 | bDescriptorSubtype | 1 | Constant | Call Management functional
| | | | descriptor subtype.
3 | bmCapabilities | 1 | Bitmap | The capabilities that this configuration
| | | | supports:
| | | | D7..D2: RESERVED (Reset to zero)
| | | | D1: 0 - Device sends/receives call
| | | | management information only over
| | | | the Communication Class
| | | | interface.
| | | | 1 - Device can send/receive call
| \ | | management information over a
| | | | Data Class interface.
| | | | D0: 0 - Device does not handle call
| | | | management itself.
| | | | 1 - Device handles call
| | | | management itself.
| | | | The previous bits, in combination, identify
| | | | which call management scenario is used. If bit
| | | | D0 is reset to 0, then the value of bit D1 is
| | | | ignored. In this case, bit D1 is reset to zero for
| | | | future compatibility.
4 | bDataInterface | 1 | Number | Interface number of Data Class interface
| | | | optionally used for call management.
------|---------------------|-------|------------|------------------------------
*/
typedef struct _CallMgmtFunctionalDescriptor
{
uint8_t bLength; /*Size of this functional descriptor, in bytes.*/
uint8_t bDescriptorType; /*CS_INTERFACE (0x24)*/
uint8_t bDescriptorSubType; /* Call Management functional descriptor subtype*/
uint8_t bmCapabilities; /* bmCapabilities: D0+D1 */
uint8_t bDataInterface; /*bDataInterface: 1*/
}
CDC_CallMgmtFuncDesc_TypeDef;
/* Abstract Control Management Functional Descriptor
--------------------------------------------------------------------------------
Offset| field | Size | Value | Description
------|---------------------|-------|------------|------------------------------
0 | bFunctionLength | 1 | number | Size of functional descriptor, in bytes.
1 | bDescriptorType | 1 | Constant | CS_INTERFACE (0x24)
2 | bDescriptorSubtype | 1 | Constant | Abstract Control Management
| | | | functional descriptor subtype.
3 | bmCapabilities | 1 | Bitmap | The capabilities that this configuration
| | | | supports ((A bit value of zero means that the
| | | | request is not supported.) )
D7..D4: RESERVED (Reset to zero)
| | | | D3: 1 - Device supports the notification
| | | | Network_Connection.
| | | | D2: 1 - Device supports the request
| | | | Send_Break
| | | | D1: 1 - Device supports the request
| \ | | combination of Set_Line_Coding,
| | | | Set_Control_Line_State, Get_Line_Coding, and the
notification Serial_State.
| | | | D0: 1 - Device supports the request
| | | | combination of Set_Comm_Feature,
| | | | Clear_Comm_Feature, and Get_Comm_Feature.
| | | | The previous bits, in combination, identify
| | | | which requests/notifications are supported by
| | | | a Communication Class interface with the
| | | | SubClass code of Abstract Control Model.
------|---------------------|-------|------------|------------------------------
*/
typedef struct _AbstractCntrlMgmtFunctionalDescriptor
{
uint8_t bLength; /*Size of this functional descriptor, in bytes.*/
uint8_t bDescriptorType; /*CS_INTERFACE (0x24)*/
uint8_t bDescriptorSubType; /* Abstract Control Management functional
descriptor subtype*/
uint8_t bmCapabilities; /* The capabilities that this configuration supports */
}
CDC_AbstCntrlMgmtFuncDesc_TypeDef;
/* Union Functional Descriptor
--------------------------------------------------------------------------------
Offset| field | Size | Value | Description
------|---------------------|-------|------------|------------------------------
0 | bFunctionLength | 1 | number | Size of this descriptor.
1 | bDescriptorType | 1 | Constant | CS_INTERFACE (0x24)
2 | bDescriptorSubtype | 1 | Constant | Union functional
| | | | descriptor subtype.
3 | bMasterInterface | 1 | Constant | The interface number of the
| | | | Communication or Data Class interface
4 | bSlaveInterface0 | 1 | Number | nterface number of first slave or associated
| | | | interface in the union.
------|---------------------|-------|------------|------------------------------
*/
typedef struct _UnionFunctionalDescriptor
{
uint8_t bLength; /*Size of this functional descriptor, in bytes*/
uint8_t bDescriptorType; /*CS_INTERFACE (0x24)*/
uint8_t bDescriptorSubType; /* Union functional descriptor SubType*/
uint8_t bMasterInterface; /* The interface number of the Communication or
Data Class interface,*/
uint8_t bSlaveInterface0; /*Interface number of first slave*/
}
CDC_UnionFuncDesc_TypeDef;
typedef struct _USBH_CDCInterfaceDesc
{
CDC_HeaderFuncDesc_TypeDef CDC_HeaderFuncDesc;
CDC_CallMgmtFuncDesc_TypeDef CDC_CallMgmtFuncDesc;
CDC_AbstCntrlMgmtFuncDesc_TypeDef CDC_AbstCntrlMgmtFuncDesc;
CDC_UnionFuncDesc_TypeDef CDC_UnionFuncDesc;
}
CDC_InterfaceDesc_Typedef;
/* Structure for CDC process */
typedef struct
{
uint8_t NotifPipe;
uint8_t NotifEp;
uint8_t buff[8];
uint16_t NotifEpSize;
}
CDC_CommItfTypedef;
typedef struct
{
uint8_t InPipe;
uint8_t OutPipe;
uint8_t OutEp;
uint8_t InEp;
uint8_t buff[8];
uint16_t OutEpSize;
uint16_t InEpSize;
}
CDC_DataItfTypedef;
/* Structure for CDC process */
typedef struct _CDC_Process
{
CDC_CommItfTypedef CommItf;
CDC_DataItfTypedef DataItf;
uint8_t *pTxData;
uint8_t *pRxData;
uint32_t TxDataLength;
uint32_t RxDataLength;
CDC_InterfaceDesc_Typedef CDC_Desc;
CDC_LineCodingTypeDef LineCoding;
CDC_LineCodingTypeDef *pUserLineCoding;
CDC_StateTypeDef state;
CDC_DataStateTypeDef data_tx_state;
CDC_DataStateTypeDef data_rx_state;
uint8_t Rx_Poll;
}
CDC_HandleTypeDef;
/**
* @}
*/
/** @defgroup USBH_CDC_CORE_Exported_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBH_CDC_CORE_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBH_CDC_CORE_Exported_Variables
* @{
*/
extern USBH_ClassTypeDef CDC_Class;
#define USBH_CDC_CLASS &CDC_Class
/**
* @}
*/
/** @defgroup USBH_CDC_CORE_Exported_FunctionsPrototype
* @{
*/
USBH_StatusTypeDef USBH_CDC_SetLineCoding(USBH_HandleTypeDef *phost,
CDC_LineCodingTypeDef *linecoding);
USBH_StatusTypeDef USBH_CDC_GetLineCoding(USBH_HandleTypeDef *phost,
CDC_LineCodingTypeDef *linecoding);
USBH_StatusTypeDef USBH_CDC_Transmit(USBH_HandleTypeDef *phost,
uint8_t *pbuff,
uint32_t length);
USBH_StatusTypeDef USBH_CDC_Receive(USBH_HandleTypeDef *phost,
uint8_t *pbuff,
uint32_t length);
uint16_t USBH_CDC_GetLastReceivedDataSize(USBH_HandleTypeDef *phost);
USBH_StatusTypeDef USBH_CDC_Stop(USBH_HandleTypeDef *phost);
void USBH_CDC_LineCodingChanged(USBH_HandleTypeDef *phost);
void USBH_CDC_TransmitCallback(USBH_HandleTypeDef *phost);
void USBH_CDC_ReceiveCallback(USBH_HandleTypeDef *phost);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBH_CDC_H */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/

View File

@ -0,0 +1,831 @@
/**
******************************************************************************
* @file usbh_cdc.c
* @author MCD Application Team
* @brief This file is the CDC Layer Handlers for USB Host CDC class.
*
******************************************************************************
* @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.
*
******************************************************************************
* @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
*
* @endverbatim
*
******************************************************************************
*/
/* BSPDependencies
- "stm32xxxxx_{eval}{discovery}{nucleo_144}.c"
- "stm32xxxxx_{eval}{discovery}_io.c"
- "stm32xxxxx_{eval}{discovery}{adafruit}_sd.c"
- "stm32xxxxx_{eval}{discovery}{adafruit}_lcd.c"
- "stm32xxxxx_{eval}{discovery}_sdram.c"
EndBSPDependencies */
/* Includes ------------------------------------------------------------------*/
#include "usbh_cdc.h"
/** @addtogroup USBH_LIB
* @{
*/
/** @addtogroup USBH_CLASS
* @{
*/
/** @addtogroup USBH_CDC_CLASS
* @{
*/
/** @defgroup USBH_CDC_CORE
* @brief This file includes CDC Layer Handlers for USB Host CDC class.
* @{
*/
/** @defgroup USBH_CDC_CORE_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup USBH_CDC_CORE_Private_Defines
* @{
*/
#define USBH_CDC_BUFFER_SIZE 1024
/**
* @}
*/
/** @defgroup USBH_CDC_CORE_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBH_CDC_CORE_Private_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USBH_CDC_CORE_Private_FunctionPrototypes
* @{
*/
static USBH_StatusTypeDef USBH_CDC_InterfaceInit(USBH_HandleTypeDef *phost);
static USBH_StatusTypeDef USBH_CDC_InterfaceDeInit(USBH_HandleTypeDef *phost);
static USBH_StatusTypeDef USBH_CDC_Process(USBH_HandleTypeDef *phost);
static USBH_StatusTypeDef USBH_CDC_SOFProcess(USBH_HandleTypeDef *phost);
static USBH_StatusTypeDef USBH_CDC_ClassRequest(USBH_HandleTypeDef *phost);
static USBH_StatusTypeDef GetLineCoding(USBH_HandleTypeDef *phost,
CDC_LineCodingTypeDef *linecoding);
static USBH_StatusTypeDef SetLineCoding(USBH_HandleTypeDef *phost,
CDC_LineCodingTypeDef *linecoding);
static void CDC_ProcessTransmission(USBH_HandleTypeDef *phost);
static void CDC_ProcessReception(USBH_HandleTypeDef *phost);
USBH_ClassTypeDef CDC_Class =
{
"CDC",
USB_CDC_CLASS,
USBH_CDC_InterfaceInit,
USBH_CDC_InterfaceDeInit,
USBH_CDC_ClassRequest,
USBH_CDC_Process,
USBH_CDC_SOFProcess,
NULL,
};
/**
* @}
*/
/** @defgroup USBH_CDC_CORE_Private_Functions
* @{
*/
/**
* @brief USBH_CDC_InterfaceInit
* The function init the CDC class.
* @param phost: Host handle
* @retval USBH Status
*/
static USBH_StatusTypeDef USBH_CDC_InterfaceInit(USBH_HandleTypeDef *phost)
{
USBH_StatusTypeDef status;
uint8_t interface;
CDC_HandleTypeDef *CDC_Handle;
interface = USBH_FindInterface(phost, COMMUNICATION_INTERFACE_CLASS_CODE,
ABSTRACT_CONTROL_MODEL, COMMON_AT_COMMAND);
if ((interface == 0xFFU) || (interface >= USBH_MAX_NUM_INTERFACES)) /* No Valid Interface */
{
USBH_DbgLog("Cannot Find the interface for Communication Interface Class.", phost->pActiveClass->Name);
return USBH_FAIL;
}
status = USBH_SelectInterface(phost, interface);
if (status != USBH_OK)
{
return USBH_FAIL;
}
phost->pActiveClass->pData = (CDC_HandleTypeDef *)USBH_malloc(sizeof(CDC_HandleTypeDef));
CDC_Handle = (CDC_HandleTypeDef *) phost->pActiveClass->pData;
if (CDC_Handle == NULL)
{
USBH_DbgLog("Cannot allocate memory for CDC Handle");
return USBH_FAIL;
}
/* Initialize cdc handler */
(void)USBH_memset(CDC_Handle, 0, sizeof(CDC_HandleTypeDef));
/*Collect the notification endpoint address and length*/
if ((phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress & 0x80U) != 0U)
{
CDC_Handle->CommItf.NotifEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress;
CDC_Handle->CommItf.NotifEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].wMaxPacketSize;
}
/*Allocate the length for host channel number in*/
CDC_Handle->CommItf.NotifPipe = USBH_AllocPipe(phost, CDC_Handle->CommItf.NotifEp);
/* Open pipe for Notification endpoint */
(void)USBH_OpenPipe(phost, CDC_Handle->CommItf.NotifPipe, CDC_Handle->CommItf.NotifEp,
phost->device.address, phost->device.speed, USB_EP_TYPE_INTR,
CDC_Handle->CommItf.NotifEpSize);
(void)USBH_LL_SetToggle(phost, CDC_Handle->CommItf.NotifPipe, 0U);
interface = USBH_FindInterface(phost, DATA_INTERFACE_CLASS_CODE,
RESERVED, NO_CLASS_SPECIFIC_PROTOCOL_CODE);
if ((interface == 0xFFU) || (interface >= USBH_MAX_NUM_INTERFACES)) /* No Valid Interface */
{
USBH_DbgLog("Cannot Find the interface for Data Interface Class.", phost->pActiveClass->Name);
return USBH_FAIL;
}
/*Collect the class specific endpoint address and length*/
if ((phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress & 0x80U) != 0U)
{
CDC_Handle->DataItf.InEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress;
CDC_Handle->DataItf.InEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].wMaxPacketSize;
}
else
{
CDC_Handle->DataItf.OutEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress;
CDC_Handle->DataItf.OutEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].wMaxPacketSize;
}
if ((phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[1].bEndpointAddress & 0x80U) != 0U)
{
CDC_Handle->DataItf.InEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[1].bEndpointAddress;
CDC_Handle->DataItf.InEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[1].wMaxPacketSize;
}
else
{
CDC_Handle->DataItf.OutEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[1].bEndpointAddress;
CDC_Handle->DataItf.OutEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[1].wMaxPacketSize;
}
/*Allocate the length for host channel number out*/
CDC_Handle->DataItf.OutPipe = USBH_AllocPipe(phost, CDC_Handle->DataItf.OutEp);
/*Allocate the length for host channel number in*/
CDC_Handle->DataItf.InPipe = USBH_AllocPipe(phost, CDC_Handle->DataItf.InEp);
/* Open channel for OUT endpoint */
(void)USBH_OpenPipe(phost, CDC_Handle->DataItf.OutPipe, CDC_Handle->DataItf.OutEp,
phost->device.address, phost->device.speed, USB_EP_TYPE_BULK,
CDC_Handle->DataItf.OutEpSize);
/* Open channel for IN endpoint */
(void)USBH_OpenPipe(phost, CDC_Handle->DataItf.InPipe, CDC_Handle->DataItf.InEp,
phost->device.address, phost->device.speed, USB_EP_TYPE_BULK,
CDC_Handle->DataItf.InEpSize);
CDC_Handle->state = CDC_IDLE_STATE;
(void)USBH_LL_SetToggle(phost, CDC_Handle->DataItf.OutPipe, 0U);
(void)USBH_LL_SetToggle(phost, CDC_Handle->DataItf.InPipe, 0U);
return USBH_OK;
}
/**
* @brief USBH_CDC_InterfaceDeInit
* The function DeInit the Pipes used for the CDC class.
* @param phost: Host handle
* @retval USBH Status
*/
static USBH_StatusTypeDef USBH_CDC_InterfaceDeInit(USBH_HandleTypeDef *phost)
{
CDC_HandleTypeDef *CDC_Handle = (CDC_HandleTypeDef *) phost->pActiveClass->pData;
if ((CDC_Handle->CommItf.NotifPipe) != 0U)
{
(void)USBH_ClosePipe(phost, CDC_Handle->CommItf.NotifPipe);
(void)USBH_FreePipe(phost, CDC_Handle->CommItf.NotifPipe);
CDC_Handle->CommItf.NotifPipe = 0U; /* Reset the Channel as Free */
}
if ((CDC_Handle->DataItf.InPipe) != 0U)
{
(void)USBH_ClosePipe(phost, CDC_Handle->DataItf.InPipe);
(void)USBH_FreePipe(phost, CDC_Handle->DataItf.InPipe);
CDC_Handle->DataItf.InPipe = 0U; /* Reset the Channel as Free */
}
if ((CDC_Handle->DataItf.OutPipe) != 0U)
{
(void)USBH_ClosePipe(phost, CDC_Handle->DataItf.OutPipe);
(void)USBH_FreePipe(phost, CDC_Handle->DataItf.OutPipe);
CDC_Handle->DataItf.OutPipe = 0U; /* Reset the Channel as Free */
}
if ((phost->pActiveClass->pData) != NULL)
{
USBH_free(phost->pActiveClass->pData);
phost->pActiveClass->pData = 0U;
}
return USBH_OK;
}
/**
* @brief USBH_CDC_ClassRequest
* The function is responsible for handling Standard requests
* for CDC class.
* @param phost: Host handle
* @retval USBH Status
*/
static USBH_StatusTypeDef USBH_CDC_ClassRequest(USBH_HandleTypeDef *phost)
{
USBH_StatusTypeDef status;
CDC_HandleTypeDef *CDC_Handle = (CDC_HandleTypeDef *) phost->pActiveClass->pData;
/* Issue the get line coding request */
status = GetLineCoding(phost, &CDC_Handle->LineCoding);
if (status == USBH_OK)
{
phost->pUser(phost, HOST_USER_CLASS_ACTIVE);
}
else if (status == USBH_NOT_SUPPORTED)
{
USBH_ErrLog("Control error: CDC: Device Get Line Coding configuration failed");
}
else
{
/* .. */
}
return status;
}
/**
* @brief USBH_CDC_Process
* The function is for managing state machine for CDC data transfers
* @param phost: Host handle
* @retval USBH Status
*/
static USBH_StatusTypeDef USBH_CDC_Process(USBH_HandleTypeDef *phost)
{
USBH_StatusTypeDef status = USBH_BUSY;
USBH_StatusTypeDef req_status = USBH_OK;
CDC_HandleTypeDef *CDC_Handle = (CDC_HandleTypeDef *) phost->pActiveClass->pData;
switch (CDC_Handle->state)
{
case CDC_IDLE_STATE:
status = USBH_OK;
break;
case CDC_SET_LINE_CODING_STATE:
req_status = SetLineCoding(phost, CDC_Handle->pUserLineCoding);
if (req_status == USBH_OK)
{
CDC_Handle->state = CDC_GET_LAST_LINE_CODING_STATE;
}
else
{
if (req_status != USBH_BUSY)
{
CDC_Handle->state = CDC_ERROR_STATE;
}
}
break;
case CDC_GET_LAST_LINE_CODING_STATE:
req_status = GetLineCoding(phost, &(CDC_Handle->LineCoding));
if (req_status == USBH_OK)
{
CDC_Handle->state = CDC_IDLE_STATE;
if ((CDC_Handle->LineCoding.b.bCharFormat == CDC_Handle->pUserLineCoding->b.bCharFormat) &&
(CDC_Handle->LineCoding.b.bDataBits == CDC_Handle->pUserLineCoding->b.bDataBits) &&
(CDC_Handle->LineCoding.b.bParityType == CDC_Handle->pUserLineCoding->b.bParityType) &&
(CDC_Handle->LineCoding.b.dwDTERate == CDC_Handle->pUserLineCoding->b.dwDTERate))
{
USBH_CDC_LineCodingChanged(phost);
}
}
else
{
if (req_status != USBH_BUSY)
{
CDC_Handle->state = CDC_ERROR_STATE;
}
}
break;
case CDC_TRANSFER_DATA:
CDC_ProcessTransmission(phost);
CDC_ProcessReception(phost);
break;
case CDC_ERROR_STATE:
req_status = USBH_ClrFeature(phost, 0x00U);
if (req_status == USBH_OK)
{
/*Change the state to waiting*/
CDC_Handle->state = CDC_IDLE_STATE;
}
break;
default:
break;
}
return status;
}
/**
* @brief USBH_CDC_SOFProcess
* The function is for managing SOF callback
* @param phost: Host handle
* @retval USBH Status
*/
static USBH_StatusTypeDef USBH_CDC_SOFProcess(USBH_HandleTypeDef *phost)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(phost);
return USBH_OK;
}
/**
* @brief USBH_CDC_Stop
* Stop current CDC Transmission
* @param phost: Host handle
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_CDC_Stop(USBH_HandleTypeDef *phost)
{
CDC_HandleTypeDef *CDC_Handle = (CDC_HandleTypeDef *) phost->pActiveClass->pData;
if (phost->gState == HOST_CLASS)
{
CDC_Handle->state = CDC_IDLE_STATE;
(void)USBH_ClosePipe(phost, CDC_Handle->CommItf.NotifPipe);
(void)USBH_ClosePipe(phost, CDC_Handle->DataItf.InPipe);
(void)USBH_ClosePipe(phost, CDC_Handle->DataItf.OutPipe);
}
return USBH_OK;
}
/**
* @brief This request allows the host to find out the currently
* configured line coding.
* @param pdev: Selected device
* @retval USBH_StatusTypeDef : USB ctl xfer status
*/
static USBH_StatusTypeDef GetLineCoding(USBH_HandleTypeDef *phost, CDC_LineCodingTypeDef *linecoding)
{
phost->Control.setup.b.bmRequestType = USB_D2H | USB_REQ_TYPE_CLASS | \
USB_REQ_RECIPIENT_INTERFACE;
phost->Control.setup.b.bRequest = CDC_GET_LINE_CODING;
phost->Control.setup.b.wValue.w = 0U;
phost->Control.setup.b.wIndex.w = 0U;
phost->Control.setup.b.wLength.w = LINE_CODING_STRUCTURE_SIZE;
return USBH_CtlReq(phost, linecoding->Array, LINE_CODING_STRUCTURE_SIZE);
}
/**
* @brief This request allows the host to specify typical asynchronous
* line-character formatting properties
* This request applies to asynchronous byte stream data class interfaces
* and endpoints
* @param pdev: Selected device
* @retval USBH_StatusTypeDef : USB ctl xfer status
*/
static USBH_StatusTypeDef SetLineCoding(USBH_HandleTypeDef *phost,
CDC_LineCodingTypeDef *linecoding)
{
phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_TYPE_CLASS |
USB_REQ_RECIPIENT_INTERFACE;
phost->Control.setup.b.bRequest = CDC_SET_LINE_CODING;
phost->Control.setup.b.wValue.w = 0U;
phost->Control.setup.b.wIndex.w = 0U;
phost->Control.setup.b.wLength.w = LINE_CODING_STRUCTURE_SIZE;
return USBH_CtlReq(phost, linecoding->Array, LINE_CODING_STRUCTURE_SIZE);
}
/**
* @brief This function prepares the state before issuing the class specific commands
* @param None
* @retval None
*/
USBH_StatusTypeDef USBH_CDC_SetLineCoding(USBH_HandleTypeDef *phost,
CDC_LineCodingTypeDef *linecoding)
{
CDC_HandleTypeDef *CDC_Handle = (CDC_HandleTypeDef *) phost->pActiveClass->pData;
if (phost->gState == HOST_CLASS)
{
CDC_Handle->state = CDC_SET_LINE_CODING_STATE;
CDC_Handle->pUserLineCoding = linecoding;
#if (USBH_USE_OS == 1U)
USBH_OS_PutMessage(phost, USBH_CLASS_EVENT, 0U, 0U);
#endif /* (USBH_USE_OS == 1U) */
}
return USBH_OK;
}
/**
* @brief This function prepares the state before issuing the class specific commands
* @param None
* @retval None
*/
USBH_StatusTypeDef USBH_CDC_GetLineCoding(USBH_HandleTypeDef *phost,
CDC_LineCodingTypeDef *linecoding)
{
CDC_HandleTypeDef *CDC_Handle = (CDC_HandleTypeDef *) phost->pActiveClass->pData;
if ((phost->gState == HOST_CLASS) || (phost->gState == HOST_CLASS_REQUEST))
{
*linecoding = CDC_Handle->LineCoding;
return USBH_OK;
}
else
{
return USBH_FAIL;
}
}
/**
* @brief This function return last received data size
* @param None
* @retval None
*/
uint16_t USBH_CDC_GetLastReceivedDataSize(USBH_HandleTypeDef *phost)
{
uint32_t dataSize;
CDC_HandleTypeDef *CDC_Handle = (CDC_HandleTypeDef *) phost->pActiveClass->pData;
if (phost->gState == HOST_CLASS)
{
dataSize = USBH_LL_GetLastXferSize(phost, CDC_Handle->DataItf.InPipe);
}
else
{
dataSize = 0U;
}
return (uint16_t)dataSize;
}
/**
* @brief This function prepares the state before issuing the class specific commands
* @param None
* @retval None
*/
USBH_StatusTypeDef USBH_CDC_Transmit(USBH_HandleTypeDef *phost, uint8_t *pbuff, uint32_t length)
{
USBH_StatusTypeDef Status = USBH_BUSY;
CDC_HandleTypeDef *CDC_Handle = (CDC_HandleTypeDef *) phost->pActiveClass->pData;
if ((CDC_Handle->state == CDC_IDLE_STATE) || (CDC_Handle->state == CDC_TRANSFER_DATA))
{
CDC_Handle->pTxData = pbuff;
CDC_Handle->TxDataLength = length;
CDC_Handle->state = CDC_TRANSFER_DATA;
CDC_Handle->data_tx_state = CDC_SEND_DATA;
Status = USBH_OK;
#if (USBH_USE_OS == 1U)
USBH_OS_PutMessage(phost, USBH_CLASS_EVENT, 0U, 0U);
#endif /* (USBH_USE_OS == 1U) */
}
return Status;
}
/**
* @brief This function prepares the state before issuing the class specific commands
* @param None
* @retval None
*/
USBH_StatusTypeDef USBH_CDC_Receive(USBH_HandleTypeDef *phost, uint8_t *pbuff, uint32_t length)
{
USBH_StatusTypeDef Status = USBH_BUSY;
CDC_HandleTypeDef *CDC_Handle = (CDC_HandleTypeDef *) phost->pActiveClass->pData;
if ((CDC_Handle->state == CDC_IDLE_STATE) || (CDC_Handle->state == CDC_TRANSFER_DATA))
{
CDC_Handle->pRxData = pbuff;
CDC_Handle->RxDataLength = length;
CDC_Handle->state = CDC_TRANSFER_DATA;
CDC_Handle->data_rx_state = CDC_RECEIVE_DATA;
Status = USBH_OK;
#if (USBH_USE_OS == 1U)
USBH_OS_PutMessage(phost, USBH_CLASS_EVENT, 0U, 0U);
#endif /* (USBH_USE_OS == 1U) */
}
return Status;
}
/**
* @brief The function is responsible for sending data to the device
* @param pdev: Selected device
* @retval None
*/
static void CDC_ProcessTransmission(USBH_HandleTypeDef *phost)
{
CDC_HandleTypeDef *CDC_Handle = (CDC_HandleTypeDef *) phost->pActiveClass->pData;
USBH_URBStateTypeDef URB_Status = USBH_URB_IDLE;
switch (CDC_Handle->data_tx_state)
{
case CDC_SEND_DATA:
if (CDC_Handle->TxDataLength > CDC_Handle->DataItf.OutEpSize)
{
(void)USBH_BulkSendData(phost,
CDC_Handle->pTxData,
CDC_Handle->DataItf.OutEpSize,
CDC_Handle->DataItf.OutPipe,
1U);
}
else
{
(void)USBH_BulkSendData(phost,
CDC_Handle->pTxData,
(uint16_t)CDC_Handle->TxDataLength,
CDC_Handle->DataItf.OutPipe,
1U);
}
CDC_Handle->data_tx_state = CDC_SEND_DATA_WAIT;
break;
case CDC_SEND_DATA_WAIT:
URB_Status = USBH_LL_GetURBState(phost, CDC_Handle->DataItf.OutPipe);
/* Check the status done for transmission */
if (URB_Status == USBH_URB_DONE)
{
if (CDC_Handle->TxDataLength > CDC_Handle->DataItf.OutEpSize)
{
CDC_Handle->TxDataLength -= CDC_Handle->DataItf.OutEpSize;
CDC_Handle->pTxData += CDC_Handle->DataItf.OutEpSize;
}
else
{
CDC_Handle->TxDataLength = 0U;
}
if (CDC_Handle->TxDataLength > 0U)
{
CDC_Handle->data_tx_state = CDC_SEND_DATA;
}
else
{
CDC_Handle->data_tx_state = CDC_IDLE;
USBH_CDC_TransmitCallback(phost);
}
#if (USBH_USE_OS == 1U)
USBH_OS_PutMessage(phost, USBH_CLASS_EVENT, 0U, 0U);
#endif /* (USBH_USE_OS == 1U) */
}
else
{
if (URB_Status == USBH_URB_NOTREADY)
{
CDC_Handle->data_tx_state = CDC_SEND_DATA;
#if (USBH_USE_OS == 1U)
USBH_OS_PutMessage(phost, USBH_CLASS_EVENT, 0U, 0U);
#endif /* (USBH_USE_OS == 1U) */
}
}
break;
default:
break;
}
}
/**
* @brief This function responsible for reception of data from the device
* @param pdev: Selected device
* @retval None
*/
static void CDC_ProcessReception(USBH_HandleTypeDef *phost)
{
CDC_HandleTypeDef *CDC_Handle = (CDC_HandleTypeDef *) phost->pActiveClass->pData;
USBH_URBStateTypeDef URB_Status = USBH_URB_IDLE;
uint32_t length;
switch (CDC_Handle->data_rx_state)
{
case CDC_RECEIVE_DATA:
(void)USBH_BulkReceiveData(phost,
CDC_Handle->pRxData,
CDC_Handle->DataItf.InEpSize,
CDC_Handle->DataItf.InPipe);
#if defined (USBH_IN_NAK_PROCESS) && (USBH_IN_NAK_PROCESS == 1U)
phost->NakTimer = phost->Timer;
#endif /* defined (USBH_IN_NAK_PROCESS) && (USBH_IN_NAK_PROCESS == 1U) */
CDC_Handle->data_rx_state = CDC_RECEIVE_DATA_WAIT;
break;
case CDC_RECEIVE_DATA_WAIT:
URB_Status = USBH_LL_GetURBState(phost, CDC_Handle->DataItf.InPipe);
/*Check the status done for reception*/
if (URB_Status == USBH_URB_DONE)
{
length = USBH_LL_GetLastXferSize(phost, CDC_Handle->DataItf.InPipe);
if (((CDC_Handle->RxDataLength - length) > 0U) && (length == CDC_Handle->DataItf.InEpSize))
{
CDC_Handle->RxDataLength -= length;
CDC_Handle->pRxData += length;
CDC_Handle->data_rx_state = CDC_RECEIVE_DATA;
}
else
{
CDC_Handle->data_rx_state = CDC_IDLE;
USBH_CDC_ReceiveCallback(phost);
}
#if (USBH_USE_OS == 1U)
USBH_OS_PutMessage(phost, USBH_CLASS_EVENT, 0U, 0U);
#endif /* (USBH_USE_OS == 1U) */
}
#if defined (USBH_IN_NAK_PROCESS) && (USBH_IN_NAK_PROCESS == 1U)
else if (URB_Status == USBH_URB_NAK_WAIT)
{
CDC_Handle->data_rx_state = CDC_RECEIVE_DATA_WAIT;
if ((phost->Timer - phost->NakTimer) > phost->NakTimeout)
{
phost->NakTimer = phost->Timer;
USBH_ActivatePipe(phost, CDC_Handle->DataItf.InPipe);
}
#if (USBH_USE_OS == 1U)
USBH_OS_PutMessage(phost, USBH_CLASS_EVENT, 0U, 0U);
#endif /* (USBH_USE_OS == 1U) */
}
#endif /* defined (USBH_IN_NAK_PROCESS) && (USBH_IN_NAK_PROCESS == 1U) */
else
{
/* .. */
}
break;
default:
break;
}
}
/**
* @brief The function informs user that data have been received
* @param pdev: Selected device
* @retval None
*/
__weak void USBH_CDC_TransmitCallback(USBH_HandleTypeDef *phost)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(phost);
}
/**
* @brief The function informs user that data have been sent
* @param pdev: Selected device
* @retval None
*/
__weak void USBH_CDC_ReceiveCallback(USBH_HandleTypeDef *phost)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(phost);
}
/**
* @brief The function informs user that Settings have been changed
* @param pdev: Selected device
* @retval None
*/
__weak void USBH_CDC_LineCodingChanged(USBH_HandleTypeDef *phost)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(phost);
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/