Loading system/bta/av/bta_av_main.cc +14 −14 Original line number Diff line number Diff line Loading @@ -1138,26 +1138,26 @@ void bta_av_sm_execute(tBTA_AV_CB* p_cb, uint16_t event, tBTA_AV_DATA* p_data) { * ******************************************************************************/ bool bta_av_hdl_event(BT_HDR* p_msg) { uint16_t event = p_msg->event; uint16_t first_event = BTA_AV_FIRST_NSM_EVT; if (event > BTA_AV_LAST_EVT) { if (p_msg->event > BTA_AV_LAST_EVT) { return true; /* to free p_msg */ } if (event >= first_event) { if (p_msg->event >= BTA_AV_FIRST_NSM_EVT) { #if (BTA_AV_DEBUG == TRUE) APPL_TRACE_VERBOSE("AV nsm event=0x%x(%s)", event, bta_av_evt_code(event)); APPL_TRACE_VERBOSE("AV nsm event=0x%x(%s)", p_msg->event, bta_av_evt_code(p_msg->event)); #else APPL_TRACE_VERBOSE("AV nsm event=0x%x", event); APPL_TRACE_VERBOSE("AV nsm event=0x%x", p_msg->event); #endif /* non state machine events */ (*bta_av_nsm_act[event - BTA_AV_FIRST_NSM_EVT])((tBTA_AV_DATA*)p_msg); } else if (event >= BTA_AV_FIRST_SM_EVT && event <= BTA_AV_LAST_SM_EVT) { (*bta_av_nsm_act[p_msg->event - BTA_AV_FIRST_NSM_EVT])( (tBTA_AV_DATA*) p_msg); } else if (p_msg->event >= BTA_AV_FIRST_SM_EVT && p_msg->event <= BTA_AV_LAST_SM_EVT) { #if (BTA_AV_DEBUG == TRUE) APPL_TRACE_VERBOSE("AV sm event=0x%x(%s)", event, bta_av_evt_code(event)); APPL_TRACE_VERBOSE("AV sm event=0x%x(%s)", p_msg->event, bta_av_evt_code(p_msg->event)); #else APPL_TRACE_VERBOSE("AV sm event=0x%x", event); APPL_TRACE_VERBOSE("AV sm event=0x%x", p_msg->event); #endif /* state machine events */ bta_av_sm_execute(&bta_av_cb, p_msg->event, (tBTA_AV_DATA*) p_msg); Loading system/btif/src/btif_rc.cc +77 −69 Original line number Diff line number Diff line Loading @@ -1388,6 +1388,65 @@ static uint8_t opcode_from_pdu(uint8_t pdu) { return opcode; } /*************************************************************************** * Function: fill_attribute_id_array * * - Argument: * cmd_attribute_number input attribute number from AVRCP command * cmd_attribute_id_array input attribute list from AVRCP command * out_array_size allocated size of out attribute id array * out_attribute_id_array output attribute list resolved here * * - Description: * Resolve attribute id array as defined by the AVRCP specification. * * - Returns: * The number of attributes filled in * ***************************************************************************/ static uint8_t fill_attribute_id_array( uint8_t cmd_attribute_number, btrc_media_attr_t* cmd_attribute_id_array, size_t out_array_size, btrc_media_attr_t* out_attribute_id_array) { /* Reset attribute array */ memset(out_attribute_id_array, 0, out_array_size); /* Default case for cmd_attribute_number == 0xFF, No attribute */ uint8_t out_attribute_number = 0; if (cmd_attribute_number == 0) { /* All attributes */ out_attribute_number = out_array_size < AVRC_MAX_NUM_MEDIA_ATTR_ID ? out_array_size : AVRC_MAX_NUM_MEDIA_ATTR_ID; for (int i = 0; i < out_attribute_number; i++) { out_attribute_id_array[i] = (btrc_media_attr_t) (i + 1); } } else if (cmd_attribute_number != 0xFF) { /* Attribute List */ out_attribute_number = 0; int filled_id_count = 0; for (int i = 0; (i < cmd_attribute_number) && (out_attribute_number < out_array_size) && (out_attribute_number < AVRC_MAX_NUM_MEDIA_ATTR_ID); i++) { /* Fill only valid entries */ if (AVRC_IS_VALID_MEDIA_ATTRIBUTE(cmd_attribute_id_array[i])) { /* Skip the duplicate entries */ for (filled_id_count = 0; filled_id_count < out_attribute_number; filled_id_count++) { if (out_attribute_id_array[filled_id_count] == cmd_attribute_id_array[i]) break; } /* New ID */ if (filled_id_count == out_attribute_number) { out_attribute_id_array[out_attribute_number] = (btrc_media_attr_t) cmd_attribute_id_array[i]; out_attribute_number++; } } } } return out_attribute_number; } /******************************************************************************* * * Function btif_rc_upstreams_evt Loading Loading @@ -1424,51 +1483,17 @@ static void btif_rc_upstreams_evt(uint16_t event, tAVRC_COMMAND* pavrc_cmd, } break; case AVRC_PDU_GET_ELEMENT_ATTR: { btrc_media_attr_t element_attrs[BTRC_MAX_ELEM_ATTR_SIZE]; uint8_t num_attr; memset(&element_attrs, 0, sizeof(element_attrs)); if (pavrc_cmd->get_elem_attrs.num_attr == 0) { /* CT requests for all attributes */ int attr_cnt; num_attr = BTRC_MAX_ELEM_ATTR_SIZE; for (attr_cnt = 0; attr_cnt < BTRC_MAX_ELEM_ATTR_SIZE; attr_cnt++) { element_attrs[attr_cnt] = (btrc_media_attr_t)(attr_cnt + 1); } } else if (pavrc_cmd->get_elem_attrs.num_attr == 0xFF) { /* 0xff indicates, no attributes requested - reject */ uint8_t num_attr = fill_attribute_id_array( pavrc_cmd->get_elem_attrs.num_attr, (btrc_media_attr_t*)pavrc_cmd->get_elem_attrs.attrs, BTRC_MAX_ELEM_ATTR_SIZE, element_attrs); if (num_attr == 0) { BTIF_TRACE_ERROR( "%s: No valid attributes requested in GET_ELEMENT_ATTRIBUTES", __func__); send_reject_response(p_dev->rc_handle, label, pavrc_cmd->pdu, AVRC_STS_BAD_PARAM, pavrc_cmd->cmd.opcode); return; } else { int attr_cnt, filled_attr_count; num_attr = 0; /* Attribute IDs from 1 to AVRC_MAX_NUM_MEDIA_ATTR_ID are only valid, * hence HAL definition limits the attributes to * AVRC_MAX_NUM_MEDIA_ATTR_ID. * Fill only valid entries. */ for (attr_cnt = 0; (attr_cnt < pavrc_cmd->get_elem_attrs.num_attr) && (num_attr < AVRC_MAX_NUM_MEDIA_ATTR_ID); attr_cnt++) { if ((pavrc_cmd->get_elem_attrs.attrs[attr_cnt] > 0) && (pavrc_cmd->get_elem_attrs.attrs[attr_cnt] <= AVRC_MAX_NUM_MEDIA_ATTR_ID)) { /* Skip the duplicate entries : PTS sends duplicate entries for * Fragment cases */ for (filled_attr_count = 0; filled_attr_count < num_attr; filled_attr_count++) { if (element_attrs[filled_attr_count] == pavrc_cmd->get_elem_attrs.attrs[attr_cnt]) break; } if (filled_attr_count == num_attr) { element_attrs[num_attr] = (btrc_media_attr_t)pavrc_cmd->get_elem_attrs.attrs[attr_cnt]; num_attr++; } } } } fill_pdu_queue(IDX_GET_ELEMENT_ATTR_RSP, ctype, label, true, p_dev); HAL_CBACK(bt_rc_callbacks, get_element_attr_cb, num_attr, element_attrs, Loading Loading @@ -1595,41 +1620,24 @@ static void btif_rc_upstreams_evt(uint16_t event, tAVRC_COMMAND* pavrc_cmd, case AVRC_PDU_GET_ITEM_ATTRIBUTES: { btrc_media_attr_t item_attrs[BTRC_MAX_ELEM_ATTR_SIZE]; uint8_t num_attr; uint8_t scope; uint16_t uid_counter; scope = pavrc_cmd->get_attrs.scope; uid_counter = pavrc_cmd->get_attrs.uid_counter; memset(&item_attrs, 0, sizeof(item_attrs)); if (pavrc_cmd->get_attrs.attr_count == 0xFF) { uint8_t num_attr = fill_attribute_id_array( pavrc_cmd->get_elem_attrs.num_attr, (btrc_media_attr_t*)pavrc_cmd->get_elem_attrs.attrs, BTRC_MAX_ELEM_ATTR_SIZE, item_attrs); if (num_attr == 0) { BTIF_TRACE_ERROR( "%s: No attributes are requested in GET_ITEM_ATTRIBUTES", __func__); /* 0xff indicates, no attributes requested - reject this */ "%s: No valid attributes requested in GET_ITEM_ATTRIBUTES", __func__); send_reject_response(p_dev->rc_handle, label, pavrc_cmd->pdu, AVRC_STS_BAD_PARAM, pavrc_cmd->cmd.opcode); return; } if (pavrc_cmd->get_attrs.attr_count == 0) { /* CT requests for all attributes */ int attr_cnt; num_attr = BTRC_MAX_ELEM_ATTR_SIZE; for (attr_cnt = 0; attr_cnt < BTRC_MAX_ELEM_ATTR_SIZE; attr_cnt++) { item_attrs[attr_cnt] = (btrc_media_attr_t)(attr_cnt + 1); } } else { num_attr = pavrc_cmd->get_attrs.attr_count; memcpy(item_attrs, pavrc_cmd->get_attrs.p_attr_list, sizeof(uint32_t) * pavrc_cmd->get_attrs.attr_count); } fill_pdu_queue(IDX_GET_ITEM_ATTR_RSP, ctype, label, true, p_dev); BTIF_TRACE_DEBUG("%s: GET_ITEM_ATTRIBUTES: num_attr: %d", __func__, num_attr); HAL_CBACK(bt_rc_callbacks, get_item_attr_cb, scope, pavrc_cmd->get_attrs.uid, uid_counter, num_attr, item_attrs, &rc_addr); HAL_CBACK(bt_rc_callbacks, get_item_attr_cb, pavrc_cmd->get_attrs.scope, pavrc_cmd->get_attrs.uid, pavrc_cmd->get_attrs.uid_counter, num_attr, item_attrs, &rc_addr); } break; case AVRC_PDU_GET_TOTAL_NUM_OF_ITEMS: { Loading system/stack/avrc/avrc_bld_tg.cc +168 −87 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ * limitations under the License. * ******************************************************************************/ #include <assert.h> #include <string.h> #include "bt_common.h" Loading Loading @@ -445,6 +446,111 @@ static tAVRC_STS avrc_bld_inform_battery_status_rsp (UNUSED_ATTR tAVRC_RSP *p_rs return AVRC_STS_NO_ERROR; } static void avrc_build_attribute_entries(int num_attrs, tAVRC_ATTR_ENTRY* p_attrs, int remaining_buffer_capacity, uint8_t** pp_data, uint8_t* p_attribute_count) { AVRC_TRACE_DEBUG("%s num_attrs: %d, remaining_buffer_capacity: %d", __func__, num_attrs, remaining_buffer_capacity); uint8_t* p_data = *pp_data; /* Fill in the Attribute ID, Character Set, Length and Values */ for (int index = 0; index < num_attrs; index++) { AVRC_TRACE_DEBUG("%s attr id[%d]: %d", __func__, index, p_attrs[index].attr_id); assert(AVRC_IS_VALID_MEDIA_ATTRIBUTE(p_attrs[index].attr_id)); if (!p_attrs[index].name.p_str) { p_attrs[index].name.str_len = 0; } /* 8 is the size of attr_id, char set and str_len */ remaining_buffer_capacity -= 8; if (remaining_buffer_capacity < 0) { AVRC_TRACE_WARNING( "%s not enough buffer space for attr_id[%d]: %d," " skipping %d attributes", __func__, index, p_attrs[index].attr_id, num_attrs - index); break; } if (remaining_buffer_capacity < p_attrs[index].name.str_len) { AVRC_TRACE_WARNING("%s not enough buffer space for attr_id[%d]: %d," " truncating attribute", __func__, index, p_attrs[index].attr_id); p_attrs[index].name.str_len = remaining_buffer_capacity; remaining_buffer_capacity = 0; } remaining_buffer_capacity -= p_attrs[index].name.str_len; UINT32_TO_BE_STREAM(p_data, p_attrs[index].attr_id); UINT16_TO_BE_STREAM(p_data, p_attrs[index].name.charset_id); UINT16_TO_BE_STREAM(p_data, p_attrs[index].name.str_len); ARRAY_TO_BE_STREAM(p_data, p_attrs[index].name.p_str, p_attrs[index].name.str_len); (*p_attribute_count)++; } *pp_data = p_data; AVRC_TRACE_DEBUG("%s filled attributes, remaining_buffer_capacity: %d", __func__, num_attrs, remaining_buffer_capacity); } /******************************************************************************* ** ** 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_ATTRS_RSP *p_rsp, BT_HDR *p_pkt) { AVRC_TRACE_API("%s", __func__); if (!p_rsp->p_attrs) { AVRC_TRACE_ERROR("%s NULL p_attrs", __func__); return AVRC_STS_BAD_PARAM; } /* Figure out how much we have left in current buffer */ int remaining_buffer_capacity = BT_DEFAULT_BUFFER_SIZE - BT_HDR_SIZE - p_pkt->offset; if (remaining_buffer_capacity < 5) { AVRC_TRACE_ERROR("%s not enough buffer for packet header", remaining_buffer_capacity); return AVRC_STS_INTERNAL_ERR; } /* Get to the beginning of PDU */ uint8_t *p_pdu_start = (uint8_t *)(p_pkt + 1) + p_pkt->offset; /* Skip PDU ID and Reserved byte to get pointer to Parameter Length */ uint8_t *p_data, *p_parameter_len; p_data = p_parameter_len = p_pdu_start + 2; /* Parse parameter length */ uint16_t parameter_len; BE_STREAM_TO_UINT16(parameter_len, p_data); /* Get pointer to Attribute Count */ uint8_t *p_attribute_count = p_data; /* Initialize field values when Parameter Length is 0 */ if (parameter_len == 0) { *p_attribute_count = 0; p_data++; } else { // TODO: Why do we need this case? p_data = p_pdu_start + p_pkt->len; } remaining_buffer_capacity -= p_data - p_pdu_start;; if (remaining_buffer_capacity < 0) { AVRC_TRACE_ERROR("%s not enough buffer capacity for response"); return AVRC_STS_BAD_PARAM; } /* Fill in the Attribute ID, Character Set, Length and Values */ avrc_build_attribute_entries(p_rsp->num_attrs, p_rsp->p_attrs, remaining_buffer_capacity, &p_data, p_attribute_count); parameter_len = p_data - p_attribute_count; UINT16_TO_BE_STREAM(p_parameter_len, parameter_len); p_pkt->len = (p_data - p_pdu_start); return AVRC_STS_NO_ERROR; } /******************************************************************************* ** ** Function avrc_bld_get_play_status_rsp Loading Loading @@ -1093,10 +1199,9 @@ static tAVRC_STS avrc_bld_change_path_rsp (tAVRC_CHG_PATH_RSP *p_rsp, BT_HDR *p_ /******************************************************************************* ** ** Function avrc_bld_get_attrs_rsp ** Function avrc_bld_get_item_attrs_rsp ** ** Description This function builds the Get Item Attributes or ** Get Element Attributes response, ** Description This function builds the GetItemAttributes response, ** ** The Get Item Attributes message goes through the ** Browsing channel (already specified in the |p_pkt|) Loading @@ -1106,93 +1211,66 @@ static tAVRC_STS avrc_bld_change_path_rsp (tAVRC_CHG_PATH_RSP *p_rsp, BT_HDR *p_ ** Otherwise, the error code. ** *******************************************************************************/ static tAVRC_STS avrc_bld_get_attrs_rsp (tAVRC_GET_ATTRS_RSP *p_rsp, BT_HDR *p_pkt) { uint8_t *p_data, *p_start; uint8_t *p_len; uint16_t len_left; uint8_t *p_num; uint16_t mtu; static tAVRC_STS avrc_bld_get_item_attrs_rsp (tAVRC_GET_ATTRS_RSP *p_rsp, BT_HDR *p_pkt) { AVRC_TRACE_API("%s", __func__); /* calculate the buffer size needed and validate the parameters */ if (!p_rsp || !p_rsp->p_attrs) { AVRC_TRACE_ERROR("NULL p_attrs"); return AVRC_STS_BAD_PARAM; } /* check the length before adding the attr to the message */ uint16_t len = 2; for (uint8_t xx = 0; xx < p_rsp->num_attrs; xx++) { if(p_rsp->p_attrs[xx].name.p_str == 0 || !AVRC_IS_VALID_MEDIA_ATTRIBUTE(p_rsp->p_attrs[xx].attr_id)) { AVRC_TRACE_ERROR("[%d] NULL p_attrs str or bad attr_id:%d", xx, p_rsp->p_attrs[xx].attr_id); if (!p_rsp->p_attrs) { AVRC_TRACE_ERROR("%s NULL p_attrs", __func__); return AVRC_STS_BAD_PARAM; } len += (p_rsp->p_attrs[xx].name.str_len + 8); } len_left = BT_DEFAULT_BUFFER_SIZE - BT_HDR_SIZE; p_data = (uint8_t *)(p_pkt + 1); /* Figure out how much we have left in current buffer */ int remaining_buffer_capacity = BT_DEFAULT_BUFFER_SIZE - BT_HDR_SIZE - p_pkt->offset; /* Get to the beginning of data section in buffer */ uint8_t *p_data = (uint8_t *)(p_pkt + 1); /* Get the MTU size that is filled in earlier */ uint16_t mtu; BE_STREAM_TO_UINT16(mtu, p_data); if (len_left > mtu) { len_left = mtu; } len_left = len_left - p_pkt->offset - p_pkt->len; AVRC_TRACE_DEBUG("len_left:%d, mtu:%d len needed:%d", len_left, mtu, len); if (len_left < 11) /* 11 is 4/attr_id + 2/charset_id + 2/str_len + 3/1st timer/attr cnt & len */ { if (remaining_buffer_capacity > mtu) { remaining_buffer_capacity = mtu; } AVRC_TRACE_DEBUG("%s remaining_buffer_capacity:%d, mtu:%d", remaining_buffer_capacity, mtu); if (remaining_buffer_capacity < 5) { AVRC_TRACE_ERROR("%s not enough buffer for packet header", remaining_buffer_capacity); return AVRC_STS_INTERNAL_ERR; } if (len > len_left) { AVRC_TRACE_ERROR("The buffer does not have enough room to hold the given data."); } /* get the existing length, if any, and also the num attributes */ p_start = (uint8_t *)(p_pkt + 1) + p_pkt->offset; p_data = p_len = p_start + 1; /* pdu */ /* the existing len */ BE_STREAM_TO_UINT16(len, p_data); p_num = p_data + 1; if (len == 0) { /* first time initialize the attribute count */ UINT8_TO_BE_STREAM(p_data, p_rsp->status); *p_num = 0; p_data++; len = 2; len_left -= 3; } else { p_data = p_start + p_pkt->len; } for (uint8_t xx = 0; (xx < p_rsp->num_attrs) && (len_left > 9); xx++) { (*p_num)++; 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); len_left -= 8; if (p_rsp->p_attrs[xx].name.str_len > len_left) p_rsp->p_attrs[xx].name.str_len = len_left; ARRAY_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].name.p_str, p_rsp->p_attrs[xx].name.str_len); len_left -= p_rsp->p_attrs[xx].name.str_len; len += (p_rsp->p_attrs[xx].name.str_len + 8); /* Get to the beginning of PDU */ uint8_t *p_pdu_start = (uint8_t *)(p_pkt + 1) + p_pkt->offset; /* Skip PDU ID to get pointer to Parameter length */ uint8_t *p_parameter_len; p_data = p_parameter_len = p_pdu_start + 1; /* Parse existing parameter length */ uint16_t parameter_len; BE_STREAM_TO_UINT16(parameter_len, p_data); /* Skip one byte to Number of Attributes */ uint8_t *p_status = p_data++; uint8_t *p_attribute_count = p_data++; if (parameter_len == 0) { /* First time, initialize the status byte */ *p_status = p_rsp->status; if (p_rsp->status != AVRC_STS_NO_ERROR) { // TODO(siyuanh): This is a hack parameter_len = 1; UINT16_TO_BE_STREAM(p_parameter_len, parameter_len); p_pkt->len = p_status - p_pdu_start; return AVRC_STS_NO_ERROR; } UINT16_TO_BE_STREAM(p_len, len); p_pkt->len = (p_data - p_start); *p_attribute_count = 0; } else { // TODO(siyuanh): Why do wee need this case? p_data = p_pdu_start + p_pkt->len; } remaining_buffer_capacity -= p_data - p_pdu_start; /* Fill in the Attribute ID, Character Set, Length and Values */ avrc_build_attribute_entries(p_rsp->num_attrs, p_rsp->p_attrs, remaining_buffer_capacity, &p_data, p_attribute_count); parameter_len = p_data - p_status; UINT16_TO_BE_STREAM(p_parameter_len, parameter_len); p_pkt->len = p_data - p_pdu_start; return AVRC_STS_NO_ERROR; } Loading Loading @@ -1469,8 +1547,7 @@ tAVRC_STS AVRC_BldResponse( uint8_t handle, tAVRC_RESPONSE *p_rsp, BT_HDR **pp_p break; case AVRC_PDU_GET_ELEMENT_ATTR: case AVRC_PDU_GET_ITEM_ATTRIBUTES: status = avrc_bld_get_attrs_rsp(&p_rsp->get_attrs, p_pkt); status = avrc_bld_get_elem_attrs_rsp(&p_rsp->get_attrs, p_pkt); break; case AVRC_PDU_GET_PLAY_STATUS: Loading Loading @@ -1517,11 +1594,15 @@ tAVRC_STS AVRC_BldResponse( uint8_t handle, tAVRC_RESPONSE *p_rsp, BT_HDR **pp_p 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_NUM_OF_ITEMS: status = avrc_bld_get_num_of_item_rsp(&p_rsp->get_num_of_items, p_pkt); break; case AVRC_PDU_SEARCH: /* 0x80 */ case AVRC_PDU_SEARCH: status = avrc_bld_search_rsp(&p_rsp->search, p_pkt); break; } Loading Loading
system/bta/av/bta_av_main.cc +14 −14 Original line number Diff line number Diff line Loading @@ -1138,26 +1138,26 @@ void bta_av_sm_execute(tBTA_AV_CB* p_cb, uint16_t event, tBTA_AV_DATA* p_data) { * ******************************************************************************/ bool bta_av_hdl_event(BT_HDR* p_msg) { uint16_t event = p_msg->event; uint16_t first_event = BTA_AV_FIRST_NSM_EVT; if (event > BTA_AV_LAST_EVT) { if (p_msg->event > BTA_AV_LAST_EVT) { return true; /* to free p_msg */ } if (event >= first_event) { if (p_msg->event >= BTA_AV_FIRST_NSM_EVT) { #if (BTA_AV_DEBUG == TRUE) APPL_TRACE_VERBOSE("AV nsm event=0x%x(%s)", event, bta_av_evt_code(event)); APPL_TRACE_VERBOSE("AV nsm event=0x%x(%s)", p_msg->event, bta_av_evt_code(p_msg->event)); #else APPL_TRACE_VERBOSE("AV nsm event=0x%x", event); APPL_TRACE_VERBOSE("AV nsm event=0x%x", p_msg->event); #endif /* non state machine events */ (*bta_av_nsm_act[event - BTA_AV_FIRST_NSM_EVT])((tBTA_AV_DATA*)p_msg); } else if (event >= BTA_AV_FIRST_SM_EVT && event <= BTA_AV_LAST_SM_EVT) { (*bta_av_nsm_act[p_msg->event - BTA_AV_FIRST_NSM_EVT])( (tBTA_AV_DATA*) p_msg); } else if (p_msg->event >= BTA_AV_FIRST_SM_EVT && p_msg->event <= BTA_AV_LAST_SM_EVT) { #if (BTA_AV_DEBUG == TRUE) APPL_TRACE_VERBOSE("AV sm event=0x%x(%s)", event, bta_av_evt_code(event)); APPL_TRACE_VERBOSE("AV sm event=0x%x(%s)", p_msg->event, bta_av_evt_code(p_msg->event)); #else APPL_TRACE_VERBOSE("AV sm event=0x%x", event); APPL_TRACE_VERBOSE("AV sm event=0x%x", p_msg->event); #endif /* state machine events */ bta_av_sm_execute(&bta_av_cb, p_msg->event, (tBTA_AV_DATA*) p_msg); Loading
system/btif/src/btif_rc.cc +77 −69 Original line number Diff line number Diff line Loading @@ -1388,6 +1388,65 @@ static uint8_t opcode_from_pdu(uint8_t pdu) { return opcode; } /*************************************************************************** * Function: fill_attribute_id_array * * - Argument: * cmd_attribute_number input attribute number from AVRCP command * cmd_attribute_id_array input attribute list from AVRCP command * out_array_size allocated size of out attribute id array * out_attribute_id_array output attribute list resolved here * * - Description: * Resolve attribute id array as defined by the AVRCP specification. * * - Returns: * The number of attributes filled in * ***************************************************************************/ static uint8_t fill_attribute_id_array( uint8_t cmd_attribute_number, btrc_media_attr_t* cmd_attribute_id_array, size_t out_array_size, btrc_media_attr_t* out_attribute_id_array) { /* Reset attribute array */ memset(out_attribute_id_array, 0, out_array_size); /* Default case for cmd_attribute_number == 0xFF, No attribute */ uint8_t out_attribute_number = 0; if (cmd_attribute_number == 0) { /* All attributes */ out_attribute_number = out_array_size < AVRC_MAX_NUM_MEDIA_ATTR_ID ? out_array_size : AVRC_MAX_NUM_MEDIA_ATTR_ID; for (int i = 0; i < out_attribute_number; i++) { out_attribute_id_array[i] = (btrc_media_attr_t) (i + 1); } } else if (cmd_attribute_number != 0xFF) { /* Attribute List */ out_attribute_number = 0; int filled_id_count = 0; for (int i = 0; (i < cmd_attribute_number) && (out_attribute_number < out_array_size) && (out_attribute_number < AVRC_MAX_NUM_MEDIA_ATTR_ID); i++) { /* Fill only valid entries */ if (AVRC_IS_VALID_MEDIA_ATTRIBUTE(cmd_attribute_id_array[i])) { /* Skip the duplicate entries */ for (filled_id_count = 0; filled_id_count < out_attribute_number; filled_id_count++) { if (out_attribute_id_array[filled_id_count] == cmd_attribute_id_array[i]) break; } /* New ID */ if (filled_id_count == out_attribute_number) { out_attribute_id_array[out_attribute_number] = (btrc_media_attr_t) cmd_attribute_id_array[i]; out_attribute_number++; } } } } return out_attribute_number; } /******************************************************************************* * * Function btif_rc_upstreams_evt Loading Loading @@ -1424,51 +1483,17 @@ static void btif_rc_upstreams_evt(uint16_t event, tAVRC_COMMAND* pavrc_cmd, } break; case AVRC_PDU_GET_ELEMENT_ATTR: { btrc_media_attr_t element_attrs[BTRC_MAX_ELEM_ATTR_SIZE]; uint8_t num_attr; memset(&element_attrs, 0, sizeof(element_attrs)); if (pavrc_cmd->get_elem_attrs.num_attr == 0) { /* CT requests for all attributes */ int attr_cnt; num_attr = BTRC_MAX_ELEM_ATTR_SIZE; for (attr_cnt = 0; attr_cnt < BTRC_MAX_ELEM_ATTR_SIZE; attr_cnt++) { element_attrs[attr_cnt] = (btrc_media_attr_t)(attr_cnt + 1); } } else if (pavrc_cmd->get_elem_attrs.num_attr == 0xFF) { /* 0xff indicates, no attributes requested - reject */ uint8_t num_attr = fill_attribute_id_array( pavrc_cmd->get_elem_attrs.num_attr, (btrc_media_attr_t*)pavrc_cmd->get_elem_attrs.attrs, BTRC_MAX_ELEM_ATTR_SIZE, element_attrs); if (num_attr == 0) { BTIF_TRACE_ERROR( "%s: No valid attributes requested in GET_ELEMENT_ATTRIBUTES", __func__); send_reject_response(p_dev->rc_handle, label, pavrc_cmd->pdu, AVRC_STS_BAD_PARAM, pavrc_cmd->cmd.opcode); return; } else { int attr_cnt, filled_attr_count; num_attr = 0; /* Attribute IDs from 1 to AVRC_MAX_NUM_MEDIA_ATTR_ID are only valid, * hence HAL definition limits the attributes to * AVRC_MAX_NUM_MEDIA_ATTR_ID. * Fill only valid entries. */ for (attr_cnt = 0; (attr_cnt < pavrc_cmd->get_elem_attrs.num_attr) && (num_attr < AVRC_MAX_NUM_MEDIA_ATTR_ID); attr_cnt++) { if ((pavrc_cmd->get_elem_attrs.attrs[attr_cnt] > 0) && (pavrc_cmd->get_elem_attrs.attrs[attr_cnt] <= AVRC_MAX_NUM_MEDIA_ATTR_ID)) { /* Skip the duplicate entries : PTS sends duplicate entries for * Fragment cases */ for (filled_attr_count = 0; filled_attr_count < num_attr; filled_attr_count++) { if (element_attrs[filled_attr_count] == pavrc_cmd->get_elem_attrs.attrs[attr_cnt]) break; } if (filled_attr_count == num_attr) { element_attrs[num_attr] = (btrc_media_attr_t)pavrc_cmd->get_elem_attrs.attrs[attr_cnt]; num_attr++; } } } } fill_pdu_queue(IDX_GET_ELEMENT_ATTR_RSP, ctype, label, true, p_dev); HAL_CBACK(bt_rc_callbacks, get_element_attr_cb, num_attr, element_attrs, Loading Loading @@ -1595,41 +1620,24 @@ static void btif_rc_upstreams_evt(uint16_t event, tAVRC_COMMAND* pavrc_cmd, case AVRC_PDU_GET_ITEM_ATTRIBUTES: { btrc_media_attr_t item_attrs[BTRC_MAX_ELEM_ATTR_SIZE]; uint8_t num_attr; uint8_t scope; uint16_t uid_counter; scope = pavrc_cmd->get_attrs.scope; uid_counter = pavrc_cmd->get_attrs.uid_counter; memset(&item_attrs, 0, sizeof(item_attrs)); if (pavrc_cmd->get_attrs.attr_count == 0xFF) { uint8_t num_attr = fill_attribute_id_array( pavrc_cmd->get_elem_attrs.num_attr, (btrc_media_attr_t*)pavrc_cmd->get_elem_attrs.attrs, BTRC_MAX_ELEM_ATTR_SIZE, item_attrs); if (num_attr == 0) { BTIF_TRACE_ERROR( "%s: No attributes are requested in GET_ITEM_ATTRIBUTES", __func__); /* 0xff indicates, no attributes requested - reject this */ "%s: No valid attributes requested in GET_ITEM_ATTRIBUTES", __func__); send_reject_response(p_dev->rc_handle, label, pavrc_cmd->pdu, AVRC_STS_BAD_PARAM, pavrc_cmd->cmd.opcode); return; } if (pavrc_cmd->get_attrs.attr_count == 0) { /* CT requests for all attributes */ int attr_cnt; num_attr = BTRC_MAX_ELEM_ATTR_SIZE; for (attr_cnt = 0; attr_cnt < BTRC_MAX_ELEM_ATTR_SIZE; attr_cnt++) { item_attrs[attr_cnt] = (btrc_media_attr_t)(attr_cnt + 1); } } else { num_attr = pavrc_cmd->get_attrs.attr_count; memcpy(item_attrs, pavrc_cmd->get_attrs.p_attr_list, sizeof(uint32_t) * pavrc_cmd->get_attrs.attr_count); } fill_pdu_queue(IDX_GET_ITEM_ATTR_RSP, ctype, label, true, p_dev); BTIF_TRACE_DEBUG("%s: GET_ITEM_ATTRIBUTES: num_attr: %d", __func__, num_attr); HAL_CBACK(bt_rc_callbacks, get_item_attr_cb, scope, pavrc_cmd->get_attrs.uid, uid_counter, num_attr, item_attrs, &rc_addr); HAL_CBACK(bt_rc_callbacks, get_item_attr_cb, pavrc_cmd->get_attrs.scope, pavrc_cmd->get_attrs.uid, pavrc_cmd->get_attrs.uid_counter, num_attr, item_attrs, &rc_addr); } break; case AVRC_PDU_GET_TOTAL_NUM_OF_ITEMS: { Loading
system/stack/avrc/avrc_bld_tg.cc +168 −87 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ * limitations under the License. * ******************************************************************************/ #include <assert.h> #include <string.h> #include "bt_common.h" Loading Loading @@ -445,6 +446,111 @@ static tAVRC_STS avrc_bld_inform_battery_status_rsp (UNUSED_ATTR tAVRC_RSP *p_rs return AVRC_STS_NO_ERROR; } static void avrc_build_attribute_entries(int num_attrs, tAVRC_ATTR_ENTRY* p_attrs, int remaining_buffer_capacity, uint8_t** pp_data, uint8_t* p_attribute_count) { AVRC_TRACE_DEBUG("%s num_attrs: %d, remaining_buffer_capacity: %d", __func__, num_attrs, remaining_buffer_capacity); uint8_t* p_data = *pp_data; /* Fill in the Attribute ID, Character Set, Length and Values */ for (int index = 0; index < num_attrs; index++) { AVRC_TRACE_DEBUG("%s attr id[%d]: %d", __func__, index, p_attrs[index].attr_id); assert(AVRC_IS_VALID_MEDIA_ATTRIBUTE(p_attrs[index].attr_id)); if (!p_attrs[index].name.p_str) { p_attrs[index].name.str_len = 0; } /* 8 is the size of attr_id, char set and str_len */ remaining_buffer_capacity -= 8; if (remaining_buffer_capacity < 0) { AVRC_TRACE_WARNING( "%s not enough buffer space for attr_id[%d]: %d," " skipping %d attributes", __func__, index, p_attrs[index].attr_id, num_attrs - index); break; } if (remaining_buffer_capacity < p_attrs[index].name.str_len) { AVRC_TRACE_WARNING("%s not enough buffer space for attr_id[%d]: %d," " truncating attribute", __func__, index, p_attrs[index].attr_id); p_attrs[index].name.str_len = remaining_buffer_capacity; remaining_buffer_capacity = 0; } remaining_buffer_capacity -= p_attrs[index].name.str_len; UINT32_TO_BE_STREAM(p_data, p_attrs[index].attr_id); UINT16_TO_BE_STREAM(p_data, p_attrs[index].name.charset_id); UINT16_TO_BE_STREAM(p_data, p_attrs[index].name.str_len); ARRAY_TO_BE_STREAM(p_data, p_attrs[index].name.p_str, p_attrs[index].name.str_len); (*p_attribute_count)++; } *pp_data = p_data; AVRC_TRACE_DEBUG("%s filled attributes, remaining_buffer_capacity: %d", __func__, num_attrs, remaining_buffer_capacity); } /******************************************************************************* ** ** 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_ATTRS_RSP *p_rsp, BT_HDR *p_pkt) { AVRC_TRACE_API("%s", __func__); if (!p_rsp->p_attrs) { AVRC_TRACE_ERROR("%s NULL p_attrs", __func__); return AVRC_STS_BAD_PARAM; } /* Figure out how much we have left in current buffer */ int remaining_buffer_capacity = BT_DEFAULT_BUFFER_SIZE - BT_HDR_SIZE - p_pkt->offset; if (remaining_buffer_capacity < 5) { AVRC_TRACE_ERROR("%s not enough buffer for packet header", remaining_buffer_capacity); return AVRC_STS_INTERNAL_ERR; } /* Get to the beginning of PDU */ uint8_t *p_pdu_start = (uint8_t *)(p_pkt + 1) + p_pkt->offset; /* Skip PDU ID and Reserved byte to get pointer to Parameter Length */ uint8_t *p_data, *p_parameter_len; p_data = p_parameter_len = p_pdu_start + 2; /* Parse parameter length */ uint16_t parameter_len; BE_STREAM_TO_UINT16(parameter_len, p_data); /* Get pointer to Attribute Count */ uint8_t *p_attribute_count = p_data; /* Initialize field values when Parameter Length is 0 */ if (parameter_len == 0) { *p_attribute_count = 0; p_data++; } else { // TODO: Why do we need this case? p_data = p_pdu_start + p_pkt->len; } remaining_buffer_capacity -= p_data - p_pdu_start;; if (remaining_buffer_capacity < 0) { AVRC_TRACE_ERROR("%s not enough buffer capacity for response"); return AVRC_STS_BAD_PARAM; } /* Fill in the Attribute ID, Character Set, Length and Values */ avrc_build_attribute_entries(p_rsp->num_attrs, p_rsp->p_attrs, remaining_buffer_capacity, &p_data, p_attribute_count); parameter_len = p_data - p_attribute_count; UINT16_TO_BE_STREAM(p_parameter_len, parameter_len); p_pkt->len = (p_data - p_pdu_start); return AVRC_STS_NO_ERROR; } /******************************************************************************* ** ** Function avrc_bld_get_play_status_rsp Loading Loading @@ -1093,10 +1199,9 @@ static tAVRC_STS avrc_bld_change_path_rsp (tAVRC_CHG_PATH_RSP *p_rsp, BT_HDR *p_ /******************************************************************************* ** ** Function avrc_bld_get_attrs_rsp ** Function avrc_bld_get_item_attrs_rsp ** ** Description This function builds the Get Item Attributes or ** Get Element Attributes response, ** Description This function builds the GetItemAttributes response, ** ** The Get Item Attributes message goes through the ** Browsing channel (already specified in the |p_pkt|) Loading @@ -1106,93 +1211,66 @@ static tAVRC_STS avrc_bld_change_path_rsp (tAVRC_CHG_PATH_RSP *p_rsp, BT_HDR *p_ ** Otherwise, the error code. ** *******************************************************************************/ static tAVRC_STS avrc_bld_get_attrs_rsp (tAVRC_GET_ATTRS_RSP *p_rsp, BT_HDR *p_pkt) { uint8_t *p_data, *p_start; uint8_t *p_len; uint16_t len_left; uint8_t *p_num; uint16_t mtu; static tAVRC_STS avrc_bld_get_item_attrs_rsp (tAVRC_GET_ATTRS_RSP *p_rsp, BT_HDR *p_pkt) { AVRC_TRACE_API("%s", __func__); /* calculate the buffer size needed and validate the parameters */ if (!p_rsp || !p_rsp->p_attrs) { AVRC_TRACE_ERROR("NULL p_attrs"); return AVRC_STS_BAD_PARAM; } /* check the length before adding the attr to the message */ uint16_t len = 2; for (uint8_t xx = 0; xx < p_rsp->num_attrs; xx++) { if(p_rsp->p_attrs[xx].name.p_str == 0 || !AVRC_IS_VALID_MEDIA_ATTRIBUTE(p_rsp->p_attrs[xx].attr_id)) { AVRC_TRACE_ERROR("[%d] NULL p_attrs str or bad attr_id:%d", xx, p_rsp->p_attrs[xx].attr_id); if (!p_rsp->p_attrs) { AVRC_TRACE_ERROR("%s NULL p_attrs", __func__); return AVRC_STS_BAD_PARAM; } len += (p_rsp->p_attrs[xx].name.str_len + 8); } len_left = BT_DEFAULT_BUFFER_SIZE - BT_HDR_SIZE; p_data = (uint8_t *)(p_pkt + 1); /* Figure out how much we have left in current buffer */ int remaining_buffer_capacity = BT_DEFAULT_BUFFER_SIZE - BT_HDR_SIZE - p_pkt->offset; /* Get to the beginning of data section in buffer */ uint8_t *p_data = (uint8_t *)(p_pkt + 1); /* Get the MTU size that is filled in earlier */ uint16_t mtu; BE_STREAM_TO_UINT16(mtu, p_data); if (len_left > mtu) { len_left = mtu; } len_left = len_left - p_pkt->offset - p_pkt->len; AVRC_TRACE_DEBUG("len_left:%d, mtu:%d len needed:%d", len_left, mtu, len); if (len_left < 11) /* 11 is 4/attr_id + 2/charset_id + 2/str_len + 3/1st timer/attr cnt & len */ { if (remaining_buffer_capacity > mtu) { remaining_buffer_capacity = mtu; } AVRC_TRACE_DEBUG("%s remaining_buffer_capacity:%d, mtu:%d", remaining_buffer_capacity, mtu); if (remaining_buffer_capacity < 5) { AVRC_TRACE_ERROR("%s not enough buffer for packet header", remaining_buffer_capacity); return AVRC_STS_INTERNAL_ERR; } if (len > len_left) { AVRC_TRACE_ERROR("The buffer does not have enough room to hold the given data."); } /* get the existing length, if any, and also the num attributes */ p_start = (uint8_t *)(p_pkt + 1) + p_pkt->offset; p_data = p_len = p_start + 1; /* pdu */ /* the existing len */ BE_STREAM_TO_UINT16(len, p_data); p_num = p_data + 1; if (len == 0) { /* first time initialize the attribute count */ UINT8_TO_BE_STREAM(p_data, p_rsp->status); *p_num = 0; p_data++; len = 2; len_left -= 3; } else { p_data = p_start + p_pkt->len; } for (uint8_t xx = 0; (xx < p_rsp->num_attrs) && (len_left > 9); xx++) { (*p_num)++; 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); len_left -= 8; if (p_rsp->p_attrs[xx].name.str_len > len_left) p_rsp->p_attrs[xx].name.str_len = len_left; ARRAY_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].name.p_str, p_rsp->p_attrs[xx].name.str_len); len_left -= p_rsp->p_attrs[xx].name.str_len; len += (p_rsp->p_attrs[xx].name.str_len + 8); /* Get to the beginning of PDU */ uint8_t *p_pdu_start = (uint8_t *)(p_pkt + 1) + p_pkt->offset; /* Skip PDU ID to get pointer to Parameter length */ uint8_t *p_parameter_len; p_data = p_parameter_len = p_pdu_start + 1; /* Parse existing parameter length */ uint16_t parameter_len; BE_STREAM_TO_UINT16(parameter_len, p_data); /* Skip one byte to Number of Attributes */ uint8_t *p_status = p_data++; uint8_t *p_attribute_count = p_data++; if (parameter_len == 0) { /* First time, initialize the status byte */ *p_status = p_rsp->status; if (p_rsp->status != AVRC_STS_NO_ERROR) { // TODO(siyuanh): This is a hack parameter_len = 1; UINT16_TO_BE_STREAM(p_parameter_len, parameter_len); p_pkt->len = p_status - p_pdu_start; return AVRC_STS_NO_ERROR; } UINT16_TO_BE_STREAM(p_len, len); p_pkt->len = (p_data - p_start); *p_attribute_count = 0; } else { // TODO(siyuanh): Why do wee need this case? p_data = p_pdu_start + p_pkt->len; } remaining_buffer_capacity -= p_data - p_pdu_start; /* Fill in the Attribute ID, Character Set, Length and Values */ avrc_build_attribute_entries(p_rsp->num_attrs, p_rsp->p_attrs, remaining_buffer_capacity, &p_data, p_attribute_count); parameter_len = p_data - p_status; UINT16_TO_BE_STREAM(p_parameter_len, parameter_len); p_pkt->len = p_data - p_pdu_start; return AVRC_STS_NO_ERROR; } Loading Loading @@ -1469,8 +1547,7 @@ tAVRC_STS AVRC_BldResponse( uint8_t handle, tAVRC_RESPONSE *p_rsp, BT_HDR **pp_p break; case AVRC_PDU_GET_ELEMENT_ATTR: case AVRC_PDU_GET_ITEM_ATTRIBUTES: status = avrc_bld_get_attrs_rsp(&p_rsp->get_attrs, p_pkt); status = avrc_bld_get_elem_attrs_rsp(&p_rsp->get_attrs, p_pkt); break; case AVRC_PDU_GET_PLAY_STATUS: Loading Loading @@ -1517,11 +1594,15 @@ tAVRC_STS AVRC_BldResponse( uint8_t handle, tAVRC_RESPONSE *p_rsp, BT_HDR **pp_p 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_NUM_OF_ITEMS: status = avrc_bld_get_num_of_item_rsp(&p_rsp->get_num_of_items, p_pkt); break; case AVRC_PDU_SEARCH: /* 0x80 */ case AVRC_PDU_SEARCH: status = avrc_bld_search_rsp(&p_rsp->search, p_pkt); break; } Loading