stm32cube-usb-hid_cdc组合设备

stm32cube-usb-hid_cdc组合设备


发布版本: 1.0

文件密级: 公开资料


前言
概述

读者

本文档(本指南)主要使用于以下工程师:

软件开发工程师

产品版本 修订记录

日期版本作者/邮箱修订说明
2019-10-7V1.0wingceltis-c/wingceltis@aliyun.com初始版本

1. 简介

USB组合设备Composite Device内只有一个Function,只有一套PID/VID,通过将不同的interface定义为不同的类来实现多个功能的组合。

2. 组合设备

复制USB_HID工程为USB_HID_CDC工程,添加CDC相关类容。(USB_HID工程和文档在参考链接中)

1.合并CDC

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.新建usbd_composite文件,并添加文件到Keil.

在这里插入图片描述

3.修改CDC所用EP端口.
在这里插入图片描述

4.修改HID所用EP端口.并添加HID_EPOUT_ADDR
在这里插入图片描述

  1. 修改设备描述符

    __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*/
    };
    
  2. 编辑复合头文件.复合用IAD.写在一起.

usbd_composite.h

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_COMPOSITE_H
#define __USBD_COMPOSITE_H
#ifdef __cplusplus
 extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include  "usbd_hid.h"
#include  "usbd_cdc.h"
#include  "usbd_cdc_if.h"

#define USBD_IAD_DESC_SIZE           0x08
#define USBD_IAD_DESCRIPTOR_TYPE     0x0B
#define USBD_CDC_FIRST_INTERFACE     0          /* CDC FirstInterface */
#define USBD_CDC_INTERFACE_NUM       2          /* CDC Interface NUM */
#define USBD_CDC_CMD_INTERFACE       0
#define USBD_CDC_DATA_INTERFACE      1
#define USBD_HID_FIRST_INTERFACE     2          /* HID FirstInterface */
#define USBD_HID_INTERFACE_NUM       1          /* HID Interface NUM */
#define USBD_HID_INTERFACE           2
	 
#define HID_INDATA_NUM              (HID_EPIN_ADDR & 0x0F)
#define HID_OUTDATA_NUM             (HID_EPOUT_ADDR & 0x0F)
#define CDC_INDATA_NUM              (CDC_IN_EP & 0x0F)
#define CDC_OUTDATA_NUM             (CDC_OUT_EP & 0x0F)
#define CDC_OUTCMD_NUM              (CDC_CMD_EP & 0x0F)
#define USBD_COMPOSITE_DESC_SIZE    (9  + 58 + 8 +  32 + 8 )
extern USBD_ClassTypeDef    USBD_COMPOSITE;

extern USBD_CDC_HandleTypeDef *pCDCData;
extern USBD_HID_HandleTypeDef *pHIDData;
/**
  * @}
  */
/**
  * @}
  */
#ifdef __cplusplus
}
#endif
#endif  /* __USBD_COMPOSITE_H */
/**
  * @}
  */
/*****************************END OF FILE****/

usbd_composite.c

