Hello Biafra,
For first statement I would recommend to do something similiar to this:
case kUSB_DeviceCdcEventSendResponse:
{
#if EXAMPLE_USES_SAME_DEVICE_CALLBACK
if (g_deviceComposite->cdcVcom.cdcAcmHandle == handle) {
if ((epCbParam->length != 0) && (!(epCbParam->length % g_cdcVcomDicEndpoints[0].maxPacketSize)))
{
/* If the last packet is the size of endpoint, then send also zero-ended packet,
** meaning that we want to inform the host that we do not have any additional
** data, so it can flush the output.
*/
USB_DeviceCdcAcmSend(handle, USB_CDC_VCOM_DIC_BULK_IN_ENDPOINT, NULL, 0);
}
else if ((1 == g_deviceComposite->cdcVcom.attach) && (1 == g_deviceComposite->cdcVcom.startTransactions))
{
if ((epCbParam->buffer != NULL) || ((epCbParam->buffer == NULL) && (epCbParam->length == 0)))
{
/* User: add your own code for send complete event */
/* Schedule buffer for next receive event */
USB_DeviceCdcAcmRecv(handle, USB_CDC_VCOM_DIC_BULK_OUT_ENDPOINT, s_currRecvBuf,
g_cdcVcomDicEndpoints[0].maxPacketSize);
}
} else {
}
} else if (g_deviceComposite->cdcVcom2.cdcAcmHandle == handle) {
if ((epCbParam->length != 0) && (!(epCbParam->length % g_cdcVcom2DicEndpoints[0].maxPacketSize)))
{
/* If the last packet is the size of endpoint, then send also zero-ended packet,
** meaning that we want to inform the host that we do not have any additional
** data, so it can flush the output.
*/
USB_DeviceCdcAcmSend(handle, USB_CDC_VCOM2_DIC_BULK_IN_ENDPOINT, NULL, 0);
}
else if ((1 == g_deviceComposite->cdcVcom2.attach) && (1 == g_deviceComposite->cdcVcom2.startTransactions))
{
if ((epCbParam->buffer != NULL) || ((epCbParam->buffer == NULL) && (epCbParam->length == 0)))
{
/* User: add your own code for send complete event */
/* Schedule buffer for next receive event */
USB_DeviceCdcAcmRecv(handle, USB_CDC_VCOM2_DIC_BULK_OUT_ENDPOINT, s_currRecvBuf2,
g_cdcVcom2DicEndpoints[0].maxPacketSize);
}
} else {
}
}
#else
As you can see on previous snippet, handle variable (which is passed to DeviceCallback) is compared with two different handlers: one for every CDC instance, so, global device structure would look like as follows:
typedef struct _usb_device_composite_struct
{
usb_device_handle deviceHandle; /* USB device handle. */
usb_cdc_vcom_struct_t cdcVcom; /* CDC virtual com device structure. */
usb_cdc_vcom_struct_t cdcVcom2; /* CDC virtual com2 device structure. */
uint8_t speed; /* Speed of USB device. USB_SPEED_FULL/USB_SPEED_LOW/USB_SPEED_HIGH. */
uint8_t attach; /* A flag to indicate whether a usb device is attached. 1: attached, 0: not attached */
uint8_t currentConfiguration; /* Current configuration value. */
uint8_t
currentInterfaceAlternateSetting[USB_INTERFACE_COUNT]; /* Current alternate setting value for each interface. */
} usb_device_composite_struct_t;
As you can see, they will be treated as two different devices with their own context so if you are using same callback for both CDC instances, you will need to distinguish which interface/handle is being used and then select the proper endpoints/variables. In order to do this, you will need to duplicate every variable and context, does it make sense to you?
An easier way to create your own CDC + CDC composite device would be to duplicate each CDC function and variable and use both CDC instances separetly. Attach you will find some files from a CDC + CDC basic example which uses this structure and it is working fine in Linux (In windows, It is necessary to use an specific driver to handle this CDC + CDC composite device correctly, so I tested this example on Linux and it worked very well, also i am attaching an image that shows how both CDC instaces are being used without any problem, this example wis based from CDC + MSD example so I used a MACRO to swith between these two configurations).
Next capture shows how both CDC instances are sending configuration settings in their INT endpoint:

Also, look how both instances are being used at the same time (look how different endpoint from interfaces 1 and 3 are used, rememer that interfaces 0 and 2 are for interrupt endpoints):

Again, I hope this can be helpful for you but if something is not clear just let me know it!
Have a nice day!
Regards,
Isaac