C_linux_233 2022-04-16 15:20 采纳率: 0%
浏览 367
已结题

使用STM32F4 做了一个HID+CDC的复合设备,但是为什么我的HID数据发不出来

使用STM32F4 做了一个HID+CDC的复合设备(用的是STM32标准库和usb-host-device_lib_v2.2.1修改的),要做成HID双向收发和CDC双向收发功能,电脑能识别到复合设备,如下图

img

但我发现只有端点1能正常收发,就是比如设置以下端点

#define HID_IN_EP                    0x83
#define HID_OUT_EP                   0x03

#define CDC_IN_EP                       0x81  /* EP1 for data IN */
#define CDC_OUT_EP                      0x01  /* EP1 for data OUT */
#define CDC_CMD_EP                      0x82  /* EP2 for CDC commands */

以下是现象

img

虚拟串口能正常收发,但是HID无法正常收发,这是一种情况

如果改成这样

#define HID_IN_EP                    0x81
#define HID_OUT_EP                   0x01

#define CDC_IN_EP                       0x83  /* EP1 for data IN */
#define CDC_OUT_EP                      0x03  /* EP1 for data OUT */
#define CDC_CMD_EP                      0x82  /* EP2 for CDC commands */

img

就变成了虚拟串口不能正常收发,HID可以正常收发,到底哪里配置错了?

下面是代码


端点配置
#define HID_IN_EP                    0x83
#define HID_OUT_EP                   0x03

#define CDC_IN_EP                       0x81  /* EP1 for data IN */
#define CDC_OUT_EP                      0x01  /* EP1 for data OUT */
#define CDC_CMD_EP                      0x82  /* EP2 for CDC commands */

