你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32 HID和CDC组合设备无法枚举成功

[复制链接]
小白小灰 提问时间:2024-12-14 12:37 / 未解决
想用STM32F103C8T6最小系统板试验HID和CDC组合设备,单独的HID和CDC都能枚举成功,但是参考网上多篇大佬的组合设备的教程,应该是一步步照做了,但插到电脑后问题弹出无法识别的USB设备,枚举不成功。求大佬帮忙看下是哪里出问题了,非常感谢。工程源码见附件。

/*********************
usbd_composite.c
**********************/

/* Includes -------------------------------------------*/
#include <usbd_composite.h>
#include "usbd_ctlreq.h"
#include "usbd_customhid.h"
#include "usbd_cdc.h"
#include "usbd_cdc_if.h"
#include "usbd_custom_hid_if.h"

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_Setup(USBD_HandleTypeDef *pdev,
USBD_SetupReqTypedef *req);

static uint8_t  *USBD_COMPOSITE_GetCfgDesc(uint16_t *length);

static uint8_t  *USBD_COMPOSITE_GetDeviceQualifierDesc(uint16_t *length);

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_EP0_RxReady(USBD_HandleTypeDef *pdev);

static uint8_t  USBD_COMPOSITE_EP0_TxReady(USBD_HandleTypeDef *pdev);

static uint8_t  USBD_COMPOSITE_SOF(USBD_HandleTypeDef *pdev);

static uint8_t  USBD_COMPOSITE_IsoINIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum);

static uint8_t  USBD_COMPOSITE_IsoOutIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum);

USBD_ClassTypeDef  USBD_COMPOSITE_ClassDriver =
{
USBD_COMPOSITE_Init,
USBD_COMPOSITE_DeInit,
USBD_COMPOSITE_Setup,
USBD_COMPOSITE_EP0_TxReady,  //NULL
USBD_COMPOSITE_EP0_RxReady,  //在上面?
USBD_COMPOSITE_DataIn,
USBD_COMPOSITE_DataOut,
USBD_COMPOSITE_SOF,//NULL
USBD_COMPOSITE_IsoINIncomplete,//NULL
USBD_COMPOSITE_IsoOutIncomplete,//NULL
USBD_COMPOSITE_GetCfgDesc,//NULL
USBD_COMPOSITE_GetCfgDesc,
USBD_COMPOSITE_GetCfgDesc,//NULL
USBD_COMPOSITE_GetDeviceQualifierDesc,
};