#include "usbd_composite.h"
#include "usbd_cdc.h"
#include "usbd_hid.h"
#include  "usbd_cdc_if.h"

 USBD_CDC_HandleTypeDef *pCDCData;
 USBD_HID_HandleTypeDef *pHIDData;

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: Configuation Descriptor size */
  USB_DESC_TYPE_CONFIGURATION,   /* bDescriptorType: Configuration */
  USBD_COMPOSITE_DESC_SIZE,  
  0x00,
  USBD_MAX_NUM_INTERFACES ,  /* bNumInterfaces: */
  0x01,   /* bConfigurationValue: */
  0x00,   /* iConfiguration: 04 */
  0xc0,   /* bmAttributes:c0 */
  0x32,   /* MaxPower 300 mA 96 */
  /****************************CDC************************************/
  /* Interface Association Descriptor */
  USBD_IAD_DESC_SIZE,               // bLength
  USBD_IAD_DESCRIPTOR_TYPE,         // bDescriptorType
  USBD_CDC_FIRST_INTERFACE,         // bFirstInterface
  USBD_CDC_INTERFACE_NUM,           // bInterfaceCount
  0x02,                             // bFunctionClass     CDC Control
  0x02,                             // bFunctionSubClass  Abstract Control Model
  0x01,                             // bInterfaceProtocol  AT Commands: V.250 etc
  0x04,                             // iFunction
  /*Interface Descriptor */
  0x09,   /* bLength: Interface Descriptor size */
  USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: Interface */
  /* Interface descriptor type */
  USBD_CDC_CMD_INTERFACE,   /* bInterfaceNumber: Number of Interface */
  0x00,   /* bAlternateSetting: Alternate setting */
  0x01,   /* bNumEndpoints: One endpoints used */
  0x02,   /* bInterfaceClass: Communication Interface Class */
  0x02,   /* bInterfaceSubClass: Abstract Control Model */
  0x01,   /* bInterfaceProtocol: Common AT commands */
  0x01,   /* 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: 1 */
  /*ACM Functional Descriptor*/
  0x04,   /* bFunctionLength */
  0x24,   /* bDescriptorType: CS_INTERFACE */
  0x02,   /* bDescriptorSubtype: Abstract Control Management desc */
  0x02,   /* bmCapabilities */
  /*Union Functional Descriptor*/
  0x05,   /* bFunctionLength */
  0x24,   /* bDescriptorType: CS_INTERFACE */
  0x06,   /* bDescriptorSubtype: Union func desc */
  USBD_CDC_CMD_INTERFACE,   /* bMasterInterface: Communication class interface */
  USBD_CDC_DATA_INTERFACE,   /* 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),
  0x01,                           /* bInterval: */
  /*Data class interface descriptor*/
  0x09,   /* bLength: Endpoint Descriptor size */
  USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: */
  USBD_CDC_DATA_INTERFACE,   /* bInterfaceNumber: Number of Interface */
  0x00,   /* bAlternateSetting: Alternate setting */
  0x02,   /* bNumEndpoints: Two endpoints used */
  0x0A,   /* bInterfaceClass: CDC */
  0x02,   /* bInterfaceSubClass: */
  0x00,   /* bInterfaceProtocol: */
  0x01,   /* 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),
  0x01,                              /* bInterval: ignore for Bulk transfer */
  /*Endpoint IN Descriptor*/
  0x07,   /* bLength: Endpoint Descriptor size */
  USB_DESC_TYPE_ENDPOINT,      /* bDescriptorType: Endpoint */
  CDC_IN_EP,                         /* bEndpointAddress */
  0x02,                              /* bmAttributes: Bulk */
  LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),  /* wMaxPacketSize: */
  HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
  0x01,                               /* bInterval: ignore for Bulk transfer */
 /****************************HID************************************/
  /* Interface Association Descriptor */
  USBD_IAD_DESC_SIZE,                        // bLength
  USBD_IAD_DESCRIPTOR_TYPE,                  // bDescriptorType
  USBD_HID_FIRST_INTERFACE,                  // bFirstInterface
  USBD_HID_INTERFACE_NUM,                    // bInterfaceCount
  0x03,                                      // bFunctionClass
  0x00,                                      // bFunctionSubClass
  0x00,                                      // bInterfaceProtocol
  0x00,
  /********************  HID interface ********************/
  0x09,   /* bLength: Interface Descriptor size */
  USB_DESC_TYPE_INTERFACE,   /* bDescriptorType: */
  USBD_HID_INTERFACE,   /* bInterfaceNumber: Number of Interface */
  0x00,   /* bAlternateSetting: Alternate setting */
  0x02,   /* bNumEndpoints*/
  0x03,   /* bInterfaceClass: HID Class */
  0x00,   /* bInterfaceSubClass : 1=BOOT, 0=no boot*/
  0x00,   /* nInterfaceProtocol 0=none, 1=keyboard, 2=mouse*/
  0x00,          /* iInterface: */
    /* 18 */
  0x09,         /*bLength: HID Descriptor size*/
  HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/
  0x10,         /*bcdHID: HID Class Spec release number*/
  0x01,
  0x00,         /*bCountryCode: Hardware target country*/
  0x01,         /*bNumDescriptors: Number of HID class descriptors to follow*/
  0x22,         /*bDescriptorType*/
  HID_MOUSE_REPORT_DESC_SIZE,/*wItemLength: Total length of Report descriptor*/
  0x00,
  /********************  HID Endpoints ********************/
  /* 27 */
  0x07,          /*bLength: Endpoint Descriptor size*/
  USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/
  HID_EPIN_ADDR,     /*bEndpointAddress: Endpoint Address (IN)*/
  0x03,          /*bmAttributes: Interrupt endpoint*/
  HID_EPIN_SIZE, /*wMaxPacketSize: 4 Byte max */
  0x00,
  HID_FS_BINTERVAL,          /*bInterval: Polling Interval (10 ms)*/
  /* 34 */
  0x07,          /*bLength: Endpoint Descriptor size*/
  USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/
  HID_EPOUT_ADDR,     /*bEndpointAddress: Endpoint Address (IN)*/
  0x03,          /*bmAttributes: Interrupt endpoint*/
  HID_EPIN_SIZE, /*wMaxPacketSize: 4 Byte max */
  0x00,
  HID_FS_BINTERVAL,          /*bInterval: Polling Interval (10 ms)*/
};
/* USB Standard Device Descriptor */
__ALIGN_BEGIN  uint8_t USBD_Composite_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC]  __ALIGN_END =
{
  USB_LEN_DEV_QUALIFIER_DESC,
  USB_DESC_TYPE_DEVICE_QUALIFIER,
  0x00,
  0x02,
  0x00,
  0x00,
  0x00,
  0x40,
  0x01,
  0x00,
};
/**
  * @brief  USBD_Composite_Init
  *         Initialize the Composite interface
  * @param  pdev: device instance
  * @param  cfgidx: Configuration index
  * @retval status
  */
