This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CC2564: How to control volume with AVRCP in A3DP multiroom Demo?

Part Number: CC2564

I am using A3DP Multirrom Demo.

I have confirmed that the commands RemotePlay and RemotePause are implemented.

However, I have noticed that RemoteVolumeup and RemoteVolumeDown are not implemented in the Demo project.

I implemented it myself, but it did not work and it had a value of 0x08.

How can I use the AVRCP profile to control the volume of my phone on the board?

The results of the RemoteVolumeup and RemoteVolumeDown commands

Source code for RemoteVolumeup and RemoteVolumeDown

int RemoteVolumeUp(ParameterList_t *TempParam)
{
    int nResult;

    // Ensure that we have an open stream first.
    if (A3DPOpened)
        nResult = SendRemoteControlCommand(rcVolumeUp);
    else
    {
        Display("A3DP Stream is not opened yet.\r\n");
        nResult = FUNCTION_ERROR;
    }

    return (nResult);
}
int RemoteVolumeDown(ParameterList_t *TempParam)
{
    int nResult;

    // Ensure that we have an open stream first.
    if (A3DPOpened)
        nResult = SendRemoteControlCommand(rcVolumeDown);
    else
    {
        Display("A3DP Stream is not opened yet.\r\n");
        nResult = FUNCTION_ERROR;
    }

    return (nResult);
}

