复合设备是啥,通俗讲就是一个USB物理设备可以实现多个功能,在主机端可以看到多个设备。通常实现HID复合设备有两种方式。第一种是使用同一个接口,修改报告描述符,增加一个功能集合,同时需要使用报告ID来区分哪一个设备,这样主机端和设备端需要增加报告ID处理,但只需要两个端点来实现功能,对于端口资源较少的MCU可以使用;第二种是使用两个接口,每个接口对应不同的报告描述符,不需要特意使用报告ID来区分,但不同接口使用独立的端点。
本文章使用不同接口来实现,基于stm32 cube例程开发。
-
开发准备
使用官方STM32Cube_FW_F1_V1.6.0,使用STM32F103XF,因此使用
STM32Cube_FW_F1_V1.6.0\Projects\STM3210E_EVAL\Applications\USB_Device\CustomHID_Standalone
这个工程 -
移植代码
2.1 修改控制控制USBDP上拉电阻引脚,(内部无法直接控制上下拉,因此增加此电路,否则主机不会枚举设备)
2.2 增加串口1输出调试信息,main函数里添加:
/* uart configuration */
MX_USART1_UART_Init();
添加如下代码实现printf功能
PUTCHAR_PROTOTYPE
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}
2.3 修改usb注册函数,main函数里修改如下代码
USBD_Init(&USBD_Device, &HID_Desc, 0);
/* Add Supported Class /
USBD_RegisterClass(&USBD_Device, &USBD_COMPOSITE);
/ Start Device Process */
USBD_Start(&USBD_Device);
2.4 修改desc
在usbd_desc.c,定义自己的desc
#define USBD_VID 0x0483
#define USBD_PID 0x5750
#define USBD_LANGID_STRING 0x409
#define USBD_MANUFACTURER_STRING “man”
#define USBD_PRODUCT_FS_STRING “HID in FS Mode”
#define USBD_CONFIGURATION_FS_STRING “HID Config”
#define USBD_INTERFACE_FS_STRING “HID Interface”
2.5 添加USBD_COMPOSITE
增加如下文件
usbd_composite.c,usbd_composite.h,usbd_customhid_if.c
usbd_customhid_if.h,usbd_keyboard.c,usbd_keyboard.h,usbd_keyboard_if.c,usbd_keyboard_if.h
usbd_composite.c具体内容如下,关键修改为USBD_Composite_CfgFSDesc。
/**
* @file usbd_composite.c
* @author
* @version
* @date
* @brief KB + HID 复合设备
* @note
* @attention
*/
#include "usbd_composite.h"
#include "usbd_customhid.h"
#include "usbd_customhid_if.h"
#include "usbd_keyboard.h"
#include "usbd_keyboard_hid_if.h"
static USBD_CUSTOM_HID_HandleTypeDef *pHIDData;
static USBD_CUSTOM_HID_HandleTypeDef *pKBData;
static uint8_t USBD_Composite_Init (USBD_HandleTypeDef *pdev,
uint8_t cfgidx);
static uint8_t USBD_Composite_DeInit (USBD_HandleTypeDef *pdev,
uint8_t cfgidx);
static uint8_t USBD_Composite_EP0_RxReady(USBD_HandleTypeDef *pdev);
static uint8_t USBD_Composite_Setup (USBD_HandleTypeDef *pdev,
USBD_SetupReqTypedef *req);
static uint8_t USBD_Composite_DataIn (USBD_HandleTypeDef *pdev,
uint8_t epnum);
static uint8_t USBD_Composite_DataOut (USBD_HandleTypeDef *pdev,
uint8_t epnum);
static uint8_t *USBD_Composite_GetFSCfgDesc (uint16_t *length);
static uint8_t *USBD_Composite_GetDeviceQualifierDescriptor (uint16_t *length);
USBD_ClassTypeDef USBD_COMPOSITE =
{
USBD_Composite_Init,
USBD_Composite_DeInit,
USBD_Composite_Setup,
NULL, /*EP0_TxSent*/
USBD_Composite_EP0_RxReady,
USBD_Composite_DataIn,
USBD_Composite_DataOut,
NULL,
NULL,
NULL,
NULL,
USBD_Composite_GetFSCfgDesc,
NULL,
USBD_Composite_GetDeviceQualifierDescriptor,
};
/* USB composite device Configuration Descriptor */
/* All Descriptors (Configuration, Interface, Endpoint, Class, Vendor */
__ALIGN_BEGIN uint8_t USBD_Composite_CfgFSDesc[USBD_COMPOSITE_DESC_SIZE] __ALIGN_END =
{
0x09, /* bLength: Configuration Descriptor size */
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
USBD_COMPOSITE_DESC_SIZE,
/* wTotalLength: Bytes returned */
0x00,
0x02, /*bNumInterfaces: 2 interface*/
0x01, /*bConfigurationValue: Configuration value*/
0x00, /*iConfiguration: Index of string descriptor describing
the configuration*/
0xC0, /*bmAttributes: bus powered */
0x32, /*MaxPower 100 mA: this current is used for detecting Vbus*/
/************** Descriptor of CUSTOM HID interface ****************/
/* 09 */
0x09, /*bLength: Interface Descriptor size*