背景:最近项目需要做一个基于USB的复合设备,实现usb转串口和U盘的功能,其中遇到些许问题,记录一下,此项目是基于stm32H747实现,其实不同芯片系列的方式都一样,大家可参考使用,不详之处,可联系补充。
文章主要分三部分展开,先实现CDC功能,在实现MSC功能,最后实现CDC+MSC功能。具有参考意义的文章会在最后端列出连接。
1、搭建环境
主芯片:stm32H747,使用M7核。
代码编译:STM32CubeIDE,也可以使用keil编译,两者就时添加源码和头文件时需要注意。
HAL库版本:可采用最新版本。
代码生成工具:CubeMX
2、USB接口实现CDC(usb转串口功能)
2.1 打开cubeMX,选择主控芯片为stm32H747系列,如下图:使能RCC的高速时钟
2.2 在connectivity中勾选USB_OTG_FS,模式选择为设备模式
2.3 在Middleware and Software Packs中配置usb设备虚拟串口
注:默认全局中断是被打开的,usb引脚也是默认的,如果与实际不符,可根据实际修改。
2.4 时钟配置
主频可以随意配置,USB的时钟选择最方便的RC48,如果想选择PLLQ1或者PLLQ3可以根据实际调整,但是最好都配置成48MHz。
2.5 代码生成
注意交叉编译工具的选择,最下面是我本人使用的HAL库版本
可以在通用代码设置中,把.h和.c文件夹区分开,也可不区分,根据个人爱好选择。
2.6 点击生成代码即可
使用IDE打开,导入生成的工程,结构如下。CDC我们需要修改的代码在应用代码中,usb转串口的接收和发送函数,以及配置函数在usbd_cdc_if.c当中。
2.7,修改代码使用
代开usbd_cdc_if.c这个文件,其中有一个static int8_t CDC_Control_FS(uint8_t cmd, uint8_t* pbuf, uint16_t length)函数,这个函数是配置波特率等串口参数的的,可以在CDC_GET_LINE_CODING分支下添加如下代码:
pbuf[0] = (uint8_t)(115200);
pbuf[1] = (uint8_t)(115200 >> 8);
pbuf[2] = (uint8_t)(115200 >> 16);
pbuf[3] = (uint8_t)(115200 >> 24);
pbuf[4] = 0; // stop bits (1)
pbuf[5] = 0; // parity (none)
pbuf[6] = 8; // number of bits (8)
在static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)函数中添加CDC_Transmit_FS(Buf, *Len);这句代码,意在回环,这个函数是usb转串口的接收函数,添加的代码是usb转串口的发送函数,目的是把接收的数据返回回去,测试使用,实际可根据自己想法修改。修改后的整体代码如下:
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : usbd_cdc_if.c
* @version : v1.0_Cube
* @brief : Usb device for Virtual Com Port.
******************************************************************************
* @attention
*
* Copyright (c) 2023 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.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc_if.h"
/* USER CODE BEGIN INCLUDE */
/* USER CODE END INCLUDE */
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
/* USER CODE END PV */
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @brief Usb device library.
* @{
*/
/** @addtogroup USBD_CDC_IF
* @{
*/
/** @defgroup USBD_CDC_IF_Private_TypesDefinitions USBD_CDC_IF_Private_TypesDefinitions
* @brief Private types.
* @{
*/
/* USER CODE BEGIN PRIVATE_TYPES */
/* USER CODE END PRIVATE_TYPES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Private_Defines USBD_CDC_IF_Private_Defines
* @brief Private defines.
* @{
*/
/* USER CODE BEGIN PRIVATE_DEFINES */
/* USER CODE END PRIVATE_DEFINES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Private_Macros USBD_CDC_IF_Private_Macros
* @brief Private macros.
* @{
*/
/* USER CODE BEGIN PRIVATE_MACRO */
/* USER CODE END PRIVATE_MACRO */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Private_Variables USBD_CDC_IF_Private_Variables
* @brief Private variables.
* @{
*/
/* Create buffer for reception and transmission */
/* It's up to user to redefine and/or remove those define */
/** Received data over USB are stored in this buffer */
uint8_t UserRxBufferFS[APP_RX_DATA_SIZE];
/** Data to send over USB CDC are stored in this buffer */
uint8_t UserTxBufferFS[APP_TX_DATA_SIZE];
/* USER CODE BEGIN PRIVATE_VARIABLES */
/* USER CODE END PRIVATE_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Exported_Variables USBD_CDC_IF_Exported_Variables
* @brief Public variables.
* @{
*/
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Private_FunctionPrototypes USBD_CDC_IF_Private_FunctionPrototypes
* @brief Private functions declaration.
* @{
*/
static int8_t CDC_Init_FS(void);
static int8_t CDC_DeInit_FS(void);
static int8_t CDC_Control_FS(uint8_t cmd, uint8_t* pbuf, uint16_t length);
static int8_t CDC_Receive_FS(uint8_t* pbuf, uint32_t *Len);
static int8_t CDC_TransmitCplt_FS(uint8_t *pbuf, uint32_t *Len, uint8_t epnum);
/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
/**
* @}
*/
USBD_CDC_ItfTypeDef USBD_Interface_fops_FS =
{
CDC_Init_FS,
CDC_DeInit_FS,
CDC_Control_FS,
CDC_Receive_FS,
CDC_TransmitCplt_FS
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief Initializes the CDC media low layer over the FS USB IP
* @retval USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Init_FS(void)
{
/* USER CODE BEGIN 3 */
/* Set Application Buffers */
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, UserTxBufferFS, 0);
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, UserRxBufferFS);
return (USBD_OK);
/* USER CODE END 3 */
}
/**
* @brief DeInitializes the CDC media low layer
* @retval USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_DeInit_FS(void)
{
/* USER CODE BEGIN 4 */
return (USBD_OK);
/* USER CODE END 4 */
}
/**
* @brief Manage the CDC class requests
* @param cmd: Command code
* @param pbuf: Buffer containing command data (request parameters)
* @param length: Number of data to be sent (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Control_FS(uint8_t cmd, uint8_t* pbuf, uint16_t length)
{
/* USER CODE BEGIN 5 */
switch(cmd)
{
case CDC_SEND_ENCAPSULATED_COMMAND:
break;
case CDC_GET_ENCAPSULATED_RESPONSE:
break;
case CDC_SET_COMM_FEATURE:
break;
case CDC_GET_COMM_FEATURE:
break;
case CDC_CLEAR_COMM_FEATURE:
break;
/*******************************************************************************/
/* Line Coding Structure */
/*-----------------------------------------------------------------------------*/
/* Offset | Field | Size | Value | Description */
/* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
/* 4 | bCharFormat | 1 | Number | Stop bits */
/* 0 - 1 Stop bit */
/* 1 - 1.5 Stop bits */
/* 2 - 2 Stop bits */
/* 5 | bParityType | 1 | Number | Parity */
/* 0 - None */
/* 1 - Odd */
/* 2 - Even */
/* 3 - Mark */
/* 4 - Space */
/* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
/*******************************************************************************/
case CDC_SET_LINE_CODING:
break;
case CDC_GET_LINE_CODING:
pbuf[0] = (uint8_t)(115200);
pbuf[1] = (uint8_t)(115200 >> 8);
pbuf[2] = (uint8_t)(115200 >> 16);
pbuf[3] = (uint8_t)(115200 >> 24);
pbuf[4] = 0; // stop bits (1)
pbuf[5] = 0; // parity (none)
pbuf[6] = 8; // number of bits (8)
break;
case CDC_SET_CONTROL_LINE_STATE:
break;
case CDC_SEND_BREAK:
break;
default:
break;
}
return (USBD_OK);
/* USER CODE END 5 */
}
/**
* @brief Data received over USB OUT endpoint are sent over CDC interface
* through this function.
*
* @note
* This function will issue a NAK packet on any OUT packet received on
* USB endpoint until exiting this function. If you exit this function
* before transfer is complete on CDC interface (ie. using DMA controller)
* it will result in receiving more data while previous ones are still
* not sent.
*
* @param Buf: Buffer of data to be received
* @param Len: Number of data received (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN 6 */
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
CDC_Transmit_FS(Buf, *Len);
return (USBD_OK);
/* USER CODE END 6 */
}
/**
* @brief CDC_Transmit_FS
* Data to send over USB IN endpoint are sent over CDC interface
* through this function.
* @note
*
*
* @param Buf: Buffer of data to be sent
* @param Len: Number of data to be sent (in bytes)
* @retval USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY
*/
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 7 */
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
if (hcdc->TxState != 0){
return USBD_BUSY;
}
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
/* USER CODE END 7 */
return result;
}
/**
* @brief CDC_TransmitCplt_FS
* Data transmitted callback
*
* @note
* This function is IN transfer complete callback used to inform user that
* the submitted Data is successfully sent over USB.
*
* @param Buf: Buffer of data to be received
* @param Len: Number of data received (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_TransmitCplt_FS(uint8_t *Buf, uint32_t *Len, uint8_t epnum)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 13 */
UNUSED(Buf);
UNUSED(Len);
UNUSED(epnum);
/* USER CODE END 13 */
return result;
}
/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
/**
* @}
*/
/**
* @}
*/
2.8 编译测试,查看效果
3、USB接口实现MSC(U盘功能)
3.1 打开cubeMX,选择主控芯片为stm32H747系列,如下图:使能RCC的高速时钟
3.2 在connectivity中勾选USB_OTG_FS,模式选择为设备模式
3.3 在Middleware and Software Packs中配置usb设备为大容量存储类
注:默认全局中断是被打开的,usb引脚也是默认的,如果与实际不符,可根据实际修改。
3.4 时钟配置
主频可以随意配置,USB的时钟选择最方便的RC48,如果想选择PLLQ1或者PLLQ3可以根据实际调整,但是最好都配置成48MHz。
3.5 代码生成
注意交叉编译工具的选择,最下面是我本人使用的HAL库版本
可以在通用代码设置中,把.h和.c文件夹区分开,也可不区分,根据个人爱好选择。
3.6 点击生成代码
3.7,不修改代码的情况下,编译直接烧录代码,电脑端仅可以出来个盘符,但是没有存储读写的共功能,因为没有实现这些接口。如下图。
3.8,实际的U盘功能,根据自己的实际情况实现,这里我仅使用一个数组做个示例,有些人可能使用MCU自身的flash做U盘,有些人可能使用的是spiflash做U盘,但是都可以参照本例程实现,具体是修改usbd_storage_if.c这个文件。
首先新建一个usb_storage.c和usb_storage.h文件在USB_DEVICE/APP/文件夹下,c文件中实现三个函数,初始化、读、写,
usb_storage.c的源码如下
/*
* usb_storage.c
*
* Created on: 2023年10月19日
* Author: pc
*/
#include "usb_storage.h"
#include <string.h>
#define STORAGE_MAX (100*1024) //100K的一个数组,模拟U盘的大小
uint8_t usb_storage[STORAGE_MAX] = {0};//模拟的U盘实体,大小与
//初始化函数
uint8_t usb_storage_init(void)
{
memset(usb_storage,0,STORAGE_MAX);
return 0;
}
//读汉书
uint8_t usb_storage_read(uint8_t* pBuffer,uint32_t ReadAddr,uint16_t NumByteToRead)
{
memcpy(pBuffer,(void *)(usb_storage + ReadAddr),NumByteToRead);
return 0;
}
//写函数
uint8_t usb_storage_write(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)
{
memcpy((void *)(usb_storage + WriteAddr),pBuffer,NumByteToWrite);
return 0;
}
usb_storage.h的源码如下
/*
* usb_storage.h
*
* Created on: 2023年10月19日
* Author: pc
*/
#ifndef APP_USB_STORAGE_H_
#define APP_USB_STORAGE_H_
#include "main.h"
uint8_t usb_storage_init(void);
uint8_t usb_storage_read(uint8_t* pBuffer,uint32_t ReadAddr,uint16_t NumByteToRead);
uint8_t usb_storage_write(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite);
#endif /* APP_USB_STORAGE_H_ */
usbd_storage_if.c代码中增加代码,主要是初始化,读写的实现,外加u盘大小的获取,
大小的定义主要是这两个宏:和usb_storage.c中定义的大小要匹配起来,
在usbd_conf.h中,修改宏MSC_MEDIA_PACKET的大小和U盘块大小(STORAGE_BLK_SIZ)一致。
usbd_storage_if.c整体的源码如下:
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : usbd_storage_if.c
* @version : v1.0_Cube
* @brief : Memory management layer.
******************************************************************************
* @attention
*
* Copyright (c) 2023 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.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "usbd_storage_if.h"
#include "usb_storage.h"
/* USER CODE BEGIN INCLUDE */
/* USER CODE END INCLUDE */
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
/* USER CODE END PV */
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @brief Usb device.
* @{
*/
/** @defgroup USBD_STORAGE
* @brief Usb mass storage device module
* @{
*/
/** @defgroup USBD_STORAGE_Private_TypesDefinitions
* @brief Private types.
* @{
*/
/* USER CODE BEGIN PRIVATE_TYPES */
/* USER CODE END PRIVATE_TYPES */
/**
* @}
*/
/** @defgroup USBD_STORAGE_Private_Defines
* @brief Private defines.
* @{
*/
#define STORAGE_LUN_NBR 1
#define STORAGE_BLK_NBR 100//0x10000
#define STORAGE_BLK_SIZ 1024//0x200
/* USER CODE BEGIN PRIVATE_DEFINES */
/* USER CODE END PRIVATE_DEFINES */
/**
* @}
*/
/** @defgroup USBD_STORAGE_Private_Macros
* @brief Private macros.
* @{
*/
/* USER CODE BEGIN PRIVATE_MACRO */
/* USER CODE END PRIVATE_MACRO */
/**
* @}
*/
/** @defgroup USBD_STORAGE_Private_Variables
* @brief Private variables.
* @{
*/
/* USER CODE BEGIN INQUIRY_DATA_FS */
/** USB Mass storage Standard Inquiry Data. */
const int8_t STORAGE_Inquirydata_FS[] = {/* 36 */
/* LUN 0 */
0x00,
0x80,
0x02,
0x02,
(STANDARD_INQUIRY_DATA_LEN - 5),
0x00,
0x00,
0x00,
'S', 'T', 'M', ' ', ' ', ' ', ' ', ' ', /* Manufacturer : 8 bytes */
'P', 'r', 'o', 'd', 'u', 'c', 't', ' ', /* Product : 16 Bytes */
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
'0', '.', '0' ,'1' /* Version : 4 Bytes */
};
/* USER CODE END INQUIRY_DATA_FS */
/* USER CODE BEGIN PRIVATE_VARIABLES */
/* USER CODE END PRIVATE_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_STORAGE_Exported_Variables
* @brief Public variables.
* @{
*/
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_STORAGE_Private_FunctionPrototypes
* @brief Private functions declaration.
* @{
*/
static int8_t STORAGE_Init_FS(uint8_t lun);
static int8_t STORAGE_GetCapacity_FS(uint8_t lun, uint32_t *block_num, uint16_t *block_size);
static int8_t STORAGE_IsReady_FS(uint8_t lun);
static int8_t STORAGE_IsWriteProtected_FS(uint8_t lun);
static int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
static int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
static int8_t STORAGE_GetMaxLun_FS(void);
/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
/**
* @}
*/
USBD_StorageTypeDef USBD_Storage_Interface_fops_FS =
{
STORAGE_Init_FS,
STORAGE_GetCapacity_FS,
STORAGE_IsReady_FS,
STORAGE_IsWriteProtected_FS,
STORAGE_Read_FS,
STORAGE_Write_FS,
STORAGE_GetMaxLun_FS,
(int8_t *)STORAGE_Inquirydata_FS
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief Initializes the storage unit (medium) over USB FS IP
* @param lun: Logical unit number.
* @retval USBD_OK if all operations are OK else USBD_FAIL
*/
int8_t STORAGE_Init_FS(uint8_t lun)
{
/* USER CODE BEGIN 2 */
//UNUSED(lun);
usb_storage_init();
return (USBD_OK);
/* USER CODE END 2 */
}
/**
* @brief Returns the medium capacity.
* @param lun: Logical unit number.
* @param block_num: Number of total block number.
* @param block_size: Block size.
* @retval USBD_OK if all operations are OK else USBD_FAIL
*/
int8_t STORAGE_GetCapacity_FS(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
{
/* USER CODE BEGIN 3 */
//UNUSED(lun);
*block_num = STORAGE_BLK_NBR;
*block_size = STORAGE_BLK_SIZ;
return (USBD_OK);
/* USER CODE END 3 */
}
/**
* @brief Checks whether the medium is ready.
* @param lun: Logical unit number.
* @retval USBD_OK if all operations are OK else USBD_FAIL
*/
int8_t STORAGE_IsReady_FS(uint8_t lun)
{
/* USER CODE BEGIN 4 */
//UNUSED(lun);
return (USBD_OK);
/* USER CODE END 4 */
}
/**
* @brief Checks whether the medium is write protected.
* @param lun: Logical unit number.
* @retval USBD_OK if all operations are OK else USBD_FAIL
*/
int8_t STORAGE_IsWriteProtected_FS(uint8_t lun)
{
/* USER CODE BEGIN 5 */
//UNUSED(lun);
return (USBD_OK);
/* USER CODE END 5 */
}
/**
* @brief Reads data from the medium.
* @param lun: Logical unit number.
* @param buf: data buffer.
* @param blk_addr: Logical block address.
* @param blk_len: Blocks number.
* @retval USBD_OK if all operations are OK else USBD_FAIL
*/
int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
/* USER CODE BEGIN 6 */
// UNUSED(lun);
// UNUSED(buf);
// UNUSED(blk_addr);
// UNUSED(blk_len);
usb_storage_read(buf,blk_addr * STORAGE_BLK_SIZ,blk_len*STORAGE_BLK_SIZ);
return (USBD_OK);
/* USER CODE END 6 */
}
/**
* @brief Writes data into the medium.
* @param lun: Logical unit number.
* @param buf: data buffer.
* @param blk_addr: Logical block address.
* @param blk_len: Blocks number.
* @retval USBD_OK if all operations are OK else USBD_FAIL
*/
int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
/* USER CODE BEGIN 7 */
// UNUSED(lun);
// UNUSED(buf);
// UNUSED(blk_addr);
// UNUSED(blk_len);
usb_storage_write(buf,blk_addr * STORAGE_BLK_SIZ,blk_len*STORAGE_BLK_SIZ);
return (USBD_OK);
/* USER CODE END 7 */
}
/**
* @brief Returns the Max Supported LUNs.
* @param None
* @retval Lun(s) number.
*/
int8_t STORAGE_GetMaxLun_FS(void)
{
/* USER CODE BEGIN 8 */
return (STORAGE_LUN_NBR - 1);
/* USER CODE END 8 */
}
/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
/**
* @}
*/
/**
* @}
*/
3.9 编译下载到MCU
出现盘符后,第一次需要格式化,大小和容量都与代码中的相匹配
格式化之后的盘符如下,估计有22K默认被占用,可能存放文件表头了,具体不是很清楚为什么只有80K。
至此U盘实验完成
4.USB实现CDC+MSC的功能
4.1 在MSC工程的基础上添加CDC的功能,拷贝cdc文件,新增复合设备的c文件。
cdc文件从cdc的工程中拷贝,仅拷贝usbd_cdc.c、usbd_cdc.h和应用代码usbd_cdc_if.c、usbd_cdc_if.h
新增的复合设备文件为:usbd_composite_builder.c usbd_composite_builder.h,这两个文件可在cubeMX的示例代码中拷贝,然后添加到工程当中,我的cubeMx安装路径在D盘,故这两个文件的路径如下,经供参考:D:\STM32CubeMX\STM32Cube\Repository\STM32Cube_FW_H7_V1.11.0\Middlewares\ST\STM32_USB_Device_Library\Class\CompositeBuilder\Src\usbd_composite_builder.c
需要把新增的文件和头文件路径在工程中添加,避免编译时找不到文件。
4.2 修改复合类设备的代码,即修改usbd_composite_builder.c
添加几个头文件
增加配置描述符,配置描述符这里不再细说,可网上参考配置描述符资料详细学习。其实就是填充USBD_CMPSIT_FSCfgDesc[USBD_CMPST_MAX_CONFDESC_SZ]这个数组。
在h文件中修改配置描述符数组长度的宏为 USBD_CMPST_MAX_CONFDESC_SZ 为106。
整体代码如下:
/**
******************************************************************************
* @file usbd_composite_builder.c
* @author MCD Application Team
* @brief This file provides all the composite builder functions.
******************************************************************************
* @attention
*
* Copyright (c) 2021 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
*
* ===================================================================
* Composite Builder Description
* ===================================================================
*
* The composite builder builds the configuration descriptors based on
* the selection of classes by user.
* It includes all USB Device classes in order to instantiate their
* descriptors, but for better management, it is possible to optimize
* footprint by removing unused classes. It is possible to do so by
* commenting the relative define in usbd_conf.h.
*
* @endverbatim
*
******************************************************************************
*/
/* BSPDependencies
- None
EndBSPDependencies */
/* Includes ------------------------------------------------------------------*/
#include "usbd_composite_builder.h"
#include "usbd_def.h"
#include "usbd_cdc.h"
#include "usbd_msc.h"
#include "usbd_core.h"
#include "usbd_desc.h"
#include "usbd_conf.h"
#ifdef USE_USBD_COMPOSITE
/** @addtogroup STM32_USB_DEVICE_LIBRARY
* @{
*/
/** @defgroup CMPSIT_CORE
* @brief Mass storage core module
* @{
*/
/** @defgroup CMPSIT_CORE_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup CMPSIT_CORE_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup CMPSIT_CORE_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup CMPSIT_CORE_Private_FunctionPrototypes
* @{
*/
/* uint8_t USBD_CMPSIT_Init (USBD_HandleTypeDef *pdev,
uint8_t cfgidx); */ /* Function not used for the moment */
/* uint8_t USBD_CMPSIT_DeInit (USBD_HandleTypeDef *pdev,
uint8_t cfgidx); */ /* Function not used for the moment */
uint8_t *USBD_CMPSIT_GetFSCfgDesc(uint16_t *length);
#ifdef USE_USB_HS
uint8_t *USBD_CMPSIT_GetHSCfgDesc(uint16_t *length);
#endif /* USE_USB_HS */
uint8_t *USBD_CMPSIT_GetOtherSpeedCfgDesc(uint16_t *length);
uint8_t *USBD_CMPSIT_GetDeviceQualifierDescriptor(uint16_t *length);
static uint8_t USBD_CMPSIT_FindFreeIFNbr(USBD_HandleTypeDef *pdev);
static void USBD_CMPSIT_AddConfDesc(uint32_t Conf, __IO uint32_t *pSze);
static void USBD_CMPSIT_AssignEp(USBD_HandleTypeDef *pdev, uint8_t Add, uint8_t Type, uint32_t Sze);
#if USBD_CMPSIT_ACTIVATE_HID == 1U
static void USBD_CMPSIT_HIDMouseDesc(USBD_HandleTypeDef *pdev, uint32_t pConf, __IO uint32_t *Sze, uint8_t speed);
#endif /* USBD_CMPSIT_ACTIVATE_HID == 1U */
#if USBD_CMPSIT_ACTIVATE_MSC == 1U
static void USBD_CMPSIT_MSCDesc(USBD_HandleTypeDef *pdev, uint32_t pConf, __IO uint32_t *Sze, uint8_t speed);
#endif /* USBD_CMPSIT_ACTIVATE_MSC == 1U */
#if USBD_CMPSIT_ACTIVATE_CDC == 1U
static void USBD_CMPSIT_CDCDesc(USBD_HandleTypeDef *pdev, uint32_t pConf, __IO uint32_t *Sze, uint8_t speed);
#endif /* USBD_CMPSIT_ACTIVATE_CDC == 1U */
#if USBD_CMPSIT_ACTIVATE_DFU == 1U
static void USBD_CMPSIT_DFUDesc(USBD_HandleTypeDef *pdev, uint32_t pConf, __IO uint32_t *Sze, uint8_t speed);
#endif /* USBD_CMPSIT_ACTIVATE_DFU == 1U */
#if USBD_CMPSIT_ACTIVATE_RNDIS == 1U
static void USBD_CMPSIT_RNDISDesc(USBD_HandleTypeDef *pdev, uint32_t pConf, __IO uint32_t *Sze, uint8_t speed);
#endif /* USBD_CMPSIT_ACTIVATE_RNDIS == 1U */
#if USBD_CMPSIT_ACTIVATE_CDC_ECM == 1U
static void USBD_CMPSIT_CDC_ECMDesc(USBD_HandleTypeDef *pdev, uint32_t pConf, __IO uint32_t *Sze, uint8_t speed);
#endif /* USBD_CMPSIT_ACTIVATE_CDC_ECM == 1U */
#if USBD_CMPSIT_ACTIVATE_AUDIO == 1U
static void USBD_CMPSIT_AUDIODesc(USBD_HandleTypeDef *pdev, uint32_t pConf, __IO uint32_t *Sze, uint8_t speed);
#endif /* USBD_CMPSIT_ACTIVATE_AUDIO == 1U */
#if USBD_CMPSIT_ACTIVATE_CUSTOMHID == 1
static void USBD_CMPSIT_CUSTOMHIDDesc(USBD_HandleTypeDef *pdev, uint32_t pConf, __IO uint32_t *Sze, uint8_t speed);
#endif /* USBD_CMPSIT_ACTIVATE_CUSTOMHID == 1U */
#if USBD_CMPSIT_ACTIVATE_VIDEO == 1U
static void USBD_CMPSIT_VIDEODesc(USBD_HandleTypeDef *pdev, uint32_t pConf, __IO uint32_t *Sze, uint8_t speed);
#endif /* USBD_CMPSIT_ACTIVATE_VIDEO == 1U */
#if USBD_CMPSIT_ACTIVATE_PRINTER == 1U
static void USBD_CMPSIT_PRNTDesc(USBD_HandleTypeDef *pdev, uint32_t pConf, __IO uint32_t *Sze, uint8_t speed);
#endif /* USBD_CMPSIT_ACTIVATE_PRINTER == 1U */
#if USBD_CMPSIT_ACTIVATE_CCID == 1U
static void USBD_CMPSIT_CCIDDesc(USBD_HandleTypeDef *pdev, uint32_t pConf, __IO uint32_t *Sze, uint8_t speed);
#endif /* USBD_CMPSIT_ACTIVATE_CCID == 1U */
#if USBD_CMPSIT_ACTIVATE_MTP == 1U
static void USBD_CMPSIT_MTPDesc(USBD_HandleTypeDef *pdev, uint32_t pConf, __IO uint32_t *Sze, uint8_t speed);
#endif /* USBD_CMPSIT_ACTIVATE_MTP == 1U */
/**
* @}
*/
/** @defgroup CMPSIT_CORE_Private_Variables
* @{
*/
/* This structure is used only for the Configuration descriptors and Device Qualifier */
USBD_ClassTypeDef USBD_CMPSIT =
{
NULL, /* Init, */
NULL, /* DeInit, */
NULL, /* Setup, */
NULL, /* EP0_TxSent, */
NULL, /* EP0_RxReady, */
NULL, /* DataIn, */
NULL, /* DataOut, */
NULL, /* SOF, */
NULL,
NULL,
#ifdef USE_USB_HS
USBD_CMPSIT_GetHSCfgDesc,
#else
NULL,
#endif /* USE_USB_HS */
USBD_CMPSIT_GetFSCfgDesc,
USBD_CMPSIT_GetOtherSpeedCfgDesc,
USBD_CMPSIT_GetDeviceQualifierDescriptor,
#if (USBD_SUPPORT_USER_STRING_DESC == 1U)
NULL,
#endif /* USBD_SUPPORT_USER_STRING_DESC */
};
/* The generic configuration descriptor buffer that will be filled by builder
Size of the buffer is the maximum possible configuration descriptor size. */
__ALIGN_BEGIN static uint8_t USBD_CMPSIT_FSCfgDesc[USBD_CMPST_MAX_CONFDESC_SZ] __ALIGN_END = {
/* Configuration Descriptor */
0x09, /* bLength: Configuration Descriptor size */
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
USBD_CMPST_MAX_CONFDESC_SZ, /* wTotalLength */
0x00,
0x03, /* bNumInterfaces: 2 interfaces */
0x01, /* bConfigurationValue: Configuration value */
0x00, /* iConfiguration: Index of string descriptor
describing the configuration */
#if (USBD_SELF_POWERED == 1U)
0xC0, /* bmAttributes: Bus Powered according to user configuration */
#else
0x80, /* bmAttributes: Bus Powered according to user configuration */
#endif /* USBD_SELF_POWERED */
USBD_MAX_POWER, /* MaxPower (mA) */
/*---------------------------------------------------------------------------*/
/* Interface Association Descriptor: CDC device (virtual com port) */
0x08, /* bLength: IAD size */
0x0B, /* bDescriptorType: Interface Association Descriptor */
0x00, /* bFirstInterface */
0x02, /* bInterfaceCount */
0x02, /* bFunctionClass: Communication Interface Class */
0x02, /* bFunctionSubClass: Abstract Control Model */
0x01, /* bFunctionProtocol: Common AT commands */
0x00, /* 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 endpoint 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 */
0x00, /* bmCapabilities: D0+D1 */
0x01, /* bDataInterface */
/* 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),
CDC_FS_BINTERVAL, /* 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 */
0x06, /* 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 */
/* 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 */
/* Interface Association Descriptor: Mass Storage device */
0x08, /* bLength: IAD size */
0x0B, /* bDescriptorType: Interface Association Descriptor */
0x02, /* bFirstInterface */
0x01, /* bInterfaceCount */
0x08, /* bFunctionClass: */
0x06, /* bFunctionSubClass: */
0x50, /* bFunctionProtocol: */
0x00, /* iFunction */
/******************** Mass Storage interface ********************/
0x09, /* bLength: Interface Descriptor size */
0x04, /* bDescriptorType: */
0x02, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x02, /* bNumEndpoints */
0x08, /* bInterfaceClass: MSC Class */
0x06, /* bInterfaceSubClass : SCSI transparent*/
0x50, /* nInterfaceProtocol */
0x00, /* iInterface: */
/******************** Mass Storage Endpoints ********************/
0x07, /* Endpoint descriptor length = 7 */
0x05, /* Endpoint descriptor type */
MSC_EPIN_ADDR, /* Endpoint address (IN, address 1) */
0x02, /* Bulk endpoint type */
LOBYTE(MSC_MAX_FS_PACKET),
HIBYTE(MSC_MAX_FS_PACKET),
0x00, /* Polling interval in milliseconds */
0x07, /* Endpoint descriptor length = 7 */
0x05, /* Endpoint descriptor type */
MSC_EPOUT_ADDR, /* Endpoint address (OUT, address 1) */
0x02, /* Bulk endpoint type */
LOBYTE(MSC_MAX_FS_PACKET),
HIBYTE(MSC_MAX_FS_PACKET),
0x00
};
static uint8_t *pCmpstFSConfDesc = USBD_CMPSIT_FSCfgDesc;
/* Variable that dynamically holds the current size of the configuration descriptor */
static __IO uint32_t CurrFSConfDescSz = USBD_CMPST_MAX_CONFDESC_SZ;
#ifdef USE_USB_HS
__ALIGN_BEGIN static uint8_t USBD_CMPSIT_HSCfgDesc[USBD_CMPST_MAX_CONFDESC_SZ] __ALIGN_END = {0};
static uint8_t *pCmpstHSConfDesc = USBD_CMPSIT_HSCfgDesc;
/* Variable that dynamically holds the current size of the configuration descriptor */
static __IO uint32_t CurrHSConfDescSz = 0U;
#endif /* USE_USB_HS */
/* USB Standard Device Descriptor */
__ALIGN_BEGIN static uint8_t USBD_CMPSIT_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END =
{
USB_LEN_DEV_QUALIFIER_DESC, /* bLength */
USB_DESC_TYPE_DEVICE_QUALIFIER, /* bDescriptorType */
0x00, /* bcdDevice low */
0x02, /* bcdDevice high */
0xEF, /* Class */
0x02, /* SubClass */
0x01, /* Protocol */
0x40, /* bMaxPacketSize0 */
0x01, /* bNumConfigurations */
0x00, /* bReserved */
};
/**
* @}
*/
/** @defgroup CMPSIT_CORE_Private_Functions
* @{
*/
/**
* @brief USBD_CMPSIT_AddClass
* Register a class in the class builder
* @param pdev: device instance
* @param pclass: pointer to the class structure to be added
* @param class: type of the class to be added (from USBD_CompositeClassTypeDef)
* @param cfgidx: configuration index
* @retval status
*/
uint8_t USBD_CMPSIT_AddClass(USBD_HandleTypeDef *pdev,
USBD_ClassTypeDef *pclass,
USBD_CompositeClassTypeDef class,
uint8_t cfgidx)
{
switch(class)
{
case CLASS_TYPE_CDC:{
pdev->tclasslist[pdev->classId].ClassType = CLASS_TYPE_CDC;
pdev->tclasslist[pdev->classId].Active = 1U;
pdev->tclasslist[pdev->classId].NumEps = 3;
pdev->tclasslist[pdev->classId].Eps[0].add = CDC_CMD_EP;
pdev->tclasslist[pdev->classId].Eps[0].type = USBD_EP_TYPE_INTR;
pdev->tclasslist[pdev->classId].Eps[0].size = CDC_CMD_PACKET_SIZE;
pdev->tclasslist[pdev->classId].Eps[0].is_used = 1U;
pdev->tclasslist[pdev->classId].Eps[1].add = CDC_OUT_EP;
pdev->tclasslist[pdev->classId].Eps[1].type = USBD_EP_TYPE_BULK;
pdev->tclasslist[pdev->classId].Eps[1].size = CDC_DATA_FS_MAX_PACKET_SIZE;
pdev->tclasslist[pdev->classId].Eps[1].is_used = 1U;
pdev->tclasslist[pdev->classId].Eps[2].add = CDC_IN_EP;
pdev->tclasslist[pdev->classId].Eps[2].type = USBD_EP_TYPE_BULK;
pdev->tclasslist[pdev->classId].Eps[2].size = CDC_DATA_FS_MAX_PACKET_SIZE;
pdev->tclasslist[pdev->classId].Eps[2].is_used = 1U;
pdev->tclasslist[pdev->classId].NumIf = 2;
pdev->tclasslist[pdev->classId].Ifs[0] = 0;
pdev->tclasslist[pdev->classId].Ifs[1] = 1;
}break;
case CLASS_TYPE_MSC:{
pdev->tclasslist[pdev->classId].ClassType = CLASS_TYPE_MSC;
pdev->tclasslist[pdev->classId].Active = 1U;
pdev->tclasslist[pdev->classId].NumEps = 2;
pdev->tclasslist[pdev->classId].Eps[0].add = MSC_EPIN_ADDR;
pdev->tclasslist[pdev->classId].Eps[0].type = USBD_EP_TYPE_BULK;
pdev->tclasslist[pdev->classId].Eps[0].size = MSC_MAX_FS_PACKET;
pdev->tclasslist[pdev->classId].Eps[0].is_used = 1U;
pdev->tclasslist[pdev->classId].Eps[1].add = MSC_EPOUT_ADDR;
pdev->tclasslist[pdev->classId].Eps[1].type = USBD_EP_TYPE_BULK;
pdev->tclasslist[pdev->classId].Eps[1].size = MSC_MAX_FS_PACKET;
pdev->tclasslist[pdev->classId].Eps[1].is_used = 1U;
pdev->tclasslist[pdev->classId].NumIf = 1;
pdev->tclasslist[pdev->classId].Ifs[0] = 2;
}break;
default:break;
}
pdev->tclasslist[pdev->classId].CurrPcktSze = 0U;
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_CMPSIT_AddToConfDesc
* Add a new class to the configuration descriptor
* @param pdev: device instance
* @retval status
*/
uint8_t USBD_CMPSIT_AddToConfDesc(USBD_HandleTypeDef *pdev)
{
uint8_t idxIf = 0U;
uint8_t iEp = 0U;
/* For the first class instance, start building the config descriptor common part */
if (pdev->classId == 0U)
{
/* Add configuration and IAD descriptors */
USBD_CMPSIT_AddConfDesc((uint32_t)pCmpstFSConfDesc, &CurrFSConfDescSz);
#ifdef USE_USB_HS
USBD_CMPSIT_AddConfDesc((uint32_t)pCmpstHSConfDesc, &CurrHSConfDescSz);
#endif /* USE_USB_HS */
}
switch (pdev->tclasslist[pdev->classId].ClassType)
{
#if USBD_CMPSIT_ACTIVATE_HID == 1
case CLASS_TYPE_HID:
/* Setup Max packet sizes (for HID, no dependency on USB Speed, both HS/FS have same packet size) */
pdev->tclasslist[pdev->classId].CurrPcktSze = HID_EPIN_SIZE;
/* Find the first available interface slot and Assign number of interfaces */
idxIf = USBD_CMPSIT_FindFreeIFNbr(pdev);
pdev->tclasslist[pdev->classId].NumIf = 1U;
pdev->tclasslist[pdev->classId].Ifs[0] = idxIf;
/* Assign endpoint numbers */
pdev->tclasslist[pdev->classId].NumEps = 1U; /* EP1_IN */
/* Set IN endpoint slot */
iEp = pdev->tclasslist[pdev->classId].EpAdd[0];
/* Assign IN Endpoint */
USBD_CMPSIT_AssignEp(pdev, iEp, USBD_EP_TYPE_INTR, pdev->tclasslist[pdev->classId].CurrPcktSze);
/* Configure and Append the Descriptor */
USBD_CMPSIT_HIDMouseDesc(pdev, (uint32_t)pCmpstFSConfDesc, &CurrFSConfDescSz, (uint8_t)USBD_SPEED_FULL);
#ifdef USE_USB_HS
USBD_CMPSIT_HIDMouseDesc(pdev, (uint32_t)pCmpstHSConfDesc, &CurrHSConfDescSz, (uint8_t)USBD_SPEED_HIGH);
#endif /* USE_USB_HS */
break;
#endif /* USBD_CMPSIT_ACTIVATE_HID */
#if USBD_CMPSIT_ACTIVATE_MSC == 1
case CLASS_TYPE_MSC:
/* Setup default Max packet size */
pdev->tclasslist[pdev->classId].CurrPcktSze = MSC_MAX_FS_PACKET;
/* Find the first available interface slot and Assign number of interfaces */
idxIf = USBD_CMPSIT_FindFreeIFNbr(pdev);
pdev->tclasslist[pdev->classId].NumIf = 1U;
pdev->tclasslist[pdev->classId].Ifs[0] = idxIf;
/* Assign endpoint numbers */
pdev->tclasslist[pdev->classId].NumEps = 2U; /* EP1_IN, EP1_OUT */
/* Set IN endpoint slot */
iEp = pdev->tclasslist[pdev->classId].EpAdd[0];
USBD_CMPSIT_AssignEp(pdev, iEp, USBD_EP_TYPE_BULK, pdev->tclasslist[pdev->classId].CurrPcktSze);
/* Set OUT endpoint slot */
iEp = pdev->tclasslist[pdev->classId].EpAdd[1];
USBD_CMPSIT_AssignEp(pdev, iEp, USBD_EP_TYPE_BULK, pdev->tclasslist[pdev->classId].CurrPcktSze);
/* Configure and Append the Descriptor */
USBD_CMPSIT_MSCDesc(pdev, (uint32_t)pCmpstFSConfDesc, &CurrFSConfDescSz, (uint8_t)USBD_SPEED_FULL);
#ifdef USE_USB_HS
USBD_CMPSIT_MSCDesc(pdev, (uint32_t)pCmpstHSConfDesc, &CurrHSConfDescSz, (uint8_t)USBD_SPEED_HIGH);
#endif /* USE_USB_HS */
break;
#endif /* USBD_CMPSIT_ACTIVATE_MSC */
#if USBD_CMPSIT_ACTIVATE_CDC == 1
case CLASS_TYPE_CDC:
/* Setup default Max packet size for FS device */
pdev->tclasslist[pdev->classId].CurrPcktSze = CDC_DATA_FS_MAX_PACKET_SIZE;
/* Find the first available interface slot and Assign number of interfaces */
idxIf = USBD_CMPSIT_FindFreeIFNbr(pdev);
pdev->tclasslist[pdev->classId].NumIf = 2U;
pdev->tclasslist[pdev->classId].Ifs[0] = idxIf;
pdev->tclasslist[pdev->classId].Ifs[1] = (uint8_t)(idxIf + 1U);
/* Assign endpoint numbers */
pdev->tclasslist[pdev->classId].NumEps = 3U;
/* Set IN endpoint slot */
iEp = pdev->tclasslist[pdev->classId].EpAdd[0];
USBD_CMPSIT_AssignEp(pdev, iEp, USBD_EP_TYPE_BULK, pdev->tclasslist[pdev->classId].CurrPcktSze);
/* Set OUT endpoint slot */
iEp = pdev->tclasslist[pdev->classId].EpAdd[1];
USBD_CMPSIT_AssignEp(pdev, iEp, USBD_EP_TYPE_BULK, pdev->tclasslist[pdev->classId].CurrPcktSze);
/* Set the second IN endpoint slot */
iEp = pdev->tclasslist[pdev->classId].EpAdd[2];
USBD_CMPSIT_AssignEp(pdev, iEp, USBD_EP_TYPE_INTR, CDC_CMD_PACKET_SIZE);
/* Configure and Append the Descriptor */
USBD_CMPSIT_CDCDesc(pdev, (uint32_t)pCmpstFSConfDesc, &CurrFSConfDescSz, (uint8_t)USBD_SPEED_FULL);
#ifdef USE_USB_HS
USBD_CMPSIT_CDCDesc(pdev, (uint32_t)pCmpstHSConfDesc, &CurrHSConfDescSz, (uint8_t)USBD_SPEED_HIGH);
#endif /* USE_USB_HS */
break;
#endif /* USBD_CMPSIT_ACTIVATE_CDC */
#if USBD_CMPSIT_ACTIVATE_DFU == 1
case CLASS_TYPE_DFU:
/* Setup Max packet sizes (for DFU, no dependency on USB Speed, both HS/FS have same packet size) */
pdev->tclasslist[pdev->classId].CurrPcktSze = 64U;
/* Find the first available interface slot and Assign number of interfaces */
idxIf = USBD_CMPSIT_FindFreeIFNbr(pdev);
pdev->tclasslist[pdev->classId].NumIf = 1U;
pdev->tclasslist[pdev->classId].Ifs[0] = idxIf;
/* Assign endpoint numbers */
pdev->tclasslist[pdev->classId].NumEps = 0U; /* only EP0 is used */
/* Configure and Append the Descriptor */
USBD_CMPSIT_DFUDesc(pdev, (uint32_t)pCmpstFSConfDesc, &CurrFSConfDescSz, (uint8_t)USBD_SPEED_FULL);
#ifdef USE_USB_HS
USBD_CMPSIT_DFUDesc(pdev, (uint32_t)pCmpstHSConfDesc, &CurrHSConfDescSz, (uint8_t)USBD_SPEED_HIGH);
#endif /* USE_USB_HS */
break;
#endif /* USBD_CMPSIT_ACTIVATE_DFU */
#if USBD_CMPSIT_ACTIVATE_RNDIS == 1
case CLASS_TYPE_RNDIS:
/* Setup default Max packet size */
pdev->tclasslist[pdev->classId].CurrPcktSze = CDC_RNDIS_DATA_FS_MAX_PACKET_SIZE;
/* Find the first available interface slot and Assign number of interfaces */
idxIf = USBD_CMPSIT_FindFreeIFNbr(pdev);
pdev->tclasslist[pdev->classId].NumIf = 2U;
pdev->tclasslist[pdev->classId].Ifs[0] = idxIf;
pdev->tclasslist[pdev->classId].Ifs[1] = (uint8_t)(idxIf + 1U);
/* Assign endpoint numbers */
pdev->tclasslist[pdev->classId].NumEps = 3U;
/* Set IN endpoint slot */
iEp = pdev->tclasslist[pdev->classId].EpAdd[0];
USBD_CMPSIT_AssignEp(pdev, iEp, USBD_EP_TYPE_BULK, pdev->tclasslist[pdev->classId].CurrPcktSze);
/* Set OUT endpoint slot */
iEp = pdev->tclasslist[pdev->classId].EpAdd[1];
USBD_CMPSIT_AssignEp(pdev, iEp, USBD_EP_TYPE_BULK, pdev->tclasslist[pdev->classId].CurrPcktSze);
/* Set the second IN endpoint slot */
iEp = pdev->tclasslist[pdev->classId].EpAdd[2];
USBD_CMPSIT_AssignEp(pdev, iEp, USBD_EP_TYPE_INTR, CDC_RNDIS_CMD_PACKET_SIZE);
/* Configure and Append the Descriptor */
USBD_CMPSIT_RNDISDesc(pdev, (uint32_t)pCmpstFSConfDesc, &CurrFSConfDescSz, (uint8_t)USBD_SPEED_FULL);
#ifdef USE_USB_HS
USBD_CMPSIT_RNDISDesc(pdev, (uint32_t)pCmpstHSConfDesc, &CurrHSConfDescSz, (uint8_t)USBD_SPEED_HIGH);
#endif /* USE_USB_HS */
break;
#endif /* USBD_CMPSIT_ACTIVATE_RNDIS */
#if USBD_CMPSIT_ACTIVATE_CDC_ECM == 1
case CLASS_TYPE_ECM:
/* Setup default Max packet size */
pdev->tclasslist[pdev->classId].CurrPcktSze = CDC_ECM_DATA_FS_MAX_PACKET_SIZE;
/* Find the first available interface slot and Assign number of interfaces */
idxIf = USBD_CMPSIT_FindFreeIFNbr(pdev);
pdev->tclasslist[pdev->classId].NumIf = 2U;
pdev->tclasslist[pdev->classId].Ifs[0] = idxIf;
pdev->tclasslist[pdev->classId].Ifs[1] = (uint8_t)(idxIf + 1U);
/* Assign endpoint numbers */
pdev->tclasslist[pdev->classId].NumEps = 3U; /* EP1_IN, EP1_OUT,CMD_EP2 */
/* Set IN endpoint slot */
iEp = pdev->tclasslist[pdev->classId].EpAdd[0];
USBD_CMPSIT_AssignEp(pdev, iEp, USBD_EP_TYPE_BULK, pdev->tclasslist[pdev->classId].CurrPcktSze);
/* Set OUT endpoint slot */
iEp = pdev->tclasslist[pdev->classId].EpAdd[1];
USBD_CMPSIT_AssignEp(pdev, iEp, USBD_EP_TYPE_BULK, pdev->tclasslist[pdev->classId].CurrPcktSze);
/* Set the second IN endpoint slot */
iEp = pdev->tclasslist[pdev->classId].EpAdd[2];
USBD_CMPSIT_AssignEp(pdev, iEp, USBD_EP_TYPE_INTR, CDC_ECM_CMD_PACKET_SIZE);
/* Configure and Append the Descriptor */
USBD_CMPSIT_CDC_ECMDesc(pdev, (uint32_t)pCmpstFSConfDesc, &CurrFSConfDescSz, (uint8_t)USBD_SPEED_FULL);
#ifdef USE_USB_HS
USBD_CMPSIT_CDC_ECMDesc(pdev, (uint32_t)pCmpstHSConfDesc, &CurrHSConfDescSz, (uint8_t)USBD_SPEED_HIGH);
#endif /* USE_USB_HS */
break;
#endif /* USBD_CMPSIT_ACTIVATE_CDC_ECM */
#if USBD_CMPSIT_ACTIVATE_AUDIO == 1
case CLASS_TYPE_AUDIO:
/* Setup Max packet sizes*/
pdev->tclasslist[pdev->classId].CurrPcktSze = USBD_AUDIO_GetEpPcktSze(pdev, 0U, 0U);
/* Find the first available interface slot and Assign number of interfaces */
idxIf = USBD_CMPSIT_FindFreeIFNbr(pdev);
pdev->tclasslist[pdev->classId].NumIf = 2U;
pdev->tclasslist[pdev->classId].Ifs[0] = idxIf;
pdev->tclasslist[pdev->classId].Ifs[1] = (uint8_t)(idxIf + 1U);
/* Assign endpoint numbers */
pdev->tclasslist[pdev->classId].NumEps = 1U; /* EP1_OUT*/
/* Set OUT endpoint slot */
iEp = pdev->tclasslist[pdev->classId].EpAdd[0];
/* Assign OUT Endpoint */
USBD_CMPSIT_AssignEp(pdev, iEp, USBD_EP_TYPE_ISOC, pdev->tclasslist[pdev->classId].CurrPcktSze);
/* Configure and Append the Descriptor (only FS mode supported) */
USBD_CMPSIT_AUDIODesc(pdev, (uint32_t)pCmpstFSConfDesc, &CurrFSConfDescSz, (uint8_t)USBD_SPEED_FULL);
break;
#endif /* USBD_CMPSIT_ACTIVATE_AUDIO */
#if USBD_CMPSIT_ACTIVATE_CUSTOMHID == 1
case CLASS_TYPE_CHID:
/* Setup Max packet sizes */
pdev->tclasslist[pdev->classId].CurrPcktSze = CUSTOM_HID_EPOUT_SIZE;
/* Find the first available interface slot and Assign number of interfaces */
idxIf = USBD_CMPSIT_FindFreeIFNbr(pdev);
pdev->tclasslist[pdev->classId].NumIf = 1U;
pdev->tclasslist[pdev->classId].Ifs[0] = idxIf;
/* Assign endpoint numbers */
pdev->tclasslist[pdev->classId].NumEps = 2U; /* EP1_IN, EP1_OUT */
/* Set IN endpoint slot */
iEp = pdev->tclasslist[pdev->classId].EpAdd[0];
USBD_CMPSIT_AssignEp(pdev, iEp, USBD_EP_TYPE_INTR, pdev->tclasslist[pdev->classId].CurrPcktSze);
/* Set OUT endpoint slot */
iEp = pdev->tclasslist[pdev->classId].EpAdd[1];
USBD_CMPSIT_AssignEp(pdev, iEp, USBD_EP_TYPE_INTR, pdev->tclasslist[pdev->classId].CurrPcktSze);
/* Configure and Append the Descriptor */
USBD_CMPSIT_CUSTOMHIDDesc(pdev, (uint32_t)pCmpstFSConfDesc, &CurrFSConfDescSz, (uint8_t)USBD_SPEED_FULL);
#ifdef USE_USB_HS
USBD_CMPSIT_CUSTOMHIDDesc(pdev, (uint32_t)pCmpstHSConfDesc, &CurrHSConfDescSz, (uint8_t)USBD_SPEED_HIGH);
#endif /* USE_USB_HS */
break;
#endif /* USBD_CMPSIT_ACTIVATE_CUSTOMHID */
#if USBD_CMPSIT_ACTIVATE_VIDEO == 1
case CLASS_TYPE_VIDEO:
/* Setup default Max packet size */
pdev->tclasslist[pdev->classId].CurrPcktSze = UVC_ISO_FS_MPS;
/* Find the first available interface slot and Assign number of interfaces */
idxIf = USBD_CMPSIT_FindFreeIFNbr(pdev);
pdev->tclasslist[pdev->classId].NumIf = 2U;
pdev->tclasslist[pdev->classId].Ifs[0] = idxIf;
pdev->tclasslist[pdev->classId].Ifs[1] = (uint8_t)(idxIf + 1U);
/* Assign endpoint numbers */
pdev->tclasslist[pdev->classId].NumEps = 1U; /* EP1_IN */
/* Set IN endpoint slot */
iEp = pdev->tclasslist[pdev->classId].EpAdd[0];
/* Assign IN Endpoint */
USBD_CMPSIT_AssignEp(pdev, iEp, USBD_EP_TYPE_ISOC, pdev->tclasslist[pdev->classId].CurrPcktSze);
/* Configure and Append the Descriptor */
USBD_CMPSIT_VIDEODesc(pdev, (uint32_t)pCmpstFSConfDesc, &CurrFSConfDescSz, (uint8_t)USBD_SPEED_FULL);
#ifdef USE_USB_HS
USBD_CMPSIT_VIDEODesc(pdev, (uint32_t)pCmpstHSConfDesc, &CurrHSConfDescSz, (uint8_t)USBD_SPEED_HIGH);
#endif /* USE_USB_HS */
break;
#endif /* USBD_CMPSIT_ACTIVATE_VIDEO */
#if USBD_CMPSIT_ACTIVATE_PRINTER == 1
case CLASS_TYPE_PRINTER:
/* Setup default Max packet size */
pdev->tclasslist[pdev->classId].CurrPcktSze = PRNT_DATA_FS_MAX_PACKET_SIZE;
/* Find the first available interface slot and Assign number of interfaces */
idxIf = USBD_CMPSIT_FindFreeIFNbr(pdev);
pdev->tclasslist[pdev->classId].NumIf = 1U;
pdev->tclasslist[pdev->classId].Ifs[0] = idxIf;
/* Assign endpoint numbers */
pdev->tclasslist[pdev->classId].NumEps = 2U;
/* Set IN endpoint slot */
iEp = pdev->tclasslist[pdev->classId].EpAdd[0];
USBD_CMPSIT_AssignEp(pdev, iEp, USBD_EP_TYPE_BULK, pdev->tclasslist[pdev->classId].CurrPcktSze);
/* Set OUT endpoint slot */
iEp = pdev->tclasslist[pdev->classId].EpAdd[1];
USBD_CMPSIT_AssignEp(pdev, iEp, USBD_EP_TYPE_BULK, pdev->tclasslist[pdev->classId].CurrPcktSze);
/* Configure and Append the Descriptor */
USBD_CMPSIT_PRNTDesc(pdev, (uint32_t)pCmpstFSConfDesc, &CurrFSConfDescSz, (uint8_t)USBD_SPEED_FULL);
#ifdef USE_USB_HS
USBD_CMPSIT_PRNTDesc(pdev, (uint32_t)pCmpstHSConfDesc, &CurrHSConfDescSz, (uint8_t)USBD_SPEED_HIGH);
#endif /* USE_USB_HS */
break;
#endif /* USBD_CMPSIT_ACTIVATE_PRINTER */
#if USBD_CMPSIT_ACTIVATE_CCID == 1
case CLASS_TYPE_CCID:
/* Setup default Max packet size */
pdev->tclasslist[pdev->classId].CurrPcktSze = CCID_DATA_FS_MAX_PACKET_SIZE;
/* Find the first available interface slot and Assign number of interfaces */
idxIf = USBD_CMPSIT_FindFreeIFNbr(pdev);
pdev->tclasslist[pdev->classId].NumIf = 1U;
pdev->tclasslist[pdev->classId].Ifs[0] = idxIf;
/* Assign endpoint numbers */
pdev->tclasslist[pdev->classId].NumEps = 3U;
/* Set IN endpoint slot */
iEp = pdev->tclasslist[pdev->classId].EpAdd[0];
USBD_CMPSIT_AssignEp(pdev, iEp, USBD_EP_TYPE_BULK, pdev->tclasslist[pdev->classId].CurrPcktSze);
/* Set OUT endpoint slot */
iEp = pdev->tclasslist[pdev->classId].EpAdd[1];
USBD_CMPSIT_AssignEp(pdev, iEp, USBD_EP_TYPE_BULK, pdev->tclasslist[pdev->classId].CurrPcktSze);
/* Set the second IN endpoint slot */
iEp = pdev->tclasslist[pdev->classId].EpAdd[2];
USBD_CMPSIT_AssignEp(pdev, iEp, USBD_EP_TYPE_INTR, CCID_CMD_PACKET_SIZE);
/* Configure and Append the Descriptor */
USBD_CMPSIT_CCIDDesc(pdev, (uint32_t)pCmpstFSConfDesc, &CurrFSConfDescSz, (uint8_t)USBD_SPEED_FULL);
#ifdef USE_USB_HS
USBD_CMPSIT_CCIDDesc(pdev, (uint32_t)pCmpstHSConfDesc, &CurrHSConfDescSz, (uint8_t)USBD_SPEED_HIGH);
#endif /* USE_USB_HS */
break;
#endif /* USBD_CMPSIT_ACTIVATE_CCID */
#if USBD_CMPSIT_ACTIVATE_MTP == 1
case CLASS_TYPE_MTP:
/* Setup default Max packet sizes */
pdev->tclasslist[pdev->classId].CurrPcktSze = MTP_DATA_MAX_FS_PACKET_SIZE;
/* Find the first available interface slot and Assign number of interfaces */
idxIf = USBD_CMPSIT_FindFreeIFNbr(pdev);
pdev->tclasslist[pdev->classId].NumIf = 1U;
pdev->tclasslist[pdev->classId].Ifs[0] = idxIf;
/* Assign endpoint numbers */
pdev->tclasslist[pdev->classId].NumEps = 3U;
/* Set IN endpoint slot */
iEp = pdev->tclasslist[pdev->classId].EpAdd[0];
USBD_CMPSIT_AssignEp(pdev, iEp, USBD_EP_TYPE_BULK, pdev->tclasslist[pdev->classId].CurrPcktSze);
/* Set OUT endpoint slot */
iEp = pdev->tclasslist[pdev->classId].EpAdd[1];
USBD_CMPSIT_AssignEp(pdev, iEp, USBD_EP_TYPE_BULK, pdev->tclasslist[pdev->classId].CurrPcktSze);
/* Set the second IN endpoint slot */
iEp = pdev->tclasslist[pdev->classId].EpAdd[2];
USBD_CMPSIT_AssignEp(pdev, iEp, USBD_EP_TYPE_INTR, MTP_CMD_PACKET_SIZE);
/* Configure and Append the Descriptor */
USBD_CMPSIT_MTPDesc(pdev, (uint32_t)pCmpstFSConfDesc, &CurrFSConfDescSz, (uint8_t)USBD_SPEED_FULL);
#ifdef USE_USB_HS
USBD_CMPSIT_MTPDesc(pdev, (uint32_t)pCmpstHSConfDesc, &CurrHSConfDescSz, (uint8_t)USBD_SPEED_HIGH);
#endif /* USE_USB_HS */
break;
#endif /* USBD_CMPSIT_ACTIVATE_MTP */
default:
UNUSED(idxIf);
UNUSED(iEp);
UNUSED(USBD_CMPSIT_FindFreeIFNbr);
UNUSED(USBD_CMPSIT_AssignEp);
break;
}
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_CMPSIT_GetFSCfgDesc
* return configuration descriptor for both FS and HS modes
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
uint8_t *USBD_CMPSIT_GetFSCfgDesc(uint16_t *length)
{
*length = (uint16_t)CurrFSConfDescSz;
return USBD_CMPSIT_FSCfgDesc;
}
#ifdef USE_USB_HS
/**
* @brief USBD_CMPSIT_GetHSCfgDesc
* return configuration descriptor for both FS and HS modes
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
uint8_t *USBD_CMPSIT_GetHSCfgDesc(uint16_t *length)
{
*length = (uint16_t)CurrHSConfDescSz;
return USBD_CMPSIT_HSCfgDesc;
}
#endif /* USE_USB_HS */
/**
* @brief USBD_CMPSIT_GetOtherSpeedCfgDesc
* return other speed configuration descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
uint8_t *USBD_CMPSIT_GetOtherSpeedCfgDesc(uint16_t *length)
{
*length = (uint16_t)CurrFSConfDescSz;
return USBD_CMPSIT_FSCfgDesc;
}
/**
* @brief DeviceQualifierDescriptor
* return Device Qualifier descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
uint8_t *USBD_CMPSIT_GetDeviceQualifierDescriptor(uint16_t *length)
{
*length = (uint16_t)(sizeof(USBD_CMPSIT_DeviceQualifierDesc));
return USBD_CMPSIT_DeviceQualifierDesc;
}
/**
* @brief USBD_CMPSIT_FindFreeIFNbr
* Find the first interface available slot
* @param pdev: device instance
* @retval The interface number to be used
*/
static uint8_t USBD_CMPSIT_FindFreeIFNbr(USBD_HandleTypeDef *pdev)
{
uint32_t idx = 0U;
/* Unroll all already activated classes */
for (uint32_t i = 0U; i < pdev->NumClasses; i++)
{
/* Unroll each class interfaces */
for (uint32_t j = 0U; j < pdev->tclasslist[i].NumIf; j++)
{
/* Increment the interface counter index */
idx++;
}
}
/* Return the first available interface slot */
return (uint8_t)idx;
}
/**
* @brief USBD_CMPSIT_AddToConfDesc
* Add a new class to the configuration descriptor
* @param pdev: device instance
* @retval none
*/
static void USBD_CMPSIT_AddConfDesc(uint32_t Conf, __IO uint32_t *pSze)
{
/* Intermediate variable to comply with MISRA-C Rule 11.3 */
USBD_ConfigDescTypeDef *ptr = (USBD_ConfigDescTypeDef *)Conf;
ptr->bLength = (uint8_t)sizeof(USBD_ConfigDescTypeDef);
ptr->bDescriptorType = USB_DESC_TYPE_CONFIGURATION;
ptr->wTotalLength = 0U;
ptr->bNumInterfaces = 0U;
ptr->bConfigurationValue = 1U;
ptr->iConfiguration = USBD_CONFIG_STR_DESC_IDX;
#if (USBD_SELF_POWERED == 1U)
ptr->bmAttributes = 0xC0U; /* bmAttributes: Self Powered according to user configuration */
#else
ptr->bmAttributes = 0x80U; /* bmAttributes: Bus Powered according to user configuration */
#endif /* USBD_SELF_POWERED */
ptr->bMaxPower = USBD_MAX_POWER;
*pSze += sizeof(USBD_ConfigDescTypeDef);
}
/**
* @brief USBD_CMPSIT_AssignEp
* Assign and endpoint
* @param pdev: device instance
* @param Add: Endpoint address
* @param Type: Endpoint type
* @param Sze: Endpoint max packet size
* @retval none
*/
static void USBD_CMPSIT_AssignEp(USBD_HandleTypeDef *pdev, uint8_t Add, uint8_t Type, uint32_t Sze)
{
uint32_t idx = 0U;
/* Find the first available endpoint slot */
while (((idx < (pdev->tclasslist[pdev->classId]).NumEps) && \
((pdev->tclasslist[pdev->classId].Eps[idx].is_used) != 0U)))
{
/* Increment the index */
idx++;
}
/* Configure the endpoint */
pdev->tclasslist[pdev->classId].Eps[idx].add = Add;
pdev->tclasslist[pdev->classId].Eps[idx].type = Type;
pdev->tclasslist[pdev->classId].Eps[idx].size = (uint8_t)Sze;
pdev->tclasslist[pdev->classId].Eps[idx].is_used = 1U;
}
#if USBD_CMPSIT_ACTIVATE_HID == 1
/**
* @brief USBD_CMPSIT_HIDMouseDesc
* Configure and Append the HID Mouse Descriptor
* @param pdev: device instance
* @param pConf: Configuration descriptor pointer
* @param Sze: pointer to the current configuration descriptor size
* @retval None
*/
static void USBD_CMPSIT_HIDMouseDesc(USBD_HandleTypeDef *pdev, uint32_t pConf,
__IO uint32_t *Sze, uint8_t speed)
{
static USBD_IfDescTypeDef *pIfDesc;
static USBD_EpDescTypeDef *pEpDesc;
static USBD_HIDDescTypeDef *pHidMouseDesc;
/* Append HID Interface descriptor to Configuration descriptor */
__USBD_CMPSIT_SET_IF(pdev->tclasslist[pdev->classId].Ifs[0], 0U, \
(uint8_t)(pdev->tclasslist[pdev->classId].NumEps), 0x03U, 0x01U, 0x02U, 0U);
/* Append HID Functional descriptor to Configuration descriptor */
pHidMouseDesc = ((USBD_HIDDescTypeDef *)(pConf + *Sze));
pHidMouseDesc->bLength = (uint8_t)sizeof(USBD_HIDDescTypeDef);
pHidMouseDesc->bDescriptorType = HID_DESCRIPTOR_TYPE;
pHidMouseDesc->bcdHID = 0x0111U;
pHidMouseDesc->bCountryCode = 0x00U;
pHidMouseDesc->bNumDescriptors = 0x01U;
pHidMouseDesc->bHIDDescriptorType = 0x22U;
pHidMouseDesc->wItemLength = HID_MOUSE_REPORT_DESC_SIZE;
*Sze += (uint32_t)sizeof(USBD_HIDDescTypeDef);
/* Append Endpoint descriptor to Configuration descriptor */
__USBD_CMPSIT_SET_EP(pdev->tclasslist[pdev->classId].Eps[0].add, USBD_EP_TYPE_INTR, HID_EPIN_SIZE, \
HID_HS_BINTERVAL, HID_FS_BINTERVAL);
/* Update Config Descriptor and IAD descriptor */
((USBD_ConfigDescTypeDef *)pConf)->bNumInterfaces += 1U;
((USBD_ConfigDescTypeDef *)pConf)->wTotalLength = (uint16_t)(*Sze);
}
#endif /* USBD_CMPSIT_ACTIVATE_HID == 1 */
#if USBD_CMPSIT_ACTIVATE_MSC == 1
/**
* @brief USBD_CMPSIT_MSCDesc
* Configure and Append the MSC Descriptor
* @param pdev: device instance
* @param pConf: Configuration descriptor pointer
* @param Sze: pointer to the current configuration descriptor size
* @retval None
*/
static void USBD_CMPSIT_MSCDesc(USBD_HandleTypeDef *pdev, uint32_t pConf, __IO uint32_t *Sze, uint8_t speed)
{
USBD_IfDescTypeDef *pIfDesc;
USBD_EpDescTypeDef *pEpDesc;
/* Append MSC Interface descriptor */
__USBD_CMPSIT_SET_IF((pdev->tclasslist[pdev->classId].Ifs[0]), (0U), \
(uint8_t)(pdev->tclasslist[pdev->classId].NumEps), (0x08U), (0x06U), (0x50U), (0U));
if (speed == (uint8_t)USBD_SPEED_HIGH)
{
pdev->tclasslist[pdev->classId].CurrPcktSze = MSC_MAX_HS_PACKET;
}
/* Append Endpoint descriptor to Configuration descriptor */
__USBD_CMPSIT_SET_EP((pdev->tclasslist[pdev->classId].Eps[0].add), (USBD_EP_TYPE_BULK), \
(pdev->tclasslist[pdev->classId].CurrPcktSze), (0U), (0U));
/* Append Endpoint descriptor to Configuration descriptor */
__USBD_CMPSIT_SET_EP((pdev->tclasslist[pdev->classId].Eps[1].add), (USBD_EP_TYPE_BULK), \
(pdev->tclasslist[pdev->classId].CurrPcktSze), (0U), (0U));
/* Update Config Descriptor and IAD descriptor */
((USBD_ConfigDescTypeDef *)pConf)->bNumInterfaces += 1U;
((USBD_ConfigDescTypeDef *)pConf)->wTotalLength = (uint16_t)(*Sze);
}
#endif /* USBD_CMPSIT_ACTIVATE_MSC == 1 */
#if USBD_CMPSIT_ACTIVATE_CDC == 1
/**
* @brief USBD_CMPSIT_MSCDesc
* Configure and Append the HID Mouse Descriptor
* @param pdev: device instance
* @param pConf: Configuration descriptor pointer
* @param Sze: pointer to the current configuration descriptor size
* @retval None
*/
static void USBD_CMPSIT_CDCDesc(USBD_HandleTypeDef *pdev, uint32_t pConf, __IO uint32_t *Sze, uint8_t speed)
{
static USBD_IfDescTypeDef *pIfDesc;
static USBD_EpDescTypeDef *pEpDesc;
static USBD_CDCHeaderFuncDescTypeDef *pHeadDesc;
static USBD_CDCCallMgmFuncDescTypeDef *pCallMgmDesc;
static USBD_CDCACMFuncDescTypeDef *pACMDesc;
static USBD_CDCUnionFuncDescTypeDef *pUnionDesc;
#if USBD_COMPOSITE_USE_IAD == 1
static USBD_IadDescTypeDef *pIadDesc;
#endif /* USBD_COMPOSITE_USE_IAD == 1 */
#if USBD_COMPOSITE_USE_IAD == 1
pIadDesc = ((USBD_IadDescTypeDef *)(pConf + *Sze));
pIadDesc->bLength = (uint8_t)sizeof(USBD_IadDescTypeDef);
pIadDesc->bDescriptorType = USB_DESC_TYPE_IAD; /* IAD descriptor */
pIadDesc->bFirstInterface = pdev->tclasslist[pdev->classId].Ifs[0];
pIadDesc->bInterfaceCount = 2U; /* 2 interfaces */
pIadDesc->bFunctionClass = 0x02U;
pIadDesc->bFunctionSubClass = 0x02U;
pIadDesc->bFunctionProtocol = 0x01U;
pIadDesc->iFunction = 0U; /* String Index */
*Sze += (uint32_t)sizeof(USBD_IadDescTypeDef);
#endif /* USBD_COMPOSITE_USE_IAD == 1 */
/* Control Interface Descriptor */
__USBD_CMPSIT_SET_IF(pdev->tclasslist[pdev->classId].Ifs[0], 0U, 1U, 0x02, 0x02U, 0x01U, 0U);
/* Control interface headers */
pHeadDesc = ((USBD_CDCHeaderFuncDescTypeDef *)((uint32_t)pConf + *Sze));
/* Header Functional Descriptor*/
pHeadDesc->bLength = 0x05U;
pHeadDesc->bDescriptorType = 0x24U;
pHeadDesc->bDescriptorSubtype = 0x00U;
pHeadDesc->bcdCDC = 0x0110U;
*Sze += (uint32_t)sizeof(USBD_CDCHeaderFuncDescTypeDef);
/* Call Management Functional Descriptor */
pCallMgmDesc = ((USBD_CDCCallMgmFuncDescTypeDef *)((uint32_t)pConf + *Sze));
pCallMgmDesc->bLength = 0x05U;
pCallMgmDesc->bDescriptorType = 0x24U;
pCallMgmDesc->bDescriptorSubtype = 0x01U;
pCallMgmDesc->bmCapabilities = 0x00U;
pCallMgmDesc->bDataInterface = pdev->tclasslist[pdev->classId].Ifs[1];
*Sze += (uint32_t)sizeof(USBD_CDCCallMgmFuncDescTypeDef);
/* ACM Functional Descriptor*/
pACMDesc = ((USBD_CDCACMFuncDescTypeDef *)((uint32_t)pConf + *Sze));
pACMDesc->bLength = 0x04U;
pACMDesc->bDescriptorType = 0x24U;
pACMDesc->bDescriptorSubtype = 0x02U;
pACMDesc->bmCapabilities = 0x02U;
*Sze += (uint32_t)sizeof(USBD_CDCACMFuncDescTypeDef);
/* Union Functional Descriptor*/
pUnionDesc = ((USBD_CDCUnionFuncDescTypeDef *)((uint32_t)pConf + *Sze));
pUnionDesc->bLength = 0x05U;
pUnionDesc->bDescriptorType = 0x24U;
pUnionDesc->bDescriptorSubtype = 0x06U;
pUnionDesc->bMasterInterface = pdev->tclasslist[pdev->classId].Ifs[0];
pUnionDesc->bSlaveInterface = pdev->tclasslist[pdev->classId].Ifs[1];
*Sze += (uint32_t)sizeof(USBD_CDCUnionFuncDescTypeDef);
/* Append Endpoint descriptor to Configuration descriptor */
__USBD_CMPSIT_SET_EP(pdev->tclasslist[pdev->classId].Eps[2].add, \
USBD_EP_TYPE_INTR, CDC_CMD_PACKET_SIZE, CDC_HS_BINTERVAL, CDC_FS_BINTERVAL);
/* Data Interface Descriptor */
__USBD_CMPSIT_SET_IF(pdev->tclasslist[pdev->classId].Ifs[1], 0U, 2U, 0x0A, 0U, 0U, 0U);
if (speed == (uint8_t)USBD_SPEED_HIGH)
{
pdev->tclasslist[pdev->classId].CurrPcktSze = CDC_DATA_HS_MAX_PACKET_SIZE;
}
/* Append Endpoint descriptor to Configuration descriptor */
__USBD_CMPSIT_SET_EP((pdev->tclasslist[pdev->classId].Eps[0].add), \
(USBD_EP_TYPE_BULK), (pdev->tclasslist[pdev->classId].CurrPcktSze), (0U), (0U));
/* Append Endpoint descriptor to Configuration descriptor */
__USBD_CMPSIT_SET_EP((pdev->tclasslist[pdev->classId].Eps[1].add), \
(USBD_EP_TYPE_BULK), (pdev->tclasslist[pdev->classId].CurrPcktSze), (0U), (0U));
/* Update Config Descriptor and IAD descriptor */
((USBD_ConfigDescTypeDef *)pConf)->bNumInterfaces += 2U;
((USBD_ConfigDescTypeDef *)pConf)->wTotalLength = (uint16_t)(*Sze);
}
#endif /* USBD_CMPSIT_ACTIVATE_CDC == 1 */
#if USBD_CMPSIT_ACTIVATE_DFU == 1
/**
* @brief USBD_CMPSIT_DFUDesc
* Configure and Append the DFU Descriptor
* @param pdev: device instance
* @param pConf: Configuration descriptor pointer
* @param Sze: pointer to the current configuration descriptor size
* @retval None
*/
static void USBD_CMPSIT_DFUDesc(USBD_HandleTypeDef *pdev, uint32_t pConf, __IO uint32_t *Sze, uint8_t speed)
{
static USBD_IfDescTypeDef *pIfDesc;
static USBD_DFUFuncDescTypeDef *pDFUFuncDesc;
uint32_t idx;
UNUSED(speed);
for (idx = 0U; idx < USBD_DFU_MAX_ITF_NUM; idx++)
{
/* Append DFU Interface descriptor to Configuration descriptor */
__USBD_CMPSIT_SET_IF(pdev->tclasslist[pdev->classId].Ifs[0], (uint8_t)idx, 0U, 0xFEU, 0x01U, 0x02U, \
(uint8_t)USBD_IDX_INTERFACE_STR + 1U + (uint8_t)idx);
}
/* Append DFU Functional descriptor to Configuration descriptor */
pDFUFuncDesc = ((USBD_DFUFuncDescTypeDef *)(pConf + *Sze));
pDFUFuncDesc->bLength = (uint8_t)sizeof(USBD_DFUFuncDescTypeDef);
pDFUFuncDesc->bDescriptorType = DFU_DESCRIPTOR_TYPE;
pDFUFuncDesc->bmAttributes = USBD_DFU_BM_ATTRIBUTES;
pDFUFuncDesc->wDetachTimeout = USBD_DFU_DETACH_TIMEOUT;
pDFUFuncDesc->wTransferSze = USBD_DFU_XFER_SIZE;
pDFUFuncDesc->bcdDFUVersion = 0x011AU;
*Sze += (uint32_t)sizeof(USBD_DFUFuncDescTypeDef);
/* Update Config Descriptor and IAD descriptor */
((USBD_ConfigDescTypeDef *)pConf)->bNumInterfaces += 1U;
((USBD_ConfigDescTypeDef *)pConf)->wTotalLength = (uint16_t)(*Sze);
UNUSED(idx);
}
#endif /* USBD_CMPSIT_ACTIVATE_DFU == 1 */
#if USBD_CMPSIT_ACTIVATE_CDC_ECM == 1
/**
* @brief USBD_CMPSIT_CDC_ECMDesc
* Configure and Append the CDC_ECM Descriptor
* @param pdev: device instance
* @param pConf: Configuration descriptor pointer
* @param Sze: pointer to the current configuration descriptor size
* @retval None
*/
static void USBD_CMPSIT_CDC_ECMDesc(USBD_HandleTypeDef *pdev, uint32_t pConf, __IO uint32_t *Sze, uint8_t speed)
{
static USBD_IfDescTypeDef *pIfDesc;
static USBD_EpDescTypeDef *pEpDesc;
static USBD_ECMFuncDescTypeDef *pFuncDesc;
static USBD_IadDescTypeDef *pIadDesc;
static USBD_CDCHeaderFuncDescTypeDef *pHeadDesc;
static USBD_CDCUnionFuncDescTypeDef *pUnionDesc;
#if USBD_COMPOSITE_USE_IAD == 1
pIadDesc = ((USBD_IadDescTypeDef *)(pConf + *Sze));
pIadDesc->bLength = (uint8_t)sizeof(USBD_IadDescTypeDef);
pIadDesc->bDescriptorType = USB_DESC_TYPE_IAD; /* IAD descriptor */
pIadDesc->bFirstInterface = pdev->tclasslist[pdev->classId].Ifs[0];
pIadDesc->bInterfaceCount = 2U; /* 2 interfaces */
pIadDesc->bFunctionClass = 0x02U;
pIadDesc->bFunctionSubClass = 0x06U;
pIadDesc->bFunctionProtocol = 0x00U;
pIadDesc->iFunction = 0U; /* String Index */
*Sze += (uint32_t)sizeof(USBD_IadDescTypeDef);
#endif /* USBD_COMPOSITE_USE_IAD == 1 */
/* Append ECM Interface descriptor to Configuration descriptor */
__USBD_CMPSIT_SET_IF(pdev->tclasslist[pdev->classId].Ifs[0], 0U, 1U, 0x02U, 0x06U, 0U, 0U);
/* Append ECM header functional descriptor to Configuration descriptor */
pHeadDesc = ((USBD_CDCHeaderFuncDescTypeDef *)(pConf + *Sze));
pHeadDesc->bLength = (uint8_t)sizeof(USBD_CDCHeaderFuncDescTypeDef);
pHeadDesc->bDescriptorType = USBD_FUNC_DESCRIPTOR_TYPE;
pHeadDesc->bDescriptorSubtype = 0x00U;
pHeadDesc->bcdCDC = 0x1000U;
*Sze += (uint32_t)sizeof(USBD_CDCHeaderFuncDescTypeDef);
/* Append ECM functional descriptor to Configuration descriptor */
pFuncDesc = ((USBD_ECMFuncDescTypeDef *)(pConf + *Sze));
pFuncDesc->bFunctionLength = (uint8_t)sizeof(USBD_ECMFuncDescTypeDef);
pFuncDesc->bDescriptorType = USBD_FUNC_DESCRIPTOR_TYPE;
pFuncDesc->bDescriptorSubType = USBD_DESC_SUBTYPE_ACM;
pFuncDesc->iMacAddress = CDC_ECM_MAC_STRING_INDEX;
pFuncDesc->bEthernetStatistics3 = CDC_ECM_ETH_STATS_BYTE3;
pFuncDesc->bEthernetStatistics2 = CDC_ECM_ETH_STATS_BYTE2;
pFuncDesc->bEthernetStatistics1 = CDC_ECM_ETH_STATS_BYTE1;
pFuncDesc->bEthernetStatistics0 = CDC_ECM_ETH_STATS_BYTE0;
pFuncDesc->wMaxSegmentSize = CDC_ECM_ETH_MAX_SEGSZE;
pFuncDesc->bNumberMCFiltes = CDC_ECM_ETH_NBR_MACFILTERS;
pFuncDesc->bNumberPowerFiltes = CDC_ECM_ETH_NBR_PWRFILTERS;
*Sze += (uint32_t)sizeof(USBD_ECMFuncDescTypeDef);
/* Append ECM Union functional descriptor to Configuration descriptor */
pUnionDesc = ((USBD_CDCUnionFuncDescTypeDef *)(pConf + *Sze));
pUnionDesc->bLength = (uint8_t)sizeof(USBD_CDCUnionFuncDescTypeDef);
pUnionDesc->bDescriptorType = 0x24U;
pUnionDesc->bDescriptorSubtype = 0x06U;
pUnionDesc->bMasterInterface = pdev->tclasslist[pdev->classId].Ifs[0];
pUnionDesc->bSlaveInterface = pdev->tclasslist[pdev->classId].Ifs[1];
*Sze += (uint32_t)sizeof(USBD_CDCUnionFuncDescTypeDef);
/* Append ECM Communication IN Endpoint Descriptor to Configuration descriptor */
__USBD_CMPSIT_SET_EP(pdev->tclasslist[pdev->classId].Eps[2].add, USBD_EP_TYPE_INTR, CDC_ECM_CMD_PACKET_SIZE, \
CDC_ECM_HS_BINTERVAL, CDC_ECM_FS_BINTERVAL);
/* Append ECM Data class interface descriptor to Configuration descriptor */
__USBD_CMPSIT_SET_IF(pdev->tclasslist[pdev->classId].Ifs[1], 0U, 2U, 0x0AU, 0U, 0U, 0U);
if (speed == (uint8_t)USBD_SPEED_HIGH)
{
pdev->tclasslist[pdev->classId].CurrPcktSze = CDC_ECM_DATA_HS_MAX_PACKET_SIZE;
}
/* Append ECM OUT Endpoint Descriptor to Configuration descriptor */
__USBD_CMPSIT_SET_EP((pdev->tclasslist[pdev->classId].Eps[0].add), (USBD_EP_TYPE_BULK), \
(pdev->tclasslist[pdev->classId].CurrPcktSze), (CDC_ECM_HS_BINTERVAL), (CDC_ECM_FS_BINTERVAL));
/* Append ECM IN Endpoint Descriptor to Configuration descriptor */
__USBD_CMPSIT_SET_EP((pdev->tclasslist[pdev->classId].Eps[1].add), (USBD_EP_TYPE_BULK), \
(pdev->tclasslist[pdev->classId].CurrPcktSze), (CDC_ECM_HS_BINTERVAL), (CDC_ECM_FS_BINTERVAL));
/* Update Config Descriptor and IAD descriptor */
((USBD_ConfigDescTypeDef *)pConf)->bNumInterfaces += 2U;
((USBD_ConfigDescTypeDef *)pConf)->wTotalLength = (uint16_t)(*Sze);
}
#endif /* USBD_CMPSIT_ACTIVATE_CDC_ECM */
#if USBD_CMPSIT_ACTIVATE_AUDIO == 1
/**
* @brief USBD_CMPSIT_AUDIODesc
* Configure and Append the AUDIO Descriptor
* @param pdev: device instance
* @param pConf: Configuration descriptor pointer
* @param Sze: pointer to the current configuration descriptor size
* @retval None
*/
static void USBD_CMPSIT_AUDIODesc(USBD_HandleTypeDef *pdev, uint32_t pConf, __IO uint32_t *Sze, uint8_t speed)
{
static USBD_IfDescTypeDef *pIfDesc;
static USBD_IadDescTypeDef *pIadDesc;
UNUSED(speed);
/* Append AUDIO Interface descriptor to Configuration descriptor */
USBD_SpeakerIfDescTypeDef *pSpIfDesc;
USBD_SpeakerInDescTypeDef *pSpInDesc;
USBD_SpeakerFeatureDescTypeDef *pSpFDesc;
USBD_SpeakerOutDescTypeDef *pSpOutDesc;
USBD_SpeakerStreamIfDescTypeDef *pSpStrDesc;
USBD_SpeakerIIIFormatIfDescTypeDef *pSpIIIDesc;
USBD_SpeakerEndDescTypeDef *pSpEpDesc;
USBD_SpeakerEndStDescTypeDef *pSpEpStDesc;
#if USBD_COMPOSITE_USE_IAD == 1
pIadDesc = ((USBD_IadDescTypeDef *)(pConf + *Sze));
pIadDesc->bLength = (uint8_t)sizeof(USBD_IadDescTypeDef);
pIadDesc->bDescriptorType = USB_DESC_TYPE_IAD; /* IAD descriptor */
pIadDesc->bFirstInterface = pdev->tclasslist[pdev->classId].Ifs[0];
pIadDesc->bInterfaceCount = 2U; /* 2 interfaces */
pIadDesc->bFunctionClass = USB_DEVICE_CLASS_AUDIO;
pIadDesc->bFunctionSubClass = AUDIO_SUBCLASS_AUDIOCONTROL;
pIadDesc->bFunctionProtocol = AUDIO_PROTOCOL_UNDEFINED;
pIadDesc->iFunction = 0U; /* String Index */
*Sze += (uint32_t)sizeof(USBD_IadDescTypeDef);
#endif /* USBD_COMPOSITE_USE_IAD == 1 */
/* Append AUDIO Interface descriptor to Configuration descriptor */
__USBD_CMPSIT_SET_IF(pdev->tclasslist[pdev->classId].Ifs[0], 0U, 0U, USB_DEVICE_CLASS_AUDIO, \
AUDIO_SUBCLASS_AUDIOCONTROL, AUDIO_PROTOCOL_UNDEFINED, 0U);
/* Append AUDIO USB Speaker Class-specific AC Interface descriptor to Configuration descriptor */
pSpIfDesc = ((USBD_SpeakerIfDescTypeDef *)(pConf + *Sze));
pSpIfDesc->bLength = (uint8_t)sizeof(USBD_IfDescTypeDef);
pSpIfDesc->bDescriptorType = AUDIO_INTERFACE_DESCRIPTOR_TYPE;
pSpIfDesc->bDescriptorSubtype = AUDIO_CONTROL_HEADER;
pSpIfDesc->bcdADC = 0x0100U;
pSpIfDesc->wTotalLength = 0x0027U;
pSpIfDesc->bInCollection = 0x01U;
pSpIfDesc->baInterfaceNr = 0x01U;
*Sze += (uint32_t)sizeof(USBD_IfDescTypeDef);
/* Append USB Speaker Input Terminal Descriptor to Configuration descriptor*/
pSpInDesc = ((USBD_SpeakerInDescTypeDef *)(pConf + *Sze));
pSpInDesc->bLength = (uint8_t)sizeof(USBD_SpeakerInDescTypeDef);
pSpInDesc->bDescriptorType = AUDIO_INTERFACE_DESCRIPTOR_TYPE;
pSpInDesc->bDescriptorSubtype = AUDIO_CONTROL_INPUT_TERMINAL;
pSpInDesc->bTerminalID = 0x01U;
pSpInDesc->wTerminalType = 0x0101U;
pSpInDesc->bAssocTerminal = 0x00U;
pSpInDesc->bNrChannels = 0x01U;
pSpInDesc->wChannelConfig = 0x0000U;
pSpInDesc->iChannelNames = 0x00U;
pSpInDesc->iTerminal = 0x00U;
*Sze += (uint32_t)sizeof(USBD_SpeakerInDescTypeDef);
/*Append USB Speaker Audio Feature Unit Descriptor to Configuration descriptor */
pSpFDesc = ((USBD_SpeakerFeatureDescTypeDef *)(pConf + *Sze));
pSpFDesc->bLength = (uint8_t)sizeof(USBD_SpeakerFeatureDescTypeDef);
pSpFDesc->bDescriptorType = AUDIO_INTERFACE_DESCRIPTOR_TYPE;
pSpFDesc->bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT;
pSpFDesc->bUnitID = AUDIO_OUT_STREAMING_CTRL;
pSpFDesc->bSourceID = 0x01U;
pSpFDesc->bControlSize = 0x01U;
pSpFDesc->bmaControls = AUDIO_CONTROL_MUTE;
pSpFDesc->iTerminal = 0x00U;
*Sze += (uint32_t)sizeof(USBD_SpeakerFeatureDescTypeDef);
/*Append USB Speaker Output Terminal Descriptor to Configuration descriptor*/
pSpOutDesc = ((USBD_SpeakerOutDescTypeDef *)(pConf + *Sze));
pSpOutDesc->bLength = (uint8_t)sizeof(USBD_SpeakerOutDescTypeDef);
pSpOutDesc->bDescriptorType = AUDIO_INTERFACE_DESCRIPTOR_TYPE;
pSpOutDesc->bDescriptorSubtype = AUDIO_CONTROL_OUTPUT_TERMINAL;
pSpOutDesc->bTerminalID = 0x03U;
pSpOutDesc->wTerminalType = 0x0301U;
pSpOutDesc->bAssocTerminal = 0x00U;
pSpOutDesc->bSourceID = 0x02U;
pSpOutDesc->iTerminal = 0x00U;
*Sze += (uint32_t)sizeof(USBD_SpeakerOutDescTypeDef);
/* USB Speaker Standard AS Interface Descriptor - Audio Streaming Zero Bandwidth */
/* Interface 1, Alternate Setting 0*/
__USBD_CMPSIT_SET_IF(pdev->tclasslist[pdev->classId].Ifs[1], 0U, 0U, USB_DEVICE_CLASS_AUDIO, \
AUDIO_SUBCLASS_AUDIOSTREAMING, AUDIO_PROTOCOL_UNDEFINED, 0U);
/* USB Speaker Standard AS Interface Descriptor -Audio Streaming Operational */
/* Interface 1, Alternate Setting 1*/
__USBD_CMPSIT_SET_IF(pdev->tclasslist[pdev->classId].Ifs[1], 0x01U, 0x01U, USB_DEVICE_CLASS_AUDIO, \
AUDIO_SUBCLASS_AUDIOSTREAMING, AUDIO_PROTOCOL_UNDEFINED, 0U);
/* USB Speaker Audio Streaming Interface Descriptor */
pSpStrDesc = ((USBD_SpeakerStreamIfDescTypeDef *)(pConf + *Sze));
pSpStrDesc->bLength = (uint8_t)sizeof(USBD_SpeakerStreamIfDescTypeDef);
pSpStrDesc->bDescriptorType = AUDIO_INTERFACE_DESCRIPTOR_TYPE;
pSpStrDesc->bDescriptorSubtype = AUDIO_STREAMING_GENERAL;
pSpStrDesc->bTerminalLink = 0x01U;
pSpStrDesc->bDelay = 0x01U;
pSpStrDesc->wFormatTag = 0x0001U;
*Sze += (uint32_t)sizeof(USBD_SpeakerStreamIfDescTypeDef);
/* USB Speaker Audio Type III Format Interface Descriptor */
pSpIIIDesc = ((USBD_SpeakerIIIFormatIfDescTypeDef *)(pConf + *Sze));
pSpIIIDesc->bLength = (uint8_t)sizeof(USBD_SpeakerIIIFormatIfDescTypeDef);
pSpIIIDesc->bDescriptorType = AUDIO_INTERFACE_DESCRIPTOR_TYPE;
pSpIIIDesc->bDescriptorSubtype = AUDIO_STREAMING_FORMAT_TYPE;
pSpIIIDesc->bFormatType = AUDIO_FORMAT_TYPE_I;
pSpIIIDesc->bNrChannels = 0x02U;
pSpIIIDesc->bSubFrameSize = 0x02U;
pSpIIIDesc->bBitResolution = 16U;
pSpIIIDesc->bSamFreqType = 1U;
pSpIIIDesc->tSamFreq2 = 0x80U;
pSpIIIDesc->tSamFreq1 = 0xBBU;
pSpIIIDesc->tSamFreq0 = 0x00U;
*Sze += (uint32_t)sizeof(USBD_SpeakerIIIFormatIfDescTypeDef);
/* Endpoint 1 - Standard Descriptor */
pSpEpDesc = ((USBD_SpeakerEndDescTypeDef *)(pConf + *Sze));
pSpEpDesc->bLength = 0x09U;
pSpEpDesc->bDescriptorType = USB_DESC_TYPE_ENDPOINT;
pSpEpDesc->bEndpointAddress = pdev->tclasslist[pdev->classId].Eps[0].add;
pSpEpDesc->bmAttributes = USBD_EP_TYPE_ISOC;
pSpEpDesc->wMaxPacketSize = (uint16_t)USBD_AUDIO_GetEpPcktSze(pdev, 0U, 0U);
pSpEpDesc->bInterval = 0x01U;
pSpEpDesc->bRefresh = 0x00U;
pSpEpDesc->bSynchAddress = 0x00U;
*Sze += 0x09U;
/* Endpoint - Audio Streaming Descriptor*/
pSpEpStDesc = ((USBD_SpeakerEndStDescTypeDef *)(pConf + *Sze));
pSpEpStDesc->bLength = (uint8_t)sizeof(USBD_SpeakerEndStDescTypeDef);
pSpEpStDesc->bDescriptorType = AUDIO_ENDPOINT_DESCRIPTOR_TYPE;
pSpEpStDesc->bDescriptor = AUDIO_ENDPOINT_GENERAL;
pSpEpStDesc->bmAttributes = 0x00U;
pSpEpStDesc->bLockDelayUnits = 0x00U;
pSpEpStDesc->wLockDelay = 0x0000U;
*Sze += (uint32_t)sizeof(USBD_SpeakerEndStDescTypeDef);
/* Update Config Descriptor and IAD descriptor */
((USBD_ConfigDescTypeDef *)pConf)->bNumInterfaces += 2U;
((USBD_ConfigDescTypeDef *)pConf)->wTotalLength = (uint16_t)(*Sze);
}
#endif /* USBD_CMPSIT_ACTIVATE_AUDIO */
#if USBD_CMPSIT_ACTIVATE_RNDIS == 1
/**
* @brief USBD_CMPSIT_MSCDesc
* Configure and Append the CDC_RNDIS Descriptor
* @param pdev: device instance
* @param pConf: Configuration descriptor pointer
* @param Sze: pointer to the current configuration descriptor size
* @retval None
*/
static void USBD_CMPSIT_RNDISDesc(USBD_HandleTypeDef *pdev, uint32_t pConf, __IO uint32_t *Sze, uint8_t speed)
{
static USBD_IfDescTypeDef *pIfDesc;
static USBD_EpDescTypeDef *pEpDesc;
static USBD_CDCHeaderFuncDescTypeDef *pHeadDesc;
static USBD_CDCCallMgmFuncDescTypeDef *pCallMgmDesc;
static USBD_CDCACMFuncDescTypeDef *pACMDesc;
static USBD_CDCUnionFuncDescTypeDef *pUnionDesc;
static USBD_IadDescTypeDef *pIadDesc;
#if USBD_COMPOSITE_USE_IAD == 1
pIadDesc = ((USBD_IadDescTypeDef *)(pConf + *Sze));
pIadDesc->bLength = (uint8_t)sizeof(USBD_IadDescTypeDef);
pIadDesc->bDescriptorType = USB_DESC_TYPE_IAD; /* IAD descriptor */
pIadDesc->bFirstInterface = pdev->tclasslist[pdev->classId].Ifs[0];
pIadDesc->bInterfaceCount = 2U; /* 2 interfaces */
pIadDesc->bFunctionClass = 0xE0U;
pIadDesc->bFunctionSubClass = 0x01U;
pIadDesc->bFunctionProtocol = 0x03U;
pIadDesc->iFunction = 0U; /* String Index */
*Sze += (uint32_t)sizeof(USBD_IadDescTypeDef);
#endif /* USBD_COMPOSITE_USE_IAD == 1 */
/* Control Interface Descriptor */
__USBD_CMPSIT_SET_IF(pdev->tclasslist[pdev->classId].Ifs[0], 0U, 1U, 0x02, 0x02, 0xFF, 0U);
/* Control interface headers */
pHeadDesc = ((USBD_CDCHeaderFuncDescTypeDef *)(pConf + *Sze));
/* Header Functional Descriptor*/
pHeadDesc->bLength = (uint8_t)sizeof(USBD_CDCHeaderFuncDescTypeDef);
pHeadDesc->bDescriptorType = 0x24U;
pHeadDesc->bDescriptorSubtype = 0x00U;
pHeadDesc->bcdCDC = 0x0110U;
*Sze += (uint32_t)sizeof(USBD_CDCHeaderFuncDescTypeDef);
/* Call Management Functional Descriptor*/
pCallMgmDesc = ((USBD_CDCCallMgmFuncDescTypeDef *)(pConf + *Sze));
pCallMgmDesc->bLength = (uint8_t)sizeof(USBD_CDCCallMgmFuncDescTypeDef);
pCallMgmDesc->bDescriptorType = 0x24U;
pCallMgmDesc->bDescriptorSubtype = 0x01U;
pCallMgmDesc->bmCapabilities = 0x00U;
pCallMgmDesc->bDataInterface = pdev->tclasslist[pdev->classId].Ifs[1];
*Sze += (uint32_t)sizeof(USBD_CDCCallMgmFuncDescTypeDef);
/* ACM Functional Descriptor*/
pACMDesc = ((USBD_CDCACMFuncDescTypeDef *)(pConf + *Sze));
pACMDesc->bLength = (uint8_t)sizeof(USBD_CDCACMFuncDescTypeDef);
pACMDesc->bDescriptorType = 0x24U;
pACMDesc->bDescriptorSubtype = 0x02U;
pACMDesc->bmCapabilities = 0x00U;
*Sze += (uint32_t)sizeof(USBD_CDCACMFuncDescTypeDef);
/* Union Functional Descriptor*/
pUnionDesc = ((USBD_CDCUnionFuncDescTypeDef *)(pConf + *Sze));
pUnionDesc->bLength = (uint8_t)sizeof(USBD_CDCUnionFuncDescTypeDef);
pUnionDesc->bDescriptorType = 0x24U;
pUnionDesc->bDescriptorSubtype = 0x06U;
pUnionDesc->bMasterInterface = pdev->tclasslist[pdev->classId].Ifs[0];
pUnionDesc->bSlaveInterface = pdev->tclasslist[pdev->classId].Ifs[1];
*Sze += (uint32_t)sizeof(USBD_CDCUnionFuncDescTypeDef);
/* Append Endpoint descriptor to Configuration descriptor */
__USBD_CMPSIT_SET_EP(pdev->tclasslist[pdev->classId].Eps[2].add, USBD_EP_TYPE_INTR, \
CDC_RNDIS_CMD_PACKET_SIZE, CDC_RNDIS_HS_BINTERVAL, CDC_RNDIS_FS_BINTERVAL);
/* Data Interface Descriptor */
__USBD_CMPSIT_SET_IF(pdev->tclasslist[pdev->classId].Ifs[1], 0U, 2U, 0x0AU, 0x00U, 0x00U, 0U);
if (speed == (uint8_t)USBD_SPEED_HIGH)
{
pdev->tclasslist[pdev->classId].CurrPcktSze = CDC_RNDIS_DATA_HS_MAX_PACKET_SIZE;
}
/* Append Endpoint descriptor to Configuration descriptor */
__USBD_CMPSIT_SET_EP((pdev->tclasslist[pdev->classId].Eps[0].add), (USBD_EP_TYPE_BULK), \
(pdev->tclasslist[pdev->classId].CurrPcktSze), (0U), (0U));
/* Append Endpoint descriptor to Configuration descriptor */
__USBD_CMPSIT_SET_EP((pdev->tclasslist[pdev->classId].Eps[1].add), (USBD_EP_TYPE_BULK), \
(pdev->tclasslist[pdev->classId].CurrPcktSze), (0U), (0U));
/* Update Config Descriptor and IAD descriptor */
((USBD_ConfigDescTypeDef *)pConf)->bNumInterfaces += 2U;
((USBD_ConfigDescTypeDef *)pConf)->wTotalLength = (uint16_t)(*Sze);
}
#endif /* USBD_CMPSIT_ACTIVATE_RNDIS == 1 */
#if USBD_CMPSIT_ACTIVATE_CUSTOMHID == 1
/**
* @brief USBD_CMPSIT_CUSTOMHIDDesc
* Configure and Append the MSC Descriptor
* @param pdev: device instance
* @param pConf: Configuration descriptor pointer
* @param Sze: pointer to the current configuration descriptor size
* @retval None
*/
static void USBD_CMPSIT_CUSTOMHIDDesc(USBD_HandleTypeDef *pdev, uint32_t pConf, __IO uint32_t *Sze, uint8_t speed)
{
static USBD_IfDescTypeDef *pIfDesc;
static USBD_EpDescTypeDef *pEpDesc;
static USBD_DescTypeDef *pDesc;
/* Control Interface Descriptor */
__USBD_CMPSIT_SET_IF(pdev->tclasslist[pdev->classId].Ifs[0], 0U, 2U, 3U, 0U, 0U, 0U);
/* Descriptor of CUSTOM_HID */
pDesc = ((USBD_DescTypeDef *)((uint32_t)pConf + *Sze));
pDesc->bLength = 0x09U;
pDesc->bDescriptorTypeCHID = CUSTOM_HID_DESCRIPTOR_TYPE;
pDesc->bcdCUSTOM_HID = 0x0111U;
pDesc->bCountryCode = 0x00U;
pDesc->bNumDescriptors = 0x01U;
pDesc->bDescriptorType = 0x22U;
pDesc->wItemLength = USBD_CUSTOM_HID_REPORT_DESC_SIZE;
*Sze += (uint32_t)sizeof(USBD_DescTypeDef);
/* Descriptor of Custom HID endpoints */
/* Append Endpoint descriptor to Configuration descriptor */
__USBD_CMPSIT_SET_EP(pdev->tclasslist[pdev->classId].Eps[0].add, \
USBD_EP_TYPE_INTR, CUSTOM_HID_EPIN_SIZE, CUSTOM_HID_HS_BINTERVAL, CUSTOM_HID_FS_BINTERVAL);
/* Append Endpoint descriptor to Configuration descriptor */
__USBD_CMPSIT_SET_EP(pdev->tclasslist[pdev->classId].Eps[1].add, \
USBD_EP_TYPE_INTR, CUSTOM_HID_EPIN_SIZE, CUSTOM_HID_HS_BINTERVAL, CUSTOM_HID_FS_BINTERVAL);
/* Update Config Descriptor and IAD descriptor */
((USBD_ConfigDescTypeDef *)pConf)->bNumInterfaces += 1U;
((USBD_ConfigDescTypeDef *)pConf)->wTotalLength = (uint16_t)(*Sze);
}
#endif /* USBD_CMPSIT_ACTIVATE_CUSTOMHID == 1U */
#if USBD_CMPSIT_ACTIVATE_VIDEO == 1
/**
* @brief USBD_CMPSIT_VIDEODesc
* Configure and Append the VIDEO Descriptor
* @param pdev: device instance
* @param pConf: Configuration descriptor pointer
* @param Sze: pointer to the current configuration descriptor size
* @retval None
*/
static void USBD_CMPSIT_VIDEODesc(USBD_HandleTypeDef *pdev, uint32_t pConf, __IO uint32_t *Sze, uint8_t speed)
{
#ifdef USBD_UVC_FORMAT_UNCOMPRESSED
__ALIGN_BEGIN static uint8_t usbd_uvc_guid[16] __ALIGN_END = {DBVAL(UVC_UNCOMPRESSED_GUID), 0x00, 0x00, 0x10,
0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71
};
#endif /* USBD_UVC_FORMAT_UNCOMPRESSED */
static USBD_IfDescTypeDef *pIfDesc;
static USBD_IadDescTypeDef *pIadDesc;
/* Append AUDIO Interface descriptor to Configuration descriptor */
USBD_specificVCInDescTypeDef *pSVCInDesc;
USBD_InputTerminalDescTypeDef *pInTerDesc;
USBD_OutputTerminalDescTypeDef *pOuTerDesc;
USBD_ClassSpecificVsHeaderDescTypeDef *pSpHeaDesc;
USBD_PayloadFormatDescTypeDef *pPayForDesc;
#ifdef USBD_UVC_FORMAT_UNCOMPRESSED
USBD_ColorMatchingDescTypeDef *pColMaDesc;
#endif /* USBD_UVC_FORMAT_UNCOMPRESSED */
USBD_StandardVCDataEPDescTypeDef *pSVCDEP;
USBD_VIDEO_VSFrameDescTypeDef *pClassSpecVS;
#if USBD_COMPOSITE_USE_IAD == 1
pIadDesc = ((USBD_IadDescTypeDef *)(pConf + *Sze));
pIadDesc->bLength = (uint8_t)sizeof(USBD_IadDescTypeDef);
pIadDesc->bDescriptorType = USB_DESC_TYPE_IAD; /* IAD descriptor */
pIadDesc->bFirstInterface = pdev->tclasslist[pdev->classId].Ifs[0];
pIadDesc->bInterfaceCount = 2U; /* 2 interfaces */
pIadDesc->bFunctionClass = UVC_CC_VIDEO;
pIadDesc->bFunctionSubClass = SC_VIDEO_INTERFACE_COLLECTION;
pIadDesc->bFunctionProtocol = PC_PROTOCOL_UNDEFINED;
pIadDesc->iFunction = 0U; /* String Index */
*Sze += (uint32_t)sizeof(USBD_IadDescTypeDef);
#endif /* USBD_COMPOSITE_USE_IAD == 1 */
/* Append VIDEO Interface descriptor to Configuration descriptor */
__USBD_CMPSIT_SET_IF(pdev->tclasslist[pdev->classId].Ifs[0], 0U, 0U, UVC_CC_VIDEO, 1U, PC_PROTOCOL_UNDEFINED, 0U);
/* Append Class-specific VC Interface Descriptor to Configuration descriptor*/
pSVCInDesc = ((USBD_specificVCInDescTypeDef *)(pConf + *Sze));
pSVCInDesc->bLength = (uint8_t)sizeof(USBD_specificVCInDescTypeDef);
pSVCInDesc->bDescriptorType = CS_INTERFACE;
pSVCInDesc->bDescriptorSubtype = VC_HEADER;
pSVCInDesc->bcdUVC = UVC_VERSION;
pSVCInDesc->wTotalLength = 0x001EU;
pSVCInDesc->dwClockFrequency = 0x02DC6C00U;
pSVCInDesc->baInterfaceNr = 0x01U;
pSVCInDesc->iTerminal = 0x01U;
*Sze += (uint32_t)sizeof(USBD_specificVCInDescTypeDef);
/*Append Input Terminal Descriptor to Configuration descriptor */
pInTerDesc = ((USBD_InputTerminalDescTypeDef *)(pConf + *Sze));
pInTerDesc->bLength = (uint8_t)sizeof(USBD_InputTerminalDescTypeDef);
pInTerDesc->bDescriptorType = CS_INTERFACE;
pInTerDesc->bDescriptorSubtype = VC_INPUT_TERMINAL;
pInTerDesc->bTerminalID = 0x01U;
pInTerDesc->wTerminalType = ITT_VENDOR_SPECIFIC;
pInTerDesc->bAssocTerminal = 0x00U;
pInTerDesc->iTerminal = 0x00U;
*Sze += (uint32_t)sizeof(USBD_InputTerminalDescTypeDef);
/* Append Output Terminal Descriptor to Configuration descriptor */
pOuTerDesc = ((USBD_OutputTerminalDescTypeDef *)(pConf + *Sze));
pOuTerDesc->bLength = (uint8_t)sizeof(USBD_OutputTerminalDescTypeDef);
pOuTerDesc->bDescriptorType = CS_INTERFACE;
pOuTerDesc->bDescriptorSubtype = VC_OUTPUT_TERMINAL;
pOuTerDesc->bTerminalID = 0x02U;
pOuTerDesc->wTerminalType = TT_STREAMING;
pOuTerDesc->bAssocTerminal = 0x00U;
pOuTerDesc->bSourceID = 0x01U;
pOuTerDesc->iTerminal = 0x00U;
*Sze += (uint32_t)sizeof(USBD_OutputTerminalDescTypeDef);
/* Standard VS (Video Streaming) Interface Descriptor */
/* Interface 1, Alternate Setting 0 = Zero Bandwidth*/
__USBD_CMPSIT_SET_IF(pdev->tclasslist[pdev->classId].Ifs[1], 0U, 0U, UVC_CC_VIDEO, \
SC_VIDEOSTREAMING, PC_PROTOCOL_UNDEFINED, 0U);
/* Append Class-specific VS Header Descriptor (Input) to Configuration descriptor */
pSpHeaDesc = ((USBD_ClassSpecificVsHeaderDescTypeDef *)(pConf + *Sze));
pSpHeaDesc->bLength = (uint8_t)sizeof(USBD_ClassSpecificVsHeaderDescTypeDef);
pSpHeaDesc->bDescriptorType = CS_INTERFACE;
pSpHeaDesc->bDescriptorSubtype = VS_INPUT_HEADER;
pSpHeaDesc->bNumFormats = 0x4D01U;
pSpHeaDesc->bVideoControlSize = 0x00U;
pSpHeaDesc->bEndPointAddress = UVC_IN_EP;
pSpHeaDesc->bmInfo = 0x00U;
pSpHeaDesc->bTerminalLink = 0x02U;
pSpHeaDesc->bStillCaptureMethod = 0x00U;
pSpHeaDesc->bTriggerSupport = 0x00U;
pSpHeaDesc->bTriggerUsage = 0x00U;
pSpHeaDesc->bControlSize = 0x01U;
pSpHeaDesc->bmaControls = 0x00U;
*Sze += (uint32_t)sizeof(USBD_ClassSpecificVsHeaderDescTypeDef);
/* Append Payload Format Descriptor to Configuration descriptor */
pPayForDesc = ((USBD_PayloadFormatDescTypeDef *)(pConf + *Sze));
pPayForDesc->bLength = (uint8_t)sizeof(USBD_PayloadFormatDescTypeDef);
pPayForDesc->bDescriptorType = CS_INTERFACE;
pPayForDesc->bDescriptorSubType = VS_FORMAT_SUBTYPE;
pPayForDesc->bFormatIndex = 0x01U;
pPayForDesc->bNumFrameDescriptor = 0x01U;
#ifdef USBD_UVC_FORMAT_UNCOMPRESSED
(void)USBD_memcpy(pPayForDesc->pGiudFormat, usbd_uvc_guid, 16);
pPayForDesc->bBitsPerPixel = UVC_BITS_PER_PIXEL;
#else
pPayForDesc->bmFlags = 0x01U;
#endif /* USBD_UVC_FORMAT_UNCOMPRESSED */
pPayForDesc->bDefaultFrameIndex = 0x01U;
pPayForDesc->bAspectRatioX = 0x00U;
pPayForDesc->bAspectRatioY = 0x00U;
pPayForDesc->bInterlaceFlags = 0x00U;
pPayForDesc->bCopyProtect = 0x00U;
*Sze += (uint32_t)sizeof(USBD_PayloadFormatDescTypeDef);
/* Append Class-specific VS (Video Streaming) Frame Descriptor to Configuration descriptor */
pClassSpecVS = ((USBD_VIDEO_VSFrameDescTypeDef *)(pConf + *Sze));
pClassSpecVS->bLength = (uint8_t)sizeof(USBD_VIDEO_VSFrameDescTypeDef);
pClassSpecVS->bDescriptorType = CS_INTERFACE;
pClassSpecVS->bDescriptorSubType = VS_FRAME_SUBTYPE;
pClassSpecVS->bFrameIndex = 0x01U;
#ifdef USBD_UVC_FORMAT_UNCOMPRESSED
pClassSpecVS->bmCapabilities = 0x00U;
#else
pClassSpecVS->bmCapabilities = 0x02U;
#endif /* USBD_UVC_FORMAT_UNCOMPRESSED */
pClassSpecVS->wWidth = UVC_WIDTH;
pClassSpecVS->wHeight = UVC_HEIGHT;
if (speed == (uint8_t)USBD_SPEED_HIGH)
{
pClassSpecVS->dwMinBitRate = UVC_MIN_BIT_RATE(UVC_CAM_FPS_HS);
pClassSpecVS->dwMaxBitRate = UVC_MAX_BIT_RATE(UVC_CAM_FPS_HS);
pClassSpecVS->dwDefaultFrameInterval = UVC_INTERVAL(UVC_CAM_FPS_HS);
pClassSpecVS->dwMinFrameInterval = UVC_INTERVAL(UVC_CAM_FPS_HS);
}
else
{
pClassSpecVS->dwMinBitRate = UVC_MIN_BIT_RATE(UVC_CAM_FPS_FS);
pClassSpecVS->dwMaxBitRate = UVC_MAX_BIT_RATE(UVC_CAM_FPS_FS);
pClassSpecVS->dwDefaultFrameInterval = UVC_INTERVAL(UVC_CAM_FPS_FS);
pClassSpecVS->dwMinFrameInterval = UVC_INTERVAL(UVC_CAM_FPS_FS);
}
pClassSpecVS->dwMaxVideoFrameBufSize = UVC_MAX_FRAME_SIZE;
pClassSpecVS->bFrameIntervalType = 0x01U;
*Sze += (uint32_t)sizeof(USBD_VIDEO_VSFrameDescTypeDef);
#ifdef USBD_UVC_FORMAT_UNCOMPRESSED
/* Append Color Matching Descriptor to Configuration descriptor */
pColMaDesc = ((USBD_ColorMatchingDescTypeDef *)(pConf + *Sze));
pColMaDesc->bLength = (uint8_t)sizeof(USBD_ColorMatchingDescTypeDef);
pColMaDesc->bDescriptorType = CS_INTERFACE;
pColMaDesc->bDescriptorSubType = VS_COLORFORMAT;
pColMaDesc->bColorPrimarie = UVC_COLOR_PRIMARIE;
pColMaDesc->bTransferCharacteristics = UVC_TFR_CHARACTERISTICS;
pColMaDesc->bMatrixCoefficients = UVC_MATRIX_COEFFICIENTS;
*Sze += (uint32_t)sizeof(USBD_ColorMatchingDescTypeDef);
#endif /* USBD_UVC_FORMAT_UNCOMPRESSED */
/* USB Standard VS Interface Descriptor - data transfer mode */
/* Interface 1, Alternate Setting 1*/
__USBD_CMPSIT_SET_IF(1U, 1U, 1U, UVC_CC_VIDEO, SC_VIDEOSTREAMING, PC_PROTOCOL_UNDEFINED, 0U);
/* Standard VS (Video Streaming) data Endpoint */
pSVCDEP = ((USBD_StandardVCDataEPDescTypeDef *)(pConf + *Sze));
pSVCDEP->bLength = (uint8_t)sizeof(USBD_StandardVCDataEPDescTypeDef);
pSVCDEP->bDescriptorType = USB_DESC_TYPE_ENDPOINT;
pSVCDEP->bEndpointAddress = UVC_IN_EP;
pSVCDEP->bmAttributes = 0x05U;
pSVCDEP->bInterval = 0x01U;
if (speed == (uint8_t)USBD_SPEED_HIGH)
{
pSVCDEP->wMaxPacketSize = UVC_ISO_HS_MPS;
}
else
{
pSVCDEP->wMaxPacketSize = UVC_ISO_FS_MPS;
}
*Sze += (uint32_t)sizeof(USBD_StandardVCDataEPDescTypeDef);
/* Update Config Descriptor and IAD descriptor */
((USBD_ConfigDescTypeDef *)pConf)->bNumInterfaces += 2U;
((USBD_ConfigDescTypeDef *)pConf)->wTotalLength = (uint16_t)(*Sze);
}
#endif /* USBD_CMPSIT_ACTIVATE_VIDEO == 1 */
#if USBD_CMPSIT_ACTIVATE_PRINTER == 1
/**
* @brief USBD_CMPSIT_PRINTERDesc
* Configure and Append the PRINTER Descriptor
* @param pdev: device instance
* @param pConf: Configuration descriptor pointer
* @param Sze: pointer to the current configuration descriptor size
* @retval None
*/
static void USBD_CMPSIT_PRNTDesc(USBD_HandleTypeDef *pdev, uint32_t pConf, __IO uint32_t *Sze, uint8_t speed)
{
static USBD_IfDescTypeDef *pIfDesc;
static USBD_EpDescTypeDef *pEpDesc;
/* Control Interface Descriptor */
__USBD_CMPSIT_SET_IF(pdev->tclasslist[pdev->classId].Ifs[0], 0U, 0x02, 0x07, 0x01U, USB_PRNT_BIDIRECTIONAL, 0U);
if (speed == (uint8_t)USBD_SPEED_HIGH)
{
pdev->tclasslist[pdev->classId].CurrPcktSze = PRNT_DATA_HS_MAX_PACKET_SIZE;
}
/* Append Endpoint descriptor to Configuration descriptor */
__USBD_CMPSIT_SET_EP((pdev->tclasslist[pdev->classId].Eps[1].add), \
(USBD_EP_TYPE_BULK), (pdev->tclasslist[pdev->classId].CurrPcktSze), (0U), (0U));
/* Append Endpoint descriptor to Configuration descriptor */
__USBD_CMPSIT_SET_EP((pdev->tclasslist[pdev->classId].Eps[0].add), \
(USBD_EP_TYPE_BULK), (pdev->tclasslist[pdev->classId].CurrPcktSze), (0U), (0U));
/* Update Config Descriptor and IAD descriptor */
((USBD_ConfigDescTypeDef *)pConf)->bNumInterfaces += 1U;
((USBD_ConfigDescTypeDef *)pConf)->wTotalLength = (uint16_t)(*Sze);
}
#endif /* USBD_CMPSIT_ACTIVATE_PRINTER == 1 */
#if USBD_CMPSIT_ACTIVATE_CCID == 1
/**
* @brief USBD_CMPSIT_CCIDDesc
* Configure and Append the CCID Descriptor
* @param pdev: device instance
* @param pConf: Configuration descriptor pointer
* @param Sze: pointer to the current configuration descriptor size
* @retval None
*/
static void USBD_CMPSIT_CCIDDesc(USBD_HandleTypeDef *pdev, uint32_t pConf, __IO uint32_t *Sze, uint8_t speed)
{
static USBD_IfDescTypeDef *pIfDesc;
static USBD_EpDescTypeDef *pEpDesc;
static USBD_CCID_DescTypeDef *pDesc;
/* Control Interface Descriptor */
__USBD_CMPSIT_SET_IF(pdev->tclasslist[pdev->classId].Ifs[0], 0U, 0x03, 0x0BU, 0U, 0U, 0U);
/* Control interface headers */
pDesc = ((USBD_CCID_DescTypeDef *)((uint32_t)pConf + *Sze));
/* Device Descriptor */
pDesc->bLength = 0x36U;
pDesc->bDescriptorType = 0x21U;
pDesc->bcdCCID = 0x0110U;
pDesc->bMaxSlotIndex = 0x00U;
pDesc->bVoltageSupport = CCID_VOLTAGE_SUPP;
pDesc->dwProtocols = USBD_CCID_PROTOCOL;
pDesc->dwDefaultClock = USBD_CCID_DEFAULT_CLOCK_FREQ;
pDesc->dwMaximumClock = USBD_CCID_MAX_CLOCK_FREQ;
pDesc->bNumClockSupported = 0x00U;
pDesc->dwDataRate = USBD_CCID_DEFAULT_DATA_RATE;
pDesc->dwMaxDataRate = USBD_CCID_MAX_DATA_RATE;
pDesc->bNumDataRatesSupported = 0x35U;
pDesc->dwMaxIFSD = USBD_CCID_MAX_INF_FIELD_SIZE;
pDesc->dwSynchProtocols = 0U;
pDesc->dwMechanical = 0U;
pDesc->dwFeatures = 0x000104BAU;
pDesc->dwMaxCCIDMessageLength = CCID_MAX_BLOCK_SIZE_HEADER;
pDesc->bClassGetResponse = 0U;
pDesc->bClassEnvelope = 0U;
pDesc->wLcdLayout = 0U;
pDesc->bPINSupport = 0x03U;
pDesc->bMaxCCIDBusySlots = 0x01U;
*Sze += (uint32_t)sizeof(USBD_CCID_DescTypeDef);
if (speed == (uint8_t)USBD_SPEED_HIGH)
{
pdev->tclasslist[pdev->classId].CurrPcktSze = CCID_DATA_HS_MAX_PACKET_SIZE;
}
/* Append Endpoint descriptor to Configuration descriptor */
__USBD_CMPSIT_SET_EP((pdev->tclasslist[pdev->classId].Eps[0].add), \
(USBD_EP_TYPE_BULK), (pdev->tclasslist[pdev->classId].CurrPcktSze), (0U), (0U));
/* Append Endpoint descriptor to Configuration descriptor */
__USBD_CMPSIT_SET_EP((pdev->tclasslist[pdev->classId].Eps[1].add), \
(USBD_EP_TYPE_BULK), (pdev->tclasslist[pdev->classId].CurrPcktSze), (0U), (0U));
/* Append Endpoint descriptor to Configuration descriptor */
__USBD_CMPSIT_SET_EP(pdev->tclasslist[pdev->classId].Eps[2].add, \
USBD_EP_TYPE_INTR, CCID_CMD_PACKET_SIZE, CCID_CMD_HS_BINTERVAL, CCID_CMD_FS_BINTERVAL);
/* Update Config Descriptor and IAD descriptor */
((USBD_ConfigDescTypeDef *)pConf)->bNumInterfaces += 1U;
((USBD_ConfigDescTypeDef *)pConf)->wTotalLength = (uint16_t)(*Sze);
}
#endif /* USBD_CMPSIT_ACTIVATE_CCID == 1 */
#if USBD_CMPSIT_ACTIVATE_MTP == 1
/**
* @brief USBD_CMPSIT_MTPDesc
* Configure and Append the MTP Descriptor
* @param pdev: device instance
* @param pConf: Configuration descriptor pointer
* @param Sze: pointer to the current configuration descriptor size
* @retval None
*/
static void USBD_CMPSIT_MTPDesc(USBD_HandleTypeDef *pdev, uint32_t pConf, __IO uint32_t *Sze, uint8_t speed)
{
USBD_IfDescTypeDef *pIfDesc;
USBD_EpDescTypeDef *pEpDesc;
/* Append MTP Interface descriptor */
__USBD_CMPSIT_SET_IF((pdev->tclasslist[pdev->classId].Ifs[0]), (0U), \
(uint8_t)(pdev->tclasslist[pdev->classId].NumEps), USB_MTP_INTRERFACE_CLASS, \
USB_MTP_INTRERFACE_SUB_CLASS, USB_MTP_INTRERFACE_PROTOCOL, (0U));
if (speed == (uint8_t)USBD_SPEED_HIGH)
{
pdev->tclasslist[pdev->classId].CurrPcktSze = MTP_DATA_MAX_HS_PACKET_SIZE;
}
/* Append Endpoint descriptor to Configuration descriptor */
__USBD_CMPSIT_SET_EP((pdev->tclasslist[pdev->classId].Eps[0].add), (USBD_EP_TYPE_BULK), \
(pdev->tclasslist[pdev->classId].CurrPcktSze), (0U), (0U));
/* Append Endpoint descriptor to Configuration descriptor */
__USBD_CMPSIT_SET_EP((pdev->tclasslist[pdev->classId].Eps[1].add), (USBD_EP_TYPE_BULK), \
(pdev->tclasslist[pdev->classId].CurrPcktSze), (0U), (0U));
/* Append Endpoint descriptor to Configuration descriptor */
__USBD_CMPSIT_SET_EP(pdev->tclasslist[pdev->classId].Eps[2].add, \
USBD_EP_TYPE_INTR, MTP_CMD_PACKET_SIZE, MTP_HS_BINTERVAL, MTP_FS_BINTERVAL);
/* Update Config Descriptor and IAD descriptor */
((USBD_ConfigDescTypeDef *)pConf)->bNumInterfaces += 1U;
((USBD_ConfigDescTypeDef *)pConf)->wTotalLength = (uint16_t)(*Sze);
}
#endif /* USBD_CMPSIT_ACTIVATE_MTP == 1 */
/**
* @brief USBD_CMPSIT_SetClassID
* Find and set the class ID relative to selected class type and instance
* @param pdev: device instance
* @param Class: Class type, can be CLASS_TYPE_NONE if requested to find class from setup request
* @param Instance: Instance number of the class (0 if first/unique instance, >0 otherwise)
* @retval The Class ID, The pdev->classId is set with the value of the selected class ID.
*/
uint32_t USBD_CMPSIT_SetClassID(USBD_HandleTypeDef *pdev, USBD_CompositeClassTypeDef Class, uint32_t Instance)
{
uint32_t idx;
uint32_t inst = 0U;
/* Unroll all already activated classes */
for (idx = 0U; idx < pdev->NumClasses; idx++)
{
/* Check if the class correspond to the requested type and if it is active */
if (((USBD_CompositeClassTypeDef)(pdev->tclasslist[idx].ClassType) == Class) &&
((pdev->tclasslist[idx].Active) == 1U))
{
if (inst == Instance)
{
/* Set the new class ID */
pdev->classId = idx;
/* Return the class ID value */
return (idx);
}
else
{
/* Increment instance index and look for next instance */
inst++;
}
}
}
/* No class found, return 0xFF */
return 0xFFU;
}
/**
* @brief USBD_CMPSIT_GetClassID
* Returns the class ID relative to selected class type and instance
* @param pdev: device instance
* @param Class: Class type, can be CLASS_TYPE_NONE if requested to find class from setup request
* @param Instance: Instance number of the class (0 if first/unique instance, >0 otherwise)
* @retval The Class ID (this function does not set the pdev->classId field.
*/
uint32_t USBD_CMPSIT_GetClassID(USBD_HandleTypeDef *pdev, USBD_CompositeClassTypeDef Class, uint32_t Instance)
{
uint32_t idx;
uint32_t inst = 0U;
/* Unroll all already activated classes */
for (idx = 0U; idx < pdev->NumClasses; idx++)
{
/* Check if the class correspond to the requested type and if it is active */
if (((USBD_CompositeClassTypeDef)(pdev->tclasslist[idx].ClassType) == Class) &&
((pdev->tclasslist[idx].Active) == 1U))
{
if (inst == Instance)
{
/* Return the class ID value */
return (idx);
}
else
{
/* Increment instance index and look for next instance */
inst++;
}
}
}
/* No class found, return 0xFF */
return 0xFFU;
}
/**
* @brief USBD_CMPST_ClearConfDesc
* Reset the configuration descriptor
* @param pdev: device instance (reserved for future use)
* @retval Status.
*/
uint8_t USBD_CMPST_ClearConfDesc(USBD_HandleTypeDef *pdev)
{
UNUSED(pdev);
/* Reset the configuration descriptor pointer to default value and its size to zero */
pCmpstFSConfDesc = USBD_CMPSIT_FSCfgDesc;
CurrFSConfDescSz = 0U;
#ifdef USE_USB_HS
pCmpstHSConfDesc = USBD_CMPSIT_HSCfgDesc;
CurrHSConfDescSz = 0U;
#endif /* USE_USB_HS */
/* All done, can't fail */
return (uint8_t)USBD_OK;
}
#endif /* USE_USBD_COMPOSITE */
4.3 修改端点的地址
cdc的在usbd_cdc.h中,
#ifndef CDC_IN_EP
#define CDC_IN_EP 0x81U /* EP1 for data IN */
#endif /* CDC_IN_EP */
#ifndef CDC_OUT_EP
#define CDC_OUT_EP 0x01U /* EP1 for data OUT */
#endif /* CDC_OUT_EP */
#ifndef CDC_CMD_EP
#define CDC_CMD_EP 0x82U /* EP2 for CDC commands */
#endif /* CDC_CMD_EP */
msc的在usbd_msc.h中
#ifndef MSC_EPIN_ADDR
#define MSC_EPIN_ADDR 0x83U
#endif /* MSC_EPIN_ADDR */
#ifndef MSC_EPOUT_ADDR
#define MSC_EPOUT_ADDR 0x03U
#endif /* MSC_EPOUT_ADDR */
4.4 修改设备类的添加函数,内部涉及接口、端点、类型等
在文件usbd_composite_builder.c中,根据类型和classID填充不同的参数,完整代码见4.2
uint8_t USBD_CMPSIT_AddClass(USBD_HandleTypeDef *pdev,
USBD_ClassTypeDef *pclass,
USBD_CompositeClassTypeDef class,
uint8_t cfgidx)
{
switch(class)
{
case CLASS_TYPE_CDC:{
pdev->tclasslist[pdev->classId].ClassType = CLASS_TYPE_CDC;
pdev->tclasslist[pdev->classId].Active = 1U;
pdev->tclasslist[pdev->classId].NumEps = 3;
pdev->tclasslist[pdev->classId].Eps[0].add = CDC_CMD_EP;
pdev->tclasslist[pdev->classId].Eps[0].type = USBD_EP_TYPE_INTR;
pdev->tclasslist[pdev->classId].Eps[0].size = CDC_CMD_PACKET_SIZE;
pdev->tclasslist[pdev->classId].Eps[0].is_used = 1U;
pdev->tclasslist[pdev->classId].Eps[1].add = CDC_OUT_EP;
pdev->tclasslist[pdev->classId].Eps[1].type = USBD_EP_TYPE_BULK;
pdev->tclasslist[pdev->classId].Eps[1].size = CDC_DATA_FS_MAX_PACKET_SIZE;
pdev->tclasslist[pdev->classId].Eps[1].is_used = 1U;
pdev->tclasslist[pdev->classId].Eps[2].add = CDC_IN_EP;
pdev->tclasslist[pdev->classId].Eps[2].type = USBD_EP_TYPE_BULK;
pdev->tclasslist[pdev->classId].Eps[2].size = CDC_DATA_FS_MAX_PACKET_SIZE;
pdev->tclasslist[pdev->classId].Eps[2].is_used = 1U;
pdev->tclasslist[pdev->classId].NumIf = 2;
pdev->tclasslist[pdev->classId].Ifs[0] = 0;
pdev->tclasslist[pdev->classId].Ifs[1] = 1;
}break;
case CLASS_TYPE_MSC:{
pdev->tclasslist[pdev->classId].ClassType = CLASS_TYPE_MSC;
pdev->tclasslist[pdev->classId].Active = 1U;
pdev->tclasslist[pdev->classId].NumEps = 2;
pdev->tclasslist[pdev->classId].Eps[0].add = MSC_EPIN_ADDR;
pdev->tclasslist[pdev->classId].Eps[0].type = USBD_EP_TYPE_BULK;
pdev->tclasslist[pdev->classId].Eps[0].size = MSC_MAX_FS_PACKET;
pdev->tclasslist[pdev->classId].Eps[0].is_used = 1U;
pdev->tclasslist[pdev->classId].Eps[1].add = MSC_EPOUT_ADDR;
pdev->tclasslist[pdev->classId].Eps[1].type = USBD_EP_TYPE_BULK;
pdev->tclasslist[pdev->classId].Eps[1].size = MSC_MAX_FS_PACKET;
pdev->tclasslist[pdev->classId].Eps[1].is_used = 1U;
pdev->tclasslist[pdev->classId].NumIf = 1;
pdev->tclasslist[pdev->classId].Ifs[0] = 2;
}break;
default:break;
}
pdev->tclasslist[pdev->classId].CurrPcktSze = 0U;
return (uint8_t)USBD_OK;
}
4.5 在usbd_conf.c中修改端点发送fifo配置
USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev)
{
/* Init USB Ip. */
if (pdev->id == DEVICE_FS) {
/* Link the driver to the stack. */
hpcd_USB_OTG_FS.pData = pdev;
pdev->pData = &hpcd_USB_OTG_FS;
hpcd_USB_OTG_FS.Instance = USB_OTG_FS;
hpcd_USB_OTG_FS.Init.dev_endpoints = 9;
hpcd_USB_OTG_FS.Init.speed = PCD_SPEED_FULL;
hpcd_USB_OTG_FS.Init.dma_enable = DISABLE;
hpcd_USB_OTG_FS.Init.phy_itface = PCD_PHY_EMBEDDED;
hpcd_USB_OTG_FS.Init.Sof_enable = DISABLE;
hpcd_USB_OTG_FS.Init.low_power_enable = DISABLE;
hpcd_USB_OTG_FS.Init.lpm_enable = DISABLE;
hpcd_USB_OTG_FS.Init.battery_charging_enable = DISABLE;
hpcd_USB_OTG_FS.Init.vbus_sensing_enable = DISABLE;
hpcd_USB_OTG_FS.Init.use_dedicated_ep1 = DISABLE;
if (HAL_PCD_Init(&hpcd_USB_OTG_FS) != HAL_OK)
{
Error_Handler( );
}
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
/* Register USB PCD CallBacks */
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_SOF_CB_ID, PCD_SOFCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_SETUPSTAGE_CB_ID, PCD_SetupStageCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_RESET_CB_ID, PCD_ResetCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_SUSPEND_CB_ID, PCD_SuspendCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_RESUME_CB_ID, PCD_ResumeCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_CONNECT_CB_ID, PCD_ConnectCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_DISCONNECT_CB_ID, PCD_DisconnectCallback);
HAL_PCD_RegisterDataOutStageCallback(&hpcd_USB_OTG_FS, PCD_DataOutStageCallback);
HAL_PCD_RegisterDataInStageCallback(&hpcd_USB_OTG_FS, PCD_DataInStageCallback);
HAL_PCD_RegisterIsoOutIncpltCallback(&hpcd_USB_OTG_FS, PCD_ISOOUTIncompleteCallback);
HAL_PCD_RegisterIsoInIncpltCallback(&hpcd_USB_OTG_FS, PCD_ISOINIncompleteCallback);
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
/* USER CODE BEGIN TxRx_Configuration */
HAL_PCDEx_SetRxFiFo(&hpcd_USB_OTG_FS, 0x80);
HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 0, 0x40);
HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 1, 0x40);
HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 3, 0x40);
/* USER CODE END TxRx_Configuration */
}
return USBD_OK;
}
在usbd_conf.h中修改支持最大接口数,同时修改此文件中的malloc和free函数
#define USBD_MAX_NUM_INTERFACES 3U
#define USBD_malloc malloc//(void *)USBD_static_malloc
/** Alias for memory release. */
#define USBD_free free//USBD_static_free
4.6 修改设备描述符
因现在是复合设备,则需要修改usbd_desc.c中的设备描述符:
__ALIGN_BEGIN uint8_t USBD_FS_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END =
{
0x12, /*bLength */
USB_DESC_TYPE_DEVICE, /*bDescriptorType*/
0x00, /*bcdUSB */
0x02,
0xEF, /*bDeviceClass*/
0x02, /*bDeviceSubClass*/
0x01, /*bDeviceProtocol*/
USB_MAX_EP0_SIZE, /*bMaxPacketSize*/
LOBYTE(USBD_VID), /*idVendor*/
HIBYTE(USBD_VID), /*idVendor*/
LOBYTE(USBD_PID_FS), /*idProduct*/
HIBYTE(USBD_PID_FS), /*idProduct*/
0x00, /*bcdDevice rel. 2.00*/
0x02,
USBD_IDX_MFC_STR, /*Index of manufacturer string*/
USBD_IDX_PRODUCT_STR, /*Index of product string*/
USBD_IDX_SERIAL_STR, /*Index of serial number string*/
USBD_MAX_NUM_CONFIGURATION /*bNumConfigurations*/
};
4.7 修改cdc的一些函数
usbd_cdc_if.c中的CDC_Init_FS(),CDC_Transmit_FS()函数
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : usbd_cdc_if.c
* @version : v1.0_Cube
* @brief : Usb device for Virtual Com Port.
******************************************************************************
* @attention
*
* Copyright (c) 2023 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.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc_if.h"
/* USER CODE BEGIN INCLUDE */
/* USER CODE END INCLUDE */
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
/* USER CODE END PV */
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @brief Usb device library.
* @{
*/
/** @addtogroup USBD_CDC_IF
* @{
*/
/** @defgroup USBD_CDC_IF_Private_TypesDefinitions USBD_CDC_IF_Private_TypesDefinitions
* @brief Private types.
* @{
*/
/* USER CODE BEGIN PRIVATE_TYPES */
/* USER CODE END PRIVATE_TYPES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Private_Defines USBD_CDC_IF_Private_Defines
* @brief Private defines.
* @{
*/
/* USER CODE BEGIN PRIVATE_DEFINES */
/* USER CODE END PRIVATE_DEFINES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Private_Macros USBD_CDC_IF_Private_Macros
* @brief Private macros.
* @{
*/
/* USER CODE BEGIN PRIVATE_MACRO */
/* USER CODE END PRIVATE_MACRO */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Private_Variables USBD_CDC_IF_Private_Variables
* @brief Private variables.
* @{
*/
/* Create buffer for reception and transmission */
/* It's up to user to redefine and/or remove those define */
/** Received data over USB are stored in this buffer */
uint8_t UserRxBufferFS[APP_RX_DATA_SIZE];
/** Data to send over USB CDC are stored in this buffer */
uint8_t UserTxBufferFS[APP_TX_DATA_SIZE];
/* USER CODE BEGIN PRIVATE_VARIABLES */
/* USER CODE END PRIVATE_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Exported_Variables USBD_CDC_IF_Exported_Variables
* @brief Public variables.
* @{
*/
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Private_FunctionPrototypes USBD_CDC_IF_Private_FunctionPrototypes
* @brief Private functions declaration.
* @{
*/
static int8_t CDC_Init_FS(void);
static int8_t CDC_DeInit_FS(void);
static int8_t CDC_Control_FS(uint8_t cmd, uint8_t* pbuf, uint16_t length);
static int8_t CDC_Receive_FS(uint8_t* pbuf, uint32_t *Len);
static int8_t CDC_TransmitCplt_FS(uint8_t *pbuf, uint32_t *Len, uint8_t epnum);
/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
/**
* @}
*/
USBD_CDC_ItfTypeDef USBD_Interface_fops_FS =
{
CDC_Init_FS,
CDC_DeInit_FS,
CDC_Control_FS,
CDC_Receive_FS,
CDC_TransmitCplt_FS
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief Initializes the CDC media low layer over the FS USB IP
* @retval USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Init_FS(void)
{
/* USER CODE BEGIN 3 */
USBD_HandleTypeDef *pdev = &hUsbDeviceFS;
uint8_t idx = USBD_CoreFindEP(pdev, CDC_IN_EP);
/* Set Application Buffers */
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, UserTxBufferFS, 0,idx);
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, UserRxBufferFS);
return (USBD_OK);
/* USER CODE END 3 */
}
/**
* @brief DeInitializes the CDC media low layer
* @retval USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_DeInit_FS(void)
{
/* USER CODE BEGIN 4 */
return (USBD_OK);
/* USER CODE END 4 */
}
/**
* @brief Manage the CDC class requests
* @param cmd: Command code
* @param pbuf: Buffer containing command data (request parameters)
* @param length: Number of data to be sent (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Control_FS(uint8_t cmd, uint8_t* pbuf, uint16_t length)
{
/* USER CODE BEGIN 5 */
switch(cmd)
{
case CDC_SEND_ENCAPSULATED_COMMAND:
break;
case CDC_GET_ENCAPSULATED_RESPONSE:
break;
case CDC_SET_COMM_FEATURE:
break;
case CDC_GET_COMM_FEATURE:
break;
case CDC_CLEAR_COMM_FEATURE:
break;
/*******************************************************************************/
/* Line Coding Structure */
/*-----------------------------------------------------------------------------*/
/* Offset | Field | Size | Value | Description */
/* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
/* 4 | bCharFormat | 1 | Number | Stop bits */
/* 0 - 1 Stop bit */
/* 1 - 1.5 Stop bits */
/* 2 - 2 Stop bits */
/* 5 | bParityType | 1 | Number | Parity */
/* 0 - None */
/* 1 - Odd */
/* 2 - Even */
/* 3 - Mark */
/* 4 - Space */
/* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
/*******************************************************************************/
case CDC_SET_LINE_CODING:
break;
case CDC_GET_LINE_CODING:
pbuf[0] = (uint8_t)(115200);
pbuf[1] = (uint8_t)(115200 >> 8);
pbuf[2] = (uint8_t)(115200 >> 16);
pbuf[3] = (uint8_t)(115200 >> 24);
pbuf[4] = 0; // stop bits (1)
pbuf[5] = 0; // parity (none)
pbuf[6] = 8; // number of bits (8)
break;
case CDC_SET_CONTROL_LINE_STATE:
break;
case CDC_SEND_BREAK:
break;
default:
break;
}
return (USBD_OK);
/* USER CODE END 5 */
}
/**
* @brief Data received over USB OUT endpoint are sent over CDC interface
* through this function.
*
* @note
* This function will issue a NAK packet on any OUT packet received on
* USB endpoint until exiting this function. If you exit this function
* before transfer is complete on CDC interface (ie. using DMA controller)
* it will result in receiving more data while previous ones are still
* not sent.
*
* @param Buf: Buffer of data to be received
* @param Len: Number of data received (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN 6 */
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
CDC_Transmit_FS(Buf, *Len);
return (USBD_OK);
/* USER CODE END 6 */
}
/**
* @brief CDC_Transmit_FS
* Data to send over USB IN endpoint are sent over CDC interface
* through this function.
* @note
*
*
* @param Buf: Buffer of data to be sent
* @param Len: Number of data to be sent (in bytes)
* @retval USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY
*/
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
#if 0
uint8_t result = USBD_OK;
/* USER CODE BEGIN 7 */
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
if (hcdc->TxState != 0){
return USBD_BUSY;
}
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
/* USER CODE END 7 */
return result;
#else
uint8_t result = USBD_OK;
USBD_HandleTypeDef *pdev = &hUsbDeviceFS;
/* Get the class index relative to this endpoint */
uint8_t idx = USBD_CoreFindEP(pdev, CDC_IN_EP);
if (((uint8_t)idx != 0xFFU) && (idx < USBD_MAX_SUPPORTED_CLASS))
{
pdev->classId = idx;
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassDataCmsit[pdev->classId];
if (hcdc->TxState != 0){
return USBD_BUSY;
}
USBD_CDC_SetTxBuffer(pdev, Buf, Len, idx);
result = USBD_CDC_TransmitPacket(pdev,idx);
return result;
}
return USBD_FAIL;
#endif
}
/**
* @brief CDC_TransmitCplt_FS
* Data transmitted callback
*
* @note
* This function is IN transfer complete callback used to inform user that
* the submitted Data is successfully sent over USB.
*
* @param Buf: Buffer of data to be received
* @param Len: Number of data received (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_TransmitCplt_FS(uint8_t *Buf, uint32_t *Len, uint8_t epnum)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 13 */
UNUSED(Buf);
UNUSED(Len);
UNUSED(epnum);
/* USER CODE END 13 */
return result;
}
/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
4.8 在工程中增加复合类的宏变量USE_USBD_COMPOSITE
或者可以在main.h中定义该宏
4.9 修改usb的初始化函数
将cdc和msc的类注册到复合设备类中,注意注册的接口和类顺序,否则会出问题,需要和设备描述符中的描述一致,先是cdc,在是msc,usb_device.c中修改如下。需要添加几个头文件
#include "usbd_cdc.h"
#include "usbd_cdc_if.h"
#include "usbd_composite_builder.h"
void MX_USB_DEVICE_Init(void)
{
/* USER CODE BEGIN USB_DEVICE_Init_PreTreatment */
/* USER CODE END USB_DEVICE_Init_PreTreatment */
/* Init Device Library, add supported class and start the library. */
#if 0
if (USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS) != USBD_OK)
{
Error_Handler();
}
if (USBD_RegisterClass(&hUsbDeviceFS, &USBD_MSC) != USBD_OK)
{
Error_Handler();
}
if (USBD_MSC_RegisterStorage(&hUsbDeviceFS, &USBD_Storage_Interface_fops_FS) != USBD_OK)
{
Error_Handler();
}
if (USBD_Start(&hUsbDeviceFS) != USBD_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USB_DEVICE_Init_PostTreatment */
HAL_PWREx_EnableUSBVoltageDetector();
/* USER CODE END USB_DEVICE_Init_PostTreatment */
#endif
if (USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS) != USBD_OK)
{
Error_Handler();
}
if(USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_Interface_fops_FS) != USBD_OK)
{
Error_Handler();
}
if(USBD_RegisterClassComposite(&hUsbDeviceFS, &USBD_CDC,CLASS_TYPE_CDC,0) != USBD_OK)
{
Error_Handler();
}
if (USBD_MSC_RegisterStorage(&hUsbDeviceFS, &USBD_Storage_Interface_fops_FS) != USBD_OK)
{
Error_Handler();
}
if(USBD_RegisterClassComposite(&hUsbDeviceFS, &USBD_MSC,CLASS_TYPE_MSC,0) != USBD_OK)
{
Error_Handler();
}
if (USBD_Start(&hUsbDeviceFS) != USBD_OK)
{
Error_Handler();
}
}
4.10,编译运行,效果如下
由于盘符是数组模拟的,故每次上电后都需要格式化一次。
2023.10.19 西安北郊,随时欢迎各位来西安游玩。