Sharing notes taken during creation a USB stack composite demo: CDC + Generic HID, this demo is based on FrdmK22f bare mental and MCUXpresso SDK2.2. Creating the CDC + Generic HID composite demo requires combining the CDC example code and HID Generic example code into a single example. 1 Find an existing example as a template A new composite device application should use the existing examples as a template. MCUXpresso SDK2.2 USB stack provides three composite device demos, HID+AUDO, MSC+CDC, and mouse+keyboard, so I select usb_device_composite_cdc_msc as a starting point. 2 Prepare the descriptor-related data structure to ensure that the correct information about the customized composite device is relayed to the USB device stack 2.1 usb_device_class_config_list_struct_t This structure is required for the composite device and relays device callback, class callback, interface numbers, and endpoint numbers of each interface to the class driver. The structure should be placed in the “composite.c” file /* USB device class information */ usb_device_class_config_struct_t g_compositeDevice[2] = { { USB_DeviceCdcVcomCallback, (class_handle_t)NULL, &g_UsbDeviceCdcVcomConfig, }, { USB_DeviceHidGenericCallback, (class_handle_t)NULL, &g_UsbDeviceHidGenericConfig, }}; /* USB device class configuration information */ usb_device_class_config_list_struct_t g_compositeDeviceConfigList = { g_compositeDevice, USB_DeviceCallback, 2, }; 2.2 usb_device_class_config_struct_t This structure is required for the composite device and provides information about each class. The structure should be placed in the “composite.c” file /* USB device class information */ usb_device_class_config_struct_t g_compositeDevice[2] = { { USB_DeviceCdcVcomCallback, (class_handle_t)NULL, &g_UsbDeviceCdcVcomConfig, }, { USB_DeviceHidGenericCallback, (class_handle_t)NULL, &g_UsbDeviceHidGenericConfig, } }; 2.3 usb_device_class_struct_t This structure is required for each class including the class type, supported configuration count and interface list for each configuration. /* Define class information for virtual com */ usb_device_class_struct_t g_UsbDeviceCdcVcomConfig = { g_UsbDeviceCdcVcomInterfaceList, kUSB_DeviceClassTypeCdc, USB_DEVICE_CONFIGURATION_COUNT, }; usb_device_class_struct_t g_UsbDeviceHidGenericConfig = { g_UsbDeviceHidGenericInterfaceList, /* The interface list of the HID generic */ kUSB_DeviceClassTypeHid, /* The HID class type */ USB_DEVICE_CONFIGURATION_COUNT, /* The configuration count */ }; 2.4 usb_device_interface_list_t This structure is required for the composite device and provides information about each class. usb_device_interface_list_t g_UsbDeviceHidGenericInterfaceList[USB_DEVICE_CONFIGURATION_COUNT] = { { USB_HID_GENERIC_INTERFACE_COUNT, /* The interface count of the HID generic */ g_UsbDeviceHidGenericInterfaces, /* The interfaces handle */ }, }; /* Define configurations for virtual com */ usb_device_interface_list_t g_UsbDeviceCdcVcomInterfaceList[USB_DEVICE_CONFIGURATION_COUNT] = { { USB_CDC_VCOM_INTERFACE_COUNT, g_cdcVcomInterfaces, }, }; 2.5 usb_device_interfaces_struct_t This structure provides alternate setting interface information about each interface. usb_device_interfaces_struct_t g_UsbDeviceHidGenericInterfaces[USB_HID_GENERIC_INTERFACE_COUNT] = { USB_HID_GENERIC_CLASS, /* HID generic class code */ USB_HID_GENERIC_SUBCLASS, /* HID generic subclass code */ USB_HID_GENERIC_PROTOCOL, /* HID generic protocol code */ USB_HID_GENERIC_INTERFACE_INDEX, /* The interface number of the HID generic */ g_UsbDeviceHidGenericInterface, /* Interfaces handle */ sizeof(g_UsbDeviceHidGenericInterface) / sizeof(usb_device_interfaces_struct_t), }; /* Define interfaces for virtual com */ usb_device_interfaces_struct_t g_cdcVcomInterfaces[USB_CDC_VCOM_INTERFACE_COUNT] = { {USB_CDC_VCOM_CIC_CLASS, USB_CDC_VCOM_CIC_SUBCLASS, USB_CDC_VCOM_CIC_PROTOCOL, USB_CDC_VCOM_CIC_INTERFACE_INDEX, g_cdcVcomCicInterface, sizeof(g_cdcVcomCicInterface) / sizeof(usb_device_interfaces_struct_t)}, {USB_CDC_VCOM_DIC_CLASS, USB_CDC_VCOM_DIC_SUBCLASS, USB_CDC_VCOM_DIC_PROTOCOL, USB_CDC_VCOM_DIC_INTERFACE_INDEX, g_cdcVcomDicInterface, sizeof(g_cdcVcomDicInterface) / sizeof(usb_device_interfaces_struct_t)}, }; 2.6 usb_device_interface_struct_t This structure provides information about each alternate setting interface for the current interface. /* Define interface for communication class */ usb_device_interface_struct_t g_cdcVcomCicInterface[] = {{0, { USB_CDC_VCOM_CIC_ENDPOINT_COUNT, g_cdcVcomCicEndpoints, }, NULL}}; /* Define interface for data class */ usb_device_interface_struct_t g_cdcVcomDicInterface[] = {{0, { USB_CDC_VCOM_DIC_ENDPOINT_COUNT, g_cdcVcomDicEndpoints, }, NULL}}; /* HID generic interface information */ usb_device_interface_struct_t g_UsbDeviceHidGenericInterface[] = {{ 0U, /* The alternate setting of the interface */ { USB_HID_GENERIC_ENDPOINT_COUNT, /* Endpoint count */ g_UsbDeviceHidGenericEndpoints, /* Endpoints handle */ }, }}; 2.7 usb_device_endpoint_struct_t This structure is required for the composite device and provides ep information /* hid generic endpoint information */ usb_device_endpoint_struct_t g_UsbDeviceHidGenericEndpoints[USB_HID_GENERIC_ENDPOINT_COUNT] = { /* HID generic interrupt IN pipe */ { USB_HID_GENERIC_ENDPOINT_IN | (USB_IN << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT), USB_ENDPOINT_INTERRUPT, FS_HID_GENERIC_INTERRUPT_IN_PACKET_SIZE, }, /* HID generic interrupt OUT pipe */ { USB_HID_GENERIC_ENDPOINT_OUT | (USB_OUT << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT), USB_ENDPOINT_INTERRUPT, FS_HID_GENERIC_INTERRUPT_OUT_PACKET_SIZE, }, }; /* cdc virtual com information */ /* Define endpoint for communication class */ usb_device_endpoint_struct_t g_cdcVcomCicEndpoints[USB_CDC_VCOM_CIC_ENDPOINT_COUNT] = { { USB_CDC_VCOM_CIC_INTERRUPT_IN_ENDPOINT | (USB_IN << 7U), USB_ENDPOINT_INTERRUPT, HS_CDC_VCOM_BULK_IN_PACKET_SIZE, }, }; /* Define endpoint for data class */ usb_device_endpoint_struct_t g_cdcVcomDicEndpoints[USB_CDC_VCOM_DIC_ENDPOINT_COUNT] = { { USB_CDC_VCOM_DIC_BULK_IN_ENDPOINT | (USB_IN << 7U), USB_ENDPOINT_BULK, FS_CDC_VCOM_BULK_IN_PACKET_SIZE, }, { USB_CDC_VCOM_DIC_BULK_OUT_ENDPOINT | (USB_OUT << 7U), USB_ENDPOINT_BULK, FS_CDC_VCOM_BULK_OUT_PACKET_SIZE, }, }; 3 Prepare the descriptors array and ensure that the descriptors are consistent with the descriptor-related data structure. The descriptors for each class can be obtained from the class-related examples and class specification. For the composite device, combine multiple class descriptors. /* Define configuration descriptor */ uint8_t g_UsbDeviceConfigurationDescriptor[USB_DESCRIPTOR_LENGTH_CONFIGURATION_ALL] = { /* Configuration Descriptor Size*/ USB_DESCRIPTOR_LENGTH_CONFIGURE, /* CONFIGURATION Descriptor Type */ USB_DESCRIPTOR_TYPE_CONFIGURE, /* Total length of data returned for this configuration. */ USB_SHORT_GET_LOW(USB_DESCRIPTOR_LENGTH_CONFIGURATION_ALL), USB_SHORT_GET_HIGH(USB_DESCRIPTOR_LENGTH_CONFIGURATION_ALL), /* Number of interfaces supported by this configuration */ USB_INTERFACE_COUNT, /* Value to use as an argument to the SetConfiguration() request to select this configuration */ USB_COMPOSITE_CONFIGURE_INDEX, /* Index of string descriptor describing this configuration */ 0, /* Configuration characteristics D7: Reserved (set to one) D6: Self-powered D5: Remote Wakeup D4...0: Reserved (reset to zero) */ (USB_DESCRIPTOR_CONFIGURE_ATTRIBUTE_D7_MASK) | (USB_DEVICE_CONFIG_SELF_POWER << USB_DESCRIPTOR_CONFIGURE_ATTRIBUTE_SELF_POWERED_SHIFT) | (USB_DEVICE_CONFIG_REMOTE_WAKEUP << USB_DESCRIPTOR_CONFIGURE_ATTRIBUTE_REMOTE_WAKEUP_SHIFT), /* Maximum power consumption of the USB * device from the bus in this specific * configuration when the device is fully * operational. Expressed in 2 mA units * (i.e., 50 = 100 mA). */ USB_DEVICE_MAX_POWER, /* Interface Association Descriptor */ /* Size of this descriptor in bytes */ USB_IAD_DESC_SIZE, /* INTERFACE_ASSOCIATION Descriptor Type */ USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, /* The first interface number associated with this function */ 0x00, /* The number of contiguous interfaces associated with this function */ 0x02, /* The function belongs to the Communication Device/Interface Class */ USB_CDC_VCOM_CIC_CLASS, 0x03, /* The function uses the No class specific protocol required Protocol */ 0x00, /* The Function string descriptor index */ 0x02, /* Interface Descriptor */ USB_DESCRIPTOR_LENGTH_INTERFACE, USB_DESCRIPTOR_TYPE_INTERFACE, USB_CDC_VCOM_CIC_INTERFACE_INDEX, 0x00, USB_CDC_VCOM_CIC_ENDPOINT_COUNT, USB_CDC_VCOM_CIC_CLASS, USB_CDC_VCOM_CIC_SUBCLASS, USB_CDC_VCOM_CIC_PROTOCOL, 0x00, /* CDC Class-Specific descriptor */ USB_DESCRIPTOR_LENGTH_CDC_HEADER_FUNC, /* Size of this descriptor in bytes */ USB_DESCRIPTOR_TYPE_CDC_CS_INTERFACE, /* CS_INTERFACE Descriptor Type */ USB_CDC_HEADER_FUNC_DESC, 0x10, 0x01, /* USB Class Definitions for Communications the Communication specification version 1.10 */ USB_DESCRIPTOR_LENGTH_CDC_CALL_MANAG, /* Size of this descriptor in bytes */ USB_DESCRIPTOR_TYPE_CDC_CS_INTERFACE, /* CS_INTERFACE Descriptor Type */ USB_CDC_CALL_MANAGEMENT_FUNC_DESC, 0x01, /*Bit 0: Whether device handle call management itself 1, Bit 1: Whether device can send/receive call management information over a Data Class Interface 0 */ 0x01, /* Indicates multiplexed commands are handled via data interface */ USB_DESCRIPTOR_LENGTH_CDC_ABSTRACT, /* Size of this descriptor in bytes */ USB_DESCRIPTOR_TYPE_CDC_CS_INTERFACE, /* CS_INTERFACE Descriptor Type */ USB_CDC_ABSTRACT_CONTROL_FUNC_DESC, 0x06, /* Bit 0: Whether device supports the request combination of Set_Comm_Feature, Clear_Comm_Feature, and Get_Comm_Feature 0, Bit 1: Whether device supports the request combination of Set_Line_Coding, Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State 1, Bit ... */ USB_DESCRIPTOR_LENGTH_CDC_UNION_FUNC, /* Size of this descriptor in bytes */ USB_DESCRIPTOR_TYPE_CDC_CS_INTERFACE, /* CS_INTERFACE Descriptor Type */ USB_CDC_UNION_FUNC_DESC, 0x00, /* The interface number of the Communications or Data Class interface */ 0x01, /* Interface number of subordinate interface in the Union */ /*Notification Endpoint descriptor */ USB_DESCRIPTOR_LENGTH_ENDPOINT, USB_DESCRIPTOR_TYPE_ENDPOINT, USB_CDC_VCOM_CIC_INTERRUPT_IN_ENDPOINT | (USB_IN << 7U), USB_ENDPOINT_INTERRUPT, USB_SHORT_GET_LOW(FS_CDC_VCOM_INTERRUPT_IN_PACKET_SIZE), USB_SHORT_GET_HIGH(FS_CDC_VCOM_INTERRUPT_IN_PACKET_SIZE), FS_CDC_VCOM_INTERRUPT_IN_INTERVAL, /* Data Interface Descriptor */ USB_DESCRIPTOR_LENGTH_INTERFACE, USB_DESCRIPTOR_TYPE_INTERFACE, USB_CDC_VCOM_DIC_INTERFACE_INDEX, 0x00, USB_CDC_VCOM_DIC_ENDPOINT_COUNT, USB_CDC_VCOM_DIC_CLASS, USB_CDC_VCOM_DIC_SUBCLASS, USB_CDC_VCOM_DIC_PROTOCOL, 0x00, /* Interface Description String Index*/ /*Bulk IN Endpoint descriptor */ USB_DESCRIPTOR_LENGTH_ENDPOINT, USB_DESCRIPTOR_TYPE_ENDPOINT, USB_CDC_VCOM_DIC_BULK_IN_ENDPOINT | (USB_IN << 7U), USB_ENDPOINT_BULK, USB_SHORT_GET_LOW(FS_CDC_VCOM_BULK_IN_PACKET_SIZE), USB_SHORT_GET_HIGH(FS_CDC_VCOM_BULK_IN_PACKET_SIZE), 0x00, /* The polling interval value is every 0 Frames */ /*Bulk OUT Endpoint descriptor */ USB_DESCRIPTOR_LENGTH_ENDPOINT, USB_DESCRIPTOR_TYPE_ENDPOINT, USB_CDC_VCOM_DIC_BULK_OUT_ENDPOINT | (USB_OUT << 7U), USB_ENDPOINT_BULK, USB_SHORT_GET_LOW(FS_CDC_VCOM_BULK_OUT_PACKET_SIZE), USB_SHORT_GET_HIGH(FS_CDC_VCOM_BULK_OUT_PACKET_SIZE), 0x00, /* The polling interval value is every 0 Frames */ USB_DESCRIPTOR_LENGTH_INTERFACE, /* Size of this descriptor in bytes */ USB_DESCRIPTOR_TYPE_INTERFACE, /* INTERFACE Descriptor Type */ USB_HID_GENERIC_INTERFACE_INDEX, /* Number of this interface. */ 0x00U, /* Value used to select this alternate setting for the interface identified in the prior field */ USB_HID_GENERIC_ENDPOINT_COUNT, /* Number of endpoints used by this interface (excluding endpoint zero). */ USB_HID_GENERIC_CLASS, /* Class code (assigned by the USB-IF). */ USB_HID_GENERIC_SUBCLASS, /* Subclass code (assigned by the USB-IF). */ USB_HID_GENERIC_PROTOCOL, /* Protocol code (assigned by the USB). */ 0x02U, /* Index of string descriptor describing this interface */ USB_DESCRIPTOR_LENGTH_HID, /* Numeric expression that is the total size of the HID descriptor. */ USB_DESCRIPTOR_TYPE_HID, /* Constant name specifying type of HID descriptor. */ 0x00U, 0x01U, /* Numeric expression identifying the HID Class Specification release. */ 0x00U, /* Numeric expression identifying country code of the localized hardware */ 0x01U, /* Numeric expression specifying the number of class descriptors(at least one report descriptor) */ USB_DESCRIPTOR_TYPE_HID_REPORT, /* Constant name identifying type of class descriptor. */ USB_SHORT_GET_LOW(USB_DESCRIPTOR_LENGTH_HID_GENERIC_REPORT), USB_SHORT_GET_HIGH(USB_DESCRIPTOR_LENGTH_HID_GENERIC_REPORT), /* Numeric expression that is the total size of the Report descriptor. */ USB_DESCRIPTOR_LENGTH_ENDPOINT, /* Size of this descriptor in bytes */ USB_DESCRIPTOR_TYPE_ENDPOINT, /* ENDPOINT Descriptor Type */ USB_HID_GENERIC_ENDPOINT_IN | (USB_IN << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT), /* The address of the endpoint on the USB device described by this descriptor. */ USB_ENDPOINT_INTERRUPT, /* This field describes the endpoint's attributes */ USB_SHORT_GET_LOW(FS_HID_GENERIC_INTERRUPT_IN_PACKET_SIZE), USB_SHORT_GET_HIGH(FS_HID_GENERIC_INTERRUPT_IN_PACKET_SIZE), /* Maximum packet size this endpoint is capable of sending or receiving when this configuration is selected. */ FS_HID_GENERIC_INTERRUPT_IN_INTERVAL, /* Interval for polling endpoint for data transfers. */ USB_DESCRIPTOR_LENGTH_ENDPOINT, /* Size of this descriptor in bytes */ USB_DESCRIPTOR_TYPE_ENDPOINT, /* ENDPOINT Descriptor Type */ USB_HID_GENERIC_ENDPOINT_OUT | (USB_OUT << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT), /* The address of the endpoint on the USB device described by this descriptor. */ USB_ENDPOINT_INTERRUPT, /* This field describes the endpoint's attributes */ USB_SHORT_GET_LOW(FS_HID_GENERIC_INTERRUPT_OUT_PACKET_SIZE), USB_SHORT_GET_HIGH(FS_HID_GENERIC_INTERRUPT_OUT_PACKET_SIZE), /* Maximum packet size this endpoint is capable of sending or receiving when this configuration is selected. */ FS_HID_GENERIC_INTERRUPT_OUT_INTERVAL, /* Interval for polling endpoint for data transfers. */ }; 4 Implement the specific descriptor-related callback function, which the USB Device stack calls to get the descriptor. Please refer to the attached source code for more details
View full article