void sendRegisterNotificationResponse( AVRCP *avrcp, avrcp_response_type resp, uint16 size_mandatory, uint8 *mandatory, uint16 size_attributes, Source attributes) { /* 1 byte error status code as data for rejected response */ uint8 error_data[1]; uint16 param_length = 1; avrcp_packet_type metadata_packet_type = avrcp_packet_type_single; /* Get the error status code */ error_data[0] = avrcpGetErrorStatusCode(&resp, AVRCP0_CTYPE_NOTIFY); if ((resp == avctp_response_interim) || (resp == avctp_response_changed)) { param_length = size_mandatory + size_attributes; } else { size_mandatory = 1; /* 1 octet length only for error code */ mandatory = &error_data[0]; } if (param_length > AVRCP_AVC_MAX_DATA_SIZE) { /* There are more fragments to be sent, store the data for the following fragments. */ /* madatory[0] contains the event ID */ avrcpStoreNextContinuationPacket(avrcp, attributes, param_length-AVRCP_AVC_MAX_DATA_SIZE, AVRCP_REGISTER_NOTIFICATION_PDU_ID, resp, GetNotificationTransaction(avrcp, mandatory[0])); param_length = AVRCP_AVC_MAX_DATA_SIZE; metadata_packet_type = avrcp_packet_type_start; } avrcpSendMetadataResponse(avrcp, resp, AVRCP_REGISTER_NOTIFICATION_PDU_ID, attributes, metadata_packet_type, param_length, size_mandatory, mandatory); }
/**************************************************************************** *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; }