static uint8_t  USBD_Composite_Init (USBD_HandleTypeDef *pdev,
                            uint8_t cfgidx)
{
  uint8_t res = 0;
  pdev->pUserData = (void *)&USBD_Interface_fops_FS;
  res +=  USBD_CDC.Init(pdev,cfgidx);
  pCDCData = pdev->pClassData;
  pdev->pUserData = (void *)NULL;
  res +=  USBD_HID.Init(pdev,cfgidx);
  pHIDData = pdev->pClassData;
  return res;
}
/**
  * @brief  USBD_Composite_DeInit
  *         DeInitilaize  the Composite configuration
  * @param  pdev: device instance
  * @param  cfgidx: configuration index
  * @retval status
  */
static uint8_t  USBD_Composite_DeInit (USBD_HandleTypeDef *pdev,
                              uint8_t cfgidx)
{
    uint8_t res = 0;
    pdev->pClassData = pCDCData;
    pdev->pUserData = (void *)&USBD_Interface_fops_FS;
    res +=  USBD_CDC.DeInit(pdev,cfgidx);
    pdev->pClassData = pHIDData;
    pdev->pUserData = (void *)NULL;
    res +=  USBD_HID.DeInit(pdev,cfgidx);
    return res;
}
static uint8_t  USBD_Composite_EP0_RxReady(USBD_HandleTypeDef *pdev)
{
    return USBD_CDC.EP0_RxReady(pdev);
}
/**
* @brief  USBD_Composite_Setup
*         Handle the Composite requests
* @param  pdev: device instance
* @param  req: USB request
* @retval status
*/
static uint8_t  USBD_Composite_Setup (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
{
  switch (req->bmRequest & USB_REQ_RECIPIENT_MASK)
  {
   case USB_REQ_RECIPIENT_INTERFACE:
     switch(req->wIndex)
      {
         case USBD_CDC_DATA_INTERFACE:
         case USBD_CDC_CMD_INTERFACE:
             pdev->pClassData = pCDCData;
             pdev->pUserData =  (void *)&USBD_Interface_fops_FS;
           return(USBD_CDC.Setup(pdev, req));
         case USBD_HID_INTERFACE:
             pdev->pClassData = pHIDData;
             pdev->pUserData =  (void *)NULL;
           return(USBD_HID.Setup (pdev, req));
         default:
            break;
     }
     break;
   case USB_REQ_RECIPIENT_ENDPOINT:
     switch(req->wIndex)
     {
         case CDC_IN_EP:
         case CDC_OUT_EP:
         case CDC_CMD_EP:
             pdev->pClassData = pCDCData;
             pdev->pUserData = (void *)&USBD_Interface_fops_FS;
           return(USBD_CDC.Setup(pdev, req));
         case HID_EPIN_ADDR:
         case HID_EPOUT_ADDR:
             pdev->pClassData = pHIDData;
             pdev->pUserData = (void *)NULL;
           return(USBD_HID.Setup (pdev, req));
         default:
            break;
     }
     break;
  }
  return USBD_OK;
}
/**
* @brief  USBD_Composite_DataIn
*         handle data IN Stage
* @param  pdev: device instance
* @param  epnum: endpoint index
* @retval status
*/
uint8_t  USBD_Composite_DataIn (USBD_HandleTypeDef *pdev,
                              uint8_t epnum)
{
  switch(epnum)
  {
      case CDC_INDATA_NUM:
         pdev->pClassData = pCDCData;
         pdev->pUserData =  (void *)&USBD_Interface_fops_FS;
         return(USBD_CDC.DataIn(pdev,epnum));
      case HID_INDATA_NUM:
		 pdev->pClassData = pHIDData;
		 pdev->pUserData = (void *)NULL;
         return(USBD_HID.DataIn(pdev,epnum));
      default:
         break;
  }
  return USBD_FAIL;
}
/**
* @brief  USBD_Composite_DataOut
*         handle data OUT Stage
* @param  pdev: device instance
* @param  epnum: endpoint index
* @retval status
*/
uint8_t  USBD_Composite_DataOut (USBD_HandleTypeDef *pdev,
                               uint8_t epnum)
{
  switch(epnum)
  {
      case CDC_OUTDATA_NUM:
      case CDC_OUTCMD_NUM:
         pdev->pClassData = pCDCData;
         pdev->pUserData = (void *)&USBD_Interface_fops_FS;
         return(USBD_CDC.DataOut(pdev,epnum));
      case HID_OUTDATA_NUM:
		 pdev->pClassData = pHIDData;
		 pdev->pUserData =  (void *)NULL;
         return(USBD_HID.DataOut(pdev,epnum));
      default:
         break;
  }
  return USBD_FAIL;
}
/**
* @brief  USBD_Composite_GetHSCfgDesc
*         return configuration descriptor
* @param  length : pointer data length
* @retval pointer to descriptor buffer
*/
uint8_t  *USBD_Composite_GetFSCfgDesc (uint16_t *length)
{
   *length = sizeof (USBD_Composite_CfgFSDesc);
   return USBD_Composite_CfgFSDesc;
}
/**
* @brief  DeviceQualifierDescriptor
*         return Device Qualifier descriptor
* @param  length : pointer data length
* @retval pointer to descriptor buffer
*/
uint8_t  *USBD_Composite_GetDeviceQualifierDescriptor (uint16_t *length)
{
  *length = sizeof (USBD_Composite_DeviceQualifierDesc);
  return USBD_Composite_DeviceQualifierDesc;
}
/**
  * @}
  */
/**
  * @}
  */
/**
  * @}
  */
  1. 修改usb_device.c初始化内容
    在这里插入图片描述

  2. 修改最大接口数.

在这里插入图片描述

  1. 修改EP端口缓存地址
    在这里插入图片描述

10.修改hid cdc设备的classdata指针。

默认classdata指针是通过hUsbDeviceFS变量获取的,但是当前系统中有两个设备,对应的classdata是分开的。接收函数是中断调用usbd_composite再调用到cdc或者hid对应方法中,在usbd_composite是有重新对classdata进行赋值 ,但是发送函数是直接获取hUsbDeviceFS变量中的,所有需要直接指定使用对应的classdata。

cdc设备修改

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

hid设备修改
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3. 功能测试

键鼠的发送函数不用修改可以直接使用,在usbd_cdc_if.c的接收函数中也添加了CDC_Transmit_FS方法,接收到任何数据都会发送回去。

  while (1)
  {
    /* USER CODE END WHILE */
	
	if((HAL_GetTick() - old_tick) >= 1000)
	{
		CDC_Transmit_FS("123",3);
		old_tick = HAL_GetTick();
	}
	mouse_send(10,10);
	HAL_Delay(100);
	//keyboard_send(4);
	HAL_Delay(1000);
	mouse_send(10,10);
	HAL_Delay(100);
	//keyboard_send(0);
	HAL_Delay(1000);
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */

4. 参考链接

https://www.lijingquan.net/?p=2355

https://blog.csdn.net/longor1991/article/details/81095896

https://www.cnblogs.com/shangdawei/p/4712305.html

5. 附件

USB_HID
https://blog.csdn.net/wingceltis/article/details/102413072

USB_CDC

https://blog.csdn.net/wingceltis/article/details/102412729

工程地址
https://download.csdn.net/download/wingceltis/11836087

  • 2
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值