使用STM32F4 做了一个HID+CDC的复合设备(用的是STM32标准库和usb-host-device_lib_v2.2.1修改的),要做成HID双向收发和CDC双向收发功能,电脑能识别到复合设备,如下图
但我发现只有端点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 */
以下是现象
虚拟串口能正常收发,但是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 */
就变成了虚拟串口不能正常收发,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