mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-01 18:50:34 +03:00
fix(bt): Fix the high issues related to AVRCP from AI review report
- SDP/registration: handle SDP record creation and discovery failures safely - AVRC stack: fix packet checks, fragment leaks, response build, and compile guards - BTC AVRCP: fix return codes, connection state, metadata parsing, and memory leaks - AVCTP: fix event passing, L2CAP conflicts, TX queue leaks, and disconnect handling - Example: remove TG RN capability setup before initialization
This commit is contained in:
@@ -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;
|
||||
@@ -520,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -952,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
|
||||
@@ -983,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);
|
||||
}
|
||||
|
||||
@@ -1066,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
|
||||
@@ -1098,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;
|
||||
}
|
||||
|
||||
@@ -318,9 +318,11 @@ tAVRC_STS AVRC_BldCommand( tAVRC_COMMAND *p_cmd, BT_HDR **pp_pkt)
|
||||
status = avrc_bld_get_element_attr_cmd(&p_cmd->get_elem_attrs, 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;
|
||||
|
||||
@@ -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);
|
||||
@@ -921,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) ) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user