复合设备配置
__ALIGN_BEGIN static uint8_t USBD_HID_CDC_CfgDesc[USB_HID_CDC_CONFIG_DESC_SIZ] __ALIGN_END =
{
  0x09, /* bLength: Configuration Descriptor size */
  USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType: Configuration */
  USB_HID_CDC_CONFIG_DESC_SIZ,
  /* wTotalLength: Bytes returned */
  0x00,
  USBD_MAX_NUM_INTERFACES,         /*bNumInterfaces: 3 interfaces (2 for CDC, 1 for MSC)*/
  0x01,         /*bConfigurationValue: Configuration value*/
  0x00,         /*iConfiguration: Index of string descriptor describing
  the configuration*/
  0xC0,         /*bmAttributes: bus powered and Support Remote Wake-up */
  0x32,         /*MaxPower 100 mA: this current is used for detecting Vbus*/
  
    /*---------------------------------------------------------------------------*/
  //IAD Interface Association Descriptor
 0x08           ,//bLenght:Interface Descriptor size
 0x0B     ,//bDescriptorType:IAD
 0x00,//bFirstInterface
 0x01,//bInterfaceCount
 0x03,//bFunctionClass:HID
 0x00,//bFunctionSubClass
 0x00,//bInterfaceProtocol
 0x05,//iFunction  
  /************** Descriptor of Joystick Mouse interface ****************/
  /* 09 */
  0x09,         /*bLength: Interface Descriptor size*/
  USB_INTERFACE_DESCRIPTOR_TYPE,/*bDescriptorType: Interface descriptor type*/
  0x00,         /*bInterfaceNumber: Number of Interface*/
  0x00,         /*bAlternateSetting: Alternate setting*/
  0x02,         /*bNumEndpoints*/
  0x03,         /*bInterfaceClass: HID*/
  0x00,         /* bInterfaceSubClass : 1=BOOT, 0=no boot */
  0x00,         /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
  0,            /*iInterface: Index of string descriptor*/
  /******************** Descriptor of Joystick Mouse HID ********************/
  /* 18 */
  0x09,         /*bLength: HID Descriptor size*/
  HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/
  0x11,         /*bcdHID: HID Class Spec release number*/
  //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,
  /******************** Descriptor of Mouse endpoint ********************/
  /* 27 */
  0x07,          /*bLength: Endpoint Descriptor size*/
  USB_ENDPOINT_DESCRIPTOR_TYPE, /*bDescriptorType:*/
  
  HID_IN_EP,     /*bEndpointAddress: Endpoint Address (IN)*/
  0x03,          /*bmAttributes: Interrupt endpoint*/
  HID_IN_PACKET, /*wMaxPacketSize: 64 Byte max */
  0x00,
  0x01,          /*bInterval: Polling Interval (10 ms)*/
  //0x01,          /* bInterval: Polling Interval (32 ms) */
  /* 34 */
  0x07,    /* bLength: Endpoint Descriptor size */
  USB_ENDPOINT_DESCRIPTOR_TYPE, /*bDescriptorType:*/
                                /*    Endpoint descriptor type */
  HID_OUT_EP,     /*bEndpointAddress: Endpoint Address (OUT)*/
  0x03,          /*bmAttributes: Interrupt endpoint*/
  HID_OUT_PACKET, /*wMaxPacketSize: 64 Byte max */
  0x00,
  0x01,    /* bInterval: Polling Interval (20 ms) */
    /* 41 */
   /******** /IAD should be positioned just before the CDC interfaces ******
                IAD to associate the two CDC interfaces */
  
  0x08, /* bLength */
  0x0B, /* bDescriptorType */
  0x01, /* bFirstInterface */
  0x02, /* bInterfaceCount */
  0x02, /* bFunctionClass */
  0x02, /* bFunctionSubClass */
  0x01, /* bFunctionProtocol */
  0x00, /* iFunction (Index of string descriptor describing this function) */
  
  
  /*---------------------------------------------------------------------------*/
  
  /*Interface Descriptor */
  0x09,   /* bLength: Interface Descriptor size */
  USB_INTERFACE_DESCRIPTOR_TYPE,  /* bDescriptorType: Interface */
  /* Interface descriptor type */
  0x01,   /* 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 */
  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 */
  0x02,   /* bDataInterface: 2 */
  
  /*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 */
  0x02,   /* bSlaveInterface0: Data Class Interface */
  
  /*Endpoint 2 Descriptor*/
  0x07,                           /* bLength: Endpoint Descriptor size */
  USB_ENDPOINT_DESCRIPTOR_TYPE,   /* bDescriptorType: Endpoint */
  CDC_CMD_EP,                     /* bEndpointAddress */
  0x03,                           /* bmAttributes: Interrupt */
  LOBYTE(CDC_CMD_PACKET_SZE),     /* wMaxPacketSize: */
  HIBYTE(CDC_CMD_PACKET_SZE),
#ifdef USE_USB_OTG_HS
  0x10,                           /* bInterval: */
#else
  0xFF,                           /* bInterval: */
#endif /* USE_USB_OTG_HS */
  
  /*---------------------------------------------------------------------------*/
  
  /*Data class interface descriptor*/
  0x09,   /* bLength: Endpoint Descriptor size */
  USB_INTERFACE_DESCRIPTOR_TYPE,  /* bDescriptorType: */
  0x02,   /* bInterfaceNumber: Number of Interface */
  0x00,   /* bAlternateSetting: Alternate setting */
  0x02,   /* bNumEndpoints: Two endpoints used */
  0x0A,   /* bInterfaceClass: CDC */
  0x00,   /* bInterfaceSubClass: */
  0x00,   /* bInterfaceProtocol: */
  0x00,   /* iInterface: */
  
  /*Endpoint OUT Descriptor*/
  0x07,   /* bLength: Endpoint Descriptor size */
  USB_ENDPOINT_DESCRIPTOR_TYPE,      /* bDescriptorType: Endpoint */
  CDC_OUT_EP,                        /* bEndpointAddress */
  0x02,                              /* bmAttributes: Bulk */
  LOBYTE(CDC_DATA_MAX_PACKET_SIZE),  /* wMaxPacketSize: */
  HIBYTE(CDC_DATA_MAX_PACKET_SIZE),
  0x00,                              /* bInterval: ignore for Bulk transfer */
  
  /*Endpoint IN Descriptor*/
  0x07,   /* bLength: Endpoint Descriptor size */
  USB_ENDPOINT_DESCRIPTOR_TYPE,      /* bDescriptorType: Endpoint */
  CDC_IN_EP,                         /* bEndpointAddress */
  0x02,                              /* bmAttributes: Bulk */
  LOBYTE(CDC_DATA_MAX_PACKET_SIZE),  /* wMaxPacketSize: */
  HIBYTE(CDC_DATA_MAX_PACKET_SIZE),
  0x00                          /* bInterval */
}


