USB Device CDC ACM Class#

This section describes the Communications Device Class (CDC) class and the associated CDC subclass supported by Silicon Labs' USB Device stack. Silicon Labs USB-Device currently supports the Abstract Control Model (ACM) subclass, which is commonly used for serial emulation.

CDC includes various telecommunication and networking devices. Telecommunication devices encompass analog modems, analog and digital telephones, ISDN terminal adapters, etc. For example, networking devices contain ADSL and cable modems, Ethernet adapters, and hubs. CDC defines a framework to encapsulate existing communication services standards, such as V.250 (for modems over telephone network) and Ethernet (for local area network devices), using a USB link. A communication device is in charge of device management, call management when needed, and data transmission.

CDC defines seven major groups of devices. Each group belongs to a model of communication, which may include several subclasses. Each group of devices has its own specification document besides the CDC base class. The seven groups are:

  • Public Switched Telephone Network (PSTN), devices including voiceband modems, telephones, and serial emulation devices.

  • Integrated Services Digital Network (ISDN) devices, including terminal adaptors and telephones.

  • Ethernet Control Model (ECM) devices, including devices supporting the IEEE 802 family (ex.: cable and ADSL modems, WiFi adapters).

  • Asynchronous Transfer Mode (ATM) devices, including ADSL modems and other devices connected to ATM networks (workstations, routers, LAN switches).

  • Wireless Mobile Communications (WMC) devices, including multi-function communications handset devices used to manage voice and data communications.

  • Ethernet Emulation Model (EEM) devices which exchange Ethernet-framed data.

  • Network Control Model (NCM) devices, including high-speed network devices (High Speed Packet Access modems, Line Terminal Equipment)

The CDC and the associated subclass implementation complies with the following specifications:

  • Universal Serial Bus, Class Definitions for Communications Devices, Revision 1.2, November 3 2010.

  • Universal Serial Bus, Communications, Subclass for PSTN Devices, Revision 1.2, February 9 2007.

USB Device CDC Base Class Overview#

A CDC device is composed of the following interfaces to implement communication capability:

  • Communications Class Interface (CCI) is responsible for the device management and optionally the call management. The device management enables the general configuration and control of the device and the notification of events to the host. The call management enables calls establishment and termination. Call management might be multiplexed through a DCI. A CCI is mandatory for all CDC devices. It identifies the CDC function by specifying the communication model supported by the CDC device. The interface(s) following the CCI can be any defined USB class interface, such as Audio or a vendor-specific interface. The vendor-specific interface is represented specifically by a DCI.

  • Data Class Interface (DCI) is responsible for data transmission. Data transmitted and/or received do not follow a specific format. Data could be raw data from a communication line, data following a proprietary format, etc. All the DCIs following the CCI can be seen as subordinate interfaces.

A CDC device must have at least one CCI and zero or more DCIs. One CCI and any subordinate DCI together provide a feature to the host. This capability is also referred to as a function. In a CDC composite device, you could have several functions. Therefore, the device would be composed of several sets of CCI and DCI(s) as shown in Figure - CDC Composite Device.

Figure - CDC Composite Device#

Figure 4 CDC Composite Device

A CDC device is likely to use the following combination of endpoints:

  • A pair of control IN and OUT endpoints called the default endpoint.

  • An optional bulk or interrupt IN endpoint.

  • A pair of bulk or isochronous IN and OUT endpoints. Note that Silicon Labs USB device stack does not currently support isochronous endpoints.

The table below shows the usage of the different endpoints and by which interface of the CDC they are used.

Table - CDC Endpoint Usage#

Endpoint

Direction

Interface

Usage

Control IN

Device-to-host

CCI

Standard requests for enumeration, class-specific requests, device management, and optionally call management.

Control OUT

Host-to-device

CCI

Standard requests for enumeration, class-specific requests, device management, and optionally call management.

Interrupt or bulk IN

Device-to-host

CCI

Events notification, such as ring detect, serial line status, network status.

Bulk or isochronous IN

Device-to-host

DCI

Raw or formatted data communication.

Bulk or isochronous OUT

Host-to-device

DCI

Raw or formatted data communication.

Most communication devices use an interrupt endpoint to notify the host of events. Isochronous endpoints should not be used for data transmission when a proprietary protocol relies on data retransmission in case of USB protocol errors. Isochronous communication can inherently lose data since it has no retry mechanisms.

The seven major models of communication encompass several subclasses. A subclass describes the way the device should use the CCI to handle the device management and call management. The table below shows all the possible subclasses and the communication model they belong to.