#if defined ( __ICCARM__ ) /*!< IAR Compiler */
#pragma data_alignment=4
#endif
/* USB COMPOSITE device Configuration Descriptor */
static uint8_t USBD_COMPOSITE_CfgDesc[USB_COMPOSITE_CONFIG_DESC_SIZ] =
{
/*配置描述符   9   */
#if 1
0x09, /* bLength: Configuation Descriptor size */
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
USB_COMPOSITE_CONFIG_DESC_SIZ,  /* wTotalLength: Bytes returned 9+66+33=0x6c*/
0x00,
0x03,         /*bNumInterfaces: 1 interface  0x03  USBD_MAX_NUM_INTERFACES 键盘1个,CDC 2个*/
0x01,         /*bConfigurationValue: Configuration value*/
0x00,         /*iConfiguration: Index of string descriptor describing the configuration*/
0x80,         /*bmAttributes: bus powered and Supports Remote Wakeup */
0x32,         /*MaxPower 100 mA: this current is used for detecting Vbus*/
/* 09 */
#endif

/********** HID 25+8**************/
#if 1
/* Interface Association Descriptor */
0x08,                        // bLength IAD描述符大小
0x0b,                  // bDescriptorType IAD描述符类型
0x00,                                      // bFirstInterface 接口描述符是在总的配置描述符中的第几个从0开始数
0x01,                                      // bInterfaceCount 接口描述符数量
0x03,                                      // bFunctionClass  设备符中的bDeviceClass
0x00,                                      // bFunctionSubClass  设备符中的bDeviceSubClass
0x00,                                      // bInterfaceProtocol 设备符中的bDeviceProtocol
0x00,

/************** Descriptor of CUSTOM HID interface ****************/

0x09,         /*bLength: Interface Descriptor size*/
USB_DESC_TYPE_INTERFACE,/*bDescriptorType: Interface descriptor type*/
USBD_INTERFACE_HID,         /*bInterfaceNumber: 0x02,接口编号 CDC是00 01,这里是02 */
0x00,         /*bAlternateSetting: Alternate setting*/
0x01,         /*bNumEndpoints  非0端点的数目。只有一个输入(从电脑来说),因此该值为1    */
0x03,         /*bInterfaceClass: CUSTOM_HID*/
0x01,         /*bInterfaceSubClass : 1=BOOT, 0=no boot*/
0x01,         /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/
0,            /*iInterface: Index of string descriptor*/
/******************** Descriptor of CUSTOM_HID *************************/
/* 9 */
0x09,         /*bLength: CUSTOM_HID Descriptor size*/
CUSTOM_HID_DESCRIPTOR_TYPE, /*bDescriptorType:CUSTOM HID描述符的编号是0x21*/
0x10,         /*bCUSTOM_HIDUSTOM_HID: HID1.1协议*/
0x01,
0x21,         /*bCountryCode: 键盘国家代码,美国为0x21*/
0x01,         /*bNumDescriptors: Number of CUSTOM_HID class descriptors to follow*/
0x22,         /*bDescriptorType*/
USBD_CUSTOM_HID_REPORT_DESC_SIZE,/*wItemLength: Total length of Report descriptor*/
0x00,
/******************** Descriptor of Custom HID endpoints ********************/
/* 18 */
0x07,          /*bLength: Endpoint Descriptor size*/
USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/

CUSTOM_HID_EPIN_ADDR,     /*bEndpointAddress: Endpoint Address (IN)*/
0x03,          /*bmAttributes: Interrupt endpoint*/
CUSTOM_HID_EPIN_SIZE, /*wMaxPacketSize: 2 Byte max */
0x00,
CUSTOM_HID_FS_BINTERVAL,          /*bInterval: Polling Interval */
/* 25 */
#endif

/********** CDC  66   **************/
#if 1

/* Interface Association Descriptor 接口关联描述符    8   */
0x08,                   // bLength IAD描述符大小
0x0b,                   // bDescriptorType IAD描述符类型为0x0b
0x01,                   // bFirstInterface 接口描述符是在总的配置描述符中的第几个从0开始数
0x02,                   // bInterfaceCount 接口描述符数量 USBD_CDC_INTERFACE_NUM
0x02,                   // bFunctionClass  设备属于哪一类bDeviceClass CDC控制类为0x02
0x02,                              // bFunctionSubClass  设备中的bDeviceSubClass
0x01,                          // bInterfaceProtocol 设备中的bDeviceProtocol
0x00,                   //
/*Interface Descriptor  08*/
0x09,   /* bLength: Interface Descriptor size */
USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: Interface *//* Interface descriptor type */
USBD_INTERFACE_CDC_CMD,   /* bInterfaceNumber: Number of Interface 0x00控制接口为0*/
0x00,   /* bAlternateSetting: Alternate setting 备用接口为0*/
0x01,   /* bNumEndpoints: One endpoints used 使用一个端点01*/
0x02,   /* bInterfaceClass: CDC类为0x02*/
0x02,   /* bInterfaceSubClass: Abstract Control Model */
0x01,   /* bInterfaceProtocol: Common AT commands */
0x00,   /* iInterface: 说明文字的编号*/

/*Header Functional Descriptor  17*/
0x05,   /* bLength: Endpoint Descriptor size */
0x24,   /* bDescriptorType: CS_INTERFACE */
0x00,   /* bDescriptorSubtype: Header Func Desc */
0x10,   /* bcdCDC: spec release number */
0x01,

/*Call Management Functional Descriptor 22*/
0x05,   /* bFunctionLength */
0x24,   /* bDescriptorType: CS_INTERFACE */
0x01,   /* bDescriptorSubtype: Call Management Func Desc */
0x00,   /* bmCapabilities: D0+D1 */
0x01,   /* bDataInterface: 1 */

/*ACM Functional Descriptor  27*/
0x04,   /* bFunctionLength */
0x24,   /* bDescriptorType: CS_INTERFACE */
0x02,   /* bDescriptorSubtype: Abstract Control Management desc */
0x02,   /* bmCapabilities 2字节*/

/*Union Functional Descriptor 31*/
0x05,   /* bFunctionLength */
0x24,   /* bDescriptorType: CS_INTERFACE */
0x06,   /* bDescriptorSubtype: Union func desc */
USBD_INTERFACE_CDC_CMD,   /* bMasterInterface: Communication class interface USBD_CDC_CMD_INTERFACE*/
USBD_INTERFACE_CDC,   /* bSlaveInterface0: Data Class Interface  USBD_CDC_DATA_INTERFACE */

/*Endpoint 2 Descriptor  36*/
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  43*/
0x09,   /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: */
USBD_INTERFACE_CDC,   /* bInterfaceNumber: Number of Interface  0x02 */
0x00,   /* bAlternateSetting: Alternate setting */
0x02,   /* bNumEndpoints: Two endpoints used */
0x0A,   /* bInterfaceClass: CDC */
0x00,   /* bInterfaceSubClass: */
0x00,   /* bInterfaceProtocol: */
0x00,   /* iInterface: */

/*Endpoint OUT Descriptor  52*/
0x07,   /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT,      /* bDescriptorType: Endpoint */
CDC_OUT_EP,                        /* bEndpointAddress */
0x02,                              /* bmAttributes: Bulk */
LOBYTE(CDC_DATA_HS_MAX_PACKET_SIZE),  /* wMaxPacketSize: */
HIBYTE(CDC_DATA_HS_MAX_PACKET_SIZE),
0x00,                              /* bInterval: ignore for Bulk transfer */

/*Endpoint IN Descriptor 59*/
0x07,   /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT,      /* bDescriptorType: Endpoint */
CDC_IN_EP,                         /* bEndpointAddress */
0x02,                              /* bmAttributes: Bulk */
LOBYTE(CDC_DATA_HS_MAX_PACKET_SIZE),  /* wMaxPacketSize: */
HIBYTE(CDC_DATA_HS_MAX_PACKET_SIZE),
0x00,                               /* bInterval: ignore for Bulk transfer */
/***66****/
#endif

};