HID报文如下
__ALIGN_BEGIN static uint8_t HID_MOUSE_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE] __ALIGN_END =
{

    //0x05:0000 01 01 ÕâÊǸöÈ«¾ÖÌõÄ¿£¬ÓÃ;ҳΪSTÒ³
    0x05, 0x8c, /* USAGE_PAGE (ST Page) */ 
    //0x09:0000 10 01 ÕâÊǸö¾Ö²¿±äÁ¿£¬ÓÃ;ΪDemo Kit
    0x09, 0x01, /* USAGE (Demo Kit) */ 
    //0xa1:1010 00 01 ÕâÊÇÒ»¸öÖ÷ÌõÄ¿£¬¼¯ºÏΪӦÓü¯ºÏ
    0xa1, 0x01, /* COLLECTION (Application) */ 
    
    /* ÊäÈ뱨¸æ*/ 
    //0x09:0000 10 01 ÕâÊǸö¾Ö²¿ÌõÄ¿£¬ÓÃ;Ϊ³§ÉÌID
    0x09,0x03, // USAGE ID - Vendor defined 
    //0x15:0001 01 01 ÕâÊǸöÈ«¾ÖÌõÄ¿£¬Âß¼­×îСֵΪ0
    0x15,0x00, // LOGICAL_MINIMUM (0) 
    //0x26:0010 01 10 ÕâÊǸöÈ«¾ÖÌõÄ¿£¬Âß¼­×î´óֵΪ255
    0x26,0x00, 0xFF, // LOGICAL_MAXIMUM (255) 
    //0x75:0111 01 01 ÕâÊǸöÈ«¾ÖÌõÄ¿£¬±¨¸æ´óСΪ8λ
    0x75,0x08, // REPORT_SIZE (8bit) 
    //0x95:1001 01 01 ÕâÊǸöÈ«¾ÖÌõÄ¿£¬±¨¸æÊýÁ¿Îª64
    0x95,0x40, // REPORT_COUNT (64Byte) 
    //0x81:1000 00 01 ÕâÊǸöÖ÷ÌõÄ¿£¬×öÊäÈ룬Data±íʾÕâЩÊý¾Ý¿É±ä£¬Var±íʾÕâЩÐì¾ÓÓÚÊǶÀÁ¢µÄ±äÁ¿£¬Abs±íʾ¾ø¶ÔÖµ
    0x81,0x02, // INPUT (Data,Var,Abs) 
    
    /*Êä³ö±¨¸æ*/ 
    //0x09:0000 10 01 ÕâÊǸö¾Ö²¿ÌõÄ¿£¬ÓÃ;Ϊ³§ÉÌID
    0x09,0x04, // USAGE ID - Vendor defined 
    //0x15:0001 01 01 ÕâÊǸöÈ«¾ÖÌõÄ¿£¬Âß¼­×îСֵΪ0
    0x15,0x00, // LOGICAL_MINIMUM (0) 
    //0x26:0010 01 10 ÕâÊǸöÈ«¾ÖÌõÄ¿£¬Âß¼­×î´óֵΪ255
    0x26,0x00,0xFF, // LOGICAL_MAXIMUM (255) 
    //0x75:0111 01 01 ÕâÊǸöÈ«¾ÖÌõÄ¿£¬±¨¸æ´óСΪ8λ
    0x75,0x08, // REPORT_SIZE (8bit) 
    //0x95:1001 01 01 ÕâÊǸöÈ«¾ÖÌõÄ¿£¬±¨¸æÊýÁ¿Îª64
    0x95,0x40, // REPORT_COUNT (64Byte) 
    //0x91:1001 00 01 ÕâÊǸöÈ«¾ÖÌõÄ¿£¬×öÊä³ö£¬Data±íʾÕâЩÊý¾Ý¿É±ä£¬Var±íʾÕâЩÐì¾ÓÓÚÊǶÀÁ¢µÄ±äÁ¿£¬Abs±íʾ¾ø¶ÔÖµ
    0x91,0x02, // OUTPUT (Data,Var,Abs) 

    0xc0 /* END_COLLECTION */
}; 



初始化如下

uint8_t  usbd_hid_cdc_Init (void *pdev,
                            uint8_t cfgidx)
{
    USBD_HID_Init(pdev,cfgidx);
    usbd_cdc_Init(pdev,cfgidx);
    return USBD_OK;
}





uint8_t  usbd_hid_cdc_DeInit (void *pdev,
                              uint8_t cfgidx)
{
    USBD_HID_DeInit(pdev,cfgidx);
    usbd_cdc_DeInit(pdev,cfgidx);
    return USBD_OK;
}




uint8_t  usbd_hid_cdc_Setup (void *pdev,
                             USB_SETUP_REQ *req)
{
        switch (req->bmRequest & USB_REQ_RECIPIENT_MASK)
        {
            case USB_REQ_RECIPIENT_INTERFACE:
                    if (req->wIndex == HID_INTERFACE)
                    {
                        return (USBD_HID_Setup (pdev, req));
                    }
                    else
                    {
                        return (usbd_cdc_Setup(pdev, req));
                    }
                
            case USB_REQ_RECIPIENT_ENDPOINT:
                    if (req->wIndex == HID_IN_EP)
                    {
                        return (USBD_HID_Setup (pdev, req));   
                    }
                    else
                    {
                        return (usbd_cdc_Setup(pdev, req));
                    }
        }   
        return USBD_OK;
}




