USB Libraries Help > USB Host Libraries > USB Audio v1.0 Host Client Driver Library > Using the Library > How the Library Works > Sending Class Specific Control Transfers
MPLAB Harmony USB Stack
Sending Class Specific Control Transfers

The Audio v1.0 Host Client Driver allows the application client to send Audio v1.0 Class specific commands to the connected device. These commands can be send using USB_HOST_AUDIO_V1_0_ControlRequest function. 

This function is 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 Audio v1.0 Host Client Driver generates a callback function. The call back function is one of the argument to the USB_HOST_AUDIO_V1_0_ControlRequest function. 

The following code shows an example of sending a Audio v1.0 class specific commands.

/* This code shows an example for Audio Control transfer */
bool isAudioDeviceAttached = false;
USB_HOST_AUDIO_V1_0_OBJ audioDeviceObj;


/*************************************************************/
/* Audio control request call back function   */
/************************************************************/
void App_USBAudioControlRequestCallback
(
    USB_HOST_AUDIO_V1_0_OBJ audioObj,
    USB_HOST_AUDIO_V1_0_REQUEST_HANDLE requestHandle,
    USB_HOST_AUDIO_V1_0_RESULT result,
    size_t size,
    uintptr_t context
)
{
    APP_USB_AUDIO_CONTROL_TRANSFER_ACTION controlAction = (APP_USB_AUDIO_CONTROL_TRANSFER_ACTION)context;
    switch (controlAction)
    {
        case APP_USB_AUDIO_MASTER_UNMUTE_SET:
            if (result == USB_HOST_AUDIO_V1_0_RESULT_SUCCESS)
            {
                appData.isMasterUnmuteSetComplete = true;
            }
            else
            {
                appData.muteStatus = 1;
            }

        break;
        default:
            break;

    }
}

/*************************************************************/
/* Function for sending Mute control to Audio device.  */
/************************************************************/
void APP_SendAudioMuteControl
(
    APP_USB_AUDIO_CONTROL_TRANSFER_ACTION action,
    uint32_t* mute
)
{
    USB_HOST_AUDIO_V1_0_RESULT result;
    USB_AUDIO_FEATURE_UNIT_CONTROL_REQUEST setupPacket;
    uint32_t status;


    /* Fill in Setup Packet */
    setupPacket.bmRequestType = (  USB_SETUP_DIRN_HOST_TO_DEVICE
                   | USB_SETUP_TYPE_CLASS
                   | USB_SETUP_RECIPIENT_INTERFACE
                  ); //interface , Host to device , Standard;
    setupPacket.bRequest = USB_AUDIO_CS_SET_CUR;
    if (action ==  APP_USB_AUDIO_MASTER_MUTE_SET)
    {
        setupPacket.channelNumber = APP_USB_AUDIO_CHANNEL_MASTER;
        status = __builtin_disable_interrupts();
        *mute = 1;
        __builtin_mtc0(12,0,status);
    }
    else if (action ==  APP_USB_AUDIO_MASTER_UNMUTE_SET)
    {
        setupPacket.channelNumber = APP_USB_AUDIO_CHANNEL_MASTER;
        status = __builtin_disable_interrupts();
        *mute = 0;
        __builtin_mtc0(12,0,status);
    }

    setupPacket.controlSelector = USB_AUDIO_MUTE_CONTROL;
    setupPacket.featureUnitId = 0x02; //appData.featureUnitDescriptor->bUnitID;
    setupPacket.wLength = 1;
    result = USB_HOST_AUDIO_V1_0_ControlRequest
             (
                appData.audioDeviceObj,
                &appData.requestHandle,
                (USB_SETUP_PACKET *)&setupPacket,
                mute,
                App_USBAudioControlRequestCallback,
                (uintptr_t)action
             );

}

/*************************************************************/
/* Audio attach event listener function */
/************************************************************/
void APP_USBHostAudioAttachEventListener
(
    USB_HOST_AUDIO_V1_0_OBJ audioObj,
    USB_HOST_AUDIO_V1_0_EVENT event,
    uintptr_t context
)
{
    /* This function gets called when the Audio v1.0 device is attached/detached. In this
     * example we let the application know that a device is attached and we
     * store the Audio v1.0 device object. This object will be required to open the
     * device. */
    switch (event)
    {
        case USB_HOST_AUDIO_V1_0_EVENT_ATTACH:
            if (isAudioDeviceAttached == false)
            {
                isAudioDeviceAttached = true;
                audioDeviceObj = audioObj;
            }
            else
            {
                /* This application supports only one Audio Device . Handle Error Here.*/
            }
        break;
        case USB_HOST_AUDIO_V1_0_EVENT_DETACH:
            if (isAudioDeviceAttached == true)
            {
                /* This means the device was detached. There is no event data
                 * associated with this event.*/
                isAudioDeviceAttached = false;
                break;
            }
        break;
    }
}

/*************************************************************/
/* Audio Tasks function */
/************************************************************/
void APP_Tasks ( void )
{
    switch (appData.state)
    {
        case APP_STATE_BUS_ENABLE:

            /* In this state the application enables the USB Host Bus. Note
             * how the Audio v1.0 Attach event handler is registered before the bus
             * is enabled. */

            USB_HOST_AUDIO_V1_0_AttachEventHandlerSet(APP_USBHostAudioAttachEventListener, (uintptr_t) 0);
            USB_HOST_BusEnable(0);
            appData.state = APP_STATE_WAIT_FOR_BUS_ENABLE_COMPLETE;
            break;

        case APP_STATE_WAIT_FOR_BUS_ENABLE_COMPLETE:
            if(USB_HOST_BusIsEnabled(0) != true)
            {
                return;
            }
            /* Here we wait for the bus enable operation to complete. */
            /* Unmute the  Device */
            appData.isMasterUnmuteSetComplete = false;
            APP_SendAudioMuteControl
            (
                APP_USB_AUDIO_MASTER_UNMUTE_SET,
                (uint32_t*)&appData.muteStatus
            );
            appData.state = APP_STATE_AUDIO_WAIT_FOR_UNMUTE_COMPLETE;
            break;
        case APP_STATE_AUDIO_WAIT_FOR_UNMUTE_COMPLETE:
            if (appData.isMasterUnmuteSetComplete == true)
            {
                /* Audio Control request completed */
            }
    }
}