/****************************************************************************** * * Copyright (C) 2003-2013 Broadcom Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ******************************************************************************/ #include #include "bt_common.h" #include "avrc_api.h" #include "avrc_defs.h" #include "avrc_int.h" #include "bt_utils.h" /***************************************************************************** ** Global data *****************************************************************************/ #if (AVRC_METADATA_INCLUDED == TRUE) #define EVT_AVAIL_PLAYER_CHANGE_RSP_LENGTH 1 #define EVT_ADDR_PLAYER_CHANGE_RSP_LENGTH 5 #define EVT_NOW_PLAYING_CHANGE_RSP_LENGTH 1 /******************************************************************************* ** ** Function avrc_bld_get_capability_rsp ** ** Description This function builds the Get Capability response. ** ** Returns AVRC_STS_NO_ERROR, if the response is built successfully ** Otherwise, the error code. ** *******************************************************************************/ static tAVRC_STS avrc_bld_get_capability_rsp (tAVRC_GET_CAPS_RSP *p_rsp, BT_HDR *p_pkt) { UINT8 *p_data, *p_start, *p_len, *p_count; UINT16 len = 0; UINT8 xx; UINT32 *p_company_id; UINT8 *p_event_id; tAVRC_STS status = AVRC_STS_NO_ERROR; if (!(AVRC_IS_VALID_CAP_ID(p_rsp->capability_id))) { AVRC_TRACE_ERROR("%s bad parameter. p_rsp: %x", __func__, p_rsp); status = AVRC_STS_BAD_PARAM; return status; } AVRC_TRACE_API("%s", __func__); /* get the existing length, if any, and also the num attributes */ p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset; p_data = p_len = p_start + 2; /* pdu + rsvd */ BE_STREAM_TO_UINT16(len, p_data); UINT8_TO_BE_STREAM(p_data, p_rsp->capability_id); p_count = p_data; if (len == 0) { *p_count = p_rsp->count; p_data++; len = 2; /* move past the capability_id and count */ } else { p_data = p_start + p_pkt->len; *p_count += p_rsp->count; } if (p_rsp->capability_id == AVRC_CAP_COMPANY_ID) { p_company_id = p_rsp->param.company_id; for (xx=0; xx< p_rsp->count; xx++) { UINT24_TO_BE_STREAM(p_data, p_company_id[xx]); } len += p_rsp->count * 3; } else { p_event_id = p_rsp->param.event_id; *p_count = 0; for (xx=0; xx< p_rsp->count; xx++) { if (AVRC_IS_VALID_EVENT_ID(p_event_id[xx])) { (*p_count)++; UINT8_TO_BE_STREAM(p_data, p_event_id[xx]); } } len += (*p_count); } UINT16_TO_BE_STREAM(p_len, len); p_pkt->len = (p_data - p_start); status = AVRC_STS_NO_ERROR; return status; } /******************************************************************************* ** ** Function avrc_bld_list_app_settings_attr_rsp ** ** Description This function builds the List Application Settings Attribute ** response. ** ** Returns AVRC_STS_NO_ERROR, if the response is built successfully ** Otherwise, the error code. ** *******************************************************************************/ static tAVRC_STS avrc_bld_list_app_settings_attr_rsp (tAVRC_LIST_APP_ATTR_RSP *p_rsp, BT_HDR *p_pkt) { UINT8 *p_data, *p_start, *p_len, *p_num; UINT16 len = 0; UINT8 xx; AVRC_TRACE_API("%s", __func__); /* get the existing length, if any, and also the num attributes */ p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset; p_data = p_len = p_start + 2; /* pdu + rsvd */ BE_STREAM_TO_UINT16(len, p_data); p_num = p_data; if (len == 0) { /* first time initialize the attribute count */ *p_num = 0; p_data++; } else { p_data = p_start + p_pkt->len; } for (xx=0; xxnum_attr; xx++) { if(AVRC_IsValidPlayerAttr(p_rsp->attrs[xx])) { (*p_num)++; UINT8_TO_BE_STREAM(p_data, p_rsp->attrs[xx]); } } len = *p_num + 1; UINT16_TO_BE_STREAM(p_len, len); p_pkt->len = (p_data - p_start); return AVRC_STS_NO_ERROR; } /******************************************************************************* ** ** Function avrc_bld_list_app_settings_values_rsp ** ** Description This function builds the List Application Setting Values ** response. ** ** Returns AVRC_STS_NO_ERROR, if the response is built successfully ** Otherwise, the error code. ** *******************************************************************************/ static tAVRC_STS avrc_bld_list_app_settings_values_rsp (tAVRC_LIST_APP_VALUES_RSP *p_rsp, BT_HDR *p_pkt) { UINT8 *p_data, *p_start, *p_len, *p_num; UINT8 xx; UINT16 len; AVRC_TRACE_API("%s", __func__); p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset; p_data = p_len = p_start + 2; /* pdu + rsvd */ /* get the existing length, if any, and also the num attributes */ BE_STREAM_TO_UINT16(len, p_data); p_num = p_data; /* first time initialize the attribute count */ if (len == 0) { *p_num = p_rsp->num_val; p_data++; } else { p_data = p_start + p_pkt->len; *p_num += p_rsp->num_val; } for (xx=0; xxnum_val; xx++) { UINT8_TO_BE_STREAM(p_data, p_rsp->vals[xx]); } len = *p_num + 1; UINT16_TO_BE_STREAM(p_len, len); p_pkt->len = (p_data - p_start); return AVRC_STS_NO_ERROR; } /******************************************************************************* ** ** Function avrc_bld_get_cur_app_setting_value_rsp ** ** Description This function builds the Get Current Application Setting Value ** response. ** ** Returns AVRC_STS_NO_ERROR, if the response is built successfully ** Otherwise, the error code. ** *******************************************************************************/ static tAVRC_STS avrc_bld_get_cur_app_setting_value_rsp (tAVRC_GET_CUR_APP_VALUE_RSP *p_rsp, BT_HDR *p_pkt) { UINT8 *p_data, *p_start, *p_len, *p_count; UINT16 len; UINT8 xx; if (!p_rsp->p_vals) { AVRC_TRACE_ERROR("%s NULL parameter", __func__); return AVRC_STS_BAD_PARAM; } AVRC_TRACE_API("%s", __func__); /* get the existing length, if any, and also the num attributes */ p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset; p_data = p_len = p_start + 2; /* pdu + rsvd */ BE_STREAM_TO_UINT16(len, p_data); p_count = p_data; if (len == 0) { /* first time initialize the attribute count */ *p_count = 0; p_data++; } else { p_data = p_start + p_pkt->len; } for (xx=0; xxnum_val; xx++) { if (avrc_is_valid_player_attrib_value(p_rsp->p_vals[xx].attr_id, p_rsp->p_vals[xx].attr_val)) { (*p_count)++; UINT8_TO_BE_STREAM(p_data, p_rsp->p_vals[xx].attr_id); UINT8_TO_BE_STREAM(p_data, p_rsp->p_vals[xx].attr_val); } } len = ((*p_count) << 1) + 1; UINT16_TO_BE_STREAM(p_len, len); p_pkt->len = (p_data - p_start); return AVRC_STS_NO_ERROR; } /******************************************************************************* ** ** Function avrc_bld_set_app_setting_value_rsp ** ** Description This function builds the Set Application Setting Value ** response. ** ** Returns AVRC_STS_NO_ERROR, if the response is built successfully ** Otherwise, the error code. ** *******************************************************************************/ static tAVRC_STS avrc_bld_set_app_setting_value_rsp (tAVRC_RSP *p_rsp, BT_HDR *p_pkt) { UNUSED(p_rsp); UNUSED(p_pkt); /* nothing to be added. */ AVRC_TRACE_API("%s", __func__); return AVRC_STS_NO_ERROR; } /******************************************************************************* ** ** Function avrc_bld_app_setting_text_rsp ** ** Description This function builds the Get Application Settings Attribute Text ** or Get Application Settings Value Text response. ** ** Returns AVRC_STS_NO_ERROR, if the response is built successfully ** Otherwise, the error code. ** *******************************************************************************/ static tAVRC_STS avrc_bld_app_setting_text_rsp (tAVRC_GET_APP_ATTR_TXT_RSP *p_rsp, BT_HDR *p_pkt) { UINT8 *p_data, *p_start, *p_len, *p_count; UINT16 len, len_left; UINT8 xx; tAVRC_STS sts = AVRC_STS_NO_ERROR; UINT8 num_added = 0; if (!p_rsp->p_attrs) { AVRC_TRACE_ERROR("%s NULL parameter", __func__); return AVRC_STS_BAD_PARAM; } /* get the existing length, if any, and also the num attributes */ p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset; p_data = p_len = p_start + 2; /* pdu + rsvd */ /* * NOTE: The buffer is allocated within avrc_bld_init_rsp_buffer(), and is * always of size BT_DEFAULT_BUFFER_SIZE. */ len_left = BT_DEFAULT_BUFFER_SIZE - BT_HDR_SIZE - p_pkt->offset - p_pkt->len; BE_STREAM_TO_UINT16(len, p_data); p_count = p_data; if (len == 0) { *p_count = 0; p_data++; } else { p_data = p_start + p_pkt->len; } for (xx=0; xxnum_attr; xx++) { if (len_left < (p_rsp->p_attrs[xx].str_len + 4)) { AVRC_TRACE_ERROR("%s out of room (str_len:%d, left:%d)", __func__, xx, p_rsp->p_attrs[xx].str_len, len_left); p_rsp->num_attr = num_added; sts = AVRC_STS_INTERNAL_ERR; break; } if ( !p_rsp->p_attrs[xx].str_len || !p_rsp->p_attrs[xx].p_str ) { AVRC_TRACE_ERROR("%s NULL attr text[%d]", __func__, xx); continue; } UINT8_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].attr_id); UINT16_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].charset_id); UINT8_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].str_len); ARRAY_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].p_str, p_rsp->p_attrs[xx].str_len); (*p_count)++; num_added++; } len = p_data - p_count; UINT16_TO_BE_STREAM(p_len, len); p_pkt->len = (p_data - p_start); return sts; } /******************************************************************************* ** ** Function avrc_bld_get_app_setting_attr_text_rsp ** ** Description This function builds the Get Application Setting Attribute Text ** response. ** ** Returns AVRC_STS_NO_ERROR, if the response is built successfully ** Otherwise, the error code. ** *******************************************************************************/ static tAVRC_STS avrc_bld_get_app_setting_attr_text_rsp (tAVRC_GET_APP_ATTR_TXT_RSP *p_rsp, BT_HDR *p_pkt) { AVRC_TRACE_API("%s", __func__); return avrc_bld_app_setting_text_rsp(p_rsp, p_pkt); } /******************************************************************************* ** ** Function avrc_bld_get_app_setting_value_text_rsp ** ** Description This function builds the Get Application Setting Value Text ** response. ** ** Returns AVRC_STS_NO_ERROR, if the response is built successfully ** Otherwise, the error code. ** *******************************************************************************/ static tAVRC_STS avrc_bld_get_app_setting_value_text_rsp (tAVRC_GET_APP_ATTR_TXT_RSP *p_rsp, BT_HDR *p_pkt) { AVRC_TRACE_API("%s", __func__); return avrc_bld_app_setting_text_rsp(p_rsp, p_pkt); } /******************************************************************************* ** ** Function avrc_bld_inform_charset_rsp ** ** Description This function builds the Inform Displayable Character Set ** response. ** ** Returns AVRC_STS_NO_ERROR, if the response is built successfully ** Otherwise, the error code. ** *******************************************************************************/ static tAVRC_STS avrc_bld_inform_charset_rsp (tAVRC_RSP *p_rsp, BT_HDR *p_pkt) { UNUSED(p_rsp); UNUSED(p_pkt); /* nothing to be added. */ AVRC_TRACE_API("%s", __func__); return AVRC_STS_NO_ERROR; } /******************************************************************************* ** ** Function avrc_bld_inform_battery_status_rsp ** ** Description This function builds the Inform Battery Status ** response. ** ** Returns AVRC_STS_NO_ERROR, if the response is built successfully ** Otherwise, the error code. ** *******************************************************************************/ static tAVRC_STS avrc_bld_inform_battery_status_rsp (tAVRC_RSP *p_rsp, BT_HDR *p_pkt) { UNUSED(p_rsp); UNUSED(p_pkt); /* nothing to be added. */ AVRC_TRACE_API("%s", __func__); return AVRC_STS_NO_ERROR; } /******************************************************************************* ** ** Function avrc_bld_get_elem_attrs_rsp ** ** Description This function builds the Get Element Attributes ** response. ** ** Returns AVRC_STS_NO_ERROR, if the response is built successfully ** Otherwise, the error code. ** *******************************************************************************/ static tAVRC_STS avrc_bld_get_elem_attrs_rsp (tAVRC_GET_ELEM_ATTRS_RSP *p_rsp, BT_HDR *p_pkt) { UINT8 *p_data, *p_start, *p_len, *p_count; UINT16 len; UINT8 xx; AVRC_TRACE_API("%s", __func__); if (!p_rsp->p_attrs) { AVRC_TRACE_ERROR("%s NULL parameter", __func__); return AVRC_STS_BAD_PARAM; } /* get the existing length, if any, and also the num attributes */ p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset; p_data = p_len = p_start + 2; /* pdu + rsvd */ BE_STREAM_TO_UINT16(len, p_data); p_count = p_data; if (len == 0) { *p_count = 0; p_data++; } else { p_data = p_start + p_pkt->len; } for (xx=0; xxnum_attr; xx++) { if (!AVRC_IS_VALID_MEDIA_ATTRIBUTE(p_rsp->p_attrs[xx].attr_id)) { AVRC_TRACE_ERROR("%s invalid attr id[%d]: %d", __func__, xx, p_rsp->p_attrs[xx].attr_id); continue; } if ( !p_rsp->p_attrs[xx].name.p_str ) { p_rsp->p_attrs[xx].name.str_len = 0; } UINT32_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].attr_id); UINT16_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].name.charset_id); UINT16_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].name.str_len); ARRAY_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].name.p_str, p_rsp->p_attrs[xx].name.str_len); (*p_count)++; } len = p_data - p_count; UINT16_TO_BE_STREAM(p_len, len); p_pkt->len = (p_data - p_start); return AVRC_STS_NO_ERROR; } /******************************************************************************* ** ** Function avrc_bld_get_play_status_rsp ** ** Description This function builds the Get Play Status ** response. ** ** Returns AVRC_STS_NO_ERROR, if the response is built successfully ** Otherwise, the error code. ** *******************************************************************************/ static tAVRC_STS avrc_bld_get_play_status_rsp (tAVRC_GET_PLAY_STATUS_RSP *p_rsp, BT_HDR *p_pkt) { UINT8 *p_data, *p_start; AVRC_TRACE_API("avrc_bld_get_play_status_rsp"); p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset; p_data = p_start + 2; /* add fixed lenth - song len(4) + song position(4) + status(1) */ UINT16_TO_BE_STREAM(p_data, 9); UINT32_TO_BE_STREAM(p_data, p_rsp->song_len); UINT32_TO_BE_STREAM(p_data, p_rsp->song_pos); UINT8_TO_BE_STREAM(p_data, p_rsp->play_status); p_pkt->len = (p_data - p_start); return AVRC_STS_NO_ERROR; } /******************************************************************************* ** ** Function avrc_bld_notify_rsp ** ** Description This function builds the Notification response. ** ** Returns AVRC_STS_NO_ERROR, if the response is built successfully ** Otherwise, the error code. ** *******************************************************************************/ static tAVRC_STS avrc_bld_notify_rsp (tAVRC_REG_NOTIF_RSP *p_rsp, BT_HDR *p_pkt) { UINT8 *p_data, *p_start; UINT8 *p_len; UINT16 len = 0; UINT8 xx; tAVRC_STS status = AVRC_STS_NO_ERROR; AVRC_TRACE_API("%s event_id %d", __func__, p_rsp->event_id); p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset; p_data = p_len = p_start + 2; /* pdu + rsvd */ p_data += 2; UINT8_TO_BE_STREAM(p_data, p_rsp->event_id); switch (p_rsp->event_id) { case AVRC_EVT_PLAY_STATUS_CHANGE: /* 0x01 */ /* p_rsp->param.play_status >= AVRC_PLAYSTATE_STOPPED is always TRUE */ if ((p_rsp->param.play_status <= AVRC_PLAYSTATE_REV_SEEK) || (p_rsp->param.play_status == AVRC_PLAYSTATE_ERROR) ) { UINT8_TO_BE_STREAM(p_data, p_rsp->param.play_status); len = 2; } else { AVRC_TRACE_ERROR("%s bad play state", __func__); status = AVRC_STS_BAD_PARAM; } break; case AVRC_EVT_TRACK_CHANGE: /* 0x02 */ ARRAY_TO_BE_STREAM(p_data, p_rsp->param.track, AVRC_UID_SIZE); len = (UINT8)(AVRC_UID_SIZE + 1); break; case AVRC_EVT_TRACK_REACHED_END: /* 0x03 */ case AVRC_EVT_TRACK_REACHED_START: /* 0x04 */ len = 1; break; case AVRC_EVT_PLAY_POS_CHANGED: /* 0x05 */ UINT32_TO_BE_STREAM(p_data, p_rsp->param.play_pos); len = 5; break; case AVRC_EVT_BATTERY_STATUS_CHANGE: /* 0x06 */ if (AVRC_IS_VALID_BATTERY_STATUS(p_rsp->param.battery_status)) { UINT8_TO_BE_STREAM(p_data, p_rsp->param.battery_status); len = 2; } else { AVRC_TRACE_ERROR("%s bad battery status", __func__); status = AVRC_STS_BAD_PARAM; } break; case AVRC_EVT_SYSTEM_STATUS_CHANGE: /* 0x07 */ if (AVRC_IS_VALID_SYSTEM_STATUS(p_rsp->param.system_status)) { UINT8_TO_BE_STREAM(p_data, p_rsp->param.system_status); len = 2; } else { AVRC_TRACE_ERROR("%s bad system status", __func__); status = AVRC_STS_BAD_PARAM; } break; case AVRC_EVT_APP_SETTING_CHANGE: /* 0x08 */ if (p_rsp->param.player_setting.num_attr > AVRC_MAX_APP_SETTINGS) p_rsp->param.player_setting.num_attr = AVRC_MAX_APP_SETTINGS; if (p_rsp->param.player_setting.num_attr > 0) { UINT8_TO_BE_STREAM(p_data, p_rsp->param.player_setting.num_attr); len = 2; for (xx=0; xxparam.player_setting.num_attr; xx++) { if (avrc_is_valid_player_attrib_value(p_rsp->param.player_setting.attr_id[xx], p_rsp->param.player_setting.attr_value[xx])) { UINT8_TO_BE_STREAM(p_data, p_rsp->param.player_setting.attr_id[xx]); UINT8_TO_BE_STREAM(p_data, p_rsp->param.player_setting.attr_value[xx]); } else { AVRC_TRACE_ERROR("%s bad player app seeting attribute or value", __func__); status = AVRC_STS_BAD_PARAM; break; } len += 2; } } else status = AVRC_STS_BAD_PARAM; break; case AVRC_EVT_AVAL_PLAYERS_CHANGE: len = EVT_AVAIL_PLAYER_CHANGE_RSP_LENGTH; break; case AVRC_EVT_ADDR_PLAYER_CHANGE: UINT16_TO_BE_STREAM(p_data,p_rsp->param.addr_player.player_id); UINT16_TO_BE_STREAM(p_data,p_rsp->param.addr_player.uid_counter); len = EVT_ADDR_PLAYER_CHANGE_RSP_LENGTH; break; case AVRC_EVT_NOW_PLAYING_CHANGE: len = EVT_NOW_PLAYING_CHANGE_RSP_LENGTH; break; case AVRC_EVT_VOLUME_CHANGE: len = 2; UINT8_TO_BE_STREAM(p_data, (AVRC_MAX_VOLUME & p_rsp->param.volume)); break; default: status = AVRC_STS_BAD_PARAM; AVRC_TRACE_ERROR("%s unknown event_id", __func__); } UINT16_TO_BE_STREAM(p_len, len); p_pkt->len = (p_data - p_start); return status; } /******************************************************************************* ** ** Function avrc_bld_next_rsp ** ** Description This function builds the Request Continue or Abort ** response. ** ** Returns AVRC_STS_NO_ERROR, if the response is built successfully ** Otherwise, the error code. ** *******************************************************************************/ static tAVRC_STS avrc_bld_next_rsp (tAVRC_RSP *p_rsp, BT_HDR *p_pkt) { UNUSED(p_rsp); UNUSED(p_pkt); /* nothing to be added. */ AVRC_TRACE_API("%s", __func__); return AVRC_STS_NO_ERROR; } /***************************************************************************** ** ** Function avrc_bld_set_address_player_rsp ** ** Description This function builds the set address player response ** ** Returns AVRC_STS_NO_ERROR ** ******************************************************************************/ static tAVRC_STS avrc_bld_set_address_player_rsp(tAVRC_RSP *p_rsp, BT_HDR *p_pkt) { AVRC_TRACE_API("%s", __func__); UINT8 *p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset; /* To calculate length */ UINT8 *p_data = p_start + 2; /* add fixed lenth status(1) */ UINT16_TO_BE_STREAM(p_data, 1); UINT8_TO_BE_STREAM(p_data, p_rsp->status); p_pkt->len = (p_data - p_start); return AVRC_STS_NO_ERROR; } /***************************************************************************** ** ** Function avrc_bld_play_item_rsp ** ** Description This function builds the play item response ** ** Returns AVRC_STS_NO_ERROR, if the response is build successfully ** ******************************************************************************/ static tAVRC_STS avrc_bld_play_item_rsp(tAVRC_RSP *p_rsp, BT_HDR *p_pkt) { AVRC_TRACE_API("%s", __func__); UINT8 *p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset; /* To calculate length */ UINT8 *p_data = p_start + 2; /* add fixed lenth status(1) */ UINT16_TO_BE_STREAM(p_data, 1); UINT8_TO_BE_STREAM(p_data, p_rsp->status); p_pkt->len = (p_data - p_start); return AVRC_STS_NO_ERROR; } /***************************************************************************** ** ** Function avrc_bld_set_absolute_volume_rsp ** ** Description This function builds the set absolute volume response ** ** Returns AVRC_STS_NO_ERROR, if the response is build successfully ** ******************************************************************************/ static tAVRC_STS avrc_bld_set_absolute_volume_rsp(uint8_t abs_vol, BT_HDR *p_pkt) { AVRC_TRACE_API("%s", __func__); UINT8 *p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset; /* To calculate length */ UINT8 *p_data = p_start + 2; /* add fixed lenth status(1) */ UINT16_TO_BE_STREAM(p_data, 1); UINT8_TO_BE_STREAM(p_data, abs_vol); p_pkt->len = (p_data - p_start); return AVRC_STS_NO_ERROR; } /******************************************************************************* ** ** Function avrc_bld_group_navigation_rsp ** ** Description This function builds the Group Navigation ** response. ** ** Returns AVRC_STS_NO_ERROR, if the response is built successfully ** Otherwise, the error code. ** *******************************************************************************/ tAVRC_STS avrc_bld_group_navigation_rsp (UINT16 navi_id, BT_HDR *p_pkt) { if (!AVRC_IS_VALID_GROUP(navi_id)) { AVRC_TRACE_ERROR("%s bad navigation op id: %d", __func__, navi_id); return AVRC_STS_BAD_PARAM; } AVRC_TRACE_API("%s", __func__); UINT8 *p_data = (UINT8 *)(p_pkt + 1) + p_pkt->offset; UINT16_TO_BE_STREAM(p_data, navi_id); p_pkt->len = 2; return AVRC_STS_NO_ERROR; } /***************************************************************************** ** ** Function avrc_bld_folder_item_values_rsp ** ** Description This function builds the folder item response. ** ** Returns AVRC_STS_NO_ERROR,if the response is built successfully ** otherwise error code ** ******************************************************************************/ static tAVRC_STS avrc_bld_folder_item_values_rsp(tAVRC_GET_ITEMS_RSP *p_rsp, BT_HDR *p_pkt ) { UINT8 *p_data, *p_start, *p_length, *p_media_element_len; UINT16 itemlength, param_length; UINT16 item_numb = 0, i, xx, media_attr_count; AVRC_TRACE_DEBUG(" avrc_bld_folder_item_values_rsp offset :x%x", p_pkt->offset); p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset; /* As per AVRCP spec, first byte of response is PDU ID * and Response does not have any opcode */ p_data = p_start; /*First OCT carry PDU information */ *p_data++ = p_rsp->pdu; /* Refer Media Play list AVRCP 1.5 22.19 (Get Folder Items) * Mark a pointer to be filled once length is calculated at last */ p_length = p_data; /*increment to adjust length*/ p_data = p_data + 2; /*Status is checked in Btif layer*/ *p_data++ = p_rsp->status; if(p_rsp->status != AVRC_STS_NO_ERROR) { //TODO Response AVRC_TRACE_ERROR(" ### Folder_item_values response error"); return p_rsp->status; } /*UID Counter OCT 4 and 5*/ UINT16_TO_BE_STREAM(p_data, p_rsp->uid_counter); /*Number of Items OCT 6 and 7*/ item_numb = p_rsp->item_count; UINT16_TO_BE_STREAM(p_data, p_rsp->item_count); param_length = 0; for (i = 0; i < item_numb; i++) { itemlength = 0; switch(p_rsp->p_item_list[i].item_type) { case AVRC_ITEM_PLAYER: UINT8_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].item_type); itemlength = 28 + p_rsp->p_item_list[i].u.player.name.str_len; UINT16_TO_BE_STREAM(p_data, itemlength); UINT16_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.player.player_id); UINT8_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.player.major_type); UINT32_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.player.sub_type); UINT8_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.player.play_status); ARRAY_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.player.features,\ AVRC_FEATURE_MASK_SIZE); UINT16_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.player.name.charset_id); UINT16_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.player.name.str_len); ARRAY_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.player.name.p_str,\ p_rsp->p_item_list[i].u.player.name.str_len); break; case AVRC_ITEM_FOLDER: UINT8_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].item_type); itemlength = 14 + p_rsp->p_item_list[i].u.folder.name.str_len; UINT16_TO_BE_STREAM(p_data, itemlength); ARRAY_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.folder.uid ,AVRC_UID_SIZE); UINT8_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.folder.type); UINT8_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.folder.playable); UINT16_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.folder.name.charset_id); UINT16_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.folder.name.str_len); ARRAY_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.folder.name.p_str,\ p_rsp->p_item_list[i].u.folder.name.str_len); break; case AVRC_ITEM_MEDIA: UINT8_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].item_type); p_media_element_len = p_data; itemlength = 13 + p_rsp->p_item_list[i].u.media.name.str_len; p_data = p_data + 2; /* for length */ ARRAY_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.media.uid ,AVRC_UID_SIZE); UINT8_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.media.type); UINT16_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.media.name.charset_id); UINT16_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.media.name.str_len); ARRAY_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.media.name.p_str,\ p_rsp->p_item_list[i].u.media.name.str_len); UINT8_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.media.attr_count); media_attr_count = p_rsp->p_item_list[i].u.media.attr_count; itemlength += 1; /* for attribute count */ for (xx = 0; xx < media_attr_count; xx++) { itemlength += 8 + p_rsp->p_item_list[i].u.media.p_attr_list[xx].name.str_len; UINT32_TO_BE_STREAM(p_data,\ p_rsp->p_item_list[i].u.media.p_attr_list[xx].attr_id); UINT16_TO_BE_STREAM(p_data,\ p_rsp->p_item_list[i].u.media.p_attr_list[xx].name.charset_id); UINT16_TO_BE_STREAM(p_data,\ p_rsp->p_item_list[i].u.media.p_attr_list[xx].name.str_len); ARRAY_TO_BE_STREAM(p_data,\ p_rsp->p_item_list[i].u.media.p_attr_list[xx].name.p_str,\ p_rsp->p_item_list[i].u.media.p_attr_list[xx].name.str_len); } UINT16_TO_BE_STREAM(p_media_element_len, itemlength); break; } param_length += itemlength + 3; /* 3 to accommodate item_len and item_type */ } param_length = param_length + 5; //Add explicit 5, 2 num items+ 2UID Counter + 1 status counter UINT16_TO_BE_STREAM(p_length, param_length); p_pkt->len = p_data - p_start; return AVRC_STS_NO_ERROR; } /************************************************************************************** ** ** Function avrc_bld_change_path_rsp ** ** Description ** ** Returns ** ************************************************************************************/ static tAVRC_STS avrc_bld_change_path_rsp (tAVRC_CHG_PATH_RSP *p_rsp, BT_HDR *p_pkt ) { UINT8 *p_data, *p_start; UINT16 param_len; /* parameter length feild of Rsp */ AVRC_TRACE_DEBUG("avrc_bld_change_path_rsp offset :x%x", p_pkt->offset); p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset; p_data = p_start; UINT8_TO_BE_STREAM(p_data, p_rsp->pdu); param_len = 5; /* refer spec */ UINT16_TO_BE_STREAM(p_data, param_len); UINT8_TO_BE_STREAM(p_data, p_rsp->status); UINT32_TO_BE_STREAM(p_data, p_rsp->num_items); p_pkt->len = p_data - p_start; AVRC_TRACE_DEBUG("length = %d",p_pkt->len); return AVRC_STS_NO_ERROR ; } /************************************************************************************** ** ** Function avrc_bld_set_browse_player_rsp ** ** Description ** ** Returns ** ************************************************************************************/ static tAVRC_STS avrc_bld_set_browse_player_rsp (tAVRC_SET_BR_PLAYER_RSP *p_rsp, BT_HDR *p_pkt ) { UINT8 *p_data, *p_start; UINT16 param_len_folder_name = 0; UINT16 param_len; /* parameter length feild of Rsp */ UINT8 folder_index = 0; AVRC_TRACE_DEBUG("avrc_bld_set_browse_player_rsp offset :x%x", p_pkt->offset); p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset; p_data = p_start; UINT8_TO_BE_STREAM(p_data, p_rsp->pdu); for(folder_index = 0; folder_index < p_rsp->folder_depth; folder_index++) { param_len_folder_name += p_rsp->p_folders[folder_index].str_len; } param_len = 10 + (p_rsp->folder_depth * 2) + param_len_folder_name; /* refer spec */ UINT16_TO_BE_STREAM(p_data, param_len); UINT8_TO_BE_STREAM(p_data, p_rsp->status); UINT16_TO_BE_STREAM(p_data, p_rsp->uid_counter); UINT32_TO_BE_STREAM(p_data, p_rsp->num_items); UINT16_TO_BE_STREAM(p_data, p_rsp->charset_id); UINT8_TO_BE_STREAM(p_data, p_rsp->folder_depth); for(folder_index = 0; folder_index < p_rsp->folder_depth; folder_index++) { UINT16_TO_BE_STREAM(p_data, p_rsp->p_folders[folder_index].str_len); ARRAY_TO_BE_STREAM(p_data,p_rsp->p_folders[folder_index].p_str, \ p_rsp->p_folders[folder_index].str_len); } p_pkt->len = p_data - p_start; AVRC_TRACE_DEBUG("length = %d",p_pkt->len); return AVRC_STS_NO_ERROR ; } /******************************************************************************* ** ** Function avrc_bld_get_item_attrs_rsp ** ** Description This function builds the Get Item Attributes ** response. ** ** Returns AVRC_STS_NO_ERROR, if the response is built successfully ** Otherwise, the error code. ** *******************************************************************************/ static tAVRC_STS avrc_bld_get_item_attrs_rsp (tAVRC_GET_ATTRS_RSP *p_rsp, BT_HDR *p_pkt) { UINT8 *p_data, *p_start; UINT16 param_len; UINT8 xx; AVRC_TRACE_API("avrc_bld_get_item_attrs_rsp"); if (!p_rsp->p_attr_list) { AVRC_TRACE_ERROR("avrc_bld_get_item_attrs_rsp NULL parameter"); return AVRC_STS_BAD_PARAM; } /* get the existing length, if any, and also the num attributes */ p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset; p_data = p_start; UINT8_TO_BE_STREAM(p_data, p_rsp->pdu); param_len = 2; /* for status and num_attr*/ for(xx = 0; xx < p_rsp->attr_count; xx++) { /* 8 for attr_id, char_set_id, attr_value_len */ param_len = param_len + 8 + p_rsp->p_attr_list[xx].name.str_len; } AVRC_TRACE_API(" param_len = %d ", param_len); UINT16_TO_BE_STREAM(p_data, param_len); UINT8_TO_BE_STREAM(p_data, p_rsp->status); UINT8_TO_BE_STREAM(p_data, p_rsp->attr_count); for (xx=0; xx < p_rsp->attr_count; xx++) { if ( !p_rsp->p_attr_list[xx].name.p_str ) { p_rsp->p_attr_list[xx].name.str_len = 0; } UINT32_TO_BE_STREAM(p_data, p_rsp->p_attr_list[xx].attr_id); UINT16_TO_BE_STREAM(p_data, p_rsp->p_attr_list[xx].name.charset_id); UINT16_TO_BE_STREAM(p_data, p_rsp->p_attr_list[xx].name.str_len); ARRAY_TO_BE_STREAM(p_data, p_rsp->p_attr_list[xx].name.p_str, \ p_rsp->p_attr_list[xx].name.str_len); } p_pkt->len = (p_data - p_start); return AVRC_STS_NO_ERROR; } /************************************************************************************** ** ** Function avrc_bld_change_path_rsp ** ** Description ** ** Returns ** ************************************************************************************/ static tAVRC_STS avrc_bld_tot_num_items_rsp (tAVRC_GET_TOT_ITEMS_RSP *p_rsp, BT_HDR *p_pkt ) { UINT8 *p_data, *p_start; UINT16 param_len; /* parameter length field of Rsp */ AVRC_TRACE_DEBUG("avrc_bld_tot_num_items_rsp offset :x%x", p_pkt->offset); p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset; p_data = p_start; UINT8_TO_BE_STREAM(p_data, p_rsp->pdu); param_len = 7; /* refer spec */ UINT16_TO_BE_STREAM(p_data, param_len); UINT8_TO_BE_STREAM(p_data, p_rsp->status); UINT16_TO_BE_STREAM(p_data, p_rsp->uid_counter); UINT32_TO_BE_STREAM(p_data, p_rsp->num_items); p_pkt->len = p_data - p_start; AVRC_TRACE_DEBUG("length = %d", p_pkt->len); return AVRC_STS_NO_ERROR; } /******************************************************************************* ** ** Function avrc_bld_rejected_rsp ** ** Description This function builds the General Response response. ** ** Returns AVRC_STS_NO_ERROR, if the response is built successfully ** *******************************************************************************/ static tAVRC_STS avrc_bld_rejected_rsp( tAVRC_RSP *p_rsp, BT_HDR *p_pkt ) { AVRC_TRACE_API("%s: status=%d, pdu:x%x", __func__, p_rsp->status, p_rsp->pdu); UINT8 *p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset; UINT8 *p_data = p_start + 2; AVRC_TRACE_DEBUG("%s pdu:x%x", __func__, *p_start); UINT16_TO_BE_STREAM(p_data, 1); UINT8_TO_BE_STREAM(p_data, p_rsp->status); p_pkt->len = p_data - p_start; return AVRC_STS_NO_ERROR; } /******************************************************************************* ** ** Function avrc_bld_browse_rejected_rsp ** ** Description This function builds the Browse Reject response. ** ** Returns AVRC_STS_NO_ERROR, if the response is built successfully ** Otherwise, the error code. ** *******************************************************************************/ static tAVRC_STS avrc_bld_browse_rejected_rsp (tAVRC_RSP *p_rsp, BT_HDR *p_pkt) { UINT8 *p_data, *p_start; AVRC_TRACE_API("avrc_bld_browse_rejected_rsp: status=%d, pdu:x%x, offset=%d", p_rsp->status, p_rsp->pdu, p_pkt->offset); p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset; p_data = p_start; *p_data++ = p_rsp->pdu; UINT16_TO_BE_STREAM(p_data, 1); //Parameter length UINT8_TO_BE_STREAM(p_data, p_rsp->status); p_pkt->len = p_data - p_start; AVRC_TRACE_DEBUG("Browse rejected rsp length=%d", p_pkt->len); return AVRC_STS_NO_ERROR; } /******************************************************************************* ** ** Function avrc_bld_init_rsp_buffer ** ** Description This function initializes the response buffer based on PDU ** ** Returns NULL, if no GKI buffer or failure to build the message. ** Otherwise, the GKI buffer that contains the initialized message. ** *******************************************************************************/ static BT_HDR *avrc_bld_init_rsp_buffer(tAVRC_RESPONSE *p_rsp) { UINT16 offset = AVRC_MSG_PASS_THRU_OFFSET; UINT16 chnl = AVCT_DATA_CTRL; UINT8 opcode = avrc_opcode_from_pdu(p_rsp->pdu); AVRC_TRACE_API("%s: pdu=%x, opcode=%x/%x", __func__, p_rsp->pdu, opcode, p_rsp->rsp.opcode); if (opcode != p_rsp->rsp.opcode && p_rsp->rsp.status != AVRC_STS_NO_ERROR && avrc_is_valid_opcode(p_rsp->rsp.opcode)) { opcode = p_rsp->rsp.opcode; AVRC_TRACE_API("%s opcode=%x", __func__, opcode); } switch (opcode) { case AVRC_OP_PASS_THRU: offset = AVRC_MSG_PASS_THRU_OFFSET; break; case AVRC_OP_VENDOR: offset = AVRC_MSG_VENDOR_OFFSET; break; } /* allocate and initialize the buffer */ BT_HDR *p_pkt = (BT_HDR *)osi_malloc(BT_DEFAULT_BUFFER_SIZE); UINT8 *p_data, *p_start; p_pkt->layer_specific = chnl; p_pkt->event = opcode; p_pkt->offset = offset; p_data = (UINT8 *)(p_pkt + 1) + p_pkt->offset; p_start = p_data; /* pass thru - group navigation - has a two byte op_id, so dont do it here */ if (opcode != AVRC_OP_PASS_THRU) *p_data++ = p_rsp->pdu; switch (opcode) { case AVRC_OP_VENDOR: /* reserved 0, packet_type 0 */ UINT8_TO_BE_STREAM(p_data, 0); /* continue to the next "case to add length */ /* add fixed lenth - 0 */ UINT16_TO_BE_STREAM(p_data, 0); break; } p_pkt->len = (p_data - p_start); p_rsp->rsp.opcode = opcode; return p_pkt; } /******************************************************************************* ** ** Function AVRC_BldResponse ** ** Description This function builds the given AVRCP response to the given ** GKI buffer ** ** Returns AVRC_STS_NO_ERROR, if the response is built successfully ** Otherwise, the error code. ** *******************************************************************************/ tAVRC_STS AVRC_BldResponse( UINT8 handle, tAVRC_RESPONSE *p_rsp, BT_HDR **pp_pkt) { tAVRC_STS status = AVRC_STS_BAD_PARAM; BT_HDR *p_pkt; BOOLEAN alloc = FALSE; UNUSED(handle); if (!p_rsp || !pp_pkt) { AVRC_TRACE_API("%s Invalid parameters passed. p_rsp=%p, pp_pkt=%p", __func__, p_rsp, pp_pkt); return AVRC_STS_BAD_PARAM; } if (*pp_pkt == NULL) { if ((*pp_pkt = avrc_bld_init_rsp_buffer(p_rsp)) == NULL) { AVRC_TRACE_API("%s Failed to initialize response buffer", __func__); return AVRC_STS_INTERNAL_ERR; } alloc = TRUE; } status = AVRC_STS_NO_ERROR; p_pkt = *pp_pkt; AVRC_TRACE_API("%s pdu=%x status=%x", __func__, p_rsp->rsp.pdu, p_rsp->rsp.status); if (p_rsp->rsp.status != AVRC_STS_NO_ERROR) { return( avrc_bld_rejected_rsp(&p_rsp->rsp, p_pkt) ); } switch (p_rsp->pdu) { case AVRC_PDU_NEXT_GROUP: case AVRC_PDU_PREV_GROUP: status = avrc_bld_group_navigation_rsp(p_rsp->pdu, p_pkt); break; case AVRC_PDU_GET_CAPABILITIES: status = avrc_bld_get_capability_rsp(&p_rsp->get_caps, p_pkt); break; case AVRC_PDU_LIST_PLAYER_APP_ATTR: status = avrc_bld_list_app_settings_attr_rsp(&p_rsp->list_app_attr, p_pkt); break; case AVRC_PDU_LIST_PLAYER_APP_VALUES: status = avrc_bld_list_app_settings_values_rsp(&p_rsp->list_app_values, p_pkt); break; case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE: status = avrc_bld_get_cur_app_setting_value_rsp(&p_rsp->get_cur_app_val, p_pkt); break; case AVRC_PDU_SET_PLAYER_APP_VALUE: status = avrc_bld_set_app_setting_value_rsp(&p_rsp->set_app_val, p_pkt); break; case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT: status = avrc_bld_get_app_setting_attr_text_rsp(&p_rsp->get_app_attr_txt, p_pkt); break; case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT: status = avrc_bld_get_app_setting_value_text_rsp(&p_rsp->get_app_val_txt, p_pkt); break; case AVRC_PDU_INFORM_DISPLAY_CHARSET: status = avrc_bld_inform_charset_rsp(&p_rsp->inform_charset, p_pkt); break; case AVRC_PDU_INFORM_BATTERY_STAT_OF_CT: status = avrc_bld_inform_battery_status_rsp(&p_rsp->inform_battery_status, p_pkt); break; case AVRC_PDU_GET_ELEMENT_ATTR: status = avrc_bld_get_elem_attrs_rsp(&p_rsp->get_elem_attrs, p_pkt); break; case AVRC_PDU_GET_PLAY_STATUS: status = avrc_bld_get_play_status_rsp(&p_rsp->get_play_status, p_pkt); break; case AVRC_PDU_REGISTER_NOTIFICATION: status = avrc_bld_notify_rsp(&p_rsp->reg_notif, p_pkt); break; case AVRC_PDU_REQUEST_CONTINUATION_RSP: /* 0x40 */ status = avrc_bld_next_rsp(&p_rsp->continu, p_pkt); break; case AVRC_PDU_ABORT_CONTINUATION_RSP: /* 0x41 */ status = avrc_bld_next_rsp(&p_rsp->abort, p_pkt); break; case AVRC_PDU_SET_ADDRESSED_PLAYER: /*PDU 0x60*/ status = avrc_bld_set_address_player_rsp(&p_rsp->addr_player, p_pkt); break; case AVRC_PDU_PLAY_ITEM: status = avrc_bld_play_item_rsp(&p_rsp->play_item, p_pkt); break; case AVRC_PDU_SET_ABSOLUTE_VOLUME: status = avrc_bld_set_absolute_volume_rsp(p_rsp->volume.volume, p_pkt); break; } if (alloc && (status != AVRC_STS_NO_ERROR) ) { osi_free(p_pkt); *pp_pkt = NULL; } AVRC_TRACE_API("%s returning %d", __func__, status); return status; } /******************************************************************************* ** ** Function avrc_bld_init_browse_rsp_buffer ** ** Description This function initializes the response buffer based on PDU ** ** Returns NULL, if no GKI buffer or failure to build the message. ** Otherwise, the GKI buffer that contains the initialized message. ** *******************************************************************************/ static BT_HDR *avrc_bld_init_browse_rsp_buffer(tAVRC_RESPONSE *p_rsp) { UINT16 offset = AVCT_BROWSE_OFFSET; UINT16 chnl = AVCT_DATA_BROWSE; UINT16 len = BT_DEFAULT_BUFFER_SIZE; BT_HDR *p_pkt = NULL; AVRC_TRACE_API("avrc_bld_init_browse_rsp_buffer "); /* allocate and initialize the buffer */ p_pkt = (BT_HDR *)osi_malloc(len); if (p_pkt != NULL) { p_pkt->layer_specific = chnl; p_pkt->event = AVRC_OP_BROWSE; /* Browsing Opcode */ p_pkt->offset = offset; } else { AVRC_TRACE_ERROR("### browse_rsp_buffer BUFF not allocated"); } return p_pkt; } /******************************************************************************* ** ** Function AVRC_BldBrowseResponse ** ** Description This function builds the given AVRCP response to the given ** GKI buffer ** ** Returns AVRC_STS_NO_ERROR, if the response is built successfully ** Otherwise, the error code. ** *******************************************************************************/ tAVRC_STS AVRC_BldBrowseResponse( UINT8 handle, tAVRC_RESPONSE *p_rsp, BT_HDR **pp_pkt) { tAVRC_STS status = AVRC_STS_BAD_PARAM; BT_HDR *p_pkt; BOOLEAN alloc = FALSE; if (!p_rsp || !pp_pkt) { AVRC_TRACE_ERROR("### BldResponse error p_rsp=%p, pp_pkt=%p", p_rsp, pp_pkt); return AVRC_STS_BAD_PARAM; } if (*pp_pkt == NULL) { if ((*pp_pkt = avrc_bld_init_browse_rsp_buffer(p_rsp)) == NULL) { AVRC_TRACE_ERROR("### BldResponse: Failed to initialize response buffer"); return AVRC_STS_INTERNAL_ERR; } alloc = TRUE; } status = AVRC_STS_NO_ERROR; p_pkt = *pp_pkt; AVRC_TRACE_API("BldResponse: pdu=%x status=%x", p_rsp->rsp.pdu, p_rsp->rsp.status); if (p_rsp->rsp.status != AVRC_STS_NO_ERROR) { AVRC_TRACE_ERROR("###ERROR AVRC_BldBrowseResponse"); return (avrc_bld_browse_rejected_rsp(&p_rsp->rsp, p_pkt)); } switch (p_rsp->pdu) { case AVRC_PDU_GET_FOLDER_ITEMS: status = avrc_bld_folder_item_values_rsp(&p_rsp->get_items, p_pkt); break; case AVRC_PDU_SET_BROWSED_PLAYER: status = avrc_bld_set_browse_player_rsp(&p_rsp->br_player, p_pkt); break; case AVRC_PDU_CHANGE_PATH: status = avrc_bld_change_path_rsp(&p_rsp->chg_path, p_pkt); break; case AVRC_PDU_GET_ITEM_ATTRIBUTES: status = avrc_bld_get_item_attrs_rsp(&p_rsp->get_attrs, p_pkt); break; case AVRC_PDU_GET_TOTAL_NUMBER_OF_ITEMS: status = avrc_bld_tot_num_items_rsp(&p_rsp->get_tot_items, p_pkt); break; default : break; } if (alloc && (status != AVRC_STS_NO_ERROR) ) { osi_free_and_reset((void **)&p_pkt); *pp_pkt = NULL; AVRC_TRACE_ERROR("### error status:%d",status); } return status; } #endif /* (AVRC_METADATA_INCLUDED == TRUE)*/