fix(bt): fix A2DP stack component issues reported by AI review

This commit is contained in:
yangfeng
2026-03-19 20:10:38 +08:00
parent 08c5766c96
commit 63f04b97f2
15 changed files with 277 additions and 57 deletions
@@ -66,6 +66,8 @@ static void a2d_sdp_cback(UINT16 status)
A2D_TRACE_API("a2d_sdp_cback status: %d", status); A2D_TRACE_API("a2d_sdp_cback status: %d", status);
memset(&a2d_svc, 0, sizeof(tA2D_Service));
if (status == SDP_SUCCESS) { if (status == SDP_SUCCESS) {
/* loop through all records we found */ /* loop through all records we found */
do { do {
@@ -74,7 +76,6 @@ static void a2d_sdp_cback(UINT16 status)
a2d_cb.find.service_uuid, p_rec)) == NULL) { a2d_cb.find.service_uuid, p_rec)) == NULL) {
break; break;
} }
memset(&a2d_svc, 0, sizeof(tA2D_Service));
/* get service name */ /* get service name */
if ((p_attr = SDP_FindAttributeInRec(p_rec, if ((p_attr = SDP_FindAttributeInRec(p_rec,
@@ -107,14 +107,15 @@ tA2D_STATUS A2D_ParsSbcInfo(tA2D_SBC_CIE *p_ie, UINT8 *p_info, BOOLEAN for_caps)
{ {
tA2D_STATUS status = A2D_SUCCESS; tA2D_STATUS status = A2D_SUCCESS;
UINT8 losc; UINT8 losc;
UINT8 media_type;
if ( p_ie == NULL || p_info == NULL) { if ( p_ie == NULL || p_info == NULL) {
status = A2D_INVALID_PARAMS; status = A2D_INVALID_PARAMS;
} else { } else {
losc = *p_info++; losc = *p_info++;
p_info++; media_type = *p_info++;
/* If the function is called for the wrong Media Type or Media Codec Type */ /* If the function is called for the wrong Media Type or Media Codec Type */
if (losc != A2D_SBC_INFO_LEN || *p_info != A2D_MEDIA_CT_SBC) { if (losc != A2D_SBC_INFO_LEN || media_type != A2D_MEDIA_TYPE_AUDIO || *p_info != A2D_MEDIA_CT_SBC) {
status = A2D_WRONG_CODEC; status = A2D_WRONG_CODEC;
} else { } else {
p_info++; p_info++;
@@ -129,14 +130,10 @@ tA2D_STATUS A2D_ParsSbcInfo(tA2D_SBC_CIE *p_ie, UINT8 *p_info, BOOLEAN for_caps)
p_ie->max_bitpool = *p_info; p_ie->max_bitpool = *p_info;
if (p_ie->min_bitpool < A2D_SBC_IE_MIN_BITPOOL || p_ie->min_bitpool > A2D_SBC_IE_MAX_BITPOOL ) { if (p_ie->min_bitpool < A2D_SBC_IE_MIN_BITPOOL || p_ie->min_bitpool > A2D_SBC_IE_MAX_BITPOOL ) {
status = A2D_BAD_MIN_BITPOOL; status = A2D_BAD_MIN_BITPOOL;
} } else if (p_ie->max_bitpool < A2D_SBC_IE_MIN_BITPOOL || p_ie->max_bitpool > A2D_SBC_IE_MAX_BITPOOL ||
p_ie->max_bitpool < p_ie->min_bitpool) {
if (p_ie->max_bitpool < A2D_SBC_IE_MIN_BITPOOL || p_ie->max_bitpool > A2D_SBC_IE_MAX_BITPOOL ||
p_ie->max_bitpool < p_ie->min_bitpool) {
status = A2D_BAD_MAX_BITPOOL; status = A2D_BAD_MAX_BITPOOL;
} } else if (for_caps == FALSE) {
if (for_caps == FALSE) {
if (A2D_BitsSet(p_ie->samp_freq) != A2D_SET_ONE_BIT) { if (A2D_BitsSet(p_ie->samp_freq) != A2D_SET_ONE_BIT) {
status = A2D_BAD_SAMP_FREQ; status = A2D_BAD_SAMP_FREQ;
} else if (A2D_BitsSet(p_ie->ch_mode) != A2D_SET_ONE_BIT) { } else if (A2D_BitsSet(p_ie->ch_mode) != A2D_SET_ONE_BIT) {
@@ -62,6 +62,9 @@ void AVCT_Register(UINT16 mtu, UINT16 mtu_br, UINT8 sec_mask)
AVCT_TRACE_API("AVCT_Register"); AVCT_TRACE_API("AVCT_Register");
/* initialize AVCTP data structures */
memset(&avct_cb, 0, sizeof(tAVCT_CB));
/* register PSM with L2CAP */ /* register PSM with L2CAP */
L2CA_Register(AVCT_PSM, (tL2CAP_APPL_INFO *) &avct_l2c_appl); L2CA_Register(AVCT_PSM, (tL2CAP_APPL_INFO *) &avct_l2c_appl);
@@ -69,9 +72,6 @@ void AVCT_Register(UINT16 mtu, UINT16 mtu_br, UINT8 sec_mask)
BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_AVCTP, sec_mask, AVCT_PSM, 0, 0); BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_AVCTP, sec_mask, AVCT_PSM, 0, 0);
BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_AVCTP, sec_mask, AVCT_PSM, 0, 0); BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_AVCTP, sec_mask, AVCT_PSM, 0, 0);
/* initialize AVCTP data structures */
memset(&avct_cb, 0, sizeof(tAVCT_CB));
#if (AVCT_BROWSE_INCLUDED == TRUE) #if (AVCT_BROWSE_INCLUDED == TRUE)
/* Include the browsing channel which uses eFCR */ /* Include the browsing channel which uses eFCR */
L2CA_Register(AVCT_BR_PSM, (tL2CAP_APPL_INFO *) &avct_l2c_br_appl); L2CA_Register(AVCT_BR_PSM, (tL2CAP_APPL_INFO *) &avct_l2c_br_appl);
@@ -142,6 +142,10 @@ UINT16 AVCT_CreateConn(UINT8 *p_handle, tAVCT_CC *p_cc, BD_ADDR peer_addr)
tAVCT_CCB *p_ccb; tAVCT_CCB *p_ccb;
tAVCT_LCB *p_lcb; tAVCT_LCB *p_lcb;
if (p_cc == NULL || p_handle == NULL) {
return AVCT_BAD_HANDLE;
}
AVCT_TRACE_API("AVCT_CreateConn: %d, control:%d", p_cc->role, p_cc->control); AVCT_TRACE_API("AVCT_CreateConn: %d, control:%d", p_cc->role, p_cc->control);
/* Allocate ccb; if no ccbs, return failure */ /* Allocate ccb; if no ccbs, return failure */
@@ -234,7 +238,7 @@ UINT16 AVCT_CreateBrowse (UINT8 handle, UINT8 role)
#if (AVCT_BROWSE_INCLUDED == TRUE) #if (AVCT_BROWSE_INCLUDED == TRUE)
UINT16 result = AVCT_SUCCESS; UINT16 result = AVCT_SUCCESS;
tAVCT_CCB *p_ccb; tAVCT_CCB *p_ccb;
tAVCT_BCB *p_bcb; tAVCT_BCB *p_bcb = NULL;
int index; int index;
AVCT_TRACE_API("AVCT_CreateBrowse: %d", role); AVCT_TRACE_API("AVCT_CreateBrowse: %d", role);
@@ -428,7 +432,12 @@ UINT16 AVCT_MsgReq(UINT8 handle, UINT8 label, UINT8 cr, BT_HDR *p_msg)
osi_free(p_msg); osi_free(p_msg);
} else { } else {
p_ccb->p_bcb = avct_bcb_by_lcb(p_ccb->p_lcb); p_ccb->p_bcb = avct_bcb_by_lcb(p_ccb->p_lcb);
avct_bcb_event(p_ccb->p_bcb, AVCT_LCB_UL_MSG_EVT, (tAVCT_LCB_EVT *) &ul_msg); if (p_ccb->p_bcb == NULL) {
result = AVCT_BAD_HANDLE;
osi_free(p_msg);
} else {
avct_bcb_event(p_ccb->p_bcb, AVCT_LCB_UL_MSG_EVT, (tAVCT_LCB_EVT *) &ul_msg);
}
} }
} }
/* send msg event to lcb */ /* send msg event to lcb */
@@ -83,7 +83,7 @@ void avct_ccb_dealloc(tAVCT_CCB *p_ccb, UINT8 event, UINT16 result, BD_ADDR bd_a
if (p_ccb->p_bcb == NULL) { if (p_ccb->p_bcb == NULL) {
memset(p_ccb, 0, sizeof(tAVCT_CCB)); memset(p_ccb, 0, sizeof(tAVCT_CCB));
} else { } else {
/* control channel is down, but the browsing channel is still connected 0 disconnect it now */ /* control channel is down, but the browsing channel is still connected - disconnect it now */
avct_bcb_event(p_ccb->p_bcb, AVCT_LCB_UL_UNBIND_EVT, (tAVCT_LCB_EVT *) &p_ccb); avct_bcb_event(p_ccb->p_bcb, AVCT_LCB_UL_UNBIND_EVT, (tAVCT_LCB_EVT *) &p_ccb);
p_ccb->p_lcb = NULL; p_ccb->p_lcb = NULL;
} }
@@ -124,6 +124,7 @@ void avct_l2c_connect_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8
} else { } else {
/* TG role only - accept the connection from CT. move the channel ID to the conflict list */ /* TG role only - accept the connection from CT. move the channel ID to the conflict list */
p_lcb->conflict_lcid = p_lcb->ch_lcid; p_lcb->conflict_lcid = p_lcb->ch_lcid;
p_lcb->ch_flags = 0;
AVCT_TRACE_DEBUG("avct_l2c_connect_ind_cback conflict_lcid:0x%x", p_lcb->conflict_lcid); AVCT_TRACE_DEBUG("avct_l2c_connect_ind_cback conflict_lcid:0x%x", p_lcb->conflict_lcid);
} }
} }
@@ -142,6 +143,7 @@ void avct_l2c_connect_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8
/* transition to configuration state */ /* transition to configuration state */
p_lcb->ch_state = AVCT_CH_CFG; p_lcb->ch_state = AVCT_CH_CFG;
p_lcb->ch_flags = 0;
/* Send L2CAP config req */ /* Send L2CAP config req */
memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO)); memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
@@ -183,6 +185,7 @@ void avct_l2c_connect_cfm_cback(UINT16 lcid, UINT16 result)
if (result == L2CAP_CONN_OK) { if (result == L2CAP_CONN_OK) {
/* set channel state */ /* set channel state */
p_lcb->ch_state = AVCT_CH_CFG; p_lcb->ch_state = AVCT_CH_CFG;
p_lcb->ch_flags = 0;
/* Send L2CAP config req */ /* Send L2CAP config req */
memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO)); memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
@@ -275,6 +278,10 @@ void avct_l2c_config_ind_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg)
/* look up lcb for this channel */ /* look up lcb for this channel */
if ((p_lcb = avct_lcb_by_lcid(lcid)) != NULL) { if ((p_lcb = avct_lcb_by_lcid(lcid)) != NULL) {
AVCT_TRACE_DEBUG("avct_l2c_config_ind_cback: 0x%x, ch_state: %d", lcid, p_lcb->ch_state); AVCT_TRACE_DEBUG("avct_l2c_config_ind_cback: 0x%x, ch_state: %d", lcid, p_lcb->ch_state);
if (p_lcb->ch_state != AVCT_CH_CFG) {
AVCT_TRACE_ERROR("avct_l2c_config_ind_cback: EINVAL state %d", p_lcb->ch_state);
return;
}
/* store the mtu in tbl */ /* store the mtu in tbl */
if (p_cfg->mtu_present) { if (p_cfg->mtu_present) {
p_lcb->peer_mtu = p_cfg->mtu; p_lcb->peer_mtu = p_cfg->mtu;
@@ -310,10 +310,16 @@ tAVCT_LCB *avct_lcb_alloc(BD_ADDR bd_addr)
for (i = 0; i < AVCT_NUM_LINKS; i++, p_lcb++) { for (i = 0; i < AVCT_NUM_LINKS; i++, p_lcb++) {
if (!p_lcb->allocated) { if (!p_lcb->allocated) {
memset(p_lcb, 0, sizeof(tAVCT_LCB));
p_lcb->allocated = (UINT8)(i + 1); p_lcb->allocated = (UINT8)(i + 1);
memcpy(p_lcb->peer_addr, bd_addr, BD_ADDR_LEN); memcpy(p_lcb->peer_addr, bd_addr, BD_ADDR_LEN);
AVCT_TRACE_DEBUG("avct_lcb_alloc %d", p_lcb->allocated); AVCT_TRACE_DEBUG("avct_lcb_alloc %d", p_lcb->allocated);
p_lcb->tx_q = fixed_queue_new(QUEUE_SIZE_MAX); p_lcb->tx_q = fixed_queue_new(QUEUE_SIZE_MAX);
if (p_lcb->tx_q == NULL) {
AVCT_TRACE_ERROR("avct_lcb_alloc: failed to create tx_q");
memset(p_lcb, 0, sizeof(tAVCT_LCB));
p_lcb = NULL;
}
break; break;
} }
} }
@@ -63,6 +63,11 @@ static BT_HDR *avct_lcb_msg_asmbl(tAVCT_LCB *p_lcb, BT_HDR *p_buf)
p = (UINT8 *)(p_buf + 1) + p_buf->offset; p = (UINT8 *)(p_buf + 1) + p_buf->offset;
AVCT_PRS_PKT_TYPE(p, pkt_type); AVCT_PRS_PKT_TYPE(p, pkt_type);
if (pkt_type > AVCT_PKT_TYPE_END) {
osi_free(p_buf);
return NULL;
}
/* quick sanity check on length */ /* quick sanity check on length */
if (p_buf->len < avct_lcb_pkt_type_len[pkt_type]) { if (p_buf->len < avct_lcb_pkt_type_len[pkt_type]) {
osi_free(p_buf); osi_free(p_buf);
@@ -114,6 +119,11 @@ static BT_HDR *avct_lcb_msg_asmbl(tAVCT_LCB *p_lcb, BT_HDR *p_buf)
/* set offset to point to where to copy next */ /* set offset to point to where to copy next */
p_lcb->p_rx_msg->offset += p_lcb->p_rx_msg->len; p_lcb->p_rx_msg->offset += p_lcb->p_rx_msg->len;
if (p_lcb->p_rx_msg->len < 1) {
osi_free(p_lcb->p_rx_msg);
p_lcb->p_rx_msg = NULL;
return NULL;
}
/* adjust length for packet header */ /* adjust length for packet header */
p_lcb->p_rx_msg->len -= 1; p_lcb->p_rx_msg->len -= 1;
} }
@@ -146,6 +156,11 @@ static BT_HDR *avct_lcb_msg_asmbl(tAVCT_LCB *p_lcb, BT_HDR *p_buf)
p_lcb->p_rx_msg = NULL; p_lcb->p_rx_msg = NULL;
osi_free(p_buf); osi_free(p_buf);
p_ret = NULL; p_ret = NULL;
} else if ((UINT32)p_lcb->p_rx_msg->len + p_buf->len > 0xFFFF) {
osi_free(p_lcb->p_rx_msg);
p_lcb->p_rx_msg = NULL;
osi_free(p_buf);
p_ret = NULL;
} else { } else {
/* copy contents of p_buf to p_rx_msg */ /* copy contents of p_buf to p_rx_msg */
memcpy((UINT8 *)(p_lcb->p_rx_msg + 1) + p_lcb->p_rx_msg->offset, memcpy((UINT8 *)(p_lcb->p_rx_msg + 1) + p_lcb->p_rx_msg->offset,
@@ -541,6 +556,7 @@ void avct_lcb_send_msg(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
/* whoops; free original msg buf and bail */ /* whoops; free original msg buf and bail */
AVCT_TRACE_ERROR ("avct_lcb_send_msg cannot alloc buffer!!"); AVCT_TRACE_ERROR ("avct_lcb_send_msg cannot alloc buffer!!");
osi_free(p_data->ul_msg.p_buf); osi_free(p_data->ul_msg.p_buf);
p_data->ul_msg.p_buf = NULL;
break; break;
} }
@@ -555,6 +571,7 @@ void avct_lcb_send_msg(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
p_data->ul_msg.p_buf->len -= p_buf->len; p_data->ul_msg.p_buf->len -= p_buf->len;
} else { } else {
p_buf = p_data->ul_msg.p_buf; p_buf = p_data->ul_msg.p_buf;
p_data->ul_msg.p_buf = NULL;
} }
curr_msg_len -= p_buf->len; curr_msg_len -= p_buf->len;
@@ -54,6 +54,9 @@ UINT8 avdt_ad_type_to_tcid(UINT8 type, tAVDT_SCB *p_scb)
if (type == AVDT_CHAN_SIG) { if (type == AVDT_CHAN_SIG) {
return 0; return 0;
} else { } else {
if (p_scb == NULL) {
return 0;
}
scb_idx = avdt_scb_to_hdl(p_scb) - 1; scb_idx = avdt_scb_to_hdl(p_scb) - 1;
/* /*
AVDT_TRACE_DEBUG("type: %d, tcid: %d", type, ((scb_idx * (AVDT_CHAN_NUM_TYPES - 1)) + type)); AVDT_TRACE_DEBUG("type: %d, tcid: %d", type, ((scb_idx * (AVDT_CHAN_NUM_TYPES - 1)) + type));
@@ -186,8 +189,19 @@ tAVDT_TC_TBL *avdt_ad_tc_tbl_by_st(UINT8 type, tAVDT_CCB *p_ccb, UINT8 state)
tAVDT_TC_TBL *avdt_ad_tc_tbl_by_lcid(UINT16 lcid) tAVDT_TC_TBL *avdt_ad_tc_tbl_by_lcid(UINT16 lcid)
{ {
UINT8 idx; UINT8 idx;
UINT16 lcid_offset;
idx = avdt_cb.ad.lcid_tbl[lcid - L2CAP_BASE_APPL_CID]; if (lcid < L2CAP_BASE_APPL_CID) {
return NULL;
}
lcid_offset = lcid - L2CAP_BASE_APPL_CID;
if (lcid_offset >= MAX_L2CAP_CHANNELS) {
return NULL;
}
idx = avdt_cb.ad.lcid_tbl[lcid_offset];
if (idx < AVDT_NUM_TC_TBL) { if (idx < AVDT_NUM_TC_TBL) {
return &avdt_cb.ad.tc_tbl[idx]; return &avdt_cb.ad.tc_tbl[idx];
@@ -316,6 +330,9 @@ void avdt_ad_tc_close_ind(tAVDT_TC_TBL *p_tbl, UINT16 reason)
/* if signaling channel, notify ccb that channel open */ /* if signaling channel, notify ccb that channel open */
if (p_tbl->tcid == 0) { if (p_tbl->tcid == 0) {
p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx); p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx);
if (p_ccb == NULL) {
return;
}
p_ccb->disc_rsn = (reason == AVDT_DISC_RSN_ABNORMAL) ? AVDT_DISC_RSN_ABNORMAL : AVDT_DISC_RSN_NORMAL; p_ccb->disc_rsn = (reason == AVDT_DISC_RSN_ABNORMAL) ? AVDT_DISC_RSN_ABNORMAL : AVDT_DISC_RSN_NORMAL;
avdt_ccb_event(p_ccb, AVDT_CCB_LL_CLOSE_EVT, NULL); avdt_ccb_event(p_ccb, AVDT_CCB_LL_CLOSE_EVT, NULL);
} }
@@ -359,6 +376,9 @@ void avdt_ad_tc_open_ind(tAVDT_TC_TBL *p_tbl)
L2CA_SetTxPriority(avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][AVDT_CHAN_SIG].lcid, L2CAP_CHNL_PRIORITY_HIGH); L2CA_SetTxPriority(avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][AVDT_CHAN_SIG].lcid, L2CAP_CHNL_PRIORITY_HIGH);
p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx); p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx);
if (p_ccb == NULL) {
return;
}
/* use err_param to indicate the role of connection. /* use err_param to indicate the role of connection.
* AVDT_ACP, if ACP */ * AVDT_ACP, if ACP */
evt.err_param = AVDT_INT; evt.err_param = AVDT_INT;
@@ -405,6 +425,9 @@ void avdt_ad_tc_cong_ind(tAVDT_TC_TBL *p_tbl, BOOLEAN is_congested)
/* if signaling channel, notify ccb of congestion */ /* if signaling channel, notify ccb of congestion */
if (p_tbl->tcid == 0) { if (p_tbl->tcid == 0) {
p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx); p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx);
if (p_ccb == NULL) {
return;
}
avdt_ccb_event(p_ccb, AVDT_CCB_LL_CONG_EVT, (tAVDT_CCB_EVT *) &is_congested); avdt_ccb_event(p_ccb, AVDT_CCB_LL_CONG_EVT, (tAVDT_CCB_EVT *) &is_congested);
} }
/* if media or other channel, notify scb that channel open */ /* if media or other channel, notify scb that channel open */
@@ -442,6 +465,10 @@ void avdt_ad_tc_data_ind(tAVDT_TC_TBL *p_tbl, BT_HDR *p_buf)
/* if signaling channel, handle control message */ /* if signaling channel, handle control message */
if (p_tbl->tcid == 0) { if (p_tbl->tcid == 0) {
p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx); p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx);
if (p_ccb == NULL) {
osi_free(p_buf);
return;
}
avdt_msg_ind(p_ccb, p_buf); avdt_msg_ind(p_ccb, p_buf);
} }
/* if media or other channel, send event to scb */ /* if media or other channel, send event to scb */
@@ -534,7 +561,7 @@ void avdt_ad_open_req(UINT8 type, tAVDT_CCB *p_ccb, tAVDT_SCB *p_scb, UINT8 role
if (role == AVDT_ACP) { if (role == AVDT_ACP) {
p_tbl->state = AVDT_AD_ST_ACP; p_tbl->state = AVDT_AD_ST_ACP;
} }
/* else we're inititator, start the L2CAP connection */ /* else we're initiator, start the L2CAP connection */
else { else {
p_tbl->state = AVDT_AD_ST_CONN; p_tbl->state = AVDT_AD_ST_CONN;
@@ -574,6 +601,9 @@ void avdt_ad_close_req(UINT8 type, tAVDT_CCB *p_ccb, tAVDT_SCB *p_scb)
tAVDT_TC_TBL *p_tbl; tAVDT_TC_TBL *p_tbl;
p_tbl = avdt_ad_tc_tbl_by_type(type, p_ccb, p_scb); p_tbl = avdt_ad_tc_tbl_by_type(type, p_ccb, p_scb);
if (p_tbl == NULL) {
return;
}
AVDT_TRACE_DEBUG("avdt_ad_close_req state: %d\n", p_tbl->state); AVDT_TRACE_DEBUG("avdt_ad_close_req state: %d\n", p_tbl->state);
switch (p_tbl->state) { switch (p_tbl->state) {
@@ -110,6 +110,9 @@ void avdt_process_timeout(TIMER_LIST_ENT *p_tle)
*******************************************************************************/ *******************************************************************************/
void AVDT_Register(tAVDT_REG *p_reg, tAVDT_CTRL_CBACK *p_cback) void AVDT_Register(tAVDT_REG *p_reg, tAVDT_CTRL_CBACK *p_cback)
{ {
if (p_reg == NULL || p_cback == NULL) {
return;
}
/* register PSM with L2CAP */ /* register PSM with L2CAP */
L2CA_Register(AVDT_PSM, (tL2CAP_APPL_INFO *) &avdt_l2c_appl); L2CA_Register(AVDT_PSM, (tL2CAP_APPL_INFO *) &avdt_l2c_appl);
@@ -251,6 +254,9 @@ UINT16 AVDT_CreateStream(UINT8 *p_handle, tAVDT_CS *p_cs)
UINT16 result = AVDT_SUCCESS; UINT16 result = AVDT_SUCCESS;
tAVDT_SCB *p_scb; tAVDT_SCB *p_scb;
if (p_handle == NULL) {
return AVDT_BAD_PARAMS;
}
/* Verify parameters; if invalid, return failure */ /* Verify parameters; if invalid, return failure */
if (((p_cs->cfg.psc_mask & (~AVDT_PSC)) != 0) || (p_cs->p_ctrl_cback == NULL)) { if (((p_cs->cfg.psc_mask & (~AVDT_PSC)) != 0) || (p_cs->p_ctrl_cback == NULL)) {
result = AVDT_BAD_PARAMS; result = AVDT_BAD_PARAMS;
@@ -929,6 +935,9 @@ UINT16 AVDT_WriteReqOpt(UINT8 handle, BT_HDR *p_pkt, UINT32 time_stamp, UINT8 m_
tAVDT_SCB_EVT evt; tAVDT_SCB_EVT evt;
UINT16 result = AVDT_SUCCESS; UINT16 result = AVDT_SUCCESS;
if (p_pkt == NULL) {
return AVDT_BAD_PARAMS;
}
/* map handle to scb */ /* map handle to scb */
if ((p_scb = avdt_scb_by_hdl(handle)) == NULL) { if ((p_scb = avdt_scb_by_hdl(handle)) == NULL) {
result = AVDT_BAD_HANDLE; result = AVDT_BAD_HANDLE;
@@ -1188,7 +1197,7 @@ UINT16 AVDT_SendReport(UINT8 handle, AVDT_REPORT_TYPE type,
/* build SR - assume fit in one packet */ /* build SR - assume fit in one packet */
p_tbl = avdt_ad_tc_tbl_by_type(AVDT_CHAN_REPORT, p_scb->p_ccb, p_scb); p_tbl = avdt_ad_tc_tbl_by_type(AVDT_CHAN_REPORT, p_scb->p_ccb, p_scb);
if ((p_tbl->state == AVDT_AD_ST_OPEN) && if ((p_tbl != NULL) && (p_tbl->state == AVDT_AD_ST_OPEN) &&
(p_pkt = (BT_HDR *)osi_malloc(p_tbl->peer_mtu)) != NULL) { (p_pkt = (BT_HDR *)osi_malloc(p_tbl->peer_mtu)) != NULL) {
p_pkt->offset = L2CAP_MIN_OFFSET; p_pkt->offset = L2CAP_MIN_OFFSET;
p = (UINT8 *)(p_pkt + 1) + p_pkt->offset; p = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
@@ -1221,9 +1230,12 @@ UINT16 AVDT_SendReport(UINT8 handle, AVDT_REPORT_TYPE type,
case AVDT_RTCP_PT_RR: /* Receiver Report */ case AVDT_RTCP_PT_RR: /* Receiver Report */
*p++ = p_data->rr.frag_lost; *p++ = p_data->rr.frag_lost;
AVDT_TRACE_API("packet_lost: %d\n", p_data->rr.packet_lost); AVDT_TRACE_API("packet_lost: %d\n", p_data->rr.packet_lost);
p_data->rr.packet_lost &= 0xFFFFFF; /* Use local 24-bit value so caller's p_data->rr.packet_lost is not mutated */
AVDT_TRACE_API("packet_lost: %d\n", p_data->rr.packet_lost); {
UINT24_TO_BE_STREAM(p, p_data->rr.packet_lost); UINT32 packet_lost_24 = p_data->rr.packet_lost & 0xFFFFFF;
AVDT_TRACE_API("packet_lost_24: %d\n", packet_lost_24);
UINT24_TO_BE_STREAM(p, packet_lost_24);
}
UINT32_TO_BE_STREAM(p, p_data->rr.seq_num_rcvd); UINT32_TO_BE_STREAM(p, p_data->rr.seq_num_rcvd);
UINT32_TO_BE_STREAM(p, p_data->rr.jitter); UINT32_TO_BE_STREAM(p, p_data->rr.jitter);
UINT32_TO_BE_STREAM(p, p_data->rr.lsr); UINT32_TO_BE_STREAM(p, p_data->rr.lsr);
@@ -31,6 +31,7 @@
#include "stack/avdtc_api.h" #include "stack/avdtc_api.h"
#include "avdt_int.h" #include "avdt_int.h"
#include "stack/btu.h" #include "stack/btu.h"
#include "osi/allocator.h"
#if (defined(AVDT_INCLUDED) && AVDT_INCLUDED == TRUE) #if (defined(AVDT_INCLUDED) && AVDT_INCLUDED == TRUE)
@@ -302,6 +303,10 @@ void avdt_ccb_event(tAVDT_CCB *p_ccb, UINT8 event, tAVDT_CCB_EVT *p_data)
UINT8 action; UINT8 action;
int i; int i;
if (p_ccb == NULL || p_ccb->state > AVDT_CCB_CLOSING_ST || event > AVDT_CCB_LL_CONG_EVT) {
return;
}
#if AVDT_DEBUG == TRUE #if AVDT_DEBUG == TRUE
AVDT_TRACE_EVENT("CCB ccb=%d event=%s state=%s\n", avdt_ccb_to_idx(p_ccb), avdt_ccb_evt_str[event], avdt_ccb_st_str[p_ccb->state]); AVDT_TRACE_EVENT("CCB ccb=%d event=%s state=%s\n", avdt_ccb_to_idx(p_ccb), avdt_ccb_evt_str[event], avdt_ccb_st_str[p_ccb->state]);
#endif #endif
@@ -396,7 +401,7 @@ tAVDT_CCB *avdt_ccb_alloc(BD_ADDR bd_addr)
** **
** Function avdt_ccb_dealloc ** Function avdt_ccb_dealloc
** **
** Description Deallocate a stream control block. ** Description Deallocate a channel control block.
** **
** **
** Returns void. ** Returns void.
@@ -406,10 +411,28 @@ void avdt_ccb_dealloc(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
{ {
UNUSED(p_data); UNUSED(p_data);
if (p_ccb == NULL) {
return;
}
AVDT_TRACE_DEBUG("avdt_ccb_dealloc %d\n", avdt_ccb_to_idx(p_ccb)); AVDT_TRACE_DEBUG("avdt_ccb_dealloc %d\n", avdt_ccb_to_idx(p_ccb));
btu_free_timer(&p_ccb->timer_entry); btu_free_timer(&p_ccb->timer_entry);
fixed_queue_free(p_ccb->cmd_q, NULL); fixed_queue_free(p_ccb->cmd_q, osi_free_func);
fixed_queue_free(p_ccb->rsp_q, NULL); fixed_queue_free(p_ccb->rsp_q, osi_free_func);
if (p_ccb->p_curr_cmd != NULL) {
osi_free(p_ccb->p_curr_cmd);
p_ccb->p_curr_cmd = NULL;
}
if (p_ccb->p_curr_msg != NULL) {
osi_free(p_ccb->p_curr_msg);
p_ccb->p_curr_msg = NULL;
}
if (p_ccb->p_rx_msg != NULL) {
osi_free(p_ccb->p_rx_msg);
p_ccb->p_rx_msg = NULL;
}
memset(p_ccb, 0, sizeof(tAVDT_CCB)); memset(p_ccb, 0, sizeof(tAVDT_CCB));
} }
@@ -425,6 +448,9 @@ void avdt_ccb_dealloc(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
*******************************************************************************/ *******************************************************************************/
UINT8 avdt_ccb_to_idx(tAVDT_CCB *p_ccb) UINT8 avdt_ccb_to_idx(tAVDT_CCB *p_ccb)
{ {
if (p_ccb == NULL) {
return AVDT_NUM_LINKS;
}
/* use array arithmetic to determine index */ /* use array arithmetic to determine index */
return (UINT8) (p_ccb - avdt_cb.ccb); return (UINT8) (p_ccb - avdt_cb.ccb);
} }
@@ -446,6 +472,9 @@ tAVDT_CCB *avdt_ccb_by_idx(UINT8 idx)
/* verify index */ /* verify index */
if (idx < AVDT_NUM_LINKS) { if (idx < AVDT_NUM_LINKS) {
p_ccb = &avdt_cb.ccb[idx]; p_ccb = &avdt_cb.ccb[idx];
if (!p_ccb->allocated) {
p_ccb = NULL;
}
} else { } else {
p_ccb = NULL; p_ccb = NULL;
AVDT_TRACE_WARNING("No ccb for idx %d\n", idx); AVDT_TRACE_WARNING("No ccb for idx %d\n", idx);
@@ -218,10 +218,21 @@ void avdt_ccb_hdl_discover_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
void avdt_ccb_hdl_getcap_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data) void avdt_ccb_hdl_getcap_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
{ {
tAVDT_SCB *p_scb; tAVDT_SCB *p_scb;
UINT8 sig_id = AVDT_SIG_GETCAP;
/* look up scb for seid sent to us */ /* look up scb for seid sent to us */
p_scb = avdt_scb_by_hdl(p_data->msg.single.seid); p_scb = avdt_scb_by_hdl(p_data->msg.single.seid);
if (p_scb == NULL) {
p_data->msg.hdr.err_code = AVDT_ERR_SEID;
p_data->msg.hdr.err_param = p_data->msg.single.seid;
if (p_data->msg.hdr.sig_id == AVDT_SIG_GET_ALLCAP) {
sig_id = AVDT_SIG_GET_ALLCAP;
}
avdt_msg_send_rej(p_ccb, sig_id, &p_data->msg);
return;
}
p_data->msg.svccap.p_cfg = &p_scb->cs.cfg; p_data->msg.svccap.p_cfg = &p_scb->cs.cfg;
avdt_ccb_event(p_ccb, AVDT_CCB_API_GETCAP_RSP_EVT, p_data); avdt_ccb_event(p_ccb, AVDT_CCB_API_GETCAP_RSP_EVT, p_data);
@@ -300,6 +311,10 @@ void avdt_ccb_hdl_start_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
UINT8 *p; UINT8 *p;
tAVDT_SCB *p_scb; tAVDT_SCB *p_scb;
if (p_ccb->p_curr_cmd == NULL) {
return;
}
/* determine rsp or rej event */ /* determine rsp or rej event */
event = (p_data->msg.hdr.err_code == 0) ? event = (p_data->msg.hdr.err_code == 0) ?
AVDT_SCB_MSG_START_RSP_EVT : AVDT_SCB_MSG_START_REJ_EVT; AVDT_SCB_MSG_START_RSP_EVT : AVDT_SCB_MSG_START_REJ_EVT;
@@ -369,6 +384,10 @@ void avdt_ccb_hdl_suspend_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
UINT8 *p; UINT8 *p;
tAVDT_SCB *p_scb; tAVDT_SCB *p_scb;
if (p_ccb->p_curr_cmd == NULL) {
return;
}
/* determine rsp or rej event */ /* determine rsp or rej event */
event = (p_data->msg.hdr.err_code == 0) ? event = (p_data->msg.hdr.err_code == 0) ?
AVDT_SCB_MSG_SUSPEND_RSP_EVT : AVDT_SCB_MSG_SUSPEND_REJ_EVT; AVDT_SCB_MSG_SUSPEND_RSP_EVT : AVDT_SCB_MSG_SUSPEND_REJ_EVT;
@@ -505,13 +524,15 @@ void avdt_ccb_snd_start_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
tAVDT_MSG avdt_msg; tAVDT_MSG avdt_msg;
UINT8 seid_list[AVDT_NUM_SEPS]; UINT8 seid_list[AVDT_NUM_SEPS];
p_data->msg.multi.num_seps = (p_data->msg.multi.num_seps > AVDT_NUM_SEPS) ?
AVDT_NUM_SEPS : p_data->msg.multi.num_seps;
/* make copy of our seid list */ /* make copy of our seid list */
memcpy(seid_list, p_data->msg.multi.seid_list, p_data->msg.multi.num_seps); memcpy(seid_list, p_data->msg.multi.seid_list, p_data->msg.multi.num_seps);
/* verify all streams in the right state */ /* verify all streams in the right state */
if ((avdt_msg.hdr.err_param = avdt_scb_verify(p_ccb, AVDT_VERIFY_OPEN, p_data->msg.multi.seid_list, if ((avdt_msg.hdr.err_param = avdt_scb_verify(p_ccb, AVDT_VERIFY_OPEN, p_data->msg.multi.seid_list,
p_data->msg.multi.num_seps, &avdt_msg.hdr.err_code)) == 0) { p_data->msg.multi.num_seps, &avdt_msg.hdr.err_code)) == 0) {
/* set peer seid list in messsage */ /* set peer seid list in message */
avdt_scb_peer_seid_list(&p_data->msg.multi); avdt_scb_peer_seid_list(&p_data->msg.multi);
/* send command */ /* send command */
@@ -576,13 +597,15 @@ void avdt_ccb_snd_suspend_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
tAVDT_MSG avdt_msg; tAVDT_MSG avdt_msg;
UINT8 seid_list[AVDT_NUM_SEPS]; UINT8 seid_list[AVDT_NUM_SEPS];
p_data->msg.multi.num_seps = (p_data->msg.multi.num_seps > AVDT_NUM_SEPS) ?
AVDT_NUM_SEPS : p_data->msg.multi.num_seps;
/* make copy of our seid list */ /* make copy of our seid list */
memcpy(seid_list, p_data->msg.multi.seid_list, p_data->msg.multi.num_seps); memcpy(seid_list, p_data->msg.multi.seid_list, p_data->msg.multi.num_seps);
/* verify all streams in the right state */ /* verify all streams in the right state */
if ((avdt_msg.hdr.err_param = avdt_scb_verify(p_ccb, AVDT_VERIFY_STREAMING, p_data->msg.multi.seid_list, if ((avdt_msg.hdr.err_param = avdt_scb_verify(p_ccb, AVDT_VERIFY_STREAMING, p_data->msg.multi.seid_list,
p_data->msg.multi.num_seps, &avdt_msg.hdr.err_code)) == 0) { p_data->msg.multi.num_seps, &avdt_msg.hdr.err_code)) == 0) {
/* set peer seid list in messsage */ /* set peer seid list in message */
avdt_scb_peer_seid_list(&p_data->msg.multi); avdt_scb_peer_seid_list(&p_data->msg.multi);
/* send command */ /* send command */
@@ -690,6 +713,12 @@ void avdt_ccb_cmd_fail(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
tAVDT_SCB *p_scb; tAVDT_SCB *p_scb;
if (p_ccb->p_curr_cmd != NULL) { if (p_ccb->p_curr_cmd != NULL) {
if (p_ccb->p_curr_cmd->event < 1 || p_ccb->p_curr_cmd->event > AVDT_SIG_MAX) {
osi_free(p_ccb->p_curr_cmd);
p_ccb->p_curr_cmd = NULL;
return;
}
/* set up data */ /* set up data */
msg.hdr.err_code = p_data->err_code; msg.hdr.err_code = p_data->err_code;
msg.hdr.err_param = 0; msg.hdr.err_param = 0;
@@ -1076,7 +1105,7 @@ void avdt_ccb_ll_opened(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
/* call callback */ /* call callback */
if (p_ccb->p_conn_cback) { if (p_ccb->p_conn_cback) {
avdt_ctrl.hdr.err_code = 0; avdt_ctrl.hdr.err_code = 0;
avdt_ctrl.hdr.err_param = p_data->msg.hdr.err_param; avdt_ctrl.hdr.err_param = (p_data != NULL) ? p_data->msg.hdr.err_param : 0;
(*p_ccb->p_conn_cback)(0, p_ccb->peer_addr, AVDT_CONNECT_IND_EVT, &avdt_ctrl); (*p_ccb->p_conn_cback)(0, p_ccb->peer_addr, AVDT_CONNECT_IND_EVT, &avdt_ctrl);
} }
} }
@@ -79,6 +79,7 @@ static void avdt_sec_check_complete_term (BD_ADDR bd_addr, tBT_TRANSPORT transpo
tL2CAP_CFG_INFO cfg; tL2CAP_CFG_INFO cfg;
tAVDT_TC_TBL *p_tbl; tAVDT_TC_TBL *p_tbl;
UNUSED(p_ref_data); UNUSED(p_ref_data);
UNUSED(transport);
AVDT_TRACE_DEBUG("avdt_sec_check_complete_term res: %d\n", res); AVDT_TRACE_DEBUG("avdt_sec_check_complete_term res: %d\n", res);
if (!bd_addr) { if (!bd_addr) {
@@ -97,9 +98,11 @@ static void avdt_sec_check_complete_term (BD_ADDR bd_addr, tBT_TRANSPORT transpo
/* Send response to the L2CAP layer. */ /* Send response to the L2CAP layer. */
L2CA_ConnectRsp (bd_addr, p_tbl->id, p_tbl->lcid, L2CAP_CONN_OK, L2CAP_CONN_OK); L2CA_ConnectRsp (bd_addr, p_tbl->id, p_tbl->lcid, L2CAP_CONN_OK, L2CAP_CONN_OK);
/* store idx in LCID table, store LCID in routing table */ if (p_tbl->lcid >= L2CAP_BASE_APPL_CID && (p_tbl->lcid - L2CAP_BASE_APPL_CID) < MAX_L2CAP_CHANNELS) {
avdt_cb.ad.lcid_tbl[p_tbl->lcid - L2CAP_BASE_APPL_CID] = avdt_ad_tc_tbl_to_idx(p_tbl); /* store idx in LCID table, store LCID in routing table */
avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].lcid = p_tbl->lcid; avdt_cb.ad.lcid_tbl[p_tbl->lcid - L2CAP_BASE_APPL_CID] = avdt_ad_tc_tbl_to_idx(p_tbl);
avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].lcid = p_tbl->lcid;
}
/* transition to configuration state */ /* transition to configuration state */
p_tbl->state = AVDT_AD_ST_CFG; p_tbl->state = AVDT_AD_ST_CFG;
@@ -134,11 +137,13 @@ static void avdt_sec_check_complete_orig (BD_ADDR bd_addr, tBT_TRANSPORT transpo
tL2CAP_CFG_INFO cfg; tL2CAP_CFG_INFO cfg;
tAVDT_TC_TBL *p_tbl; tAVDT_TC_TBL *p_tbl;
UNUSED(p_ref_data); UNUSED(p_ref_data);
UNUSED(transport);
AVDT_TRACE_DEBUG("avdt_sec_check_complete_orig res: %d\n", res); AVDT_TRACE_DEBUG("avdt_sec_check_complete_orig res: %d\n", res);
if (bd_addr) { if (bd_addr) {
p_ccb = avdt_ccb_by_bd(bd_addr); p_ccb = avdt_ccb_by_bd(bd_addr);
} }
p_tbl = avdt_ad_tc_tbl_by_st(AVDT_CHAN_SIG, p_ccb, AVDT_AD_ST_SEC_INT); p_tbl = avdt_ad_tc_tbl_by_st(AVDT_CHAN_SIG, p_ccb, AVDT_AD_ST_SEC_INT);
if (p_tbl == NULL) { if (p_tbl == NULL) {
return; return;
@@ -188,6 +193,11 @@ void avdt_l2c_connect_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8
} else { } else {
/* allocate and set up entry; first channel is always signaling */ /* allocate and set up entry; first channel is always signaling */
p_tbl = avdt_ad_tc_tbl_alloc(p_ccb); p_tbl = avdt_ad_tc_tbl_alloc(p_ccb);
if (p_tbl == NULL) {
avdt_ccb_dealloc(p_ccb, NULL);
L2CA_ConnectRsp(bd_addr, id, lcid, L2CAP_CONN_NO_RESOURCES, 0);
return;
}
p_tbl->my_mtu = avdt_cb.rcb.ctrl_mtu; p_tbl->my_mtu = avdt_cb.rcb.ctrl_mtu;
p_tbl->my_flush_to = L2CAP_DEFAULT_FLUSH_TO; p_tbl->my_flush_to = L2CAP_DEFAULT_FLUSH_TO;
p_tbl->tcid = AVDT_CHAN_SIG; p_tbl->tcid = AVDT_CHAN_SIG;
@@ -238,10 +248,11 @@ void avdt_l2c_connect_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8
/* if result ok, proceed with connection */ /* if result ok, proceed with connection */
if (result == L2CAP_CONN_OK) { if (result == L2CAP_CONN_OK) {
/* store idx in LCID table, store LCID in routing table */ if (lcid >= L2CAP_BASE_APPL_CID && lcid < (L2CAP_BASE_APPL_CID + MAX_L2CAP_CHANNELS)) {
avdt_cb.ad.lcid_tbl[lcid - L2CAP_BASE_APPL_CID] = avdt_ad_tc_tbl_to_idx(p_tbl); /* store idx in LCID table, store LCID in routing table */
avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].lcid = lcid; avdt_cb.ad.lcid_tbl[lcid - L2CAP_BASE_APPL_CID] = avdt_ad_tc_tbl_to_idx(p_tbl);
avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].lcid = lcid;
}
/* transition to configuration state */ /* transition to configuration state */
p_tbl->state = AVDT_AD_ST_CFG; p_tbl->state = AVDT_AD_ST_CFG;
@@ -420,13 +431,12 @@ void avdt_l2c_disconnect_ind_cback(UINT16 lcid, BOOLEAN ack_needed)
if (ack_needed) { if (ack_needed) {
/* send L2CAP disconnect response */ /* send L2CAP disconnect response */
L2CA_DisconnectRsp(lcid); L2CA_DisconnectRsp(lcid);
} else { }
if ((p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx)) != NULL) { if ((p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx)) != NULL) {
UINT16 rsn = L2CA_GetDisconnectReason(p_ccb->peer_addr, BT_TRANSPORT_BR_EDR); UINT16 rsn = L2CA_GetDisconnectReason(p_ccb->peer_addr, BT_TRANSPORT_BR_EDR);
if (rsn != 0 && rsn != HCI_ERR_PEER_USER) { if (rsn != 0 && rsn != HCI_ERR_PEER_USER) {
disc_rsn = AVDT_DISC_RSN_ABNORMAL; disc_rsn = AVDT_DISC_RSN_ABNORMAL;
AVDT_TRACE_EVENT("avdt link disc rsn 0x%x", rsn); AVDT_TRACE_EVENT("avdt link disc rsn 0x%x", rsn);
}
} }
} }
@@ -462,8 +462,10 @@ static void avdt_msg_bld_multi(UINT8 **p, tAVDT_MSG *p_msg)
static void avdt_msg_bld_security_cmd(UINT8 **p, tAVDT_MSG *p_msg) static void avdt_msg_bld_security_cmd(UINT8 **p, tAVDT_MSG *p_msg)
{ {
AVDT_MSG_BLD_SEID(*p, p_msg->security_cmd.hdr.seid); AVDT_MSG_BLD_SEID(*p, p_msg->security_cmd.hdr.seid);
memcpy(*p, p_msg->security_cmd.p_data, p_msg->security_cmd.len); if (p_msg->security_cmd.p_data && p_msg->security_cmd.len > 0) {
*p += p_msg->security_cmd.len; memcpy(*p, p_msg->security_cmd.p_data, p_msg->security_cmd.len);
*p += p_msg->security_cmd.len;
}
} }
/******************************************************************************* /*******************************************************************************
@@ -625,6 +627,11 @@ static UINT8 avdt_msg_prs_cfg(tAVDT_CFG *p_cfg, UINT8 *p, UINT16 len, UINT8 *p_e
} }
} }
if ((size_t)(p_end - p) < elem_len) {
err = AVDT_ERR_LENGTH;
break;
}
if ((elem_len > avdt_msg_ie_len_max[elem]) || if ((elem_len > avdt_msg_ie_len_max[elem]) ||
(elem_len < avdt_msg_ie_len_min[elem])) { (elem_len < avdt_msg_ie_len_min[elem])) {
err = avdt_msg_ie_err[elem]; err = avdt_msg_ie_err[elem];
@@ -975,12 +982,19 @@ static UINT8 avdt_msg_prs_discover_rsp(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len)
int i; int i;
UINT8 err = 0; UINT8 err = 0;
if (p_msg->discover_rsp.p_sep_info == NULL) {
return AVDT_ERR_BAD_STATE;
}
/* determine number of seps; seps in msg is len/2, but set to minimum /* determine number of seps; seps in msg is len/2, but set to minimum
** of seps app has supplied memory for and seps in msg ** of seps app has supplied memory for and seps in msg
*/ */
if (p_msg->discover_rsp.num_seps > (len / 2)) { if (p_msg->discover_rsp.num_seps > (len / 2)) {
p_msg->discover_rsp.num_seps = (len / 2); p_msg->discover_rsp.num_seps = (len / 2);
} }
if (p_msg->discover_rsp.num_seps > AVDT_NUM_SEPS) {
p_msg->discover_rsp.num_seps = AVDT_NUM_SEPS;
}
/* parse out sep info */ /* parse out sep info */
for (i = 0; i < p_msg->discover_rsp.num_seps; i++) { for (i = 0; i < p_msg->discover_rsp.num_seps; i++) {
@@ -1018,6 +1032,8 @@ static UINT8 avdt_msg_prs_svccap(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len)
UINT8 err = avdt_msg_prs_cfg(p_msg->svccap.p_cfg, p, len, &p_msg->hdr.err_param, AVDT_SIG_GETCAP); UINT8 err = avdt_msg_prs_cfg(p_msg->svccap.p_cfg, p, len, &p_msg->hdr.err_param, AVDT_SIG_GETCAP);
if (p_msg->svccap.p_cfg) { if (p_msg->svccap.p_cfg) {
p_msg->svccap.p_cfg->psc_mask &= AVDT_LEG_PSC; p_msg->svccap.p_cfg->psc_mask &= AVDT_LEG_PSC;
} else {
return AVDT_ERR_BAD_STATE;
} }
return (err); return (err);
@@ -1039,6 +1055,8 @@ static UINT8 avdt_msg_prs_all_svccap(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len)
UINT8 err = avdt_msg_prs_cfg(p_msg->svccap.p_cfg, p, len, &p_msg->hdr.err_param, AVDT_SIG_GET_ALLCAP); UINT8 err = avdt_msg_prs_cfg(p_msg->svccap.p_cfg, p, len, &p_msg->hdr.err_param, AVDT_SIG_GET_ALLCAP);
if (p_msg->svccap.p_cfg) { if (p_msg->svccap.p_cfg) {
p_msg->svccap.p_cfg->psc_mask &= AVDT_MSG_PSC_MASK; p_msg->svccap.p_cfg->psc_mask &= AVDT_MSG_PSC_MASK;
} else {
return AVDT_ERR_BAD_STATE;
} }
return (err); return (err);
} }
@@ -1152,6 +1170,10 @@ BOOLEAN avdt_msg_send(tAVDT_CCB *p_ccb, BT_HDR *p_msg)
p_ccb->p_curr_msg = p_msg; p_ccb->p_curr_msg = p_msg;
} }
if (p_ccb->p_curr_msg == NULL) {
return FALSE;
}
/* store copy of curr_msg->len */ /* store copy of curr_msg->len */
curr_msg_len = p_ccb->p_curr_msg->len; curr_msg_len = p_ccb->p_curr_msg->len;
@@ -1368,10 +1390,16 @@ BT_HDR *avdt_msg_asmbl(tAVDT_CCB *p_ccb, BT_HDR *p_buf)
(UINT8 *)(p_buf + 1) + p_buf->offset, p_buf->len); (UINT8 *)(p_buf + 1) + p_buf->offset, p_buf->len);
if (pkt_type == AVDT_PKT_TYPE_END) { if (pkt_type == AVDT_PKT_TYPE_END) {
p_ccb->p_rx_msg->offset -= p_ccb->p_rx_msg->len; if (p_ccb->p_rx_msg->len <= p_ccb->p_rx_msg->offset) {
p_ccb->p_rx_msg->len += p_buf->len; p_ccb->p_rx_msg->offset -= p_ccb->p_rx_msg->len;
p_ret = p_ccb->p_rx_msg; p_ccb->p_rx_msg->len += p_buf->len;
p_ccb->p_rx_msg = NULL; p_ret = p_ccb->p_rx_msg;
p_ccb->p_rx_msg = NULL;
} else {
osi_free(p_ccb->p_rx_msg);
p_ccb->p_rx_msg = NULL;
p_ret = NULL;
}
} else { } else {
p_ccb->p_rx_msg->offset += p_buf->len; p_ccb->p_rx_msg->offset += p_buf->len;
p_ccb->p_rx_msg->len += p_buf->len; p_ccb->p_rx_msg->len += p_buf->len;
@@ -1405,6 +1433,10 @@ void avdt_msg_send_cmd(tAVDT_CCB *p_ccb, void *p_scb, UINT8 sig_id, tAVDT_MSG *p
UINT8 *p; UINT8 *p;
UINT8 *p_start; UINT8 *p_start;
if (sig_id < AVDT_SIG_DISCOVER || sig_id > AVDT_SIG_MAX) {
return;
}
/* get a buffer */ /* get a buffer */
p_buf = (BT_HDR *) osi_malloc(AVDT_CMD_BUF_SIZE); p_buf = (BT_HDR *) osi_malloc(AVDT_CMD_BUF_SIZE);
if (p_buf == NULL) { if (p_buf == NULL) {
@@ -1470,6 +1502,10 @@ void avdt_msg_send_rsp(tAVDT_CCB *p_ccb, UINT8 sig_id, tAVDT_MSG *p_params)
UINT8 *p; UINT8 *p;
UINT8 *p_start; UINT8 *p_start;
if (sig_id < AVDT_SIG_DISCOVER || sig_id > AVDT_SIG_MAX) {
return;
}
/* get a buffer */ /* get a buffer */
p_buf = (BT_HDR *) osi_malloc(AVDT_CMD_BUF_SIZE); p_buf = (BT_HDR *) osi_malloc(AVDT_CMD_BUF_SIZE);
if (p_buf == NULL) { if (p_buf == NULL) {
@@ -1656,7 +1692,11 @@ void avdt_msg_ind(tAVDT_CCB *p_ccb, BT_HDR *p_buf)
gen_rej = TRUE; gen_rej = TRUE;
if (p_ccb->p_curr_cmd != NULL) { if (p_ccb->p_curr_cmd != NULL) {
msg.hdr.sig_id = sig = (UINT8) p_ccb->p_curr_cmd->event; msg.hdr.sig_id = sig = (UINT8) p_ccb->p_curr_cmd->event;
evt = avdt_msg_rej_2_evt[sig - 1]; if (sig >= AVDT_SIG_DISCOVER && sig <= AVDT_SIG_MAX) {
evt = avdt_msg_rej_2_evt[sig - 1];
} else {
ok = FALSE;
}
msg.hdr.err_code = AVDT_ERR_NSC; msg.hdr.err_code = AVDT_ERR_NSC;
msg.hdr.err_param = 0; msg.hdr.err_param = 0;
} }
@@ -541,6 +541,10 @@ void avdt_scb_event(tAVDT_SCB *p_scb, UINT8 event, tAVDT_SCB_EVT *p_data)
UINT8 action; UINT8 action;
int i; int i;
if (p_scb == NULL || p_scb->state > AVDT_SCB_CLOSING_ST || event > AVDT_SCB_DELAY_RPT_RSP_TOUT_EVT) {
return;
}
#if AVDT_DEBUG == TRUE #if AVDT_DEBUG == TRUE
AVDT_TRACE_EVENT("SCB hdl=%d event=%d/%s state=%s\n", avdt_scb_to_hdl(p_scb), event, avdt_scb_evt_str[event], avdt_scb_st_str[p_scb->state]); AVDT_TRACE_EVENT("SCB hdl=%d event=%d/%s state=%s\n", avdt_scb_to_hdl(p_scb), event, avdt_scb_evt_str[event], avdt_scb_st_str[p_scb->state]);
#endif #endif
@@ -558,7 +562,9 @@ void avdt_scb_event(tAVDT_SCB *p_scb, UINT8 event, tAVDT_SCB_EVT *p_data)
/* execute action functions */ /* execute action functions */
for (i = 0; i < AVDT_SCB_ACTIONS; i++) { for (i = 0; i < AVDT_SCB_ACTIONS; i++) {
if ((action = state_table[event][i]) != AVDT_SCB_IGNORE) { if ((action = state_table[event][i]) != AVDT_SCB_IGNORE) {
(*avdt_cb.p_scb_act[action])(p_scb, p_data); if (action < AVDT_SCB_NUM_ACTIONS) {
(*avdt_cb.p_scb_act[action])(p_scb, p_data);
}
} else { } else {
break; break;
} }
@@ -273,6 +273,9 @@ void avdt_scb_hdl_pkt_no_frag(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
/* skip over any csrc's in packet */ /* skip over any csrc's in packet */
offset += o_cc * 4; offset += o_cc * 4;
p += o_cc * 4; p += o_cc * 4;
if (len < offset) {
goto length_error;
}
/* check for and skip over extension header */ /* check for and skip over extension header */
if (o_x) { if (o_x) {
@@ -283,6 +286,9 @@ void avdt_scb_hdl_pkt_no_frag(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
} }
p += 2; p += 2;
BE_STREAM_TO_UINT16(ex_len, p); BE_STREAM_TO_UINT16(ex_len, p);
if ((UINT32)ex_len * 4 > (UINT32)(len - offset)) {
goto length_error;
}
p += ex_len * 4; p += ex_len * 4;
} }
@@ -317,12 +323,12 @@ void avdt_scb_hdl_pkt_no_frag(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
#if AVDT_MULTIPLEXING == TRUE #if AVDT_MULTIPLEXING == TRUE
if ((p_scb->cs.p_media_cback != NULL) if ((p_scb->cs.p_media_cback != NULL)
&& (p_scb->p_media_buf != NULL) && (p_scb->p_media_buf != NULL)
&& (p_scb->media_buf_len > len)) { && (p_scb->media_buf_len > p_data->p_pkt->len)) {
/* media buffer enough length is assigned by application. Lets use it*/ /* media buffer enough length is assigned by application. Lets use it*/
memcpy(p_scb->p_media_buf, (UINT8 *)(p_data->p_pkt + 1) + p_data->p_pkt->offset, memcpy(p_scb->p_media_buf, (UINT8 *)(p_data->p_pkt + 1) + p_data->p_pkt->offset,
len); p_data->p_pkt->len);
(*p_scb->cs.p_media_cback)(avdt_scb_to_hdl(p_scb), p_scb->p_media_buf, (*p_scb->cs.p_media_cback)(avdt_scb_to_hdl(p_scb), p_scb->p_media_buf,
p_scb->media_buf_len, time_stamp, seq, m_pt, marker); p_data->p_pkt->len, time_stamp, seq, m_pt, marker);
} }
#endif #endif
goto length_error; goto length_error;
@@ -355,6 +361,8 @@ UINT8 *avdt_scb_hdl_report(tAVDT_SCB *p_scb, UINT8 *p, UINT16 len)
AVDT_REPORT_TYPE pt; AVDT_REPORT_TYPE pt;
tAVDT_REPORT_DATA report; tAVDT_REPORT_DATA report;
memset(&report, 0, sizeof(report));
AVDT_TRACE_DEBUG( "avdt_scb_hdl_report"); AVDT_TRACE_DEBUG( "avdt_scb_hdl_report");
if (p_scb->cs.p_report_cback) { if (p_scb->cs.p_report_cback) {
/* parse report packet header */ /* parse report packet header */
@@ -417,7 +425,7 @@ UINT8 *avdt_scb_hdl_report(tAVDT_SCB *p_scb, UINT8 *p, UINT16 len)
goto avdt_scb_hdl_report_exit; goto avdt_scb_hdl_report_exit;
} }
uint8_t name_length; uint8_t name_length;
BE_STREAM_TO_UINT8(name_length, p);\ BE_STREAM_TO_UINT8(name_length, p);
if ((name_length > len - min_len) || (name_length > AVDT_MAX_CNAME_SIZE)) { if ((name_length > len - min_len) || (name_length > AVDT_MAX_CNAME_SIZE)) {
result = AVDT_BAD_PARAMS; result = AVDT_BAD_PARAMS;
} else { } else {
@@ -643,6 +651,11 @@ void avdt_scb_hdl_pkt_frag(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
pad_len = 0; pad_len = 0;
} }
/* payload length */ /* payload length */
if ((pad_len + p_payload) >= (p_scb->p_media_buf + p_scb->frag_off)) {
AVDT_TRACE_WARNING("length check3 p_payload:%p pad_len:%d p_media_buf:%p frag_off:%d",
p_payload, pad_len, p_scb->p_media_buf, p_scb->frag_off);
break;
}
payload_len = (UINT32)(p_scb->p_media_buf + p_scb->frag_off - pad_len - p_payload); payload_len = (UINT32)(p_scb->p_media_buf + p_scb->frag_off - pad_len - p_payload);
AVDT_TRACE_DEBUG("Received last fragment header=%d len=%d\n", AVDT_TRACE_DEBUG("Received last fragment header=%d len=%d\n",
@@ -1054,10 +1067,13 @@ void avdt_scb_hdl_tc_close(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
tAVDT_CTRL avdt_ctrl; tAVDT_CTRL avdt_ctrl;
UINT8 event; UINT8 event;
tAVDT_CCB *p_ccb = p_scb->p_ccb; tAVDT_CCB *p_ccb = p_scb->p_ccb;
BD_ADDR remote_addr; BD_ADDR remote_addr;
if (p_ccb != NULL) {
memcpy (remote_addr, p_ccb->peer_addr, BD_ADDR_LEN); memcpy(remote_addr, p_ccb->peer_addr, BD_ADDR_LEN);
} else {
memset(remote_addr, 0, BD_ADDR_LEN);
}
/* set up hdr */ /* set up hdr */
avdt_ctrl.hdr.err_code = p_scb->close_code; avdt_ctrl.hdr.err_code = p_scb->close_code;
@@ -1331,6 +1347,12 @@ void avdt_scb_hdl_write_req_no_frag(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
if ( !(p_data->apiwrite.opt & AVDT_DATA_OPT_NO_RTP) ) { if ( !(p_data->apiwrite.opt & AVDT_DATA_OPT_NO_RTP) ) {
ssrc = avdt_scb_gen_ssrc(p_scb); ssrc = avdt_scb_gen_ssrc(p_scb);
if (p_data->apiwrite.p_buf->offset < AVDT_MEDIA_HDR_SIZE) {
osi_free(p_data->apiwrite.p_buf);
p_data->apiwrite.p_buf = NULL;
return;
}
p_data->apiwrite.p_buf->len += AVDT_MEDIA_HDR_SIZE; p_data->apiwrite.p_buf->len += AVDT_MEDIA_HDR_SIZE;
p_data->apiwrite.p_buf->offset -= AVDT_MEDIA_HDR_SIZE; p_data->apiwrite.p_buf->offset -= AVDT_MEDIA_HDR_SIZE;
p_scb->media_seq++; p_scb->media_seq++;
@@ -1838,6 +1860,11 @@ void avdt_scb_cb_err(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
avdt_ctrl.hdr.err_code = AVDT_ERR_BAD_STATE; avdt_ctrl.hdr.err_code = AVDT_ERR_BAD_STATE;
avdt_ctrl.hdr.err_param = 0; avdt_ctrl.hdr.err_param = 0;
if (p_scb->curr_evt >= (sizeof(avdt_scb_cback_evt) / sizeof(avdt_scb_cback_evt[0]))) {
AVDT_TRACE_ERROR("avdt_scb_cb_err curr_evt %u OOR", p_scb->curr_evt);
return;
}
/* call callback, using lookup table to get callback event */ /* call callback, using lookup table to get callback event */
(*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb), (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb),
NULL, NULL,