Table - CDC Subclasses#

Subclass

Communication Model

Example of Devices Using This Subclass

Direct Line Control Model

PSTN

Modem devices directly controlled by the USB host

Abstract Control Model

PSTN

Serial emulation devices, modem devices controlled through a serial command set

Telephone Control Model

PSTN

Voice telephony devices

Multi-Channel Control Model

ISDN

Basic rate terminal adaptors, primary rate terminal adaptors, telephones

CAPI Control Model

ISDN

Basic rate terminal adaptors, primary rate terminal adaptors, telephones

Ethernet Networking Control Model

ECM

DOC-SIS cable modems, ADSL modems that support PPPoE emulation, Wi-Fi adaptors (IEEE 802.11-family), IEEE 802.3 adaptors

ATM Networking Control Model

ATM

ADSL modems

Wireless Handset Control Model

WMC

Mobile terminal equipment connecting to wireless devices

Device Management

WMC

Mobile terminal equipment connecting to wireless devices

Mobile Direct Line Model

WMC

Mobile terminal equipment connecting to wireless devices

OBEX

WMC

Mobile terminal equipment connecting to wireless devices

Ethernet Emulation Model

EEM

Devices using Ethernet frames as the next layer of transport. Not intended for routing and Internet connectivity devices

Network Control Model

NCM

IEEE 802.3 adaptors carrying high-speed data bandwidth on network

USB Device CDC ACM Class Resource Needs from Core#

Each time you add a CDC ACM class instance to a USB configuration via a call to the function sl_usbd_cdc_acm_add_to_configuration(), the following resources will be allocated from the core.

Resource

Quantity

Interfaces

2

Alternate interfaces

2

Endpoints

3

Interface groups

1

Note that those numbers are per configuration. When setting up your SL_USBD_INTERFACE_QUANTITY, SL_USBD_ALT_INTERFACE_QUANTITY, SL_USBD_INTERFACE_GROUP_QUANTITY and SL_USBD_DESCRIPTOR_QUANTITY configuration values, don't forget to take into account on how many configurations the class will be added. For the SL_USBD_OPEN_ENDPOINTS_QUANTITY configuration value, since endpoints are opened only when a configuration is set by the host, you just need to take into account the number of needed endpoints for a class instance.

USB Device CDC ACM Subclass Overview#

The CDC base class is composed of a Communications Class Interface (CCI) and Data Class Interface (DCI), which is discussed in detail in USB Device CDC Base Class Overview . This section discusses a CCI of type ACM. It consists of a default endpoint for the management element and an interrupt endpoint for the notification element. A pair of bulk endpoints is used to carry unspecified data over the DCI.

The ACM subclass is used by two types of communication devices:

  • Devices supporting AT commands (for instance, voiceband modems).

  • Serial emulation devices which are also called Virtual COM port devices.

There are several subclass-specific requests for the ACM subclass. They allow you to control and configure the device. The complete list and description of all ACM requests can be found in the specification “Universal Serial Bus, Communications, Subclass for PSTN Devices, revision 1.2, February 9, 2007”, section 6.2.2.

From this list, Silicon Labs’ ACM subclass supports the following:

Table - ACM Requests Supported by Silicon Labs#

Subclass Request

Description

SetCommFeature

The host sends this request to control the settings for a given communications feature. Not used for serial emulation.

GetCommFeature

The host sends this request to get the current settings for a given communications feature. Not used for serial emulation.

ClearCommFeature

The host sends this request to clear the settings for a given communications feature. Not used for serial emulation.

SetLineCoding

The host sends this request to configure the ACM device settings: baud rate, number of stop bits, parity type and number of data bits. For a serial emulation, this request is sent automatically by a serial terminal each time you configure the serial settings for an open virtual COM port.

GetLineCoding

The host sends this request to get the current ACM settings (baud rate, stop bits, parity, data bits). For a serial emulation, serial terminals send this request automatically during virtual COM port opening.

SetControlLineState

The host sends this request to control the carrier for half-duplex modems and indicate that Data Terminal Equipment (DTE) is ready or not. In the serial emulation case, the DTE is a serial terminal. For a serial emulation, certain serial terminals allow you to send this request with the controls set.

SetBreak

The host sends this request to generate an RS-232 style break. For a serial emulation, certain serial terminals allow you to send this request.

Silicon Labs’ ACM subclass uses the interrupt IN endpoint to notify the host about the current serial line state. The serial line state is a bitmap informing the host about:

  • Data discarded because of overrun

  • Parity error

  • Framing error

  • State of the ring signal detection

  • State of break detection mechanism

  • State of transmission carrier

  • State of receiver carrier detection