Source code for SendRemoteControlCommand is same as Demo.
int SendRemoteControlCommand(RemoteControlCommand_t Command)
{
    int                               nResult;
    Boolean_t                         ProcessCommand;
    AUD_Remote_Control_Command_Data_t RemoteCommand;

    // Ensure that we have an open stream first.
    if (A3DPOpened)
    {
        // Initialize local variables.
        nResult        = 0;
        ProcessCommand = TRUE;

        // Initialize common members of the pass through command.
        // * NOTE * State flag of FALSE specifies button down.
        RemoteCommand.MessageType                                            = amtPassThrough;
        RemoteCommand.MessageData.PassThroughCommandData.CommandType         = AVRCP_CTYPE_CONTROL;
        RemoteCommand.MessageData.PassThroughCommandData.SubunitType         = AVRCP_SUBUNIT_TYPE_PANEL;
        RemoteCommand.MessageData.PassThroughCommandData.SubunitID           = AVRCP_SUBUNIT_ID_INSTANCE_0;
        RemoteCommand.MessageData.PassThroughCommandData.OperationID         = (Byte_t)0;
        RemoteCommand.MessageData.PassThroughCommandData.StateFlag           = (Boolean_t)FALSE;
        RemoteCommand.MessageData.PassThroughCommandData.OperationDataLength = 0;
        RemoteCommand.MessageData.PassThroughCommandData.OperationData       = NULL;

        // Determine the command and go ahead and build it.
        switch(Command)
        {
        case rcPlayPause:
            // Verify that we do not have another play/pause pending.
            if (StreamState != ssPending)
            {
                if (StreamState == ssStarted)
                    RemoteCommand.MessageData.PassThroughCommandData.OperationID = (Byte_t)AVRCP_PASS_THROUGH_ID_PAUSE;
                else
                    RemoteCommand.MessageData.PassThroughCommandData.OperationID = (Byte_t)AVRCP_PASS_THROUGH_ID_PLAY;

                StreamState = ssPending;
            }
            else
            {
                // Command already pending so don't process this request.
                ProcessCommand = FALSE;
            }
            break;

        case rcPlay:
            RemoteCommand.MessageData.PassThroughCommandData.OperationID = (Byte_t)AVRCP_PASS_THROUGH_ID_PLAY;
            break;

        case rcPause:
            RemoteCommand.MessageData.PassThroughCommandData.OperationID = (Byte_t)AVRCP_PASS_THROUGH_ID_PAUSE;
            break;

        case rcNext:
            RemoteCommand.MessageData.PassThroughCommandData.OperationID = (Byte_t)AVRCP_PASS_THROUGH_ID_FORWARD;
            break;

        case rcBack:
            RemoteCommand.MessageData.PassThroughCommandData.OperationID = (Byte_t)AVRCP_PASS_THROUGH_ID_BACKWARD;
            break;

        case rcVolumeUp:
            RemoteCommand.MessageData.PassThroughCommandData.OperationID = (Byte_t)AVRCP_PASS_THROUGH_ID_VOLUME_UP;
            break;

        case rcVolumeDown:
            RemoteCommand.MessageData.PassThroughCommandData.OperationID = (Byte_t)AVRCP_PASS_THROUGH_ID_VOLUME_DOWN;
            break;

        case rcSampleRateUp:
            RemoteCommand.MessageData.PassThroughCommandData.OperationID = (Byte_t)AVRCP_PASS_THROUGH_ID_0;
            break;

        case rcSampleRateDown:
            RemoteCommand.MessageData.PassThroughCommandData.OperationID = (Byte_t)AVRCP_PASS_THROUGH_ID_1;
            break;

        default:
            // Unsupported - flag error.
            nResult = INVALID_PARAMETERS_ERROR;
            break;
        }

        // Continue only if we have a command to process.
        if (ProcessCommand)
        {
            // Proceed only if the AVRCP command is supported.
            if (!nResult)
                nResult = AUD_Send_Remote_Control_Command(BluetoothStackID, A2DPRemoteBD_ADDR, &RemoteCommand, 0);

            if (nResult > 0)
            {
                // Now we must send the button-up command to finish up.
                RemoteCommand.MessageData.PassThroughCommandData.StateFlag = TRUE;
                nResult = AUD_Send_Remote_Control_Command(BluetoothStackID, A2DPRemoteBD_ADDR, &RemoteCommand, 1000);

                if (nResult > 0)
                {
                    Display("AVRCP command sent successfully.\r\n");
                    nResult = 0;
                }
                else
                {
                    DisplayV("AUD_Send_Remote_Control_Command() Failed: %d\r\n", nResult);
                    nResult = FUNCTION_ERROR;
                }
            }
            else
            {
                DisplayV("AUD_Send_Remote_Control_Command() Failed: %d\r\n", nResult);
                nResult = FUNCTION_ERROR;
            }
        }
    }
    else
        nResult = FUNCTION_ERROR;

    return (nResult);
}

  • Hi,

    Dong Won Lee said:
    How can I use the AVRCP profile to control the volume of my phone on the board?

    Have you verified that the AVRCP profile on your phone supports remote volume control commands? Most phones do not support this.

    Best regards,

    Vihang 

  • However, the remoteplay and remotepause commands provided by the demo work. If so, AVRCP is not a problem, and I wonder why the above code does not work even if remotevolumeup, down is implemented.
  • Dong Won Lee said:
    However, the remoteplay and remotepause commands provided by the demo work. If so, AVRCP is not a problem,

    This just tells you that the phone's OS has native support for remoteplay and remotepause commands of the AVRCP. Still it is possible that the AVRCP volume control commands are not implemented on the phone OS side. If you do not know for sure, please capture the over the air traffic using sniffer or btsnoop logs (if using android phone) to verify.

    Best regards,

    Vihang

  • Hi,

    I tested it with iphone today.
    When I pressed the volume button on the Sony speakers,
    I noticed that the volume on the iPhone screen got bigger and smaller.

    However, the volumeup and down commands I have implemented do not work on the iPhone.
    The remoteplay and pause commands work on the iPhone.
    Sony speakers have been confirmed to work on iPhone OS, but I wonder why it does not work with A3DP Demo code.
  • Dong,

    Dong Won Lee said:
    wonder why it does not work with A3DP Demo code.

    Please capture the air sniffer logs of the following 2 scenario for further analysis.

    (i) A3DP Demo (w volume control commands) connected to iPhone

    (ii) Sony speaker connected to iPhone

    Best regards,

    Vihang