STM32 USB Device Library v2.10.0 is not complete for composite device implementation.
The composite device implementation (CompositeBuilder) provides more reliable method to define USB descriptors and methods but I think it lacks some documentation on how we use it. Moreover, there must be some additional changes required for individual class methods (initialization) to make it work, as described below:
There is no concrete example to show how a composite device can be registered as well as operations for each class. Consider an example in which an audio and a cdc class is defined in a composite build. Then (following the Cube architecture) the interface function MX_USB_DEVICE_Init in ../USB_DEVICE/App/usb_device.c should make the following calls:
static uint8_t AUDIOEpAddr[] = {..};
static uint8_t CDCEpAddr[] = {..};
/* Init Device Library, add supported class and start the library. */
if (USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS) != USBD_OK) {
Error_Handler();
}
/* USB Audio */
USBD_RegisterClassComposite(&hUsbDeviceFS,
USBD_AUDIO_CLASS,
CLASS_TYPE_AUDIO,
AUDIOInEpAddr);
/* CDC Virtual Comm Ports */
USBD_RegisterClassComposite(&hUsbDeviceFS,
USBD_CDC_CLASS,
CLASS_TYPE_CDC,
CDCEpAddr);
USBD_AUDIO_RegisterInterface(&hUsbDeviceFS, &USBD_AUDIO_fops);
USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_CDC_fops, 0);The only problem with this interface is that the typedef USB_HandleTypeDef which defines the hUsbDeviceFS use a global index classId to access to each class definitions and methods. Each time USBD_RegisterClassComposite is called classID is incremented by one. When USB_AUDIO_RegisterInterface is called then classID is expected to be 0 for the AUDIO CLASS (first class in a composite build) but it is set to 2 due to addition of two classes. Therefore, the function USBD_AUDIO_RegisterInterface call points to an undefined class with ID 2. One way to fix this is to include the following additions to reset the classID of USBD_HandleTypeDef to point to correct class data in the RegisterInterface function:
uint8_t USBD_AUDIO_RegisterInterface(USBD_HandleTypeDef *pdev,
USBD_AUDIO_ItfTypeDef *fops)
{
/* User additions */
pdev->classId = USBD_CMPSIT_GetClassID(pdev, CLASS_TYPE_AUDIO, 0U);
if (pdev->classId == 0xFFU) {
return (uint8_t)USBD_FAIL;
}
/* End of user additions */
if (fops == NULL)
{
return (uint8_t)USBD_FAIL;
}
pdev->pUserData[pdev->classId] = fops;
return (uint8_t)USBD_OK;
}Here the added call USBD_CMPSIT_GetClassID is defined in ../Middlewares/ST/STM32_USB_Device_Library/Class/CompositeBuilder/Src/usbd_composite_builder.c. The same addition should be done for the CDC class also (and the other classes added).
My questions are the following:
- Is the described method above to add and register classes correct?
- How should we use the global index classID of USBD_HandleTypeDef t properly? Is there any guidance on its use? Is adding the call USBD_CMPSIT_GetClassID to class functions enough to make it work?