#if defined ( __ICCARM__ ) /*!< IAR Compiler */
#pragma data_alignment=4
#endif
/* USB Standard Device Descriptor */
static uint8_t USBD_COMPOSITE_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] =
{
USB_LEN_DEV_QUALIFIER_DESC,
USB_DESC_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x01,
0x00,
};

static uint8_t  USBD_COMPOSITE_Init(USBD_HandleTypeDef *pdev,
uint8_t cfgidx)
{
uint8_t res = 0;
/*CDC*/
pdev->pUserData=(void *)&USBD_CDC_fops_FS;
res+=USBD_CDC_Init(pdev,cfgidx);
pClassDataCDC=pdev->pClassData;
/*hid*/
//        pdev->pUserData=(void *)&USBD_CustomHID_fops_FS;
pdev->pUserData=NULL;//根据STM32配置组合设备(HID+CDC)改
res+=USBD_CUSTOM_HID_Init(pdev,cfgidx);
pClassDataHID=pdev->pClassData;
return res;
}

static uint8_t  USBD_COMPOSITE_DeInit(USBD_HandleTypeDef *pdev,
uint8_t cfgidx)
{
uint8_t res = 0;
/*CDC*/
pdev->pUserData=(void *)&USBD_CDC_fops_FS;
pClassDataCDC=pdev->pClassData;
res+=USBD_CDC_DeInit(pdev,cfgidx);
/*hid*/
//        pdev->pUserData=(void *)&USBD_CustomHID_fops_FS;
pdev->pUserData=NULL;//根据STM32配置组合设备(HID+CDC)改
res+=USBD_CUSTOM_HID_DeInit(pdev,cfgidx);
//        pClassDataHID=pdev->pClassData;

return res;
}

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_INTERFACE_CDC:
case USBD_INTERFACE_CDC_CMD:
pdev->pClassData=pClassDataCDC;
pdev->pUserData=&USBD_CDC_fops_FS;
return(USBD_CDC.Setup(pdev,req));

          case USBD_INTERFACE_HID:
                          pdev->pClassData=pClassDataHID;
//                                  pdev->pUserData=&USBD_CustomHID_fops_FS;
pdev->pUserData=NULL;
return(USBD_CUSTOM_HID.Setup(pdev,req));

          default:
//          printf("[%s]%d:req->wIndex=%x\r\n",__func__,__LINE__,req->wIndex);
break;
}
break;

