/****************************************************************************
* NAME    
* avrcpSendCommonFragmentedMetadataCfm    
*
* DESCRIPTION
*   Send MetaData confirm to the CT application with the extracted data from 
*   the response
*
* RETURNS
*    void
*******************************************************************************/
void avrcpSendCommonFragmentedMetadataCfm(AVRCP         *avrcp, 
                                          avrcp_status_code  status,
                                          uint16         id, 
                                          uint16         metadata_packet_type,
                                          uint16         data_length, 
                                          const uint8*   data)
{
    uint16 offset=0;
    MAKE_AVRCP_MESSAGE(AVRCP_COMMON_FRAGMENTED_METADATA_CFM);
    
    message->avrcp = avrcp;
    message->status = status;

#ifdef AVRCP_ENABLE_DEPRECATED
    if(avrcp->av_msg)
    {
        message->transaction = (avrcp->av_msg[AVCTP_HEADER_START_OFFSET] >> 
                                AVCTP0_TRANSACTION_SHIFT);
    }
/****************************************************************************
 *NAME    
 *    avrcpHandleRegisterNotificationCommand  
 *
 *DESCRIPTION
 *   Handle an incoming Register Notification command.
 *
 *PARAMETERS
 * avrcp            - AVRCP instance
 * ptr              - Data pointer to the command. 
 ****************************************************************************/
void avrcpHandleRegisterNotificationCommand(AVRCP *avrcp, const uint8 *ptr)
{
    uint8 event = ptr[0];

    MAKE_AVRCP_MESSAGE(AVRCP_REGISTER_NOTIFICATION_IND);
    message->avrcp = avrcp;
#ifdef AVRCP_ENABLE_DEPRECATED 
    /* Deprecated fields will be removed later */
    message->transaction = avrcp->rsp_transaction_label;
#endif
    message->event_id = event;
    message->playback_interval = convertUint8ValuesToUint32(&ptr[1]);

    /* Store which event has been registered for. */
    avrcp->registered_events |= (1<<event);
    /* Store the transaction label associated with the event. */
    avrcp->notify_transaction_label[event-1] = avrcp->rsp_transaction_label;

    MessageSend(avrcp->clientTask,AVRCP_REGISTER_NOTIFICATION_IND,message);
}
/****************************************************************************
*NAME    
*    AvrcpEventSystemStatusChangedResponse    
*
*DESCRIPTION
*  API function to notify battery status change event at TG.
*    
*PARAMETERS
*   avrcp       - Task
*   response    - On success , avctp_response_interim for intermediate response
*                 and avctp_response_changed for final response.
*   battery_status - Current battery status
*
*RETURN
*****************************************************************************/
void AvrcpEventSystemStatusChangedResponse(AVRCP *avrcp, 
                                           avrcp_response_type response, 
                                           avrcp_system_status system_status)
{
    /* Only send a response if this event was registered by the CT. */
    if (avrcp->registered_events & (1<<EVENT_SYSTEM_STATUS_CHANGED))
    {
        MAKE_AVRCP_MESSAGE(AVRCP_INTERNAL_EVENT_SYSTEM_STATUS_CHANGED_RES);
        message->response = response;
        message->system_status = system_status;
        MessageSend(&avrcp->task,
                    AVRCP_INTERNAL_EVENT_SYSTEM_STATUS_CHANGED_RES, message);
        if (response == avctp_response_changed)
            clearRegisterNotification(avrcp, EVENT_SYSTEM_STATUS_CHANGED);
    }
    else
    {
        AVRCP_INFO(("AvrcpEventSystemStatusChangedResponse: Event not registered\n"));
    }
}
void avrcpSendGetPlayStatusCfm(AVRCP *avrcp, 
                               avrcp_status_code status, 
                               uint32 song_length, 
                               uint32 song_elapsed, 
                               avrcp_play_status play_status, 
                               uint8 transaction) 
{
    MAKE_AVRCP_MESSAGE(AVRCP_GET_PLAY_STATUS_CFM);

    message->avrcp = avrcp;
#ifdef AVRCP_ENABLE_DEPRECATED 
    /* Deprecated fields will be removed later */
    message->transaction = transaction;
#endif
    message->status = status;
    message->song_length = song_length;
    message->song_elapsed = song_elapsed;
    message->play_status = play_status;

    MessageSend(avrcp->clientTask, AVRCP_GET_PLAY_STATUS_CFM, message);
}
void AvrcpEventPlaybackPosChangedResponse(AVRCP *avrcp, 
                                          avrcp_response_type response, 
                                          uint32 playback_pos)
{
    /* Only send a response if this event was registered by the CT. */
    if (avrcp->registered_events & (1<<EVENT_PLAYBACK_POS_CHANGED))
    {
        MAKE_AVRCP_MESSAGE(AVRCP_INTERNAL_EVENT_PLAYBACK_POS_CHANGED_RES);
        message->response = response;
        message->playback_pos = playback_pos;
        MessageSend(&avrcp->task, 
                    AVRCP_INTERNAL_EVENT_PLAYBACK_POS_CHANGED_RES, 
                    message);
        if (response == avctp_response_changed)
            clearRegisterNotification(avrcp, EVENT_PLAYBACK_POS_CHANGED);
    }
    else
    {
        AVRCP_INFO(("AvrcpEventPlaybackPosChangedResponse: Event not registered\n"));
    }
}
/****************************************************************************
 *NAME    
 *    avrcpHandleListAppValuesCommand    
 *
 *DESCRIPTION
 *  Handle the incoming PlayerApplicationListValues Command from CT. 
 *
 *PARAMETERS
 *  AVRCP       -  AVRCP Instance
 *  attribute_id -  Requested attribute ID for Value.
 ****************************************************************************/
void avrcpHandleListAppValuesCommand(AVRCP *avrcp, uint16 attribute_id)
{

    if (!isAvrcpPlayerSettingsEnabled(avrcpGetDeviceTask()))
    {
        sendListValuesResponse(avrcp, avctp_response_not_implemented, 0, 0);
    }
    else
    {
        /* We know this PDU cannot be fragmented.
           Pass the request directly to the client. */
        MAKE_AVRCP_MESSAGE(AVRCP_LIST_APP_VALUE_IND);
        message->avrcp = avrcp;
#ifdef AVRCP_ENABLE_DEPRECATED 
    /* Deprecated fields will be removed later */
        message->transaction =  avrcp->rsp_transaction_label;
#endif
        message->attribute_id = attribute_id;
        MessageSend(avrcp->clientTask, AVRCP_LIST_APP_VALUE_IND, message);
    }
}
/****************************************************************************
*NAME    
*    AvrcpSetAbsoluteVolumeResponse
*
*DESCRIPTION
*  API function to respond to SetAbsoluteVolume request. TG application shall
*  call function on receiving AVRCP_SET_ABSOLUTE_VOLUME_IND. If the volume 
*  got changed due to this procedure, Application must call 
*  AvrcpEventVolumeChangedResponse() if CT has registered for 
*  EVENT_VOLUME_CHANGED notification.
*    
*PARAMETERS
*   avrcp                   - Task
*   avrcp_response_code     - response.  Expected responses are 
*                             avctp_response_accepted or avctp_response_rejected
*                             or avrcp_response_rejected_internal_error.
*   uint8                   - Volume at TG. 0x0 as Minimum and 0x7F as Max 
*
*RETURN
*******************************************************************************/
void AvrcpSetAbsoluteVolumeResponse(AVRCP               *avrcp, 
                                    avrcp_response_type response, 
                                    uint8               volume) 
{

    if (avrcp->block_received_data == avrcp_absolute_volume)
    {
        MAKE_AVRCP_MESSAGE(AVRCP_INTERNAL_SET_ABSOLUTE_VOL_RES); 

        message->volume=(volume < AVRCP_MAX_VOL_MASK)?volume:AVRCP_MAX_VOL_MASK;
        message->response=response;
        MessageSend(&avrcp->task, 
                    AVRCP_INTERNAL_SET_ABSOLUTE_VOL_RES,
                    message);
    }
    else
    {
        AVRCP_INFO(("AvrcpSetAbsoluteVolumeResponse: CT is not waiting for"
                     " the response\n"));  
    }
} 
/*lint -e818 -e830 */
void AvrcpVendorDependent(AVRCP *avrcp, avc_subunit_type subunit_type, avc_subunit_id subunit_id, uint8 ctype, uint32 company_id, uint16 data_length, Source data)
{
    
#ifdef AVRCP_DEBUG_LIB	
	if (subunit_type > 0x1F)
	{
		AVRCP_DEBUG(("Out of range subunit type  0x%x\n", subunit_type));
	}
    if (subunit_id > 0x07)
	{
		AVRCP_DEBUG(("Out of range subunit id  0x%x\n", subunit_id));
	}
    if (company_id > 0xFFFFFF)
	{
		AVRCP_DEBUG(("Out of range company id  0x%lx\n", company_id));
	}
#endif
    
	if (avrcp->block_received_data || (avrcp->pending && (avrcp->pending < avrcp_get_caps)))
		avrcpSendVendordependentCfmToClient(avrcp, avrcp_busy, 0);
	else if (!avrcp->sink)
    {
        /* Immediately reject the request if we have not been passed a valid sink */
        if (avrcp->pending >= avrcp_get_caps)
            avrcpSendMetadataFailCfmToClient(avrcp, avrcp_invalid_sink);
        else
			avrcpSendVendordependentCfmToClient(avrcp, avrcp_invalid_sink, 0);
    }
	else
	{
		MAKE_AVRCP_MESSAGE(AVRCP_INTERNAL_VENDORDEPENDENT_REQ);
		message->company_id = company_id;
		message->subunit_type = subunit_type;
		message->subunit_id = subunit_id;
		message->ctype = ctype;
		message->data = data;
		message->data_length = data_length;
		MessageSend(&avrcp->task, AVRCP_INTERNAL_VENDORDEPENDENT_REQ, message);
	}
}
void AvrcpEventTrackChangedResponse(AVRCP               *avrcp, 
                                    avrcp_response_type response, 
                                    uint32              track_index_high, 
                                    uint32              track_index_low)
{
    /* Only send a response if this event was registered by the CT. */
    if (avrcp->registered_events & (1<<EVENT_TRACK_CHANGED))
    {
        MAKE_AVRCP_MESSAGE(AVRCP_INTERNAL_EVENT_TRACK_CHANGED_RES);
        message->response = response;
        message->track_index_high = track_index_high;
        message->track_index_low = track_index_low;
        MessageSend(&avrcp->task, 
                    AVRCP_INTERNAL_EVENT_TRACK_CHANGED_RES, message);
        if (response == avctp_response_changed)
            clearRegisterNotification(avrcp, EVENT_TRACK_CHANGED);
    }
    else
    {
        AVRCP_INFO(("AvrcpEventTrackChangedResponse: Event not registered\n"));
    }
}
Exemple #10
0
/****************************************************************************
*NAME 
*   AvrcpBrowseSearchResponse
*
*DESCRIPTION
*   This function is used to send response for  Search command to CT.
*   This will be called in response to a AVRCP_BROWSE_SEARCH_IND
*   message.
*
*PARAMETRS
*   avrcp              - Task
*   avrcp_response_type- response. avrcp_response_browsing_success on Success.
*   uint16             - UID Counter
*   uint32             - Number of matching items
*****************************************************************************/
void AvrcpBrowseSearchResponse(AVRCP*               avrcp,         
                               avrcp_response_type  response,     
                               uint16               uid_counter, 
                               uint32               num_items)
{
    AVBP *avbp = (AVBP*)avrcp->avbp_task;

    if(isAvbpCheckConnected(avbp))
    {
        if(avbp->blocking_cmd == AVBP_SEARCH_PDU_ID)
        {
            MAKE_AVRCP_MESSAGE(AVRCP_INTERNAL_SEARCH_RES);
            message->response = response;
            message->num_items = num_items;

            if(isAvrcpDatabaseEnabled(avrcpGetDeviceTask()))
            {
                message->uid_counter = uid_counter;
            }
            else
            {
               message->uid_counter = 0;
            }

             /* Queue the Response */
            MessageSend(&avbp->task,
                        AVRCP_INTERNAL_SEARCH_RES,
                        message);
        }
        else
        {
            AVRCP_INFO(("GetFolderItems Command is not pending\n"));
        }
    }
    else
    {
        AVRCP_INFO(("Browsing channel not connected. Ignoring the response\n"));
    }
}
/*lint -e818 -e830 */
void AvrcpSubUnitInfo(AVRCP *avrcp, uint8 page)
{
    
#ifdef AVRCP_DEBUG_LIB	
	if (page > 0x07)
	{
		AVRCP_DEBUG(("Out of range page  0x%x\n", page));
	}
#endif
    
	if (avrcp->dataFreeTask.sent_data || avrcp->block_received_data || avrcp->pending)
		avrcpSendSubunitInfoCfmToClient(avrcp, avrcp_busy, 0, 0);
	else if (!avrcp->sink)
		/* Immediately reject the request if we have not been passed a valid sink */
		avrcpSendSubunitInfoCfmToClient(avrcp, avrcp_invalid_sink, 0, 0);
	else
	{
		MAKE_AVRCP_MESSAGE(AVRCP_INTERNAL_SUBUNITINFO_REQ);
		message->page = page;
		MessageSend(&avrcp->task, AVRCP_INTERNAL_SUBUNITINFO_REQ, message);
	}	
}
/****************************************************************************
*NAME    
*   AvrcpEventVolumeChangedResponse 
*
*DESCRIPTION
*  TG shall use this API function to send volume change events if CT has
*  Registered for EVENT_VOLUME_CHANGED notifications. TG shall send an interim
*  response immediately after receiving a AVRCP_REGISTER_NOTIFICATION_IND  for 
*  EVENT_VOLUME_CHANGED from the CT before sending the final response on Volume 
*  change.  Otherwise lib will reject the Register Notification request from CT
*  after timeout of 1000ms. 
* 
*    
*PARAMETERS
*   avrcp                   - Task
*   avrcp_response_code     - response.  Response indicating whether the volume
*                             has been changed or the notification was 
*                             rejected. 
*                             Expected response values avctp_response_changed, 
*                             avrcp_response_interim or avctp_response_rejected.
*   uint8                   - Volume at TG. 0x0 as Minimum and 0x7F as Max 
*
*RETURN
*******************************************************************************/
void AvrcpEventVolumeChangedResponse(AVRCP               *avrcp, 
                                     avrcp_response_type response,
                                     uint8               volume)
{
      /* Only send a response if this event was registered by the CT. */
    if (isEventRegistered(avrcp,EVENT_VOLUME_CHANGED))
    {
        /* Internal Event response */
        MAKE_AVRCP_MESSAGE(AVRCP_INTERNAL_EVENT_VOLUME_CHANGED_RES); 

        message->volume=(volume < AVRCP_MAX_VOL_MASK)?volume:AVRCP_MAX_VOL_MASK;
        message->response=response;
        MessageSend(&avrcp->task, 
                    AVRCP_INTERNAL_EVENT_VOLUME_CHANGED_RES,
                    message);

    }
    else
    {
       AVRCP_INFO(("AvrcpEventVolumeChangedResponse: " 
                    "Event not registered\n"));
    }
}
void AvrcpConnectLazy(Task clientTask, const bdaddr *bd_addr, const avrcp_init_params *config)
{
    if (!config)
    {
        /* Client must pass down a valid config so report connect fail */
        MAKE_AVRCP_MESSAGE(AVRCP_CONNECT_CFM);
	    message->status = avrcp_fail;
	    message->sink = 0;
	    message->avrcp = 0;
	    MessageSend(clientTask, AVRCP_CONNECT_CFM, message);

        /* 
            TODO use fun below but it needs updating
        avrcpSendCommonCfmMessageToApp(AVRCP_CONNECT_CFM, avrcp_fail, 0, avrcp);
        */
    }
    else
    {
        AVRCP *avrcp = PanicUnlessNew(AVRCP);
        avrcpInitTaskData(avrcp, clientTask, avrcpReady, config->device_type, config->supported_controller_features, config->supported_target_features, config->profile_extensions, 1);
        avrcpSendInternalConnectReq(avrcp, bd_addr);
    }
}
Exemple #14
0
/****************************************************************************
*NAME 
*   AvrcpBrowseChangePathResponse
*
*DESCRIPTION
*   This function is used to send response for  Changepath command to CT.
*   This will be called in response to a AVRCP_BROWSE_CHANGE_PATH_IND message.
*
*PARAMETRS
*   avrcp              - Task
*   avrcp_response_type- response. avrcp_response_browsing_success on Success.
*   uint32             - number of items
*****************************************************************************/
void AvrcpBrowseChangePathResponse(AVRCP*               avrcp,
                                   avrcp_response_type  response,
                                   uint32               num_items)
{
    AVBP *avbp = (AVBP*)avrcp->avbp_task;

    /* validate avbp and send the message if it is connected */
    if((isAvbpCheckConnected(avbp)) && 
      (avbp->blocking_cmd == AVBP_CHANGE_PATH_PDU_ID))
    {
        MAKE_AVRCP_MESSAGE(AVRCP_INTERNAL_CHANGE_PATH_RES);
        message->response = response;
        message->num_items = num_items;

        /* Queue the Response */
        MessageSend(&avbp->task,
                    AVRCP_INTERNAL_CHANGE_PATH_RES,
                    message);
    }
    else
    {
        AVRCP_INFO(("Wrong state.Ignoring the response\n"));
    }
}
/****************************************************************************
*NAME    
*    AvrcpEventPlayerAppSettingChangedResponse    
*
*DESCRIPTION
*  API function to notify player app setting change event at TG.
*    
*PARAMETERS
*   avrcp       - Task
*   response    - On success , avctp_response_interim for intermediate response
*                 and avctp_response_changed for final response.
*   size_attributes - The length of the supplied attribute data (in bytes)
*   attributes -  The list of attribute data returned in the response.
*
*RETURN
*****************************************************************************/
void AvrcpEventPlayerAppSettingChangedResponse(AVRCP    *avrcp, 
                                              avrcp_response_type response, 
                                              uint16    size_attributes, 
                                              Source    attributes)
{
    /* Only send a response if this event was registered by the CT. */
    if (avrcp->registered_events & (1<<EVENT_PLAYER_SETTING_CHANGED))
    {
        MAKE_AVRCP_MESSAGE(AVRCP_INTERNAL_EVENT_PLAYER_APP_SETTING_CHANGED_RES);
        message->response = response;
        message->size_attributes = size_attributes;
        message->attributes = attributes;
        MessageSend(&avrcp->task, 
                    AVRCP_INTERNAL_EVENT_PLAYER_APP_SETTING_CHANGED_RES,
                    message);
        if (response == avctp_response_changed)
            clearRegisterNotification(avrcp, EVENT_PLAYER_SETTING_CHANGED);
    }
    else
    {
        AVRCP_INFO(("AvrcpEventPlayerAppSettingChangedResponse: "
                "Event not registered\n"));
    }
}
Exemple #16
0
/****************************************************************************
*NAME 
*   AvrcpBrowseGetFolderItemsRequest
*
*DESCRIPTION
*   This function is used to send GetFolderItems Command to the TG.
*
*PARAMETRS
*   avrcp                  - Task
*   avrcp_browse_scope     - Scope for media navigation.
*   start                  - Start index of the item in the folder.
*   end                    - End index of the item in the folder
*   uint8                  - Number of attributes requested. 0 for all and 
*                            0xFF for No attributes.
*   Source                 - Size of source should be number of attributes * 4.
*
*RETURN
*   AVRCP_BROWSE_GET_FOLDER_ITEMS_CFM
*****************************************************************************/
void AvrcpBrowseGetFolderItemsRequest( AVRCP*              avrcp,   
                                avrcp_browse_scope  scope,   
                                uint32              start,   
                                uint32              end,      
                                uint8               num_attr, 
                                Source              attr_list)
{
    AVBP *avbp = (AVBP*)avrcp->avbp_task;
    uint16 size_attr_list = num_attr * 4;

    if(num_attr == 0 || num_attr == 0xFF)
    {
        if(attr_list)
        {
            SourceEmpty(attr_list);
        }
        size_attr_list =  0;
        attr_list = 0;
    }
    else
    {
        /* Validate the length */
        if(SourceBoundary(attr_list) < size_attr_list)
        {
            AVRCP_INFO(("Invalid length of attributes \n"));
            avrcpGetFolderItemsCfm(avbp,avrcp_rejected_invalid_content,
                                     NULL, 0); 
            if(attr_list)
            {
                SourceEmpty(attr_list);
            }
            return;
        }
    }

    /* validate the start and end index */
    if(start > end)
    {
        AVRCP_INFO(("End index > Start\n"));
        avrcpGetFolderItemsCfm(avbp, avrcp_rejected_out_of_bound, NULL, 0);
        if(attr_list)
        {
            SourceEmpty(attr_list);
        }
        return; 
    }

    if(isAvbpCheckConnected(avbp))
    {
        MAKE_AVRCP_MESSAGE(AVRCP_INTERNAL_GET_FOLDER_ITEMS_REQ);
        message->scope = scope;
        message->start = start;
        message->end = end;
        message->num_attr = num_attr;
        message->attr_list_size = size_attr_list;
        message->attr_list = attr_list;
        

        /* Queue the Command if there is any Outstanding command in progress */
        MessageSendConditionally(&avbp->task,
                                  AVRCP_INTERNAL_GET_FOLDER_ITEMS_REQ,
                                  message,
                                  &avbp->blocking_cmd);

    }
    else
    {
        AVRCP_INFO(("Browsing channel not connected\n"));
        avrcpGetFolderItemsCfm(avbp, avrcp_browsing_channel_not_connected,
                                 NULL, 0); 
        if(attr_list)
        {
            SourceEmpty(attr_list);
        }
    }
}
Exemple #17
0
/****************************************************************************
*NAME 
*   AvrcpBrowseGetItemAttributesRequest
*
*DESCRIPTION
*   This function is used to send GetItemAttributes Command to the TG.
*
*PARAMETRS
*   avrcp                  - Task
*   avrcp_browse_scope     - Scope in which the UID of the media element 
*                            item or folder item is valid.
*   avrcp_browse_uid       - The UID of the  media element item or folder item
*   uint16                 - UID Counter
*   uint8                  - Number of attributes requested. 0 for all and 
*                            0xFF for No attributes.
*   Source                 - Size of source should be number of attributes * 4.
*
*RETURN
*   AVRCP_BROWSE_GET_ITEM_ATTRIBUTES_CFM
*****************************************************************************/
void AvrcpBrowseGetItemAttributesRequest(  AVRCP*               avrcp,
                                    avrcp_browse_scope   scope,  
                                    avrcp_browse_uid     uid,   
                                    uint16               uid_counter, 
                                    uint8                num_attr, 
                                    Source               attr_list)
{
    AVBP *avbp = (AVBP*)avrcp->avbp_task;
    uint16 size_attr_list = num_attr * 4;

    if(num_attr == 0 || num_attr == 0xFF)
    {
        if(attr_list)
        {
            SourceEmpty(attr_list);
        }
        size_attr_list =  0;
        attr_list = 0;
    }
    else
    {
        /* Validate the length */
        if(SourceBoundary(attr_list) < size_attr_list)
        {
            AVRCP_INFO(("Invalid length of attributes \n"));
            avrcpGetItemAttributesCfm(avbp,avrcp_rejected_invalid_content,
                                     NULL, 0); 
            if(attr_list)
            {
                SourceEmpty(attr_list);
            }
            return;
        }
    }

    /* validate avbp and send the message if it is connected */
    if(isAvbpCheckConnected(avbp))
    {
        MAKE_AVRCP_MESSAGE(AVRCP_INTERNAL_GET_ITEM_ATTRIBUTES_REQ);
        message->scope = scope;
        message->uid = uid;
        message->uid_counter = uid_counter;
        message->num_attr = num_attr;
        message->attr_list_size = size_attr_list;
        message->attr_list = attr_list;
        

        /* Queue the Command if there is any Outstanding command in progress */
        MessageSendConditionally(&avbp->task,
                                  AVRCP_INTERNAL_GET_ITEM_ATTRIBUTES_REQ,
                                  message,
                                  &avbp->blocking_cmd);

    }
    else
    {
        AVRCP_INFO(("Browsing channel not connected\n"));
        avrcpGetItemAttributesCfm(avbp, avrcp_browsing_channel_not_connected,
                                 NULL, 0); 
        if(attr_list)
        {
            SourceEmpty(attr_list);
        }
    }
}
/****************************************************************************
 *NAME    
 *    avrcpSendNotification  
 *
 *DESCRIPTION
 *   Send Notification Indications to the CT application.
 *
 *PARAMETERS
 * avrcp            - AVRCP instance
 * response         - Response code
 * ptr              - Pointer to the response data
 * packet_size      - Data size in ptr
 ****************************************************************************/
void avrcpSendNotification( AVRCP *avrcp,  
                            avrcp_response_type response, 
                            const uint8* ptr, 
                            uint16 packet_size)
{
    avrcp_supported_events event_id;
    uint16 data_len    = 0;
    uint16 data_start  = 0;
    uint16 transaction = (avrcp->av_msg[0] & AVCTP_TRANSACTION_MASK) >>
                         AVCTP0_TRANSACTION_SHIFT;
    if(!packet_size)
    {
        /* Unknown event. Ignore */
        return;
    }

    if(response == avctp_response_rejected)
    {
        for(event_id = 1; event_id <= AVRCP_MAX_NUM_EVENTS; event_id++)
        {
            if(isEventRegistered(avrcp, event_id) &&
                GetNotificationTransaction(avrcp, event_id) == transaction)
            {
                break;
            }
        }       

        /* data[0] would be error status code */
        response = ptr[data_start] | AVRCP_ERROR_STATUS_BASE;
    }
    else
    {
        event_id = ptr[data_start];
        data_start++;
        data_len = packet_size-data_start;
    }
    
    switch (event_id)
    {
    case avrcp_event_playback_status_changed:
        {
            MAKE_AVRCP_MESSAGE(AVRCP_EVENT_PLAYBACK_STATUS_CHANGED_IND);
            message->avrcp = avrcp;

#ifdef AVRCP_ENABLE_DEPRECATED 
        /* Deprecated fields will be removed later */
            message->transaction = transaction;
#endif
            
            message->response = response;

            /* EVENT_PLAYBACK_STATUS_CHANGED Length expected is 1 */
            if(data_len){
                message->play_status = ptr[data_start];
            }
            else
            {
                /* This will be error value on rejected response. 
                   App will ignore it */
                message->play_status = 0xFF;
            }
            MessageSend(avrcp->clientTask,
                         AVRCP_EVENT_PLAYBACK_STATUS_CHANGED_IND, message);
            
        }
        break;
    case avrcp_event_track_changed:
        {
            MAKE_AVRCP_MESSAGE(AVRCP_EVENT_TRACK_CHANGED_IND);
            message->avrcp = avrcp;

#ifdef AVRCP_ENABLE_DEPRECATED 
        /* Deprecated fields will be removed later */
            message->transaction = transaction;
#endif
            
            /*
             * If the Packet comes in continuation or end packet
             * fragmented, it may  not process
             * Identifier is 8 octets long
             */
            message->response = response;
            if(data_len >= 8)
            {
                message->track_index_high =
                               convertUint8ValuesToUint32(&ptr[data_start]);
                message->track_index_low = 
                               convertUint8ValuesToUint32(&ptr[data_start+4]);
            }
            else
            {
                message->track_index_high = 0;
                message->track_index_low = 0;
            }
            MessageSend(avrcp->clientTask, 
                        AVRCP_EVENT_TRACK_CHANGED_IND, message);
        }
        break;
    case avrcp_event_track_reached_end:
        {
            MAKE_AVRCP_MESSAGE(AVRCP_EVENT_TRACK_REACHED_END_IND);
            message->avrcp = avrcp;
#ifdef AVRCP_ENABLE_DEPRECATED 
        /* Deprecated fields will be removed later */
            message->transaction = transaction;
#endif
            message->response = response;
            MessageSend(avrcp->clientTask, 
                        AVRCP_EVENT_TRACK_REACHED_END_IND, message);
        }
        break;
    case avrcp_event_track_reached_start:
        {
            MAKE_AVRCP_MESSAGE(AVRCP_EVENT_TRACK_REACHED_START_IND);
            message->avrcp = avrcp;
#ifdef AVRCP_ENABLE_DEPRECATED 
        /* Deprecated fields will be removed later */
            message->transaction = transaction;
#endif
            message->response = response;
            MessageSend(avrcp->clientTask, 
                        AVRCP_EVENT_TRACK_REACHED_START_IND, message);
        }
        break;
    case avrcp_event_playback_pos_changed:
        {
            MAKE_AVRCP_MESSAGE(AVRCP_EVENT_PLAYBACK_POS_CHANGED_IND);
            message->avrcp = avrcp;
#ifdef AVRCP_ENABLE_DEPRECATED 
        /* Deprecated fields will be removed later */
            message->transaction = transaction;
#endif

            message->response = response;
            /*
             * If the Packet comes in continuation or end packet fragmented,
             * it may  not process the Identifier which is 8 octets long
             */
            if(data_len >= 4)
            {
                message->playback_pos =
                             convertUint8ValuesToUint32(&ptr[data_start]);
            }
            else
            {
                message->playback_pos = 0;
            }
            MessageSend(avrcp->clientTask,
                        AVRCP_EVENT_PLAYBACK_POS_CHANGED_IND, message);
        }
        break;
    case avrcp_event_batt_status_changed:
        {
            MAKE_AVRCP_MESSAGE(AVRCP_EVENT_BATT_STATUS_CHANGED_IND);
            message->avrcp = avrcp;
#ifdef AVRCP_ENABLE_DEPRECATED 
        /* Deprecated fields will be removed later */
            message->transaction = transaction;
#endif
            message->response = response;
            if(data_len)
            {
                message->battery_status = ptr[data_start];
            }
            else
            {
                message->battery_status = 0;
            }
            MessageSend(avrcp->clientTask,
                        AVRCP_EVENT_BATT_STATUS_CHANGED_IND, message);
        }
        break;
    case avrcp_event_system_status_changed:
        {
            MAKE_AVRCP_MESSAGE(AVRCP_EVENT_SYSTEM_STATUS_CHANGED_IND);
            message->avrcp = avrcp;
#ifdef AVRCP_ENABLE_DEPRECATED 
        /* Deprecated fields will be removed later */
            message->transaction = transaction;
#endif

            message->response = response;
            if(data_len)
            {
                message->system_status = ptr[data_start];
            }
            else
            {
                message->system_status = 0;
            }
            MessageSend(avrcp->clientTask,
                        AVRCP_EVENT_SYSTEM_STATUS_CHANGED_IND, message);
        }
        break;
    case avrcp_event_player_app_setting_changed:
        {
            MAKE_AVRCP_MESSAGE(AVRCP_EVENT_PLAYER_APP_SETTING_CHANGED_IND);

            message->avrcp = avrcp;
#ifdef AVRCP_ENABLE_DEPRECATED 
        /* Deprecated fields will be removed later */
            message->transaction = transaction;
            message->no_packets = 0;
            message->ctp_packet_type = AVCTP0_PACKET_TYPE_SINGLE;
            message->data_offset = 0;
            message->metadata_packet_type = avrcp_packet_type_single;
#endif

            message->response = response;

            if(data_len >= 3){
                message->number_of_attributes = ptr[data_start];
                message->attributes =avrcpSourceFromConstData(avrcp, 
                                    ptr+data_start+1, data_len-1);
                message->size_attributes = data_len - 1;
            }
            else
            {
                message->number_of_attributes = 0;
                message->size_attributes = 0;
                message->attributes = 0;
            }

            MessageSend(avrcp->clientTask,
                        AVRCP_EVENT_PLAYER_APP_SETTING_CHANGED_IND, message);

        }
        break;
    case avrcp_event_now_playing_content_changed:
        {
            MAKE_AVRCP_MESSAGE(AVRCP_EVENT_NOW_PLAYING_CONTENT_CHANGED_IND);
            message->avrcp = avrcp;
             message->response = response;
            MessageSend(avrcp->clientTask,
                       AVRCP_EVENT_NOW_PLAYING_CONTENT_CHANGED_IND, 
                       message);

        }
        break;

    case avrcp_event_available_players_changed:
        {
            MAKE_AVRCP_MESSAGE(AVRCP_EVENT_AVAILABLE_PLAYERS_CHANGED_IND);
            message->avrcp = avrcp;
            message->response = response;
            MessageSend(avrcp->clientTask,
                       AVRCP_EVENT_AVAILABLE_PLAYERS_CHANGED_IND, message);
        }
        break;

    case  avrcp_event_addressed_player_changed:
        {
            MAKE_AVRCP_MESSAGE(AVRCP_EVENT_ADDRESSED_PLAYER_CHANGED_IND);
            message->avrcp = avrcp;

            message->response = response;
            if(data_len >= 4)
            {
                AVRCP_UINT8_TO_UINT16(ptr, message->player_id, data_start);
                AVRCP_UINT8_TO_UINT16(ptr, message->uid_counter, data_start+2);
                                     
            }
            else
            {
                message->player_id = 0;
                message->uid_counter = 0;
            }

            MessageSend(avrcp->clientTask,
                        AVRCP_EVENT_ADDRESSED_PLAYER_CHANGED_IND, message);
        }
        break;

    case avrcp_event_uids_changed:
        {
            MAKE_AVRCP_MESSAGE(AVRCP_EVENT_UIDS_CHANGED_IND);
            message->avrcp = avrcp;

            message->response = response;
            if(data_len >= 2)
            {
                AVRCP_UINT8_TO_UINT16(ptr,message->uid_counter,data_start);
            }
            else
            {
                message->uid_counter = 0;
            }

            MessageSend(avrcp->clientTask,
                       AVRCP_EVENT_UIDS_CHANGED_IND, 
                       message);
        }
    
        break;

    case avrcp_event_volume_changed:
        {
            MAKE_AVRCP_MESSAGE(AVRCP_EVENT_VOLUME_CHANGED_IND);

            message->avrcp = avrcp;

            message->response = response;
            if(data_len)
            {
                message->volume = ptr[data_start];
            }
            else
            {
                message->volume = 0;
            }
            MessageSend(avrcp->clientTask,
                        AVRCP_EVENT_VOLUME_CHANGED_IND, message);
        }   
        break;
    default:
        /* Unknown event. ignore */
        return;
    }

    if(response != avctp_response_interim)
    {
        clearRegisterNotification(avrcp, event_id);
    }

    /* Clear the pending flag only if the library was waiting for 
       the corresponding REGISTER_NOTIFICATION response. 
       otherwise ignore */
    if((event_id + avrcp_events_start_dummy) == avrcp->pending)
    {
        (void) MessageCancelAll(&avrcp->task, AVRCP_INTERNAL_WATCHDOG_TIMEOUT);
        avrcp->pending = avrcp_none;
    }

    return;

}
void avrcpSendInformBatteryResponse(AVRCP *avrcp, avrcp_response_type response)
{
    MAKE_AVRCP_MESSAGE(AVRCP_INTERNAL_INFORM_BATTERY_STATUS_RES);   
    message->response = response;
    MessageSend(&avrcp->task, AVRCP_INTERNAL_INFORM_BATTERY_STATUS_RES, message);
}
void avrcpSendInformCharSetResponse(AVRCP *avrcp, avrcp_response_type response)
{
    MAKE_AVRCP_MESSAGE(AVRCP_INTERNAL_INFORM_CHAR_SET_RES);   
    message->response = response;
    MessageSend(&avrcp->task, AVRCP_INTERNAL_INFORM_CHAR_SET_RES, message);
}
void sendGroupResponse(AVRCP *avrcp, avrcp_response_type response)
{
    MAKE_AVRCP_MESSAGE(AVRCP_INTERNAL_GROUP_RES);   
    message->response = response;
    MessageSend(&avrcp->task, AVRCP_INTERNAL_GROUP_RES, message);
}
void sendSetValuesResponse(AVRCP *avrcp, avrcp_response_type response)
{
    MAKE_AVRCP_MESSAGE(AVRCP_INTERNAL_SET_APP_VALUE_RES);
    message->response = response;
    MessageSend(&avrcp->task, AVRCP_INTERNAL_SET_APP_VALUE_RES, message);
}
bool avrcpSendNotification( AVRCP *avrcp,  
                            avrcp_response_type response, 
                            const uint8* ptr, 
                            uint16 packet_size)
{
    uint16 event_id;
    bool source_processed = TRUE;
    uint16 data_len = 0;
    uint16 data_start=0;

#ifdef AVRCP_ENABLE_DEPRECATED 
    /* Deprecated fields will be removed later */
    uint16 transaction = (avrcp->av_msg[0] & AVCTP_TRANSACTION_MASK) >>
                         AVCTP0_TRANSACTION_SHIFT;
#endif
    
    event_id = ptr[data_start];
    data_start=1;
    data_len = packet_size-data_start;

    switch (event_id)
    {
    case avrcp_event_playback_status_changed:
        {
            MAKE_AVRCP_MESSAGE(AVRCP_EVENT_PLAYBACK_STATUS_CHANGED_IND);
            message->avrcp = avrcp;

#ifdef AVRCP_ENABLE_DEPRECATED 
        /* Deprecated fields will be removed later */
            message->transaction = transaction;
#endif
            
            /* EVENT_PLAYBACK_STATUS_CHANGED Length expected is 1 */
            if(data_len >= 1){
                message->response = response;
                message->play_status = ptr[data_start];
            }
            else
            {
                message->response = avrcp_rejected_invalid_content;
                message->play_status = 0xFF;
            }
            MessageSend(avrcp->clientTask,
                         AVRCP_EVENT_PLAYBACK_STATUS_CHANGED_IND, message);
            
        }
        break;
    case avrcp_event_track_changed:
        {
            MAKE_AVRCP_MESSAGE(AVRCP_EVENT_TRACK_CHANGED_IND);
            message->avrcp = avrcp;

#ifdef AVRCP_ENABLE_DEPRECATED 
        /* Deprecated fields will be removed later */
            message->transaction = transaction;
#endif
            
            /*
             * If the Packet comes in continuation or end packet
             * fragmented, it may  not process
             * Identifier is 8 octets long
             */
            if(data_len >= 8)
            {
                message->response = response;
                message->track_index_high =
                               convertUint8ValuesToUint32(&ptr[data_start]);
                message->track_index_low = 
                               convertUint8ValuesToUint32(&ptr[data_start+4]);
            }
            else
            {
                message->response = avrcp_rejected_invalid_content;
                message->track_index_high = 0;
                message->track_index_low = 0;
            }
            MessageSend(avrcp->clientTask, 
                        AVRCP_EVENT_TRACK_CHANGED_IND, message);
        }
        break;
    case avrcp_event_track_reached_end:
        {
            MAKE_AVRCP_MESSAGE(AVRCP_EVENT_TRACK_REACHED_END_IND);
            message->avrcp = avrcp;
#ifdef AVRCP_ENABLE_DEPRECATED 
        /* Deprecated fields will be removed later */
            message->transaction = transaction;
#endif
            message->response = response;
            MessageSend(avrcp->clientTask, 
                        AVRCP_EVENT_TRACK_REACHED_END_IND, message);
        }
        break;
    case avrcp_event_track_reached_start:
        {
            MAKE_AVRCP_MESSAGE(AVRCP_EVENT_TRACK_REACHED_START_IND);
            message->avrcp = avrcp;
#ifdef AVRCP_ENABLE_DEPRECATED 
        /* Deprecated fields will be removed later */
            message->transaction = transaction;
#endif
            message->response = response;
            MessageSend(avrcp->clientTask, 
                        AVRCP_EVENT_TRACK_REACHED_START_IND, message);
        }
        break;
    case avrcp_event_playback_pos_changed:
        {
            MAKE_AVRCP_MESSAGE(AVRCP_EVENT_PLAYBACK_POS_CHANGED_IND);
            message->avrcp = avrcp;
#ifdef AVRCP_ENABLE_DEPRECATED 
        /* Deprecated fields will be removed later */
            message->transaction = transaction;
#endif
            /*
             * If the Packet comes in continuation or end packet fragmented,
             * it may  not process the Identifier which is 8 octets long
             */
            if(data_len >= 4)
            {
                message->response = response;
                message->playback_pos =
                             convertUint8ValuesToUint32(&ptr[data_start]);
            }
            else
            {
                message->response = avrcp_rejected_invalid_content;
                message->playback_pos = 0;
            }
            MessageSend(avrcp->clientTask,
                        AVRCP_EVENT_PLAYBACK_POS_CHANGED_IND, message);
        }
        break;
    case avrcp_event_batt_status_changed:
        {
            MAKE_AVRCP_MESSAGE(AVRCP_EVENT_BATT_STATUS_CHANGED_IND);
            message->avrcp = avrcp;
#ifdef AVRCP_ENABLE_DEPRECATED 
        /* Deprecated fields will be removed later */
            message->transaction = transaction;
#endif
            if(data_len >= 1){
                message->response = response;
                message->battery_status = ptr[data_start];
            }
            else
            {
                message->response = avrcp_rejected_invalid_content;
                message->battery_status = 0;
            }
            MessageSend(avrcp->clientTask,
                        AVRCP_EVENT_BATT_STATUS_CHANGED_IND, message);
        }
        break;
    case avrcp_event_system_status_changed:
        {
            MAKE_AVRCP_MESSAGE(AVRCP_EVENT_SYSTEM_STATUS_CHANGED_IND);
            message->avrcp = avrcp;
#ifdef AVRCP_ENABLE_DEPRECATED 
        /* Deprecated fields will be removed later */
            message->transaction = transaction;
#endif

            if(data_len >= 1){
                message->response = response;
                message->system_status = ptr[data_start];
            }
            else
            {
                message->system_status = 0;
                message->response = avrcp_rejected_invalid_content;
            }
            MessageSend(avrcp->clientTask,
                        AVRCP_EVENT_SYSTEM_STATUS_CHANGED_IND, message);
        }
        break;
    case avrcp_event_player_app_setting_changed:
        {
            MAKE_AVRCP_MESSAGE(AVRCP_EVENT_PLAYER_APP_SETTING_CHANGED_IND);

            message->avrcp = avrcp;
#ifdef AVRCP_ENABLE_DEPRECATED 
        /* Deprecated fields will be removed later */
            message->transaction = transaction;
            message->no_packets = 0;
            message->ctp_packet_type = AVCTP0_PACKET_TYPE_SINGLE;
            message->data_offset = 0;
#endif
            message->metadata_packet_type = AVCTP0_PACKET_TYPE_SINGLE;

            message->response = response;

            if(data_len >= 3){
                message->number_of_attributes = ptr[data_start];
                source_processed = FALSE;
                message->attributes =avrcpSourceFromConstData(avrcp, 
                                    ptr+1, data_len-1);
                message->size_attributes = data_len - 1;
            }
            else
            {
                message->number_of_attributes = 0;
                message->size_attributes = 0;
                message->attributes = 0;
                message->response = avrcp_rejected_invalid_content;
            }

            MessageSend(avrcp->clientTask,
                        AVRCP_EVENT_PLAYER_APP_SETTING_CHANGED_IND, message);

        }
        break;

     case avrcp_event_volume_changed:
        {
            MAKE_AVRCP_MESSAGE(AVRCP_EVENT_VOLUME_CHANGED_IND);

            message->avrcp = avrcp;

            if(data_len >= 1){
                message->response = response;
                message->volume = ptr[data_start];
            }
            else
            {
                message->volume = 0;
                message->response = avrcp_rejected_invalid_content;
            }
            MessageSend(avrcp->clientTask,
                        AVRCP_EVENT_VOLUME_CHANGED_IND, message);
        }   
        break;
    default:
        /* Unknown event. ignore */
        break;
    }

    /* Clear the pending flag only if the library was waiting for 
       the corresponding REGISTER_NOTIFICATION response. 
       otherwise ignore */
    if((event_id + avrcp_events_start_dummy) == avrcp->pending)
    {
        (void) MessageCancelAll(&avrcp->task, AVRCP_INTERNAL_WATCHDOG_TIMEOUT);
        avrcp->pending = avrcp_none;
    }

    return source_processed;

}
static void avrcpSendInternalConnectReq(AVRCP *avrcp, const bdaddr *bd_addr)
{
    MAKE_AVRCP_MESSAGE(AVRCP_INTERNAL_CONNECT_REQ);
    message->bd_addr = *bd_addr;
	MessageSend(&avrcp->task, AVRCP_INTERNAL_CONNECT_REQ, message);
}