uint8_t  *USBD_hid_cdc_GetCfgDesc (uint8_t speed, uint16_t *length)
{
  *length = sizeof (USBD_HID_CDC_CfgDesc);
  return USBD_HID_CDC_CfgDesc;
}



uint8_t  usbd_hid_cdc_DataIn (void *pdev,
                              uint8_t epnum)
{
  if (epnum == (CDC_IN_EP&~0x80) )
  {
    return (usbd_cdc_DataIn(pdev, epnum));
  }
  else
  {
    return (USBD_HID_DataIn(pdev, epnum));
  }
}


uint8_t  usbd_hid_cdc_DataOut (void *pdev,
                               uint8_t epnum)
{
    if (epnum == (CDC_CMD_EP &0x0F) )
  {
    return (usbd_cdc_DataOut(pdev, epnum));
  }
  else
  {
    return (USBD_HID_DataOut(pdev, epnum));
  }
    
  //return (usbd_cdc_DataOut(pdev, epnum)); 
}

uint8_t  usbd_hid_cdc_SOF (void *pdev)
{      
  return (usbd_cdc_SOF(pdev));
}




uint8_t  usbd_hid_cdc_EP0_RxReady(void *pdev)
{

  return (usbd_cdc_EP0_RxReady(pdev));
}



如有需要可以下载此代码,用的是正点原子阿波罗F429开发板,已经移植好了,编译烧录即可用,也是同样的现象,HID 和CDC只有选择了0x81和0x01端点才能正常收发
链接:https://pan.baidu.com/s/1U4ItHVa4fkGUywtKpOsx1w?pwd=xkov
提取码:xkov

  • 写回答

1条回答 默认 最新

  • C_linux_233 2022-04-16 18:18
    关注

    自己解决了哈
    在usb_core.c里的USB_OTG_SelectCore函数中有这么一段

      if (coreID == USB_OTG_FS_CORE_ID)
      {
        baseAddress                = USB_OTG_FS_BASE_ADDR;
        pdev->cfg.coreID           = USB_OTG_FS_CORE_ID;
        pdev->cfg.host_channels    = 8 ;
        pdev->cfg.dev_endpoints    = 4 ;
        pdev->cfg.TotalFifoSize    = 320; /* in 32-bits */
        pdev->cfg.phy_itface       = USB_OTG_EMBEDDED_PHY;     
        
    #ifdef USB_OTG_FS_SOF_OUTPUT_ENABLED    
        pdev->cfg.Sof_output       = 1;    
    #endif 
        
    #ifdef USB_OTG_FS_LOW_PWR_MGMT_SUPPORT    
        pdev->cfg.low_power        = 1;    
    #endif     
      }
    
    

    其中pdev->cfg.TotalFifoSize是指定了缓冲区大小

    而我的程序里面,在usb_conf.h中

    #ifdef USB_OTG_FS_CORE
     #define RX_FIFO_FS_SIZE                          128
     #define TX0_FIFO_FS_SIZE                          64
     #define TX1_FIFO_FS_SIZE                        128 
     #define TX2_FIFO_FS_SIZE                          64
     #define TX3_FIFO_FS_SIZE                          64
    
    

    已经大于320了

    做出以下修改

    #ifdef USB_OTG_FS_CORE
     #define RX_FIFO_FS_SIZE                          64
     #define TX0_FIFO_FS_SIZE                          64
     #define TX1_FIFO_FS_SIZE                        64 
     #define TX2_FIFO_FS_SIZE                          64
     #define TX3_FIFO_FS_SIZE                          64
    
    

    HID 和CDC就可以正常收发了

    评论

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 4月16日
  • 修改了问题 4月16日
  • 赞助了问题酬金50元 4月16日
  • 修改了问题 4月16日
  • 展开全部

悬赏问题

  • ¥15 为什么eclipse不能再下载了?
  • ¥15 编辑cmake lists 明明写了project项目名,但是还是报错怎么回事
  • ¥15 关于#计算机视觉#的问题:求一份高质量桥梁多病害数据集
  • ¥15 特定网页无法访问,已排除网页问题
  • ¥50 如何将脑的图像投影到颅骨上
  • ¥15 提问一个关于vscode相关的环境配置问题,就是输入中文但是显示不出来,代码在idea可以显示中文,但在vscode不行,不知道怎么配置环境
  • ¥15 netcore使用PuppeteerSharp截图
  • ¥20 这张图页头,页脚具体代码该怎么写?
  • ¥20 WPF MVVM模式 handycontrol 框架, hc:SearchBar 控件 Text="{Binding NavMenusKeyWords}" 绑定取不到值
  • ¥15 需要手写数字信号处理Dsp三个简单题 不用太复杂