diff --git a/components/bt/host/bluedroid/bta/ar/bta_ar.c b/components/bt/host/bluedroid/bta/ar/bta_ar.c index f1b270036cc..d96f9606cc6 100644 --- a/components/bt/host/bluedroid/bta/ar/bta_ar.c +++ b/components/bt/host/bluedroid/bta/ar/bta_ar.c @@ -246,8 +246,12 @@ void bta_ar_reg_avrc(UINT16 service_uuid, char *service_name, char *provider_nam if (service_uuid == UUID_SERVCLASS_AV_REM_CTRL_TARGET) { if (bta_ar_cb.sdp_tg_handle == 0) { + UINT32 sdp_handle = SDP_CreateRecord(); + if (sdp_handle == 0) { + return; + } bta_ar_cb.tg_registered = mask; - bta_ar_cb.sdp_tg_handle = SDP_CreateRecord(); + bta_ar_cb.sdp_tg_handle = sdp_handle; AVRC_AddRecord(service_uuid, service_name, provider_name, categories, bta_ar_cb.sdp_tg_handle, browsing_en); bta_sys_add_uuid(service_uuid); } @@ -257,7 +261,12 @@ void bta_ar_reg_avrc(UINT16 service_uuid, char *service_name, char *provider_nam bta_ar_cb.ct_categories [mask - 1] = categories; categories = bta_ar_cb.ct_categories[0] | bta_ar_cb.ct_categories[1]; if (bta_ar_cb.sdp_ct_handle == 0) { - bta_ar_cb.sdp_ct_handle = SDP_CreateRecord(); + UINT32 sdp_handle = SDP_CreateRecord(); + if (sdp_handle == 0) { + bta_ar_cb.ct_categories[mask - 1] = 0; + return; + } + bta_ar_cb.sdp_ct_handle = sdp_handle; AVRC_AddRecord(service_uuid, service_name, provider_name, categories, bta_ar_cb.sdp_ct_handle, browsing_en); bta_sys_add_uuid(service_uuid); } else { diff --git a/components/bt/host/bluedroid/btc/profile/std/avrc/btc_avrc.c b/components/bt/host/bluedroid/btc/profile/std/avrc/btc_avrc.c index df5f63e1146..0f5e229885e 100644 --- a/components/bt/host/bluedroid/btc/profile/std/avrc/btc_avrc.c +++ b/components/bt/host/bluedroid/btc/profile/std/avrc/btc_avrc.c @@ -487,11 +487,15 @@ static void handle_rc_connect (tBTA_AV_RC_OPEN *p_rc_open) if (btc_rc_cb.rc_connected) { BTC_TRACE_ERROR("Got RC OPEN in connected state, Connected RC: %d \ and Current RC: %d", btc_rc_cb.rc_handle, p_rc_open->rc_handle ); - if ((btc_rc_cb.rc_handle != p_rc_open->rc_handle) - && (bdcmp(btc_rc_cb.rc_addr, p_rc_open->peer_addr))) { - BTC_TRACE_DEBUG("Got RC connected for some other handle"); - BTA_AvCloseRc(p_rc_open->rc_handle); - return; + if (btc_rc_cb.rc_handle != p_rc_open->rc_handle) { + if (bdcmp(btc_rc_cb.rc_addr, p_rc_open->peer_addr) == 0) { + /* same device reconnected with new handle - close stale one */ + BTA_AvCloseRc(btc_rc_cb.rc_handle); + } else { + BTC_TRACE_DEBUG("Got RC connected for some other handle"); + BTA_AvCloseRc(p_rc_open->rc_handle); + return; + } } } memcpy(btc_rc_cb.rc_addr, p_rc_open->peer_addr, sizeof(BD_ADDR)); @@ -526,7 +530,11 @@ static void handle_rc_connect (tBTA_AV_RC_OPEN *p_rc_open) } else { BTC_TRACE_ERROR("%s Connect failed with error code: %d", __FUNCTION__, p_rc_open->status); - btc_rc_cb.rc_connected = FALSE; + /* only clear state if the failure belongs to the active connection */ + if (p_rc_open->rc_handle == btc_rc_cb.rc_handle || + bdcmp(btc_rc_cb.rc_addr, p_rc_open->peer_addr) == 0) { + btc_rc_cb.rc_connected = FALSE; + } } } @@ -541,9 +549,18 @@ static void handle_rc_connect (tBTA_AV_RC_OPEN *p_rc_open) static void handle_rc_disconnect (tBTA_AV_RC_CLOSE *p_rc_close) { BTC_TRACE_DEBUG("%s: rc_handle: %d", __FUNCTION__, p_rc_close->rc_handle); - if ((p_rc_close->rc_handle != btc_rc_cb.rc_handle) - && (bdcmp(btc_rc_cb.rc_addr, p_rc_close->peer_addr))) { - BTC_TRACE_ERROR("Got disconnect of unknown device"); + if (!btc_rc_cb.rc_connected) { + BTC_TRACE_WARNING("Got disconnect when not connected"); + return; + } + if (p_rc_close->rc_handle != btc_rc_cb.rc_handle) { + if (bdcmp(btc_rc_cb.rc_addr, p_rc_close->peer_addr) != 0) { + BTC_TRACE_ERROR("Got disconnect of unknown device"); + return; + } + /* ignore disconnect for superseded handle on same device */ + BTC_TRACE_DEBUG("Ignoring disconnect for stale rc_handle %d (current %d)", + p_rc_close->rc_handle, btc_rc_cb.rc_handle); return; } @@ -640,6 +657,12 @@ static void handle_rc_attributes_rsp (tAVRC_MSG_VENDOR *vendor_msg) ((uint32_t)vendor_msg->p_vendor_data[1 + attr_index] << 16) | ((uint32_t)vendor_msg->p_vendor_data[attr_index] << 24); + if (!AVRC_IS_VALID_MEDIA_ATTRIBUTE(attr_id)) { + BTC_TRACE_WARNING("invalid attr_id 0x%x, skip", attr_id); + attr_index += attr_length + 8; + continue; + } + //Convert to mask id param[i].meta_rsp.attr_id = (1 << (attr_id - 1)); @@ -1153,6 +1176,11 @@ void btc_rc_handler(tBTA_AV_EVT event, tBTA_AV *p_data) ***************************************************************************/ BOOLEAN btc_rc_get_connected_peer(BD_ADDR peer_addr) { +#if AVRC_DYNAMIC_MEMORY == TRUE + if (btc_rc_cb_ptr == NULL) { + return FALSE; + } +#endif if (btc_rc_cb.rc_connected == TRUE) { bdcpy(peer_addr, btc_rc_cb.rc_addr); return TRUE; @@ -1257,7 +1285,7 @@ static void btc_avrc_ct_deinit(void) static bt_status_t btc_avrc_ct_send_set_player_value_cmd(uint8_t tl, uint8_t attr_id, uint8_t value_id) { - tAVRC_STS status = BT_STATUS_UNSUPPORTED; + bt_status_t ret = BT_STATUS_UNSUPPORTED; #if (AVRC_METADATA_INCLUDED == TRUE) CHECK_ESP_RC_CONNECTED; @@ -1265,6 +1293,7 @@ static bt_status_t btc_avrc_ct_send_set_player_value_cmd(uint8_t tl, uint8_t att tAVRC_COMMAND avrc_cmd = {0}; BT_HDR *p_msg = NULL; tAVRC_APP_SETTING values = {0}; + tAVRC_STS cmd_status; values.attr_id = attr_id; values.attr_val = value_id; @@ -1276,13 +1305,15 @@ static bt_status_t btc_avrc_ct_send_set_player_value_cmd(uint8_t tl, uint8_t att avrc_cmd.set_app_val.pdu = AVRC_PDU_SET_PLAYER_APP_VALUE; if (btc_rc_cb.rc_features & BTA_AV_FEAT_METADATA) { - status = AVRC_BldCommand(&avrc_cmd, &p_msg); - if (status == AVRC_STS_NO_ERROR) { + cmd_status = AVRC_BldCommand(&avrc_cmd, &p_msg); + if (cmd_status == AVRC_STS_NO_ERROR) { BTA_AvMetaCmd(btc_rc_cb.rc_handle, tl, BTA_AV_CMD_CTRL, p_msg); - status = BT_STATUS_SUCCESS; + ret = BT_STATUS_SUCCESS; + } else { + ret = BT_STATUS_FAIL; } } else { - status = BT_STATUS_FAIL; + ret = BT_STATUS_FAIL; BTC_TRACE_DEBUG("%s: feature not supported", __FUNCTION__); } @@ -1290,18 +1321,19 @@ static bt_status_t btc_avrc_ct_send_set_player_value_cmd(uint8_t tl, uint8_t att BTC_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__); #endif - return status; + return ret; } static bt_status_t btc_avrc_ct_send_get_rn_caps_cmd(uint8_t tl) { - tAVRC_STS status = BT_STATUS_UNSUPPORTED; + bt_status_t ret = BT_STATUS_UNSUPPORTED; #if (AVRC_METADATA_INCLUDED == TRUE) CHECK_ESP_RC_CONNECTED; tAVRC_COMMAND avrc_cmd = {0}; BT_HDR *p_msg = NULL; + tAVRC_STS cmd_status; avrc_cmd.get_caps.opcode = AVRC_OP_VENDOR; avrc_cmd.get_caps.status = AVRC_STS_NO_ERROR; @@ -1309,13 +1341,15 @@ static bt_status_t btc_avrc_ct_send_get_rn_caps_cmd(uint8_t tl) avrc_cmd.get_caps.capability_id = AVRC_CAP_EVENTS_SUPPORTED; if (btc_rc_cb.rc_features & BTA_AV_FEAT_METADATA) { - status = AVRC_BldCommand(&avrc_cmd, &p_msg); - if (status == AVRC_STS_NO_ERROR) { + cmd_status = AVRC_BldCommand(&avrc_cmd, &p_msg); + if (cmd_status == AVRC_STS_NO_ERROR) { BTA_AvMetaCmd(btc_rc_cb.rc_handle, tl, AVRC_CMD_STATUS, p_msg); - status = BT_STATUS_SUCCESS; + ret = BT_STATUS_SUCCESS; + } else { + ret = BT_STATUS_FAIL; } } else { - status = BT_STATUS_FAIL; + ret = BT_STATUS_FAIL; BTC_TRACE_DEBUG("%s: feature not supported", __FUNCTION__); } @@ -1323,18 +1357,19 @@ static bt_status_t btc_avrc_ct_send_get_rn_caps_cmd(uint8_t tl) BTC_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__); #endif - return status; + return ret; } static bt_status_t btc_avrc_ct_send_register_notification_cmd(uint8_t tl, uint8_t event_id, uint32_t event_parameter) { - tAVRC_STS status = BT_STATUS_UNSUPPORTED; + bt_status_t ret = BT_STATUS_UNSUPPORTED; #if (AVRC_METADATA_INCLUDED == TRUE) CHECK_ESP_RC_CONNECTED; tAVRC_COMMAND avrc_cmd = {0}; BT_HDR *p_msg = NULL; + tAVRC_STS cmd_status; avrc_cmd.reg_notif.opcode = AVRC_OP_VENDOR; avrc_cmd.reg_notif.status = AVRC_STS_NO_ERROR; @@ -1343,13 +1378,15 @@ static bt_status_t btc_avrc_ct_send_register_notification_cmd(uint8_t tl, uint8_ avrc_cmd.reg_notif.pdu = AVRC_PDU_REGISTER_NOTIFICATION; if (btc_rc_cb.rc_features & BTA_AV_FEAT_METADATA) { - status = AVRC_BldCommand(&avrc_cmd, &p_msg); - if (status == AVRC_STS_NO_ERROR) { + cmd_status = AVRC_BldCommand(&avrc_cmd, &p_msg); + if (cmd_status == AVRC_STS_NO_ERROR) { BTA_AvMetaCmd(btc_rc_cb.rc_handle, tl, AVRC_CMD_NOTIF, p_msg); - status = BT_STATUS_SUCCESS; + ret = BT_STATUS_SUCCESS; + } else { + ret = BT_STATUS_FAIL; } } else { - status = BT_STATUS_FAIL; + ret = BT_STATUS_FAIL; BTC_TRACE_DEBUG("%s: feature not supported", __FUNCTION__); } @@ -1357,18 +1394,19 @@ static bt_status_t btc_avrc_ct_send_register_notification_cmd(uint8_t tl, uint8_ BTC_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__); #endif - return status; + return ret; } static bt_status_t btc_avrc_ct_send_set_absolute_volume_cmd(uint8_t tl, uint8_t volume) { - tAVRC_STS status = BT_STATUS_UNSUPPORTED; + bt_status_t ret = BT_STATUS_UNSUPPORTED; #if (AVRC_METADATA_INCLUDED == TRUE) CHECK_ESP_RC_CONNECTED; tAVRC_COMMAND avrc_cmd = {0}; BT_HDR *p_msg = NULL; + tAVRC_STS cmd_status; avrc_cmd.volume.opcode = AVRC_OP_VENDOR; avrc_cmd.volume.status = AVRC_STS_NO_ERROR; @@ -1376,13 +1414,15 @@ static bt_status_t btc_avrc_ct_send_set_absolute_volume_cmd(uint8_t tl, uint8_t avrc_cmd.volume.pdu = AVRC_PDU_SET_ABSOLUTE_VOLUME; if (btc_rc_cb.rc_features & BTA_AV_FEAT_METADATA) { - status = AVRC_BldCommand(&avrc_cmd, &p_msg); - if (status == AVRC_STS_NO_ERROR) { + cmd_status = AVRC_BldCommand(&avrc_cmd, &p_msg); + if (cmd_status == AVRC_STS_NO_ERROR) { BTA_AvMetaCmd(btc_rc_cb.rc_handle, tl, AVRC_CMD_CTRL, p_msg); - status = BT_STATUS_SUCCESS; + ret = BT_STATUS_SUCCESS; + } else { + ret = BT_STATUS_FAIL; } } else { - status = BT_STATUS_FAIL; + ret = BT_STATUS_FAIL; BTC_TRACE_DEBUG("%s: feature not supported", __FUNCTION__); } @@ -1390,12 +1430,12 @@ static bt_status_t btc_avrc_ct_send_set_absolute_volume_cmd(uint8_t tl, uint8_t BTC_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__); #endif - return status; + return ret; } static bt_status_t btc_avrc_ct_send_metadata_cmd (uint8_t tl, uint8_t attr_mask) { - tAVRC_STS status = BT_STATUS_UNSUPPORTED; + bt_status_t ret = BT_STATUS_UNSUPPORTED; #if (AVRC_METADATA_INCLUDED == TRUE) CHECK_ESP_RC_CONNECTED; @@ -1403,6 +1443,7 @@ static bt_status_t btc_avrc_ct_send_metadata_cmd (uint8_t tl, uint8_t attr_mask) tAVRC_COMMAND avrc_cmd = {0}; BT_HDR *p_msg = NULL; + tAVRC_STS cmd_status; avrc_cmd.get_elem_attrs.opcode = AVRC_OP_VENDOR; avrc_cmd.get_elem_attrs.status = AVRC_STS_NO_ERROR; @@ -1418,13 +1459,15 @@ static bt_status_t btc_avrc_ct_send_metadata_cmd (uint8_t tl, uint8_t attr_mask) avrc_cmd.get_elem_attrs.num_attr = index; if (btc_rc_cb.rc_features & BTA_AV_FEAT_METADATA) { - status = AVRC_BldCommand(&avrc_cmd, &p_msg); - if (status == AVRC_STS_NO_ERROR) { + cmd_status = AVRC_BldCommand(&avrc_cmd, &p_msg); + if (cmd_status == AVRC_STS_NO_ERROR) { BTA_AvMetaCmd(btc_rc_cb.rc_handle, tl, AVRC_CMD_STATUS, p_msg); - status = BT_STATUS_SUCCESS; + ret = BT_STATUS_SUCCESS; + } else { + ret = BT_STATUS_FAIL; } } else { - status = BT_STATUS_FAIL; + ret = BT_STATUS_FAIL; BTC_TRACE_DEBUG("%s: feature not supported", __FUNCTION__); } @@ -1432,31 +1475,34 @@ static bt_status_t btc_avrc_ct_send_metadata_cmd (uint8_t tl, uint8_t attr_mask) BTC_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__); #endif - return status; + return ret; } static bt_status_t btc_avrc_ct_send_get_play_status_cmd(uint8_t tl) { - tAVRC_STS status = BT_STATUS_UNSUPPORTED; + bt_status_t ret = BT_STATUS_UNSUPPORTED; #if (AVRC_METADATA_INCLUDED == TRUE) CHECK_ESP_RC_CONNECTED; tAVRC_COMMAND avrc_cmd = {0}; BT_HDR *p_msg = NULL; + tAVRC_STS cmd_status; avrc_cmd.get_play_status.opcode = AVRC_OP_VENDOR; avrc_cmd.get_play_status.status = AVRC_STS_NO_ERROR; avrc_cmd.get_play_status.pdu = AVRC_PDU_GET_PLAY_STATUS; if (btc_rc_cb.rc_features & BTA_AV_FEAT_METADATA) { - status = AVRC_BldCommand(&avrc_cmd, &p_msg); - if (status == AVRC_STS_NO_ERROR) { + cmd_status = AVRC_BldCommand(&avrc_cmd, &p_msg); + if (cmd_status == AVRC_STS_NO_ERROR) { BTA_AvMetaCmd(btc_rc_cb.rc_handle, tl, AVRC_CMD_STATUS, p_msg); - status = BT_STATUS_SUCCESS; + ret = BT_STATUS_SUCCESS; + } else { + ret = BT_STATUS_FAIL; } } else { - status = BT_STATUS_FAIL; + ret = BT_STATUS_FAIL; BTC_TRACE_DEBUG("%s: feature not supported", __FUNCTION__); } @@ -1464,7 +1510,7 @@ static bt_status_t btc_avrc_ct_send_get_play_status_cmd(uint8_t tl) BTC_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__); #endif - return status; + return ret; } static bt_status_t btc_avrc_ct_send_passthrough_cmd(uint8_t tl, uint8_t key_code, uint8_t key_state) @@ -1758,6 +1804,8 @@ void btc_avrc_ct_call_handler(btc_msg_t *msg) default: BTC_TRACE_WARNING("%s : unhandled event: %d\n", __FUNCTION__, msg->act); } + + btc_avrc_arg_deep_free(msg); } void btc_avrc_tg_call_handler(btc_msg_t *msg) diff --git a/components/bt/host/bluedroid/stack/avct/avct_api.c b/components/bt/host/bluedroid/stack/avct/avct_api.c index 09ce64e8184..72cba350e41 100644 --- a/components/bt/host/bluedroid/stack/avct/avct_api.c +++ b/components/bt/host/bluedroid/stack/avct/avct_api.c @@ -118,6 +118,9 @@ void AVCT_Deregister(void) /* deregister PSM with L2CAP */ L2CA_Deregister(AVCT_PSM); +#if (AVCT_BROWSE_INCLUDED == TRUE) + L2CA_Deregister(AVCT_BR_PSM); +#endif } /******************************************************************************* @@ -173,9 +176,14 @@ UINT16 AVCT_CreateConn(UINT8 *p_handle, tAVCT_CC *p_cc, BD_ADDR peer_addr) if (result == AVCT_SUCCESS) { /* bind lcb to ccb */ + tAVCT_LCB_EVT evt; p_ccb->p_lcb = p_lcb; AVCT_TRACE_DEBUG("ch_state: %d", p_lcb->ch_state); - avct_lcb_event(p_lcb, AVCT_LCB_UL_BIND_EVT, (tAVCT_LCB_EVT *) &p_ccb); + evt.p_ccb = p_ccb; + avct_lcb_event(p_lcb, AVCT_LCB_UL_BIND_EVT, &evt); + if (!p_ccb->allocated) { + result = AVCT_NOT_OPEN; + } } } } @@ -212,7 +220,9 @@ UINT16 AVCT_RemoveConn(UINT8 handle) } /* send unbind event to lcb */ else { - avct_lcb_event(p_ccb->p_lcb, AVCT_LCB_UL_UNBIND_EVT, (tAVCT_LCB_EVT *) &p_ccb); + tAVCT_LCB_EVT evt; + evt.p_ccb = p_ccb; + avct_lcb_event(p_ccb->p_lcb, AVCT_LCB_UL_UNBIND_EVT, &evt); } return result; } diff --git a/components/bt/host/bluedroid/stack/avct/avct_l2c.c b/components/bt/host/bluedroid/stack/avct/avct_l2c.c index d6896e18095..f67c745f203 100644 --- a/components/bt/host/bluedroid/stack/avct/avct_l2c.c +++ b/components/bt/host/bluedroid/stack/avct/avct_l2c.c @@ -234,6 +234,9 @@ void avct_l2c_config_cfm_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg) if ((p_lcb = avct_lcb_by_lcid(lcid)) != NULL) { AVCT_TRACE_DEBUG("avct_l2c_config_cfm_cback: 0x%x, ch_state: %d, res: %d", lcid, p_lcb->ch_state, p_cfg->result); + if (p_lcb->conflict_lcid == lcid) { + return; + } /* if in correct state */ if (p_lcb->ch_state == AVCT_CH_CFG) { /* if result successful */ @@ -294,6 +297,10 @@ void avct_l2c_config_ind_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg) p_cfg->result = L2CAP_CFG_OK; L2CA_ConfigRsp(lcid, p_cfg); + if (p_lcb->conflict_lcid == lcid) { + return; + } + /* if first config ind */ if ((p_lcb->ch_flags & AVCT_L2C_CFG_IND_DONE) == 0) { /* update flags */ @@ -322,7 +329,7 @@ void avct_l2c_config_ind_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg) void avct_l2c_disconnect_ind_cback(UINT16 lcid, BOOLEAN ack_needed) { tAVCT_LCB *p_lcb; - UINT16 result = AVCT_RESULT_FAIL; + tAVCT_LCB_EVT evt; /* look up lcb for this channel */ if ((p_lcb = avct_lcb_by_lcid(lcid)) != NULL) { @@ -332,7 +339,13 @@ void avct_l2c_disconnect_ind_cback(UINT16 lcid, BOOLEAN ack_needed) L2CA_DisconnectRsp(lcid); } - avct_lcb_event(p_lcb, AVCT_LCB_LL_CLOSE_EVT, (tAVCT_LCB_EVT *) &result); + if (p_lcb->conflict_lcid == lcid) { + p_lcb->conflict_lcid = 0; + return; + } + + evt.result = AVCT_RESULT_FAIL; + avct_lcb_event(p_lcb, AVCT_LCB_LL_CLOSE_EVT, &evt); AVCT_TRACE_DEBUG("ch_state di: %d ", p_lcb->ch_state); } } @@ -356,6 +369,10 @@ void avct_l2c_disconnect_cfm_cback(UINT16 lcid, UINT16 result) if ((p_lcb = avct_lcb_by_lcid(lcid)) != NULL) { AVCT_TRACE_DEBUG("avct_l2c_disconnect_cfm_cback: 0x%x, ch_state: %d, res: %d", lcid, p_lcb->ch_state, result); + if (p_lcb->conflict_lcid == lcid) { + p_lcb->conflict_lcid = 0; + return; + } /* result value may be previously stored */ res = (p_lcb->ch_result != 0) ? p_lcb->ch_result : result; p_lcb->ch_result = 0; diff --git a/components/bt/host/bluedroid/stack/avct/avct_lcb.c b/components/bt/host/bluedroid/stack/avct/avct_lcb.c index ab19b1b4ce7..bac7922c164 100644 --- a/components/bt/host/bluedroid/stack/avct/avct_lcb.c +++ b/components/bt/host/bluedroid/stack/avct/avct_lcb.c @@ -364,7 +364,7 @@ void avct_lcb_dealloc(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data) AVCT_TRACE_DEBUG("%s Freeing LCB", __func__); osi_free(p_lcb->p_rx_msg); - fixed_queue_free(p_lcb->tx_q, NULL); + fixed_queue_free(p_lcb->tx_q, osi_free_func); memset(p_lcb, 0, sizeof(tAVCT_LCB)); } diff --git a/components/bt/host/bluedroid/stack/avct/avct_lcb_act.c b/components/bt/host/bluedroid/stack/avct/avct_lcb_act.c index 97d81b497ee..41401f90cee 100644 --- a/components/bt/host/bluedroid/stack/avct/avct_lcb_act.c +++ b/components/bt/host/bluedroid/stack/avct/avct_lcb_act.c @@ -425,7 +425,12 @@ void avct_lcb_chnl_disc(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data) { UNUSED(p_data); - L2CA_DisconnectReq(p_lcb->ch_lcid); + tAVCT_LCB_EVT evt; + + if (!L2CA_DisconnectReq(p_lcb->ch_lcid)) { + evt.result = AVCT_RESULT_FAIL; + avct_lcb_event(p_lcb, AVCT_LCB_LL_CLOSE_EVT, &evt); + } } /******************************************************************************* @@ -474,6 +479,7 @@ void avct_lcb_cong_ind(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data) if (L2CA_DataWrite(p_lcb->ch_lcid, p_buf) == L2CAP_DW_CONGESTED) { p_lcb->cong = TRUE; + event = AVCT_CONG_IND_EVT; } } } diff --git a/components/bt/host/bluedroid/stack/avrc/avrc_api.c b/components/bt/host/bluedroid/stack/avrc/avrc_api.c index 004613b3508..a1099364ea0 100644 --- a/components/bt/host/bluedroid/stack/avrc/avrc_api.c +++ b/components/bt/host/bluedroid/stack/avrc/avrc_api.c @@ -64,6 +64,31 @@ static const UINT8 avrc_ctrl_event_map[] = { #define AVRC_OP_SUB_UNIT_INFO_RSP_LEN 8 #define AVRC_OP_REJ_MSG_LEN 11 +#if (AVRC_METADATA_INCLUDED == TRUE) +/****************************************************************************** +** +** Function avrc_free_far_cb +** +** Description Free fragmentation/reassembly buffers for a connection. +** +******************************************************************************/ +static void avrc_free_far_cb(UINT8 handle) +{ + if (handle >= AVCT_NUM_CONN) { + return; + } + if (avrc_cb.fcb[handle].p_fmsg) { + osi_free(avrc_cb.fcb[handle].p_fmsg); + avrc_cb.fcb[handle].p_fmsg = NULL; + } + avrc_cb.fcb[handle].frag_enabled = FALSE; + if (avrc_cb.rcb[handle].p_rmsg) { + osi_free(avrc_cb.rcb[handle].p_rmsg); + avrc_cb.rcb[handle].p_rmsg = NULL; + } +} +#endif /* (AVRC_METADATA_INCLUDED == TRUE) */ + /****************************************************************************** ** ** Function avrc_ctrl_cback @@ -83,6 +108,13 @@ static void avrc_ctrl_cback(UINT8 handle, UINT8 event, UINT16 result, return; } + /* Release pending fragment/reassembly buffers on disconnect */ + if (event == AVCT_DISCONNECT_CFM_EVT || event == AVCT_DISCONNECT_IND_EVT) { +#if (AVRC_METADATA_INCLUDED == TRUE) + avrc_free_far_cb(handle); +#endif + } + if (event <= AVRC_MAX_RCV_CTRL_EVT && avrc_cb.ccb[handle].p_ctrl_cback) { avrc_event = avrc_ctrl_event_map[event]; if (event == AVCT_CONNECT_CFM_EVT) { @@ -298,6 +330,11 @@ static BT_HDR *avrc_proc_vendor_command(UINT8 handle, UINT8 label, if (p_msg->company_id == AVRC_CO_METADATA) { switch (*p_data) { case AVRC_PDU_ABORT_CONTINUATION_RSP: + if (p_pkt->len < (AVRC_VENDOR_HDR_SIZE + AVRC_ABORT_CONTINUATION_RSP_CMD_SIZE)) { + status = AVRC_STS_INTERNAL_ERR; + abort_frag = TRUE; + break; + } /* aborted by CT - send accept response */ abort_frag = TRUE; p_begin = (UINT8 *)(p_pkt + 1) + p_pkt->offset; @@ -315,6 +352,11 @@ static BT_HDR *avrc_proc_vendor_command(UINT8 handle, UINT8 label, break; case AVRC_PDU_REQUEST_CONTINUATION_RSP: + if (p_pkt->len < (AVRC_VENDOR_HDR_SIZE + AVRC_REQUEST_CONTINUATION_RSP_CMD_SIZE)) { + status = AVRC_STS_INTERNAL_ERR; + abort_frag = TRUE; + break; + } if (*(p_data + 4) == p_fcb->frag_pdu) { avrc_send_continue_frag(handle, label); p_msg->hdr.opcode = AVRC_OP_DROP_N_FREE; @@ -435,18 +477,17 @@ static UINT8 avrc_proc_far_msg(UINT8 handle, UINT8 label, UINT8 cr, BT_HDR **pp_ /* Free original START packet, replace with pointer to reassembly buffer */ osi_free(p_pkt); *pp_pkt = p_rcb->p_rmsg; - } else { - /* Unable to allocate buffer for fragmented avrc message. Reuse START - buffer for reassembly (re-assembled message may fit into ACL buf) */ - AVRC_TRACE_DEBUG ("Unable to allocate buffer for fragmented avrc message, \ - reusing START buffer for reassembly"); - p_rcb->rasm_offset = p_pkt->offset; - p_rcb->p_rmsg = p_pkt; - } - /* set offset to point to where to copy next - use the same re-asm logic as AVCT */ - p_rcb->p_rmsg->offset += p_rcb->p_rmsg->len; - req_continue = TRUE; + /* set offset to point to where to copy next - use the same re-asm logic as AVCT */ + p_rcb->p_rmsg->offset += p_rcb->p_rmsg->len; + req_continue = TRUE; + } else { + /* do not reuse START buffer; it is smaller than BT_DEFAULT_BUFFER_SIZE */ + AVRC_TRACE_ERROR("Unable to allocate buffer for fragmented avrc message"); + drop_code = 5; + osi_free(p_pkt); + *pp_pkt = NULL; + } } else if (p_rcb->p_rmsg == NULL) { /* Received a CONTINUE/END, but no corresponding START (or previous fragmented response was dropped) */ @@ -521,6 +562,14 @@ static UINT8 avrc_proc_far_msg(UINT8 handle, UINT8 label, UINT8 cr, BT_HDR **pp_ if (AVRC_BldCommand ((tAVRC_COMMAND *)&avrc_cmd, &p_cmd) == AVRC_STS_NO_ERROR) { drop_code = 2; AVRC_MsgReq (handle, (UINT8)(label), AVRC_CMD_CTRL, p_cmd); + } else { + AVRC_TRACE_ERROR("Failed to build continuation command"); + if (p_rcb->p_rmsg) { + osi_free(p_rcb->p_rmsg); + p_rcb->p_rmsg = NULL; + *pp_pkt = NULL; + } + drop_code = 5; } } } @@ -953,6 +1002,8 @@ UINT16 AVRC_Open(UINT8 *p_handle, tAVRC_CONN_CB *p_ccb, BD_ADDR_PTR peer_addr) if (status == AVCT_SUCCESS) { memcpy(&avrc_cb.ccb[*p_handle], p_ccb, sizeof(tAVRC_CONN_CB)); #if (AVRC_METADATA_INCLUDED == TRUE) + /* free fragmentation/reassembly buffers before memset clears pointers */ + avrc_free_far_cb(*p_handle); memset(&avrc_cb.fcb[*p_handle], 0, sizeof(tAVRC_FRAG_CB)); memset(&avrc_cb.rcb[*p_handle], 0, sizeof(tAVRC_RASM_CB)); #endif @@ -984,6 +1035,10 @@ UINT16 AVRC_Open(UINT8 *p_handle, tAVRC_CONN_CB *p_ccb, BD_ADDR_PTR peer_addr) UINT16 AVRC_Close(UINT8 handle) { AVRC_TRACE_DEBUG("AVRC_Close handle:%d", handle); +#if (AVRC_METADATA_INCLUDED == TRUE) + /* release pending fragment/reassembly buffers before removing connection */ + avrc_free_far_cb(handle); +#endif return AVCT_RemoveConn(handle); } @@ -1067,7 +1122,7 @@ UINT16 AVRC_MsgReq (UINT8 handle, UINT8 label, UINT8 ctype, BT_HDR *p_pkt) /* AVRCP spec has not defined any control channel commands that needs fragmentation at this level * check for fragmentation only on the response */ - if ((cr == AVCT_RSP) && (chk_frag == TRUE)) { + if ((cr == AVCT_RSP) && (chk_frag == TRUE) && (p_pkt->event == AVRC_OP_VENDOR)) { if (p_pkt->len > AVRC_MAX_CTRL_DATA_LEN) { int offset_len = MAX(AVCT_MSG_OFFSET, p_pkt->offset); p_pkt_new = (BT_HDR *)osi_malloc((UINT16)(AVRC_PACKET_LEN + offset_len @@ -1099,6 +1154,9 @@ UINT16 AVRC_MsgReq (UINT8 handle, UINT8 label, UINT8 ctype, BT_HDR *p_pkt) p_pkt->len, len, p_fcb->p_fmsg->len ); } else { AVRC_TRACE_ERROR ("AVRC_MsgReq no buffers for fragmentation" ); + if (p_pkt_new) { + osi_free(p_pkt_new); + } osi_free(p_pkt); return AVRC_NO_RESOURCES; } diff --git a/components/bt/host/bluedroid/stack/avrc/avrc_bld_ct.c b/components/bt/host/bluedroid/stack/avrc/avrc_bld_ct.c index 4c260cbec3d..99fcb7314f4 100644 --- a/components/bt/host/bluedroid/stack/avrc/avrc_bld_ct.c +++ b/components/bt/host/bluedroid/stack/avrc/avrc_bld_ct.c @@ -336,9 +336,11 @@ tAVRC_STS AVRC_BldCommand( tAVRC_COMMAND *p_cmd, BT_HDR **pp_pkt) status = avrc_bld_get_play_status_cmd(&p_cmd->get_play_status, p_pkt); break; +#if (AVRC_ADV_CTRL_INCLUDED == TRUE) case AVRC_PDU_REGISTER_NOTIFICATION: /* 0x31 */ status = avrc_bld_register_change_notfn(p_cmd->reg_notif.event_id, p_cmd->reg_notif.param, p_pkt); break; +#endif case AVRC_PDU_GET_CAPABILITIES: status = avrc_bld_get_caps_cmd(&p_cmd->get_caps, p_pkt); break; diff --git a/components/bt/host/bluedroid/stack/avrc/avrc_bld_tg.c b/components/bt/host/bluedroid/stack/avrc/avrc_bld_tg.c index e82a0512723..abf34f44989 100644 --- a/components/bt/host/bluedroid/stack/avrc/avrc_bld_tg.c +++ b/components/bt/host/bluedroid/stack/avrc/avrc_bld_tg.c @@ -87,15 +87,17 @@ static tAVRC_STS avrc_bld_get_capability_rsp (tAVRC_GET_CAPS_RSP *p_rsp, BT_HDR } len += count * 3; } else { + UINT8 valid_count = 0; p_event_id = p_rsp->param.event_id; - *p_count = 0; + *p_count -= count; for (xx = 0; xx < count; xx++) { if (AVRC_IS_VALID_EVENT_ID(p_event_id[xx])) { - (*p_count)++; + valid_count++; UINT8_TO_BE_STREAM(p_data, p_event_id[xx]); } } - len += (*p_count); + *p_count += valid_count; + len += valid_count; } UINT16_TO_BE_STREAM(p_len, len); p_pkt->len = (p_data - p_start); @@ -314,12 +316,6 @@ static tAVRC_STS avrc_bld_app_setting_text_rsp (tAVRC_GET_APP_ATTR_TXT_RSP *p_rs 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; @@ -331,6 +327,7 @@ static tAVRC_STS avrc_bld_app_setting_text_rsp (tAVRC_GET_APP_ATTR_TXT_RSP *p_rs } for (xx = 0; xx < p_rsp->num_attr; xx++) { + len_left = (UINT16)(((UINT8 *)p_pkt + BT_DEFAULT_BUFFER_SIZE) - p_data); if (len_left < (p_rsp->p_attrs[xx].str_len + 4)) { AVRC_TRACE_ERROR("avrc_bld_app_setting_text_rsp out of room %d(str_len:%d, left:%d)", xx, p_rsp->p_attrs[xx].str_len, len_left); @@ -926,6 +923,10 @@ tAVRC_STS AVRC_BldResponse( UINT8 handle, tAVRC_RESPONSE *p_rsp, BT_HDR **pp_pkt case AVRC_PDU_SET_ABSOLUTE_VOLUME: /* 0x50 */ status = avrc_bld_set_absolute_volume_rsp(&p_rsp->volume, p_pkt); break; + + default: + status = AVRC_STS_BAD_PARAM; + break; } if (alloc && (status != AVRC_STS_NO_ERROR) ) { diff --git a/components/bt/host/bluedroid/stack/avrc/avrc_pars_tg.c b/components/bt/host/bluedroid/stack/avrc/avrc_pars_tg.c index 840f4c98559..1ffe9f29500 100644 --- a/components/bt/host/bluedroid/stack/avrc/avrc_pars_tg.c +++ b/components/bt/host/bluedroid/stack/avrc/avrc_pars_tg.c @@ -52,9 +52,6 @@ static tAVRC_STS avrc_pars_vendor_cmd(tAVRC_MSG_VENDOR *p_msg, tAVRC_COMMAND *p_ tAVRC_APP_SETTING *p_app_set; /* Check the vendor data */ - if (p_msg->vendor_len == 0) { - return AVRC_STS_NO_ERROR; - } if ((p_msg->p_vendor_data == NULL) || (p_msg->vendor_len < AVRC_CMD_FIXED_SIZE)) { return AVRC_STS_INTERNAL_ERR; } diff --git a/components/bt/host/bluedroid/stack/avrc/avrc_sdp.c b/components/bt/host/bluedroid/stack/avrc/avrc_sdp.c index 5eb3e0031b2..6f76323b213 100644 --- a/components/bt/host/bluedroid/stack/avrc/avrc_sdp.c +++ b/components/bt/host/bluedroid/stack/avrc/avrc_sdp.c @@ -199,6 +199,11 @@ UINT16 AVRC_FindService(UINT16 service_uuid, BD_ADDR bd_addr, /* perform service search */ result = SDP_ServiceSearchAttributeRequest(bd_addr, p_db->p_db, avrc_sdp_cback); + if (!result) { + avrc_cb.service_uuid = 0; + avrc_cb.p_db = NULL; + avrc_cb.p_cback = NULL; + } } return (result ? AVRC_SUCCESS : AVRC_FAIL); @@ -413,6 +418,17 @@ void AVRC_Deinit(void) { #if AVRC_DYNAMIC_MEMORY if (avrc_cb_ptr){ +#if (AVRC_METADATA_INCLUDED == TRUE) + UINT8 i; + for (i = 0; i < AVCT_NUM_CONN; i++) { + if (avrc_cb_ptr->fcb[i].p_fmsg) { + osi_free(avrc_cb_ptr->fcb[i].p_fmsg); + } + if (avrc_cb_ptr->rcb[i].p_rmsg) { + osi_free(avrc_cb_ptr->rcb[i].p_rmsg); + } + } +#endif osi_free(avrc_cb_ptr); avrc_cb_ptr = NULL; } diff --git a/examples/bluetooth/bluedroid/classic_bt/a2dp_source/main/main.c b/examples/bluetooth/bluedroid/classic_bt/a2dp_source/main/main.c index 77cbc2a6b3c..87330fdb9b1 100644 --- a/examples/bluetooth/bluedroid/classic_bt/a2dp_source/main/main.c +++ b/examples/bluetooth/bluedroid/classic_bt/a2dp_source/main/main.c @@ -325,10 +325,6 @@ static void bt_av_hdl_stack_evt(uint16_t event, void *p_param) esp_avrc_ct_init(); esp_avrc_ct_register_callback(bt_app_rc_ct_cb); - esp_avrc_rn_evt_cap_mask_t evt_set = {0}; - esp_avrc_rn_evt_bit_mask_operation(ESP_AVRC_BIT_MASK_OP_SET, &evt_set, ESP_AVRC_RN_VOLUME_CHANGE); - ESP_ERROR_CHECK(esp_avrc_tg_set_rn_evt_cap(&evt_set)); - esp_a2d_source_init(); esp_a2d_register_callback(&bt_app_a2d_cb); esp_a2d_source_register_data_callback(bt_app_a2d_data_cb);