图1 设备显示名称
根据这些参数,通过封装好的函数直接处理符合设备之间的关系,函数如下:
//MM32 USB复合设备类型初始化函数void u***d_class_init(void){ U8 if_num = 0;U16 desc_ptr = 0;desc_ptr += start_desc_fill(&USBD_ConfigDescriptor[desc_ptr], &USBD_ConfigDescriptor_HS[desc_ptr], if_num); #if (USBD_ADC_ENABLE)u***d_adc_init();#endif#if (USBD_MSC_ENABLE) #if !(defined(MSC_BL)) && defined(DRAG_N_DROP_SUPPORT)//change descriptors hereif (config_ram_get_disable_msd() == 1 || flash_algo_valid()==0 ){u***d_if_num -= USBD_MSC_ENABLE;USB_CONFIGURATION_DESCRIPTOR * u***_conf_desc = (USB_CONFIGURATION_DESCRIPTOR *)USBD_ConfigDescriptor;u***_conf_desc->bNumInterfaces = u***d_if_num;U16 u***_wtotal_len = USBD_WTOTALLENGTH_MAX - (USBD_MSC_DESC_LEN * USBD_MSC_ENABLE);u***_conf_desc->wTotalLength = u***_wtotal_len;USBD_ConfigDescriptor[u***_wtotal_len] = 0;USBD_HID_DescriptorOffset -= USBD_MSC_ENABLE * USBD_MSC_DESC_LEN;#if (USBD_HS_ENABLE == 1)u***_conf_desc = (USB_CONFIGURATION_DESCRIPTOR *)USBD_ConfigDescriptor_HS;u***_conf_desc->bNumInterfaces = u***d_if_num;u***_conf_desc->wTotalLength = u***_wtotal_len;USBD_ConfigDescriptor_HS[u***_wtotal_len] = 0;#endif } else#endif{u***d_msc_if_num = if_num++;desc_ptr += msc_desc_fill(&USBD_ConfigDescriptor[desc_ptr], &USBD_ConfigDescriptor_HS[desc_ptr], u***d_msc_if_num);u***d_msc_init();}#endif //#if (USBD_MSC_ENABLE) #if (USBD_CDC_ACM_ENABLE)u***d_cdc_acm_cif_num = if_num++;u***d_cdc_acm_dif_num = if_num++;desc_ptr += acm_cdc_desc_fill(&USBD_ConfigDescriptor[desc_ptr], &USBD_ConfigDescriptor_HS[desc_ptr], u***d_cdc_acm_cif_num);USBD_CDC_ACM_Initialize();#endif#if (USBD_HID_ENABLE) u***d_hid_if_num = if_num++;desc_ptr += hid_desc_fill(&USBD_ConfigDescriptor[desc_ptr], &USBD_ConfigDescriptor_HS[desc_ptr], u***d_hid_if_num);u***d_hid_init();#endif#if (USBD_WEBUSB_ENABLE)u***d_webu***_if_num = if_num++; desc_ptr += webu***_desc_fill(&USBD_ConfigDescriptor[desc_ptr], &USBD_ConfigDescriptor_HS[desc_ptr], u***d_webu***_if_num);#endif#if (USBD_BULK_ENABLE)u***d_bulk_if_num = if_num++; desc_ptr += bulk_desc_fill(&USBD_ConfigDescriptor[desc_ptr], &USBD_ConfigDescriptor_HS[desc_ptr], u***d_bulk_if_num);u***d_bulk_init();#endif#if (USBD_CLS_ENABLE)u***d_cls_init();#endif}//初始的描述配置填充static U16 start_desc_fill(U8 * config_desc, U8 * config_desc_hs, U8 if_num) {U8 * pD = 0;const U8 start_desc[] = { /* Configuration 1 */USB_CONFIGUARTION_DESC_SIZE, // bLength USB_CONFIGURATION_DESCRIPTOR_TYPE, // bDescriptorType WBVAL(USBD_WTOTALLENGTH_MAX), // wTotalLength USBD_IF_NUM_MAX, // bNumInterfaces 0x01, // bConfigurationValue: 0x01 is used to select this configuration 0x00, // iConfiguration: no string to describe this configuration USBD_CFGDESC_BMATTRIBUTES | // bmAttributes (USBD_POWER << 6),USBD_CFGDESC_BMAXPOWER // bMaxPower, device power consumption };pD = config_desc;memcpy(pD, start_desc, sizeof(start_desc));#if (USBD_HS_ENABLE == 1)pD = config_desc_hs;memcpy(pD, start_desc, sizeof(start_desc));#endifreturn sizeof(start_desc);}//HID的描述配置填充static U16 hid_desc_fill(U8 * config_desc, U8 * config_desc_hs, U8 if_num) {U8 * pD = 0;const U8 hid_desc[] = {HID_DESC#if ((USBD_HID_EP_INTOUT != 0) && (USBD_HID_EP_INTIN != 0))HID_EP_INOUT#elif (USBD_HID_EP_INTIN != 0)HID_EP_IN#elif (USBD_HID_EP_INTOUT != 0)HID_EP_OUT#endif};pD = config_desc;memcpy(pD, hid_desc, sizeof(hid_desc));((USB_INTERFACE_DESCRIPTOR *)pD)->bInterfaceNumber = if_num;#if (USBD_HS_ENABLE == 1) const U8 hid_desc_hs[] = {HID_DESC#if ((USBD_HID_EP_INTOUT != 0) && (USBD_HID_EP_INTIN != 0))HID_EP_INOUT_HS#elif (USBD_HID_EP_INTIN != 0) //#elseHID_EP_IN_HS#elif (USBD_HID_EP_INTOUT != 0)HID_EP_OUT_HS#endif};pD = config_desc_hs;memcpy(pD, hid_desc_hs, sizeof(hid_desc_hs));((USB_INTERFACE_DESCRIPTOR *)pD)->bInterfaceNumber = if_num;#endif return sizeof(hid_desc);}//CDC的描述配置填充static U16 acm_cdc_desc_fill(U8 * config_desc, U8 * config_desc_hs, U8 if_num) {U8 * pD = 0;const U8 cdc_desc[] = {#if (USBD_MULTI_IF)CDC_ACM_DESC_IAD(0, 2)#endifCDC_ACM_DESC_IF0CDC_ACM_EP_IF0CDC_ACM_DESC_IF1CDC_ACM_EP_IF1};pD = config_desc;memcpy(pD, cdc_desc, sizeof(cdc_desc));#if (USBD_MULTI_IF)((USB_INTERFACE_ASSOCIATION_DESCRIPTOR *)pD)->bFirstInterface = if_num;pD += USB_INTERFACE_ASSOC_DESC_SIZE;#endif ((USB_INTERFACE_DESCRIPTOR *)pD)->bInterfaceNumber = if_num;pD += USB_INTERFACE_DESC_SIZE + CDC_HEADER_SIZE + CDC_CALL_MANAGEMENT_SIZE + CDC_ABSTRACT_CONTROL_MANAGEMENT_SIZE;((UNION_FUNCTIONAL_DESCRIPTOR*)pD)->bMasterInterface = if_num;((UNION_FUNCTIONAL_DESCRIPTOR*)pD)->bSlaveInterface0 = if_num + 1;pD += CDC_UNION_SIZE + USB_ENDPOINT_DESC_SIZE;((USB_INTERFACE_DESCRIPTOR *)pD)->bInterfaceNumber = if_num + 1; #if (USBD_HS_ENABLE == 1) const U8 cdc_desc_hs[] = {#if (USBD_MULTI_IF)CDC_ACM_DESC_IAD(0, 2)#endifCDC_ACM_DESC_IF0CDC_ACM_EP_IF0_HSCDC_ACM_DESC_IF1CDC_ACM_EP_IF1_HS};pD = config_desc_hs;memcpy(pD, cdc_desc_hs, sizeof(cdc_desc_hs));#if (USBD_MULTI_IF)((USB_INTERFACE_ASSOCIATION_DESCRIPTOR *)pD)->bFirstInterface = if_num;pD += USB_INTERFACE_ASSOC_DESC_SIZE;#endif ((USB_INTERFACE_DESCRIPTOR *)pD)->bInterfaceNumber = if_num;pD += USB_INTERFACE_DESC_SIZE + CDC_HEADER_SIZE + CDC_CALL_MANAGEMENT_SIZE + CDC_ABSTRACT_CONTROL_MANAGEMENT_SIZE;((UNION_FUNCTIONAL_DESCRIPTOR*)pD)->bMasterInterface = if_num;((UNION_FUNCTIONAL_DESCRIPTOR*)pD)->bSlaveInterface0 = if_num + 1;pD += CDC_UNION_SIZE + USB_ENDPOINT_DESC_SIZE;((USB_INTERFACE_DESCRIPTOR *)pD)->bInterfaceNumber = if_num +1 ;#endif //(USBD_HS_ENABLE == 1) return sizeof(cdc_desc);}//MSC的描述配置填充static U16 msc_desc_fill(U8 * config_desc, U8 * config_desc_hs, U8 if_num) {U8 * pD = 0;const U8 msc_desc[] = { MSC_DESCMSC_EP};pD = config_desc;memcpy(pD, msc_desc, sizeof(msc_desc));((USB_INTERFACE_DESCRIPTOR *)pD)->bInterfaceNumber = if_num;#if (USBD_HS_ENABLE == 1) const U8 msc_desc_hs[] = { MSC_DESCMSC_EP_HS};pD = config_desc_hs;memcpy(pD, msc_desc_hs, sizeof(msc_desc_hs));((USB_INTERFACE_DESCRIPTOR *)pD)->bInterfaceNumber = if_num;#endifreturn sizeof(msc_desc);}#if (USBD_WEBUSB_ENABLE)//WEBUSB的描述配置填充static U16 webu***_desc_fill(U8 * config_desc, U8 * config_desc_hs, U8 if_num) {U8 * pD = 0;const U8 webu***_desc[] = {WEBUSB_DESC};pD = config_desc;memcpy(pD, webu***_desc, sizeof(webu***_desc));((USB_INTERFACE_DESCRIPTOR *)pD)->bInterfaceNumber = if_num;#if (USBD_HS_ENABLE == 1)pD = config_desc_hs;memcpy(pD, webu***_desc, sizeof(webu***_desc));((USB_INTERFACE_DESCRIPTOR *)pD)->bInterfaceNumber = if_num;#endif#if (USBD_WINUSB_ENABLE)pD = USBD_WinUSBDescriptorSetDescriptor + WINUSB_DESCRIPTOR_SET_HEADER_SIZE; ((WINUSB_FUNCTION_SUBSET_HEADER*)pD)->bFirstInterface = if_num;#else#error "WEBUSB requires WINUSB!"#endifreturn sizeof(webu***_desc); }#endif#if (USBD_BULK_ENABLE)//BUCK USB的描述配置填充static U16 bulk_desc_fill(U8 * config_desc, U8 * config_desc_hs, U8 if_num) {U8 * pD = 0;const U8 bulk_desc[] = { BULK_DESCBULK_EP};pD = config_desc;memcpy(pD, bulk_desc, sizeof(bulk_desc)); ((USB_INTERFACE_DESCRIPTOR *)pD)->bInterfaceNumber = if_num;#if (USBD_HS_ENABLE == 1) const U8 bulk_desc_hs[] = { BULK_DESCBULK_EP_HS};pD = config_desc_hs;memcpy(pD, bulk_desc_hs, sizeof(bulk_desc_hs)); ((USB_INTERFACE_DESCRIPTOR *)pD)->bInterfaceNumber = if_num;#endif#if (USBD_WINUSB_ENABLE)pD = USBD_WinUSBDescriptorSetDescriptor + WINUSB_DESCRIPTOR_SET_HEADER_SIZE;#if (USBD_WEBUSB_ENABLE)pD += WINUSB_FUNCTION_SUBSET_HEADER_SIZE + WINUSB_FEATURE_COMPATIBLE_ID_SIZE + DEVICE_INTERFACE_GUIDS_FEATURE_LEN;#endif ((WINUSB_FUNCTION_SUBSET_HEADER*)pD)->bFirstInterface = if_num;#else#error "BULK interfaces requires WINUSB!"#endifreturn sizeof(bulk_desc);}#endif
在使用MM32复合设备功能之前先调用USB初始化函数来初始化USB协议栈。
int main(void)
{
// USB Device Initialization and connect
u***d_init();
u***d_connect(__TRUE);
while (!u***d_configured()) // Wait for USB Device to configure
{
}
while (1)
{
……
}
}
然后和之前一样实现HID、WINUSB、CDC的函数接口即可,这样我们就完成MM32 MCU的复合设备功能,将程序下载到板子中,USB插上电脑,电脑上会枚举出复合设备,如下显示:
图2 设备管理器复合设备枚举列表
从图上可以看到MM32实现的复合设备在电脑上同时显示出HID、WINUSB以及CDC。对于MM32的复合设备来说,和单一设备一样简单方便,使用时只需要加入各自功能的代码即可。
0