ACM Subclass
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.
Micrium’s ACM subclass implementation complies with the following specification:
- Universal Serial Bus, Communications, Subclass for PSTN Devices, revision 1.2, February 9, 2007.
Overview
The general characteristics of the CDC base class in terms of Communications Class Interface (CCI) and Data Class Interface (DCI) were presented in the CDC Class Overview page. In this section, a CCI of type ACM is considered. It will consist 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.
Several subclass-specific requests exists 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, Micrium’s ACM subclass supports:
Subclass request | Description |
---|---|
SetCommFeature | The host sends this request to control the settings for a particular communications feature. Not used for serial emulation. |
GetCommFeature | The host sends this request to get the current settings for a particular communications feature. Not used for serial emulation. |
ClearCommFeature | The host sends this request to clear the settings for a particular communications feature. Not used for serial emulation. |
SetLineCoding | The host sends this request to configure the ACM device settings in terms of 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. |
Micrium’s 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
Configuration
usbd_cfg.h
.
Constant | Description | Possible Values |
---|---|---|
USBD_ACM_SERIAL_CFG_MAX_NBR_DEV | Configures the maximum number of subclass instances. The constant value cannot be greater than USBD_CDC_CFG_MAX_NBR_DEV . Unless you plan on having multiple configurations or interfaces using different class instances, this can be set to the default value. | From 1 to USBD_CDC_CFG_MAX_NBR_DEV . Default value is 1. |
Subclass Instance Configuration
Before starting the communication phase, your application needs to initialize and configure the class to suit its needs. Table - ACM Subclass Initialization API Summary summarizes the initialization functions provided by the ACM subclass. For more details about the functions’ parameters, refer to the CDC ACM Subclass Functions reference.
Function name | Operation |
---|---|
USBD_ACM_SerialInit() | Initializes ACM subclass internal structures and variables. |
USBD_ACM_SerialAdd() | Creates a new instance of ACM subclass. |
USBD_ACM_SerialCfgAdd() | Adds an existing ACM instance to the specified device configuration. |
USBD_ACM_SerialLineCodingReg() | Registers line coding notification callback. |
USBD_ACM_SerialLineCtrlReg() | Registers line control notification callback. |
You need to call these functions in the order shown below to successfully initialize the ACM subclass:
- Call
USBD_ACM_SerialInit()
This function initializes all internal structures and variables that the ACM subclass needs. You should call this function only once even if you use multiple class instances. - Call
USBD_ACM_SerialAdd()
This function allocates an ACM subclass instance. Internally, this function allocates a CDC class instance. It also allows you to specify the line state notification interval expressed in milliseconds and the Call Management capabilities. - Call
USBD_ACM_SerialLineCodingReg()
This function allows you to register a callback used by the ACM subclass to notify the application about a change in the serial line coding settings (that is baud rate, number of stop bits, parity and number of data bits). - Call
USBD_ACM_SerialLineCtrlReg()
This function allows you to register a callback used by the ACM subclass to notify the application about a change in the serial line state (that is RS-232 break signal, carrier control, i.e. RS-232 RTS signal, and a flag indicating that data equipment terminal is present or not, i.e. RS-232 DTR signal,). - Call
USBD_ACM_SerialCfgAdd()
Finally, once the ACM subclass instance has been created, you must add it to a specific configuration.
Listing - CDC ACM Subclass Initialization Example illustrates the use of the previous functions for initializing the ACM subclass. Note that the error handling has been omitted for clarity.
CPU_BOOLEAN App_USBD_CDC_Init (CPU_INT08U dev_nbr, CPU_INT08U cfg_hs, CPU_INT08U cfg_fs) { USBD_ERR err; CPU_INT08U subclass_nbr; USBD_CDC_Init(&err); (1) USBD_ACM_SerialInit(&err); (2) (3) subclass_nbr = USBD_ACM_SerialAdd(64u, (USBD_ACM_SERIAL_CALL_MGMT_DATA_CCI_DCI | USBD_ACM_SERIAL_CALL_MGMT_DEV), &err); USBD_ACM_SerialLineCodingReg( subclass_nbr, (4) App_USBD_CDC_SerialLineCoding, (void *)0, &err); USBD_ACM_SerialLineCtrlReg( subclass_nbr, (5) App_USBD_CDC_SerialLineCtrl, (void *)0, &err); if (cfg_hs != USBD_CFG_NBR_NONE) { USBD_ACM_SerialCfgAdd(subclass_nbr, dev_nbr, cfg_hs, &err); (6) } if (cfg_fs != USBD_CFG_NBR_NONE) { USBD_ACM_SerialCfgAdd(subclass_nbr, dev_nbr, cfg_fs, &err); (7) } }
(1) Initialize CDC internal structures and variables.
(2) Initialize CDC ACM internal structures and variables.
(3) Create a new CDC ACM subclass instance. In this example, the line state notification interval is 64 ms. In the CCI, an interrupt IN endpoint is used to asynchronously notify the host of the status of the different signals forming the serial line. The line state notification interval corresponds to the interrupt endpoint’s polling interval. The second argument allows to specify the Call Management support of the CDC ACM function. In this example, the device handles the call management itself (USBD_ACM_SERIAL_CALL_MGMT_DEV
) and information can be set over a DCI (USBD_ACM_SERIAL_CALL_MGMT_DATA_CCI_DCI
).
Mac OS X supports only all combinations of the call management capabilities except: (USBD_ACM_SERIAL_CALL_MGMT_DEV)
. For this latter combination, Mac OS X won't recognize the CDC ACM function. Windows and Linux operating systems accept any combinations of the flags. See
USBD_ACM_SerialAdd()
for more details about the possible flags combinations.
(4) Register the application callback, App_USBD_CDC_SerialLineCoding()
. It is called by the ACM subclass when the class-specific request SET_LINE_CODING
has been received by the device. This request allows the host to specify the serial line settings (baud rate, stop bits, parity and data bits). Refer to “CDC PSTN Subclass, revision 1.2”, section 6.3.10 for more details about this class-specific request.
(5) Register the application callback, App_USBD_CDC_SerialLineCtrl()
. It is called by the ACM subclass when the class-specific request SET_CONTROL_LINE_STATE
has been received by the device. This request generates RS-232/V.24 style control signals. Refer to “CDC PSTN Subclass, revision 1.2”, section 6.3.12 for more details about this class-specific request.
(6) Check if the high-speed configuration is active and proceed to add the ACM subclass instance to this configuration.
(7) Check if the full-speed configuration is active and proceed to add the ACM subclass instance to this configuration.
Listing - CDC ACM Subclass Initialization Example also illustrates an example of multiple configurations. The functions USBD_ACM_SerialAdd()
and USBD_ACM_SerialCfgAdd()
allow you to create multiple configurations and multiple instances architecture. Refer to the Class Instance Concept page for more details about multiple class instances.
Subclass Notification and Management
You have access to some functions provides in the ACM subclass which relate to the ACM requests and the serial line state previously presented in the Overview section. shows these functions. Refer to the CDC ACM Subclass Functions reference for more details about the functions’ parameters.
Function | Relates to... | Description |
---|---|---|
USBD_ACM_SerialLineCodingGet() | SetLineCoding | Application can get the current line coding settings set either by the host with SetLineCoding requests or by USBD_ACM_SerialLineCodingSet() |
USBD_ACM_SerialLineCodingSet() | GetLineCoding | Application can set the line coding. The host can retrieve the settings with the GetLineCoding request. |
USBD_ACM_SerialLineCodingReg() | SetLineCoding | Application registers a callback called by the ACM subclass upon reception of the SetLineCoding request. Application can perform any specific operations. |
USBD_ACM_SerialLineCtrlGet() | SetControlLineState | Application can get the current control line state set by the host with the SetControlLineState request. |
USBD_ACM_SerialLineCtrlReg() |
| Application registers a callback called by the ACM subclass upon reception of the SendBreak or SetControlLineState requests. Application can perform any specific operations. |
USBD_ACM_SerialLineStateSet() | Serial line state | 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. |
USBD_ACM_SerialLineStateClr() | Serial line state | 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. |
Micrium’s ACM subclass always uses the interrupt endpoint to notify the host of the serial line state. You cannot disable the interrupt endpoint.
Subclass Instance Communication
Micrium’s ACM subclass offers the following functions to communicate with the host. For more details about the functions’ parameters, refer to the CDC ACM Subclass Functions reference.
Function name | Operation |
---|---|
USBD_ACM_SerialRx() | Receives data from host through a bulk OUT endpoint. This function is blocking. |
USBD_ACM_SerialTx() | Sends data to host through a bulk IN endpoint. This function is blocking. |
USBD_ACM_SerialRx()
and USBD_ACM_SerialTx()
provide synchronous communication which means that the transfer is blocking. Upon calling the function, the application blocks until transfer completion with or without an error. A timeout can be specified to avoid waiting forever. Listing - Serial Read and Write Example presents a read and write example to receive data from the host using the bulk OUT endpoint and to send data to the host using the bulk IN endpoint.
CPU_INT08U rx_buf[2]; CPU_INT08U tx_buf[2]; USBD_ERR err; (void)USBD_ACM_SerialRx(subclass_nbr, (1) &rx_buf[0], (2) 2u, 0u, (3) &err); if (err != USBD_ERR_NONE) { /* Handle the error. */ } (void)USBD_ACM_SerialTx(subclass_nbr, (1) &tx_buf[0], (4) 2u, 0u, (3) &err); if (err != USBD_ERR_NONE) { /* Handle the error. */ }
(1) The class instance number created with USBD_ACM_SerialAdd()
will serve internally to the ACM subclass to route the transfer to the proper bulk OUT or IN endpoint.
(2) The application must ensure that the buffer provided to the function is large enough to accommodate all the data. Otherwise, synchronization issues might happen.
(3) In order to avoid an infinite blocking situation, a timeout expressed in milliseconds can be specified. A value of ‘0’ makes the application task wait forever.
(4) The application provides the initialized transmit buffer.