Silicon Labs’ ACM subclass implementation complies with the following specification:

  • Universal Serial Bus, Communications, Subclass for PSTN Devices, revision 1.2, February 9, 2007.

USB Device CDC ACM Class Configuration#

This section discusses how to configure the CDC ACM Class (Communication Device Class, Abstract Control Model). There are two groups of configuration parameters:

USB Device CDC ACM Class Application Specific Configurations#

CDC Base Class#

First, to use the Silicon Labs USB device CDC class module, you will need to adjust the CDC compile-time configuration #define-s according to your application needs. They are regrouped inside the sl_usbd_core_config.h header file under the CDC section. Their purpose is to inform the USB device module about how many USB CDC objects to allocate.

The table below describes each configuration field available in this configuration structure.

Table - USB Device CDC Configuration Defines#

Configuration Name

Description

Default Value

SL_USBD_CDC_CLASS_INSTANCE_QUANTITY

Number of class instances you will allocate via a call to the function sl_usbd_cdc_acm_create_instance().

2

SL_USBD_CDC_CONFIGURATION_QUANTITY

Number of configurations. ACM class instances can be added to one or more configurations via a call to the sl_usbd_cdc_acm_add_to_configuration().

1

SL_USBD_CDC_DATA_INTERFACE_QUANTITY

Total number of data interfaces (DCI) for all the CDC functions. Each CDC ACM function added via a call to the function sl_usbd_cdc_acm_create_instance() will add a data interface.

2

ACM Subclass#

The ACM subclass has one compile-time configuration shown in the table below.

Table - USB Device CDC ACM Configuration Define#

Configuration Name

Description

Default Value

SL_USBD_CDC_ACM_SUBCLASS_INSTANCE_QUANTITY

Configures the number of subclass instances you will allocate via a call to the function sl_usbd_cdc_acm_create_instance().

2

USB Device CDC ACM Class Instance Configurations#

This section defines the configurations related to the CDC ACM serial class instances.

Class Instance Creation#

To create a CDC ACM serial class instance, call the function sl_usbd_cdc_acm_create_instance(). This function takes three configuration arguments, as described here.

line_state_interval

This is the interval (in milliseconds) that your CDC ACM serial class instance will report the line state notifications to the host. This value must be a power of two (1, 2, 4, 8, 16, etc).

call_mgmt_capabilities#

Call Management Capabilities bitmap. Possible values of the bitmap are as follows:

Value (bit)

Description

SL_USBD_ACM_SERIAL_CALL_MGMT_DEV

Device handles call management itself.

SL_USBD_ACM_SERIAL_CALL_MGMT_DATA_CCI_DCI

Device can send/receive call management information over a Data Class interface.

p_acm_callbacks#

p_acm_callbacks is a pointer to a structure of type sl_usbd_cdc_acm_callbacks_t. Its purpose is to give the CDC ACM Class a set of callback functions to be called when a CDC ACM event occurs.

Not all callbacks are mandatory and a null pointer (NULL) can be passed in the callbacks structure variable when the callback is not needed.

The table below describes each configuration field available in this configuration structure.

Table - sl_usbd_cdc_acm_callbacks_t Configuration Structure#

Fields

Description

Function Signature

.enable

Called when the USB class instance is enabled successfully.

void app_usbd_cdc_acm_enable(uint8_t subclass_nbr);

.disable

Called when the USB class instance is disabled.

void app_usbd_cdc_acm_disable(uint8_t subclass_nbr);

.line_control_changed

Called when a line control change is received.

void app_usbd_cdc_acm_line_control_changed(uint8_t subclass_nbr, uint8_t event, uint8_t event_chngd);

line_coding_changed

Called when a line coding change is received.