case USB_REQ_RECIPIENT_ENDPOINT:
  switch (req->wIndex)
  {
          case CDC_IN_EP:
          case CDC_OUT_EP:
          case CDC_CMD_EP:
                          pdev->pClassData=pClassDataCDC;
                          pdev->pUserData=&USBD_CDC_fops_FS;
                          return(USBD_CDC.Setup(pdev,req));

          case CUSTOM_HID_EPIN_ADDR:
//      case CUSTOM_HID_EPOUT_ADDR:
                            pdev->pClassData=pClassDataHID;
//              pdev->pUserData=&USBD_CustomHID_fops_FS;
                          pdev->pUserData=NULL;//根据STM32配置组合设备(HID+CDC)改
                          return(USBD_CUSTOM_HID.Setup(pdev,req));

                default:
//                printf("[%s]%d:\r\n",__func__,__LINE__);
                  break;
  }
  break;

default:

  break;
}

return USBD_OK;
}

static uint8_t  *USBD_COMPOSITE_GetCfgDesc(uint16_t *length)
{
*length = sizeof(USBD_COMPOSITE_CfgDesc);
return USBD_COMPOSITE_CfgDesc;
}

uint8_t  *USBD_COMPOSITE_DeviceQualifierDescriptor(uint16_t *length)
{
*length = sizeof(USBD_COMPOSITE_DeviceQualifierDesc);
return USBD_COMPOSITE_DeviceQualifierDesc;
}

static uint8_t  USBD_COMPOSITE_DataIn(USBD_HandleTypeDef *pdev,uint8_t epnum)
{
switch(epnum)
{
case (CDC_IN_EP & 0x0f):
pdev->pClassData=pClassDataCDC;
pdev->pUserData=&USBD_CDC_fops_FS;
return(USBD_CDC.DataIn(pdev,epnum));

        case (CUSTOM_HID_EPIN_ADDR & 0x0f):
                        pdev->pClassData=pClassDataHID;
//                                pdev->pUserData=(void *)&USBD_CustomHID_fops_FS;
pdev->pUserData=NULL;
return(USBD_CUSTOM_HID.DataIn(pdev,epnum));

        default:
                  break;
}
return USBD_FAIL;
}

static uint8_t  USBD_COMPOSITE_EP0_RxReady(USBD_HandleTypeDef *pdev)
{
pdev->pClassData=pClassDataCDC;
pdev->pUserData=&USBD_CDC_fops_FS;
return USBD_CDC.EP0_RxReady(pdev);

//        USBD_CUSTOM_HID_HandleTypeDef     *hhid = (USBD_CUSTOM_HID_HandleTypeDef *)pdev->pClassData;
//
//        if (hhid->IsReportAvailable == 1U)
//        {
//                ((USBD_CUSTOM_HID_ItfTypeDef *)pdev->pUserData)->OutEvent(hhid->Report_buf[0],
//                                                                                                                                  hhid->Report_buf[1]);
//                hhid->IsReportAvailable = 0U;
//        }
//    return USBD_CUSTOM_HID.EP0_RxReady(pdev);
//    return USBD_OK;
}

static uint8_t  USBD_COMPOSITE_EP0_TxReady(USBD_HandleTypeDef *pdev)
{

return USBD_OK;
}

static uint8_t  USBD_COMPOSITE_SOF(USBD_HandleTypeDef *pdev)
{

return USBD_OK;
}

static uint8_t  USBD_COMPOSITE_IsoINIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum)
{

return USBD_OK;
}

static uint8_t  USBD_COMPOSITE_IsoOutIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum)
{

return USBD_OK;
}

static uint8_t  USBD_COMPOSITE_DataOut(USBD_HandleTypeDef *pdev,
uint8_t epnum)
{
switch(epnum)
{

        case CDC_OUT_EP:
        case CDC_CMD_EP:
                        pdev->pClassData=pClassDataCDC;
                        pdev->pUserData=&USBD_CDC_fops_FS;
                        return(USBD_CDC.DataOut(pdev,epnum));
//                case CUSTOM_HID_EPOUT_ADDR:
//                                pdev->pClassData=pClassDataHID;
//                                pdev->pUserData=(void *)&USBD_CustomHID_fops_FS;
//                                return(USBD_CUSTOM_HID.DataOut(pdev,epnum));

        default:
                        break;
}
return USBD_FAIL;
}

uint8_t  *USBD_COMPOSITE_GetDeviceQualifierDesc(uint16_t *length)
{
*length = sizeof(USBD_COMPOSITE_DeviceQualifierDesc);
return USBD_COMPOSITE_DeviceQualifierDesc;
}
目录.jpg

HID_CDC.zip

下载

7.44 MB, 下载次数: 2, 下载积分: ST金币 -1

收藏 评论0 发布时间:2024-12-14 12:37

举报

0个回答

所属标签

相似问题

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版