/**************************************************************************** *NAME * avrcpHandleInformCharSetCommand * *DESCRIPTION * Handle the incoming InformCharSetCommand command from CT. * *PARAMETERS * AVRCP - AVRCP Instance * ptr - Received Data in the command * packet_size - size of data ****************************************************************************/ void avrcpHandleInformCharSetCommand(AVRCP *avrcp, const uint8* ptr, uint16 packet_size) { if(isAvrcpPlayerSettingsEnabled(avrcpGetDeviceTask()) && packet_size) { Source source=0; uint16 data_offset=1; packet_size-= data_offset; if(packet_size) { if(!(source=avrcpSourceFromConstData(avrcp, ptr+data_offset, packet_size))) { packet_size=0; } } avrcpSendCommonFragmentedMetadataInd(avrcp, AVRCP_INFORM_CHARACTER_SET_IND, ptr[0], packet_size, source); } else { avrcpSendRejectMetadataResponse(avrcp, avctp_response_not_implemented, AVRCP_INFORM_CHARACTER_SET_PDU_ID); } }
/**************************************************************************** *NAME * avrcpHandleGetAppAttributeTextCommand * *DESCRIPTION * Handle the incoming GetApplicationAttributesText Command from CT. * *PARAMETERS * AVRCP - AVRCP Instance * ptr - Received Data in the command * packet_size - size of data ****************************************************************************/ void avrcpHandleGetAppAttributeTextCommand(AVRCP *avrcp, const uint8* ptr, uint16 packet_size) { Source source=0; uint16 data_offset=1; if(isAvrcpPlayerSettingsEnabled(avrcpGetDeviceTask()) && packet_size) { packet_size-= data_offset; if(packet_size) { source=avrcpSourceFromConstData(avrcp, ptr+data_offset, packet_size); if(!source) { packet_size = 0; } } avrcpSendCommonFragmentedMetadataInd(avrcp, AVRCP_GET_APP_ATTRIBUTE_TEXT_IND, ptr[0], packet_size, source); } else { avrcpSendRejectMetadataResponse(avrcp, avctp_response_not_implemented, AVRCP_GET_APP_ATTRIBUTE_TEXT_PDU_ID); } }
/**************************************************************************** * NAME * avrcpHandleGetElementAttributesCommand * * DESCRIPTION * Handle the incoming Get Element Attributes command * * PARAMETERS * avrcp - AVRCP Instance * ptr - Pointer to the data packet * packet_size - Packet size *******************************************************************************/ void avrcpHandleGetElementAttributesCommand(AVRCP *avrcp, const uint8 *ptr, uint16 packet_size) { uint16 data_offset=9; uint32 identifier_high = 0, identifier_low = 0; uint8 attribute_count=0; Source source=0; if(packet_size >= AVRCP_GET_ELEMENTS_HDR_SIZE) { data_offset=9; identifier_high = convertUint8ValuesToUint32(&ptr[0]); identifier_low = convertUint8ValuesToUint32(&ptr[4]); attribute_count= ptr[8]; packet_size -= data_offset; if(packet_size) { if(!(source=avrcpSourceFromConstData(avrcp, ptr+data_offset, packet_size))) { packet_size = 0; } } } { MAKE_AVRCP_MESSAGE(AVRCP_GET_ELEMENT_ATTRIBUTES_IND); message->avrcp = avrcp; message->identifier_high = identifier_high; message->identifier_low = identifier_low; message->number_of_attributes = attribute_count; message->size_attributes = packet_size; message->attributes = source; #ifdef AVRCP_ENABLE_DEPRECATED /* Deprecated fields will be removed later */ message->metadata_packet_type = avrcp_packet_type_single; message->transaction = avrcp->rsp_transaction_label; message->no_packets = 1; message->ctp_packet_type = AVCTP0_PACKET_TYPE_SINGLE; message->data_offset = 0; #endif MessageSend(avrcp->clientTask, AVRCP_GET_ELEMENT_ATTRIBUTES_IND, message); } }
/**************************************************************************** *NAME * avrcpHandleGetAppValueTextCommand * *DESCRIPTION * Handle the incoming GetApplicationValueText Command from CT. * *PARAMETERS * AVRCP - AVRCP Instance * ptr - Received Data in the command * packet_size - size of data ****************************************************************************/ void avrcpHandleGetAppValueTextCommand(AVRCP *avrcp, const uint8* data, uint16 packet_size) { if(isAvrcpPlayerSettingsEnabled(avrcpGetDeviceTask()) && (packet_size > 1)) { Source source=0; uint16 data_offset=2; packet_size-= data_offset; if(packet_size) { source=avrcpSourceFromConstData(avrcp, data+data_offset, packet_size); if(!source) { packet_size=0; } } { MAKE_AVRCP_MESSAGE(AVRCP_GET_APP_VALUE_TEXT_IND); message->avrcp = avrcp; message->attribute_id = data[0]; message->number_of_attributes = data[1]; message->size_attributes = packet_size; message->attributes = source; #ifdef AVRCP_ENABLE_DEPRECATED /* Deprecated fields will be removed later */ message->metadata_packet_type = avrcp_packet_type_single; message->transaction = avrcp->rsp_transaction_label; message->no_packets = 0; message->ctp_packet_type = AVCTP0_PACKET_TYPE_SINGLE; message->data_offset = 0; #endif MessageSend(avrcp->clientTask, AVRCP_GET_APP_VALUE_TEXT_IND, message); } } else { avrcpSendRejectMetadataResponse(avrcp, avctp_response_not_implemented, AVRCP_GET_APP_VALUE_PDU_ID); } }
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; }
/**************************************************************************** *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; }