USB Libraries Help > USB Host Libraries > USB CDC Host Library > Using the Library > How the Library Works > Sending Class-specific Control Transfers
MPLAB Harmony USB Stack
Sending Class-specific Control Transfers

The CDC Host Client Driver allows the application client to send CDC Class specific commands to the connected device. These commands allows the application client to:

  • Set the device line coding (USB_HOST_CDC_LineCodingSet)
  • Retrieve the device line coding (USB_HOST_CDC_LineCodingGet)
  • Set the device control line state (USB_HOST_CDC_ControlLineStateSet)
  • Ask the device to send a break signal (USB_HOST_CDC_BreakSend)

These functions are non-blocking. The functions will return before the actual command execution is complete. The return value indicates if the command was scheduled successfully, or if the driver is busy and cannot accept commands, or if the command failed due to an unknown reason. If the command failed because the driver was busy, it can be retried. If scheduled successfully, the function will return a valid request handle. This request handle is unique and tracks the requested command. 

When the command related control transfer has completed, the CDC Host Client Driver generates a command specific completion event. This event is accompanied by a data structure that contains information about the completion of the command. The request handler generated at the time of calling the command request function is also returned along with the event. The request handle expires after the event handler exits. The following tables show the command functions, along with the respective events and the type of the event related data. 

Table 1: Set Line Coding  

Function 
Event 
USB_HOST_CDC_EVENT_ACM_SET_LINE_CODING_COMPLETE 
Event Data Type 

Table 2: Get Line Coding

Function 
USB_HOST_CDC_ACM_LineCodingGet 
Event 
USB_HOST_CDC_EVENT_ACM_GET_LINE_CODING_COMPLETE 
Event Data Type 

Table 3: Set Control Line State

Function 
Event 
USB_HOST_CDC_EVENT_ACM_CONTROL_LINE_STATE_SET_COMPLETE 
Event Data Type 
USB_HOST_CDC_EVENT_ACM_CONTROL_LINE_STATE_SET_COMPLETE _DATA 

Table 4: Send Break

Function 
USB_HOST_CDC_ACM_SendBreak 
Event 
USB_HOST_CDC_EVENT_ACM_SEND_BREAK_COMPLETE 
Event Data Type 
USB_HOST_CDC_EVENT_ACM_SEND_BREAK_COMPLETE _DATA 

The following code shows an example of sending a CDC class specific commands. Refer to the Event Handling section for details on setting the event handler function. 

Example:  

/* This code shows an example of how to send CDC Class specific command
 * requests. The event handling related to each command is also shown. */

USB_HOST_CDC_EVENT_RESPONSE APP_USBHostCDCEventHandler
(
    USB_HOST_CDC_HANDLE cdcHandle,
    USB_HOST_CDC_EVENT event,
    void * eventData,
    uintptr_t context
)
{
    /* This function is called when a CDC Host event has occurred. A pointer to
     * this function is registered after opening the device. See the call to
     * USB_HOST_CDC_EventHandlerSet() function. */

    USB_HOST_CDC_EVENT_ACM_SET_LINE_CODING_COMPLETE_DATA * setLineCodingEventData;
    USB_HOST_CDC_EVENT_ACM_SET_CONTROL_LINE_STATE_COMPLETE_DATA * setControlLineStateEventData;
    USB_HOST_CDC_EVENT_WRITE_COMPLETE_DATA * writeCompleteEventData;
    USB_HOST_CDC_EVENT_READ_COMPLETE_DATA * readCompleteEventData;

    switch(event)
    {
        case USB_HOST_CDC_EVENT_ACM_SET_LINE_CODING_COMPLETE:

            /* This means the application requested Set Line Coding request is
             * complete. */
            setLineCodingEventData = (USB_HOST_CDC_EVENT_ACM_SET_LINE_CODING_COMPLETE_DATA *)(eventData);
            appData.controlRequestDone = true;
            appData.controlRequestResult = setLineCodingEventData->result;
            break;

        case USB_HOST_CDC_EVENT_ACM_SET_CONTROL_LINE_STATE_COMPLETE:

            /* This means the application requested Set Control Line State
             * request has completed. */
            setControlLineStateEventData = (USB_HOST_CDC_EVENT_ACM_SET_CONTROL_LINE_STATE_COMPLETE_DATA *)(eventData);
            appData.controlRequestDone = true;
            appData.controlRequestResult = setControlLineStateEventData->result;
            break;

        default:
            break;

    }
}

void APP_Tasks(void)
{

    switch(appData.state)
    {
        /* The application states that enable the bus and wait for device attach are
         * not shown here for brevity */

        case APP_STATE_OPEN_DEVICE:

            /* In this state the application opens the attached device */
            appData.cdcHostHandle = USB_HOST_CDC_Open(appData.cdcObj);
            if(appData.cdcHostHandle != USB_HOST_CDC_HANDLE_INVALID)
            {
                /* The driver was opened successfully. Set the event handler
                 * and then go to the next state. */
                USB_HOST_CDC_EventHandlerSet(appData.cdcHostHandle, APP_USBHostCDCEventHandler, (uintptr_t)0);
                appData.state = APP_STATE_SET_LINE_CODING;
            }
            break;

        case APP_STATE_SET_LINE_CODING:

            /* Here we set the Line coding. The control request done flag will
             * be set to true when the control request has completed. */

            appData.controlRequestDone = false;
            result = USB_HOST_CDC_ACM_LineCodingSet(appData.cdcHostHandle, NULL, &appData.cdcHostLineCoding);

            if(result == USB_HOST_CDC_RESULT_SUCCESS)
            {
                /* We wait for the set line coding to complete */
                appData.state = APP_STATE_WAIT_FOR_SET_LINE_CODING;
            }

            break;

        case APP_STATE_WAIT_FOR_SET_LINE_CODING:

            if(appData.controlRequestDone)
            {
                if(appData.controlRequestResult != USB_HOST_CDC_RESULT_SUCCESS)
                {
                    /* The control request was not successful. */
                    appData.state = APP_STATE_ERROR;
                }
                else
                {
                    /* Next we set the Control Line State */
                    appData.state = APP_STATE_SEND_SET_CONTROL_LINE_STATE;
                }
            }
            break;

        case APP_STATE_SEND_SET_CONTROL_LINE_STATE:

            /* Here we set the control line state */
            appData.controlRequestDone = false;
            result = USB_HOST_CDC_ACM_ControlLineStateSet(appData.cdcHostHandle, NULL,
                    &appData.controlLineState);

            if(result == USB_HOST_CDC_RESULT_SUCCESS)
            {
                /* We wait for the set line coding to complete */
                appData.state = APP_STATE_WAIT_FOR_SET_CONTROL_LINE_STATE;
            }

            break;

        case APP_STATE_WAIT_FOR_SET_CONTROL_LINE_STATE:

            /* Here we wait for the control line state set request to complete */
            if(appData.controlRequestDone)
            {
                if(appData.controlRequestResult != USB_HOST_CDC_RESULT_SUCCESS)
                {
                    /* The control request was not successful. */
                    appData.state = APP_STATE_ERROR;
                }
                else
                {
                    /* Next we set the Control Line State */
                    appData.state = APP_STATE_SEND_PROMPT_TO_DEVICE;
                }
            }

            break;

        default:
            break;
    }
}