bool app_usbd_cdc_acm_line_coding_changed(uint8_t subclass_nbr, subclass_nbr, sl_usbd_cdc_acm_line_coding_t *p_line_coding

See section Registering Event Notification Callbacks for callback functions example.

USB Device CDC ACM Class Programming Guide#

This section explains how to use the CDC Abstract Control Model class.

Initializing the USB Device CDC ACM Class#

To add CDC ACM class functionality to your device, you must first initialize the CDC base class and the ACM subclass by calling the functions sl_usbd_cdc_init() and sl_usbd_cdc_acm_init().

The example below shows how to call sl_usbd_cdc_init() and sl_usbd_cdc_acm_init() using default arguments.

Example - Initialization of CDC ACM Class#
sl_status_t  status;

status = sl_usbd_cdc_init();
if (status != SL_STATUS_OK) {
  /* An error occurred. Error handling should be added here. */
}

status = sl_usbd_cdc_acm_init();
if (status != SL_STATUS_OK) {
  /* An error occurred. Error handling should be added here. */
}

Adding a USB Device CDC ACM Class Instance to Your Device#

To add CDC ACM class functionality to your device, you must create an instance, then add it to your device's configuration(s).

Creating a CDC ACM Class Instance#

Create a CDC ACM class instance by calling the function sl_usbd_cdc_acm_create_instance().

The example below shows how to create a CDC ACM class instance via sl_usbd_cdc_acm_create_instance().

Example - Creating a CDC ACM Function via sl_usbd_cdc_acm_create_instance()#
uint8_t      subclass_nbr;
sl_status_t  status;

status = sl_usbd_cdc_acm_create_instance(64u,
                                         SL_USBD_ACM_SERIAL_CALL_MGMT_DATA_CCI_DCI | SL_USBD_ACM_SERIAL_CALL_MGMT_DEV,
                                         NULL,
                                         &subclass_nbr);
if (status != SL_STATUS_OK) {
  /* An error occurred. Error handling should be added here. */
}

Adding the CDC ACM Class Instance to Your Device's Configuration(s)#

After you have created a CDC ACM class instance, you can add it to a configuration by calling the function sl_usbd_cdc_acm_add_to_configuration().

The example below shows how to call sl_usbd_cdc_acm_add_to_configuration().

Example - Call to USBD ACM sl_usbd_cdc_acm_add_to_configuration()#
sl_status_t  status;

status = sl_usbd_cdc_acm_add_to_configuration(subclass_nbr,                       (1)
                                              config_nbr_fs);                     (2)
if (status != SL_STATUS_OK) {
  /* An error occurred. Error handling should be added here. */
}

(1) Class number to add to the configuration returned by sl_usbd_cdc_acm_create_instance().

(2) Configuration number (here adding it to a Full-Speed configuration).

Registering Event Notification Callbacks#

The CDC ACM Serial class can notify your application of any changes in line control or coding via notification callback functions. A callback functions structure can be passed as argument during the ACM instance creation. Note that those callbacks are optional. Example - CDC ACM Callbacks Registration illustrates the use of the callback registration functions. Example - CDC ACM Callbacks Implementation shows an example of implementation of the callback functions.

Example - CDC ACM Callbacks Registration#
uint8_t      subclass_nbr;
sl_status_t  status;

sl_usbd_cdc_acm_callbacks_t sli_usbd_cdc_acm_callbacks = {
  app_usbd_cdc_acm_connect,
  app_usbd_cdc_acm_disconnect,
  app_usbd_cdc_acm_line_control_changed,
  app_usbd_cdc_acm_line_coding_changed,
};

status = sl_usbd_cdc_acm_create_instance(64u,
                                         SL_USBD_ACM_SERIAL_CALL_MGMT_DATA_CCI_DCI | SL_USBD_ACM_SERIAL_CALL_MGMT_DEV,
                                         &sli_usbd_cdc_acm_callbacks,
                                         &subclass_nbr);
if (status != SL_STATUS_OK) {
  /* An error occurred. Error handling should be added here. */
}
Example - CDC ACM Callbacks Implementation#
bool  app_usbd_cdc_acm_line_coding_changed (uint8_t                        subclass_nbr,
                                            sl_usbd_cdc_acm_line_coding_t  *p_line_coding)
{
    uint32_t  baudrate_new;
    uint8_t   parity_new;
    uint8_t   stop_bits_new;
    uint8_t   data_bits_new;

    /* TODO: Apply new line coding.*/
    baudrate_new  = p_line_coding->BaudRate;
    parity_new    = p_line_coding->Parity;
    stop_bits_new = p_line_coding->StopBits;
    data_bits_new = p_line_coding->DataBits;

    return (true);                                       (1)
}

void  app_usbd_cdc_acm_line_control_changed (uint8_t   subclass_nbr,
                                             uint8_t   event,
                                             uint8_t   event_changed)
{
    bool  rts_state;
    bool  rts_state_changed;
    bool  dtr_state;
    bool  dtr_state_changed;
    bool  brk_state;
    bool  brk_state_changed;

    /* TODO: Apply new line control.  */
    rts_state         = ((event & SL_USBD_CDC_ACM_CTRL_RTS) != 0) ? true : false;
    rts_state_changed = ((event_changed & SL_USBD_CDC_ACM_CTRL_RTS) != 0) ? true : false;
    dtr_state         = ((event & SL_USBD_CDC_ACM_CTRL_DTR) != 0) ? true : false;
    dtr_state_changed = ((event_changed & SL_USBD_CDC_ACM_CTRL_DTR) != 0) ? true : false;
    brk_state         = ((event & SL_USBD_CDC_ACM_CTRL_BREAK) != 0) ? true : false;
    brk_state_changed = ((event_changed & SL_USBD_CDC_ACM_CTRL_BREAK) != 0) ? true : false;
}

(1) It is important to return false to this function if the line coding applying failed. Otherwise, return true.

Communicating Using the CDC ACM Class#

Serial Status#

Line Coding#

The USB host controls the line coding (baud rate, parity, etc) of the CDC ACM device. When necessary, the application is responsible for setting the line coding.

There are two functions provided to retrieve and set the current line coding, as described in the table below.

Table - CDC ACM Line Coding Functions#

Function

Description

sl_usbd_cdc_acm_get_line_coding()

Your application can get the current line coding settings set either from the host with SetLineCoding requests or with the function sl_usbd_cdc_acm_set_line_coding().

sl_usbd_cdc_acm_set_line_coding()

Your application can set the line coding. The host can retrieve the settings with the GetLineCoding request.

Line Control#

The USB host controls the line control (RTS and DTR pins, break signal, and so on) of the CDC ACM device. When necessary, your application is responsible for applying the line controls.

A function is provided to retrieve and set the current line controls, as are described in the table below.

Table - CDC ACM Line Control Functions#

Function

sl_usbd_cdc_acm_get_line_control_state()

Your application can get the current control line state set by the host with the SetControlLineState request.

Line State#

The USB host retrieves the line state at a regular interval. Your application must update the line state each time it changes. When necessary, your application is responsible for setting the line state.

Two functions are provided to retrieve and set the current line controls, as described in the table below.

Table - CDC ACM Line State Functions#

Function

sl_usbd_cdc_acm_set_line_state_event()

Your application can set any line state event(s). While setting the line state, an interrupt IN transfer is sent to the host to inform about it a change in the serial line state.

sl_usbd_cdc_acm_clear_line_state_event()

Application can clear two events of the line state: transmission carrier and receiver carrier detection. All the other events are self-cleared by the ACM serial emulation subclass.

Subclass Instance Communication#

Silicon Labs' ACM subclass offers the following functions to communicate with the host. For more details about the functions’ parameters, see the CDC ACM Subclass Functions reference.

Function name

Operation

sl_usbd_cdc_acm_read()

Receives data from host through a bulk OUT endpoint. This function is blocking.

sl_usbd_cdc_acm_write()

Sends data to host through a bulk IN endpoint. This function is blocking.

Table - CDC ACM Communication API Summary

sl_usbd_cdc_acm_read() and sl_usbd_cdc_acm_write() provide synchronous communication, which means that the transfer is blocking. In other words, upon calling the function, the application blocks until the transfer is complete with or without an error. A timeout can be specified to avoid waiting forever. The example below shows a read and write example that receives data from the host using the bulk OUT endpoint and sends data to the host using the bulk IN endpoint.

Listing - Serial Read and Write Example#
__ALIGNED(4) uint8_t  rx_buf[2];
__ALIGNED(4) uint8_t  tx_buf[2];
uint32_t              xfer_len;
sl_status_t           status;

status = sl_usbd_cdc_acm_read(subclass_nbr,                                         (1)
                              rx_buf,                                               (2)
                              2u,
                              0u,                                                   (3)
                              &xfer_len);
if (status != SL_STATUS_OK) {
  /* An error occurred. Error handling should be added here. */
}

status = sl_usbd_cdc_acm_write(subclass_nbr,                                         (1)
                               tx_buf,                                               (4)
                               2u,
                               0u,                                                   (3)
                               &xfer_len);
if (status != SL_STATUS_OK) {
  /* An error occurred. Error handling should be added here. */
}

(1) The class instance number created with sl_usbd_cdc_acm_create_instance() provides an internal reference to the ACM subclass to route the transfer to the proper bulk OUT or IN endpoint.

(2) Your application must ensure that the buffer provided to the function is large enough to accommodate all the data. Otherwise, synchronization issues might happen.

(3) To avoid an infinite blocking situation, specify a timeout expressed in milliseconds. A value of ‘0’ makes the application task wait forever.

(4) The application provides the initialized transmit buffer.