KSDK 1.3 USB Descriptor for MSD and CDC

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

KSDK 1.3 USB Descriptor for MSD and CDC

Jump to solution
6,033 Views
philipp
Contributor II

Hello,

 

I am trying to implement the USB classes for MSD and CDC with the TWR-K60D100m. I am using KSDK 1.3 and Processor Expert.

I used the fsl_usb_device_msd_class component of KSDK 1.3 which is working well. Because there is no class for cdc, I used the example for the TWR-K60 from Freescale (composite device msd_cdc) and took the cdc files.

MSD and CDC are both working but only separately.

 

Because the Towerboard is just my testing device, I would like to use Processor Expert, so that it is easier to implement on my custom device (which I currently dont' have). That's why I would like to know, how I can enable the CDC or composite class driver configuration in the fsl_usb_descriptors. The MSD class driver configuration is enabled because I added fsl_usb_device_msd_class. But for the other ones, I can't find the classes...

 

I guess the alternative would be to write the USB descriptor with the different interfaces by myself. But if you know how to do this with Processor Expert (and KSDK 1.3), it would be great, if you can help me.

 

Thank you!

Labels (1)
0 Kudos
1 Solution
4,002 Views
isaacavila
NXP Employee
NXP Employee

Hello Philipp,

You have to create this CDC component "manually" and do some modifications in generated code in order to get it working. Here, you can find some steps that I followed to create this CDC + MSD project in FRDM-K64F.

  • Add fsl_usb_device_msd_class to your project (4 components will be also added, among them, you can identify the fsl_usb_descriptors component that will be modified later).
  • Configure fsl_usb_device_msd_class component as desired (enable USB RAM DISK if necessary).
  • Configure fsl_usb_descriptors as follows:
    • Class Code:

Class Code.jpg

    • Class list will be 1 by default, so you need to add another class (set to 2). Class 0 will handle MSD configuration and Class 1 will allocate CDC configuration.
    • Modify Class 1 as shown below:

Class 1 Configuration.jpg

    • Set 2 interfaces to this class (One is used for control and other for data), configure them as follows:

     Interface configuration.jpg

  • Generate code. Now we proceed to do some modifications on generated code (For next modifications, you can use CDC_MSD example available in KSDK 1.3), I am adding a preprocessor definition to identify the added code.
  • In usbDsc1 file, include reference for a header file that will be created later (named cdc1.h):

#include "cdc1.h"

  • Modify lenght size for usbDsc1_Full_Speed_Configuration_1:

#if ADD_CDC_SUPPORT

        0x47 + 8 + 5 + 5 + 4 + 5,0x00,       /* Total length of data for this configuration */

#else

        0x47,0x00,                           /* Total length of data for this configuration: 71 bytes */

#endif

  • After MSD's endpoints descriptros, it is necessary to add Interface Association descriptor for CDC control and data:

/***************************************************************************/

        /* msd1: Endpoint FS Bulk EP2 Bulk OUT, up to 1.216 MB/s Descriptor        */

        /***************************************************************************/

        0x07,                                /* Descriptor size: 7 bytes */

        USB_ENDPOINT_DESCRIPTOR,             /* Descriptor type: ENDPOINT descriptor */

        0x02,                                /* Address: 2 OUT */

        0x02,                                /* Transfer type: Bulk */

        0x40,0x00,                           /* Max. packet size: 64 byte(s) */

        0x01,                                /* Maximum NAK rate: 0x01 microframe(s) */

#if ADD_CDC_SUPPORT

        /* Interface Association Descriptor */

        0x08,                                /* Size of this descriptor */

        0x0B,                                /* INTERFACE ASSOCIATION Descriptor */

        0x01,                                /* Interface number of the CDC Control

                                          interface that is associated with this function */

        0x02,                                /* Number of contiguous CDC interfaces

                                          that are associated with this function */

        0x02,                                /* CDC_CC */

        0x03,

        0x00,                                /* Not used */

        0x00,                                /* Index to string descriptor */

#endif

  • Before endpoint descriptors for CDC, add next descriptors needed for CDC:

/***************************************************************************/

        /* cdc: Interface 1 Alternate setting 0 Descriptor                         */

        /***************************************************************************/

        0x09,                                /* Descriptor size: 9 bytes */

        USB_INTERFACE_DESCRIPTOR,            /* Descriptor type: INTERFACE descriptor */

        0x01,                                /* Interface number: 1 */

        0x00,                                /* Alternative setting number: 0 */

        0x01,                                /* Number of EPs(excluding EP0): 1 */

        0x02,                                /* Class code: 0x02 Communication (Communications and CDC Control) */

        0x02,                                /* Subclass code: 0x02 */

        0x00,                                /* Protocol code: 0x00 */

        0x00,                                /* String descriptor index */

#if ADD_CDC_SUPPORT

        /* CDC Class-Specific descriptor */

        0x05,                                 /* size of Functional Desc in bytes */

        USB_CS_INTERFACE_DESCRIPTOR,          /* descriptor type*/

        USB_CDC_HEADER_FUNC_DESCRIPTOR,

        0x10, 0x01,                           /* USB Class Definitions for CDC spec release number in BCD */

        0x05,                                 /* Size of this descriptor */

        USB_CS_INTERFACE_DESCRIPTOR,          /* descriptor type*/

        USB_CDC_CALL_MANAGEMENT_FUNC_DESCRIPTOR,

        0x01,                                 /* device handles call management itself(D0 set)

                                              and will process commands multiplexed over the data interface */

        0x01,                                 /* Indicates multiplexed commands are handled via data interface */

        0x04,                                 /* Size of this descriptor */

        USB_CS_INTERFACE_DESCRIPTOR,          /* descriptor type*/

        USB_CDC_ABSTRACT_CONTROL_FUNC_DESCRIPTOR,

        0x06,                                 /* Device Supports all commands for ACM - CDC

                                              PSTN SubClass bmCapabilities */

        0x05,                                 /* size of Functional Desc in bytes */

        USB_CS_INTERFACE_DESCRIPTOR,          /* descriptor type*/

        USB_CDC_UNION_FUNC_DESCRIPTOR,

        0x01,                                 /* Interface Number of Control */

        0x02,                                 /* Interface Number of Subordinate (Data Class) Interface */

#endif

  • Also, some other modifications are needed:

#if ADD_CDC_SUPPORT static uint8_t g_alternate_interface[3]; #else volatile uint8_t usbDsc1_CurrentConfiguration = 0U; #endif

  • USB_Desc_Get_Entity_Config_Struct_0 function:

static uint8_t USB_Desc_Get_Entity_Config_Struct_0(uint32_t handle,entity_type type, uint32_t * object) {     switch (type)  {     case USB_CLASS_INFO:    #if !ADD_CDC_SUPPORT         if (usbDsc1_CurrentConfiguration == 0U) {                        *object = (uint32_t)FS_Cfg_1_ClassInfoArray;         }           #endif         break;     case USB_COMPOSITE_INFO: #if !ADD_CDC_SUPPORT         if (usbDsc1_CurrentConfiguration == 0U) {                        *object = (uint32_t)&FS_Cfg_1_CompositInfo;         } #else         *object = (uint32_t)&FS_Cfg_1_CompositInfo; #endif         break;     case USB_CLASS_INTERFACE_INDEX_INFO: #if !ADD_CDC_SUPPORT         if (usbDsc1_CurrentConfiguration == 0U) {             *object = FS_Cfg_1_ClassInfoArray[0].interfaces.interface[0].index;         } #else         *object = 0xff;         if (handle == (uint32_t)cdc1_Handle)         {             *object = (uint32_t)FS_Cfg_1_ClassInfoArray[1].interfaces.interface[g_alternate_interface[1]].index; /* Interface index for CDC*/             break;         }         else if (handle == (uint32_t)msd1_MsdHandle)         {             *object = (uint32_t)(uint32_t)FS_Cfg_1_ClassInfoArray[0].interfaces.interface[g_alternate_interface[0]].index; /* Interface index for MSD*/             break;         } #endif         break;     case USB_MSC_LBA_INFO:         /* Call registered callback */         msd1_get_desc_entity(handle, USB_MSC_LBA_INFO, object);         break;     default :         break;     }/* End Switch */     return USB_OK; }

  • USB_Desc_Get_Interface and USB_Desc_Set_Interface functions:

static uint8_t USB_Desc_Get_Interface (         uint32_t      handle,         uint8_t       interface,         uint8_t      *alt_interface ) {     UNUSED_ARGUMENT(handle); #if ADD_CDC_SUPPORT     /* if interface valid */     if(interface < 3)     {         /* get alternate interface*/         *alt_interface = g_alternate_interface[interface];         return USB_OK;     } #endif     return USBERR_INVALID_REQ_TYPE; }

static uint8_t USB_Desc_Set_Interface (         uint32_t  handle,         uint8_t       interface,         uint8_t       alt_interface ) {     UNUSED_ARGUMENT(handle); #if ADD_CDC_SUPPORT     /* if interface valid */     if(interface < 3)     {         /* set alternate interface*/         g_alternate_interface[interface]=alt_interface;         return USB_OK;     } #endif     return USBERR_INVALID_REQ_TYPE; }

  • USB_Set_Configuration function:

static uint8_t USB_Set_Configuration (         uint32_t      handle,         uint8_t       config ) {     UNUSED_ARGUMENT(handle); #if !ADD_CDC_SUPPORT     usbDsc1_CurrentConfiguration = (config - 1U); #else     uint32_t i;     for(i = 0; i < FS_Cfg_1_CompositInfo.count; i++) {         switch(FS_Cfg_1_CompositInfo.class_handle[i].type)         {         case USB_CLASS_COMMUNICATION:             FS_Cfg_1_ClassInfoArray[i].interfaces.interface = &FS_Cfg_1_Class_1_InterfaceInfoArray[config - 1];             break;         case USB_CLASS_MASS_STORAGE:             FS_Cfg_1_ClassInfoArray[i].interfaces.interface = &FS_Cfg_1_Class_0_InterfaceInfoArray[config - 1];             break;         default:             break;         }     } #endif return USB_OK; }

  • Also ClassConfigInfoArray requires to define callbacks for CDC (these callbacks will be defined in cdc1.h and cdc1.c):

static class_config_struct_t ClassConfigInfoArray[] = {         {                 { /* Application callback setting */                         msd1_application_callback,                                     /* Callback address */                         NULL,                                                          /* Callback argument */                 },                 { /* VendorRequest callback setting */                         NULL,                                                          /* Callback address */                         NULL,                                                          /* Callback argument */                 },                 { /* ClassSpecific callback setting */                         msd1_class_specific_callback,                                  /* Callback address */                         NULL,                                                          /* Callback argument */                 },                 &usbDsc1_desc_callback_Config_Struct_0,                           /* Callback function data structure for the specified type of class */                 { /* BoardInit callback setting */                         NULL,                                                          /* Callback address */                         0,                                                             /* Callback argument */                 },                 0U,                                                               /* Class handle */                 USB_CLASS_MASS_STORAGE                                            /* Class name */         }, #if ADD_CDC_SUPPORT         /* CDC callbacks */         {                 { /* Application callback setting */                         cdc1_application_callback,                                     /* Callback address */                         NULL,                                                          /* Callback argument */                 },                 { /* VendorRequest callback setting */                         NULL,                                                          /* Callback address */                         NULL,                                                          /* Callback argument */                 },                 { /* ClassSpecific callback setting */                         cdc1_class_specific_callback,                                  /* Callback address */                         NULL,                                                          /* Callback argument */                 },                 &usbDsc1_desc_callback_Config_Struct_0,                           /* Callback function data structure for the specified type of class */                 { /* BoardInit callback setting */                         NULL,                                                          /* Callback address */                         0,                                                             /* Callback argument */                 },                 0U,                                                               /* Class handle */                 USB_CLASS_COMMUNICATION                                           /* Class name */         } #endif };

  • Last modification on usbDsc1.c is:

composite_config_struct_t usbDsc1_CompositeConfigStructure = { #if !ADD_CDC_SUPPORT         1,                                                                  /* Number of classes */ #else         2,                                                                  /* Number of classes */ #endif         ClassConfigInfoArray                                                /* Class configuration structure array */ };

  • Then, Cpu.c file needs to be modified in order to initialize CDC handling:

View solution in original post

24 Replies
790 Views
isaacavila
NXP Employee
NXP Employee

Hi Philipp,

UART5 is used for on board OSBDM/serial bridge interface that is used trhough J17 USB connector.

If you want to use TWR-SER's RS-232 connector then you will need to configure UART3 module (and

use PTC16 and PTC17) and configure J17, J18 and J19 jumpers in TWR-SER.

You can check TWR-SER and TWR-K60D100M's schematic for more deatils.

Regards,

Isaac

0 Kudos
790 Views
philipp
Contributor II

Hi Isaac,

thanks again for your help!

Well if I use the UART 5 with the J17 USB, I can flash the Towerboard but cannot debug. It's not recognized as MSD or Freescale CDC Device (but as OSBDM - Debug port). Is it possible to use this port for flashing and debugging? I tried to figure it out in the schematic but it was not really successful.

Is it also possible to use the USB connector of the TWR-Ser for the debug console? I didn't find a way to connect the UART3 with the USB port.. the RS-232 doesn't help because I want to use MSD and CDC with just one USB port..

Thank you!

0 Kudos
790 Views
isaacavila
NXP Employee
NXP Employee

Hello Philipp,

What you want to implement is to use the CDC interface as the debug console, don't you? If so, there are some important thing to understand:

  • J17 (TWR-K60D100M board) is connected to U11 (MC9S08JM60) that is used to flash the MCU (JTAG) and also it works as USB-UART bridge, so K60 is communicating through UART5 and U11 is sending this through USB that is why Debug Console is configured in UART5.
  • TWR-SER's J14 cannot serve to program K60, this is connected to K60's USB module not to MCU's JTAG.
  • Debug console is configured to be used with UART, so you need to change its default configuration to use USB. Take in mind that by default, CDC application is implementing a loopback and it does not defined functions needed for debug console. For more details please check this post: How do I setup the debug console to use the Virtual COM port (USB CDC driver)?

Taking in mide these considerations, I've modified the CDC + MSD example in order to use CDC instance as Debug Console:

  • ​fsl_debug_console:

#if 0

  #include "usb_descriptor.h"

  #include "virtual_com.h"

#else

  #include "usbDsc1.h"

  #include "cdc1.h"

#endif

#if 0

extern uint32_t g_app_handle;

#else

extern cdc_handle_t cdc1_Handle;

#endif

#if 0

        usb_status_t (* USB_Receive)(uint32_t base, uint8_t *buf, uint32_t count);

#else

        usb_status (* USB_Receive)(uint32_t base, uint8_t *buf, uint32_t count);

#endif

#if 0

                VirtualCom_Init();

                s_debugConsole.base = (void*)g_app_handle;

                s_debugConsole.ops.tx_union.USB_Send = VirtualCom_SendDataBlocking;

                s_debugConsole.ops.rx_union.USB_Receive = VirtualCom_ReceiveDataBlocking;

#else

                /* Virtual COM initialization is made on Composite initialization */

                s_debugConsole.base = (void*)cdc1_Handle;

                s_debugConsole.ops.tx_union.USB_Send = VirtualCom_SendDataBlocking;

                s_debugConsole.ops.rx_union.USB_Receive = VirtualCom_ReceiveDataBlocking;

#endif

  • Cpu.c (take in mind that every time you generate code, these changes need to be added again in case you do not enable "Don generate code" option)

void Components_Init(void)

{

  /*! usbDsc1 Auto initialization start */

  (void)USB_Composite_Init(USBFMW1_USB_CONTROLLER_ID, &usbDsc1_CompositeConfigStructure, &usbDsc1_CompositeHandle);

  msd1_MsdHandle = usbDsc1_CompositeConfigStructure.class_app_callback[0].class_handle;

#if ADD_CDC_SUPPORT

  cdc_preinit();

  cdc1_Handle = usbDsc1_CompositeConfigStructure.class_app_callback[1].class_handle;

#endif

  /*! usbDsc1 Auto initialization end */

  /*! DbgCs1 Auto initialization start */

  /* Debug console initialization */

  DbgConsole_Init(BOARD_DEBUG_UART_INSTANCE, DEBUG_UART_BAUD, /*DEBUG_UART_TYPE*/kDebugConsoleUSBCDC);

  /*! DbgCs1 Auto initialization end */

}

  • cdc1.h

void VirtualCom_SendDataBlocking (uint32_t base, const uint8_t *buf, uint32_t count);

usb_status VirtualCom_ReceiveDataBlocking (uint32_t base, uint8_t *buf, uint32_t count);

  • cdc1.c

bool start_app = FALSE;

bool start_transactions = FALSE;

static bool g_sendFinished = FALSE;

static bool g_receiveDone = FALSE;

void cdc_preinit(void)

{

    g_recv_size = 0;

    g_send_size = 0;

    g_sendFinished = FALSE;

    g_receiveDone = FALSE;

}

void cdc1_application_callback(uint8_t event_type, void * val, void * arg)

{

    switch (event_type) {

    case USB_DEV_EVENT_BUS_RESET:       /* BUS reset received */

      /* Write your code here ... */

        if (USB_OK == USB_Class_CDC_Get_Speed(cdc1_Handle, &g_device_speed)) {

            usbDsc1_USB_Desc_Set_Speed(cdc1_Handle, g_device_speed);

        }

      break;

    case USB_DEV_EVENT_CONFIG_CHANGED:   /* Device enumerated process complete */

      /* Write your code here ... */

        /* Schedule buffer for receive */

#if 0

        USB_Class_CDC_Recv_Data(cdc1_Handle, CDC_data_PipeOut, g_curr_recv_buf, DATA_BUFF_SIZE);

#endif

        start_app = TRUE;

      break;

In cdc1_class_specific_callback also, two events are modified:

case USB_DEV_EVENT_DATA_RECEIVED:

            if (*size != 0xFFFFFFFF) {

                g_recv_size = *size;

                g_receiveDone = TRUE;

            }

#if 0

          /* Write your code here... */

            if ((start_app == TRUE) && (start_transactions == TRUE)) {

                g_recv_size = *size;

                if (!g_recv_size) {

                    /* Schedule buffer for next receive event */

                    USB_Class_CDC_Recv_Data(cdc1_Handle, CDC_data_PipeOut, g_curr_recv_buf, DATA_BUFF_SIZE);

                }

            }

#endif

          break;

case USB_DEV_EVENT_SEND_COMPLETE:

            if ((size != NULL) && (*size != 0) && !(*size % DATA_BUFF_SIZE)) {

                /* 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_Class_CDC_Send_Data(cdc1_Handle, CDC_data_PipeIn, NULL, 0);

            }

            else if ((start_app == TRUE) && (start_transactions == TRUE))

            {

                if ((*data != NULL) || ((*data == NULL) && (*size == 0)))

                {

                    /* User: add your own code for send complete event */

#if 0

                    /* Schedule buffer for next receive event */

                    USB_Class_CDC_Recv_Data(cdc1_Handle, CDC_data_PipeOut, g_curr_recv_buf, DATA_BUFF_SIZE);

#else

                    g_sendFinished = TRUE;

#endif

                }

            }

          break;

void VirtualCom_SendDataBlocking (uint32_t base, const uint8_t *buf, uint32_t count) {

    usb_status error = USB_OK;

    if (buf == NULL) {

        error = USBERR_INVALID_PARAM;

    } else {

        if ((start_app != TRUE) || (start_transactions != TRUE)) {

            error = USBERR_DEVICE_NOT_FOUND;

        } else {

            OS_Mem_copy(buf, g_curr_send_buf, count > DATA_BUFF_SIZE ? DATA_BUFF_SIZE : count);

            error = USB_Class_CDC_Send_Data(base, CDC_data_PipeIn, g_curr_send_buf, count > DATA_BUFF_SIZE ? DATA_BUFF_SIZE : count);

            if (error != USB_OK)

            {

                /* Failure to send Data Handling code here */

            } else {

                /* Wait until transmission are done */

                while (!g_sendFinished) {};

                g_sendFinished = FALSE;

            }

        }

    }

}

usb_status VirtualCom_ReceiveDataBlocking (uint32_t base, uint8_t *buf, uint32_t count) {

    usb_status error = USB_OK;

    if (buf == NULL) {

        error = USBERR_INVALID_PARAM;

    } else {

        /* validate that count is not greater than bulk max size */

        error = USB_Class_CDC_Recv_Data(base, CDC_data_PipeOut, g_curr_recv_buf, count);

        if (error != USB_OK)

        {

            /* Failure to received Data Handling code here */

        } else {

            while (!g_receiveDone) {};

            OS_Mem_copy(g_curr_recv_buf, buf, g_recv_size != count ? g_recv_size : count);

            g_receiveDone = FALSE;

        }

    }

    return error;

}

And for a quick test, in main I added this basic code:

extern bool start_app;

extern bool start_transactions;

/* User includes (#include below this line is not maintained by Processor Expert) */

/*lint -save  -e970 Disable MISRA rule (6.3) checking. */

int main(void)

/*lint -restore Enable MISRA rule (6.3) checking. */

{

  /* Write your local variable definition here */

    uint32_t index = 0;

  /*** Processor Expert internal initialization. DON'T REMOVE THIS CODE!!! ***/

  PE_low_level_init();

  /*** End of Processor Expert internal initialization.                    ***/

  /* Write your code here */

  /* For example: for(;;) { } */

  while (1) {

      //cdc_vcom_task();

      while ((start_app == TRUE) && (start_transactions == TRUE)) {

          PRINTF(" %d\r\n", index++);

      }

  }

Please note that this is a basic implementation, you can modified Send and Received fucntions as desired (for RTOS enviroment for example)

I hope this can help you!

Best Regards,

Isaac

0 Kudos
4,003 Views
isaacavila
NXP Employee
NXP Employee

Hello Philipp,

You have to create this CDC component "manually" and do some modifications in generated code in order to get it working. Here, you can find some steps that I followed to create this CDC + MSD project in FRDM-K64F.

  • Add fsl_usb_device_msd_class to your project (4 components will be also added, among them, you can identify the fsl_usb_descriptors component that will be modified later).
  • Configure fsl_usb_device_msd_class component as desired (enable USB RAM DISK if necessary).
  • Configure fsl_usb_descriptors as follows:
    • Class Code:

Class Code.jpg

    • Class list will be 1 by default, so you need to add another class (set to 2). Class 0 will handle MSD configuration and Class 1 will allocate CDC configuration.
    • Modify Class 1 as shown below:

Class 1 Configuration.jpg

    • Set 2 interfaces to this class (One is used for control and other for data), configure them as follows:

     Interface configuration.jpg

  • Generate code. Now we proceed to do some modifications on generated code (For next modifications, you can use CDC_MSD example available in KSDK 1.3), I am adding a preprocessor definition to identify the added code.
  • In usbDsc1 file, include reference for a header file that will be created later (named cdc1.h):

#include "cdc1.h"

  • Modify lenght size for usbDsc1_Full_Speed_Configuration_1:

#if ADD_CDC_SUPPORT

        0x47 + 8 + 5 + 5 + 4 + 5,0x00,       /* Total length of data for this configuration */

#else

        0x47,0x00,                           /* Total length of data for this configuration: 71 bytes */

#endif

  • After MSD's endpoints descriptros, it is necessary to add Interface Association descriptor for CDC control and data:

/***************************************************************************/

        /* msd1: Endpoint FS Bulk EP2 Bulk OUT, up to 1.216 MB/s Descriptor        */

        /***************************************************************************/

        0x07,                                /* Descriptor size: 7 bytes */

        USB_ENDPOINT_DESCRIPTOR,             /* Descriptor type: ENDPOINT descriptor */

        0x02,                                /* Address: 2 OUT */

        0x02,                                /* Transfer type: Bulk */

        0x40,0x00,                           /* Max. packet size: 64 byte(s) */

        0x01,                                /* Maximum NAK rate: 0x01 microframe(s) */

#if ADD_CDC_SUPPORT

        /* Interface Association Descriptor */

        0x08,                                /* Size of this descriptor */

        0x0B,                                /* INTERFACE ASSOCIATION Descriptor */

        0x01,                                /* Interface number of the CDC Control

                                          interface that is associated with this function */

        0x02,                                /* Number of contiguous CDC interfaces

                                          that are associated with this function */

        0x02,                                /* CDC_CC */

        0x03,

        0x00,                                /* Not used */

        0x00,                                /* Index to string descriptor */

#endif

  • Before endpoint descriptors for CDC, add next descriptors needed for CDC:

/***************************************************************************/

        /* cdc: Interface 1 Alternate setting 0 Descriptor                         */

        /***************************************************************************/

        0x09,                                /* Descriptor size: 9 bytes */

        USB_INTERFACE_DESCRIPTOR,            /* Descriptor type: INTERFACE descriptor */

        0x01,                                /* Interface number: 1 */

        0x00,                                /* Alternative setting number: 0 */

        0x01,                                /* Number of EPs(excluding EP0): 1 */

        0x02,                                /* Class code: 0x02 Communication (Communications and CDC Control) */

        0x02,                                /* Subclass code: 0x02 */

        0x00,                                /* Protocol code: 0x00 */

        0x00,                                /* String descriptor index */

#if ADD_CDC_SUPPORT

        /* CDC Class-Specific descriptor */

        0x05,                                 /* size of Functional Desc in bytes */

        USB_CS_INTERFACE_DESCRIPTOR,          /* descriptor type*/

        USB_CDC_HEADER_FUNC_DESCRIPTOR,

        0x10, 0x01,                           /* USB Class Definitions for CDC spec release number in BCD */

        0x05,                                 /* Size of this descriptor */

        USB_CS_INTERFACE_DESCRIPTOR,          /* descriptor type*/

        USB_CDC_CALL_MANAGEMENT_FUNC_DESCRIPTOR,

        0x01,                                 /* device handles call management itself(D0 set)

                                              and will process commands multiplexed over the data interface */

        0x01,                                 /* Indicates multiplexed commands are handled via data interface */

        0x04,                                 /* Size of this descriptor */

        USB_CS_INTERFACE_DESCRIPTOR,          /* descriptor type*/

        USB_CDC_ABSTRACT_CONTROL_FUNC_DESCRIPTOR,

        0x06,                                 /* Device Supports all commands for ACM - CDC

                                              PSTN SubClass bmCapabilities */

        0x05,                                 /* size of Functional Desc in bytes */

        USB_CS_INTERFACE_DESCRIPTOR,          /* descriptor type*/

        USB_CDC_UNION_FUNC_DESCRIPTOR,

        0x01,                                 /* Interface Number of Control */

        0x02,                                 /* Interface Number of Subordinate (Data Class) Interface */

#endif

  • Also, some other modifications are needed:

#if ADD_CDC_SUPPORT static uint8_t g_alternate_interface[3]; #else volatile uint8_t usbDsc1_CurrentConfiguration = 0U; #endif

  • USB_Desc_Get_Entity_Config_Struct_0 function:

static uint8_t USB_Desc_Get_Entity_Config_Struct_0(uint32_t handle,entity_type type, uint32_t * object) {     switch (type)  {     case USB_CLASS_INFO:    #if !ADD_CDC_SUPPORT         if (usbDsc1_CurrentConfiguration == 0U) {                        *object = (uint32_t)FS_Cfg_1_ClassInfoArray;         }           #endif         break;     case USB_COMPOSITE_INFO: #if !ADD_CDC_SUPPORT         if (usbDsc1_CurrentConfiguration == 0U) {                        *object = (uint32_t)&FS_Cfg_1_CompositInfo;         } #else         *object = (uint32_t)&FS_Cfg_1_CompositInfo; #endif         break;     case USB_CLASS_INTERFACE_INDEX_INFO: #if !ADD_CDC_SUPPORT         if (usbDsc1_CurrentConfiguration == 0U) {             *object = FS_Cfg_1_ClassInfoArray[0].interfaces.interface[0].index;         } #else         *object = 0xff;         if (handle == (uint32_t)cdc1_Handle)         {             *object = (uint32_t)FS_Cfg_1_ClassInfoArray[1].interfaces.interface[g_alternate_interface[1]].index; /* Interface index for CDC*/             break;         }         else if (handle == (uint32_t)msd1_MsdHandle)         {             *object = (uint32_t)(uint32_t)FS_Cfg_1_ClassInfoArray[0].interfaces.interface[g_alternate_interface[0]].index; /* Interface index for MSD*/             break;         } #endif         break;     case USB_MSC_LBA_INFO:         /* Call registered callback */         msd1_get_desc_entity(handle, USB_MSC_LBA_INFO, object);         break;     default :         break;     }/* End Switch */     return USB_OK; }

  • USB_Desc_Get_Interface and USB_Desc_Set_Interface functions:

static uint8_t USB_Desc_Get_Interface (         uint32_t      handle,         uint8_t       interface,         uint8_t      *alt_interface ) {     UNUSED_ARGUMENT(handle); #if ADD_CDC_SUPPORT     /* if interface valid */     if(interface < 3)     {         /* get alternate interface*/         *alt_interface = g_alternate_interface[interface];         return USB_OK;     } #endif     return USBERR_INVALID_REQ_TYPE; }

static uint8_t USB_Desc_Set_Interface (         uint32_t  handle,         uint8_t       interface,         uint8_t       alt_interface ) {     UNUSED_ARGUMENT(handle); #if ADD_CDC_SUPPORT     /* if interface valid */     if(interface < 3)     {         /* set alternate interface*/         g_alternate_interface[interface]=alt_interface;         return USB_OK;     } #endif     return USBERR_INVALID_REQ_TYPE; }

  • USB_Set_Configuration function:

static uint8_t USB_Set_Configuration (         uint32_t      handle,         uint8_t       config ) {     UNUSED_ARGUMENT(handle); #if !ADD_CDC_SUPPORT     usbDsc1_CurrentConfiguration = (config - 1U); #else     uint32_t i;     for(i = 0; i < FS_Cfg_1_CompositInfo.count; i++) {         switch(FS_Cfg_1_CompositInfo.class_handle[i].type)         {         case USB_CLASS_COMMUNICATION:             FS_Cfg_1_ClassInfoArray[i].interfaces.interface = &FS_Cfg_1_Class_1_InterfaceInfoArray[config - 1];             break;         case USB_CLASS_MASS_STORAGE:             FS_Cfg_1_ClassInfoArray[i].interfaces.interface = &FS_Cfg_1_Class_0_InterfaceInfoArray[config - 1];             break;         default:             break;         }     } #endif return USB_OK; }

  • Also ClassConfigInfoArray requires to define callbacks for CDC (these callbacks will be defined in cdc1.h and cdc1.c):

static class_config_struct_t ClassConfigInfoArray[] = {         {                 { /* Application callback setting */                         msd1_application_callback,                                     /* Callback address */                         NULL,                                                          /* Callback argument */                 },                 { /* VendorRequest callback setting */                         NULL,                                                          /* Callback address */                         NULL,                                                          /* Callback argument */                 },                 { /* ClassSpecific callback setting */                         msd1_class_specific_callback,                                  /* Callback address */                         NULL,                                                          /* Callback argument */                 },                 &usbDsc1_desc_callback_Config_Struct_0,                           /* Callback function data structure for the specified type of class */                 { /* BoardInit callback setting */                         NULL,                                                          /* Callback address */                         0,                                                             /* Callback argument */                 },                 0U,                                                               /* Class handle */                 USB_CLASS_MASS_STORAGE                                            /* Class name */         }, #if ADD_CDC_SUPPORT         /* CDC callbacks */         {                 { /* Application callback setting */                         cdc1_application_callback,                                     /* Callback address */                         NULL,                                                          /* Callback argument */                 },                 { /* VendorRequest callback setting */                         NULL,                                                          /* Callback address */                         NULL,                                                          /* Callback argument */                 },                 { /* ClassSpecific callback setting */                         cdc1_class_specific_callback,                                  /* Callback address */                         NULL,                                                          /* Callback argument */                 },                 &usbDsc1_desc_callback_Config_Struct_0,                           /* Callback function data structure for the specified type of class */                 { /* BoardInit callback setting */                         NULL,                                                          /* Callback address */                         0,                                                             /* Callback argument */                 },                 0U,                                                               /* Class handle */                 USB_CLASS_COMMUNICATION                                           /* Class name */         } #endif };

  • Last modification on usbDsc1.c is:

composite_config_struct_t usbDsc1_CompositeConfigStructure = { #if !ADD_CDC_SUPPORT         1,                                                                  /* Number of classes */ #else         2,                                                                  /* Number of classes */ #endif         ClassConfigInfoArray                                                /* Class configuration structure array */ };

  • Then, Cpu.c file needs to be modified in order to initialize CDC handling: