Merge branch 'bugfix/ai_review_a2dp' into 'master'

fix(bt): fix A2DP issues reported by AI code review

Closes BT-4288

See merge request espressif/esp-idf!46787
This commit is contained in:
Wang Meng Yang
2026-04-20 09:21:12 +08:00
33 changed files with 592 additions and 147 deletions
@@ -77,7 +77,7 @@ esp_err_t esp_a2d_sink_register_stream_endpoint(uint8_t seid, const esp_a2d_mcc_
return ESP_ERR_INVALID_STATE;
}
if (seid >= ESP_A2D_MAX_SEPS) {
if (mcc == NULL || seid >= ESP_A2D_MAX_SEPS) {
return ESP_ERR_INVALID_ARG;
}
@@ -209,6 +209,7 @@ esp_err_t esp_a2d_sink_disconnect(esp_bd_addr_t remote_bda)
msg.pid = BTC_PID_A2DP;
msg.act = BTC_AV_SINK_API_DISCONNECT_EVT;
memset(&arg, 0, sizeof(btc_av_args_t));
/* Switch to BTC context */
memcpy(&(arg.disconn), remote_bda, sizeof(bt_bdaddr_t));
stat = btc_transfer_context(&msg, &arg, sizeof(btc_av_args_t), NULL, NULL);
@@ -292,7 +293,7 @@ esp_err_t esp_a2d_media_ctrl(esp_a2d_media_ctrl_t ctrl)
return ESP_ERR_INVALID_STATE;
}
if (ctrl > ESP_A2D_MEDIA_CTRL_SUSPEND) {
if (ctrl <= ESP_A2D_MEDIA_CTRL_NONE || ctrl > ESP_A2D_MEDIA_CTRL_SUSPEND) {
return ESP_ERR_INVALID_ARG;
}
@@ -388,7 +389,7 @@ esp_err_t esp_a2d_source_register_stream_endpoint(uint8_t seid, const esp_a2d_mc
return ESP_ERR_INVALID_STATE;
}
if (seid >= ESP_A2D_MAX_SEPS) {
if (mcc == NULL || seid >= ESP_A2D_MAX_SEPS) {
return ESP_ERR_INVALID_ARG;
}
+13 -10
View File
@@ -146,10 +146,11 @@ void bta_ar_dereg_avdt(tBTA_SYS_ID sys_id)
bta_ar_cb.p_avk_conn_cback = NULL;
mask = BTA_AR_AVK_MASK;
}
bta_ar_cb.avdt_registered &= ~mask;
if (bta_ar_cb.avdt_registered == 0) {
AVDT_Deregister();
if (mask) {
bta_ar_cb.avdt_registered &= ~mask;
if (bta_ar_cb.avdt_registered == 0) {
AVDT_Deregister();
}
}
}
@@ -170,6 +171,7 @@ void bta_ar_avdt_conn(tBTA_SYS_ID sys_id, BD_ADDR bd_addr)
UINT8 event = BTA_AR_AVDT_CONN_EVT;
tAVDT_CTRL data;
memset(&data, 0, sizeof(tAVDT_CTRL));
if (sys_id == BTA_ID_AV) {
if (bta_ar_cb.p_avk_conn_cback) {
(*bta_ar_cb.p_avk_conn_cback)(0, bd_addr, event, &data);
@@ -215,10 +217,11 @@ void bta_ar_dereg_avct(tBTA_SYS_ID sys_id)
{
UINT8 mask = bta_ar_id (sys_id);
bta_ar_cb.avct_registered &= ~mask;
if (bta_ar_cb.avct_registered == 0) {
AVCT_Deregister();
if (mask) {
bta_ar_cb.avct_registered &= ~mask;
if (bta_ar_cb.avct_registered == 0) {
AVCT_Deregister();
}
}
}
@@ -299,12 +302,12 @@ void bta_ar_dereg_avrc(UINT16 service_uuid, tBTA_SYS_ID sys_id)
bta_ar_cb.ct_categories [mask - 1] = 0;
categories = bta_ar_cb.ct_categories[0] | bta_ar_cb.ct_categories[1];
if (!categories) {
/* no CT is still registered - cleaup */
/* no CT is still registered - cleanup */
SDP_DeleteRecord(bta_ar_cb.sdp_ct_handle);
bta_ar_cb.sdp_ct_handle = 0;
bta_sys_remove_uuid(service_uuid);
} else {
/* change supported categories to the remaning one */
/* change supported categories to the remaining one */
p = temp;
UINT16_TO_BE_STREAM(p, categories);
SDP_AddAttribute(bta_ar_cb.sdp_ct_handle, ATTR_ID_SUPPORTED_FEATURES, UINT_DESC_TYPE,
@@ -522,6 +522,11 @@ static void bta_av_proc_stream_evt(UINT8 handle, BD_ADDR bd_addr, UINT8 event, t
}
/* look up application event */
/* bounds check to avoid out-of-bounds read */
if (event >= sizeof(bta_av_stream_evt_ok) / sizeof(bta_av_stream_evt_ok[0])) {
osi_free(p_msg);
return;
}
if ((p_data == NULL) || (p_data->hdr.err_code == 0)) {
p_msg->hdr.event = bta_av_stream_evt_ok[event];
if (p_msg->hdr.event == BTA_AV_STR_START_OK_EVT) {
@@ -582,7 +587,7 @@ void bta_av_stream_data_cback(UINT8 handle, BT_HDR *p_pkt, UINT32 time_stamp, UI
/* Get SCB and correct sep type*/
for (index = 0; index < BTA_AV_NUM_STRS; index ++ ) {
p_scb = bta_av_cb.p_scb[index];
if ((p_scb->avdt_handle == handle) && (p_scb->seps[p_scb->sep_idx].tsep == AVDT_TSEP_SNK)) {
if (p_scb && (p_scb->avdt_handle == handle) && (p_scb->seps[p_scb->sep_idx].tsep == AVDT_TSEP_SNK)) {
break;
}
}
@@ -731,6 +736,7 @@ static void bta_av_a2d_sdp_cback(BOOLEAN found, tA2D_Service *p_service)
bta_sys_sendmsg(p_msg);
} else {
APPL_TRACE_ERROR ("bta_av_a2d_sdp_cback, no scb found for handle(0x%x)", bta_av_cb.handle);
osi_free(p_msg);
}
}
}
@@ -1643,7 +1649,7 @@ void bta_av_disc_results (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
p_data->str_msg.msg.discover_cfm.p_sep_info[i].tsep
);
}
for (i = 0; i < p_scb->num_seps; i++) {
for (i = 0; i < num_seps; i++) {
/* steam not in use, is a sink, and is audio */
if ((p_scb->sep_info[i].in_use == FALSE) &&
(p_scb->sep_info[i].media_type == p_scb->media_type)) {
@@ -1883,6 +1889,11 @@ void bta_av_getcap_results (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
UINT16 uuid_int; /* UUID for which connection was initiated */
tBTA_AV_SNK_PSC_CFG psc_cfg = {0};
if (p_scb->p_cap == NULL) {
APPL_TRACE_ERROR("bta_av_getcap_results: p_cap is NULL");
bta_av_ssm_execute(p_scb, BTA_AV_STR_GETCAP_FAIL_EVT, p_data);
return;
}
memcpy(&cfg, &p_scb->cfg, sizeof(tAVDT_CFG));
cfg.num_codec = 1;
cfg.num_protect = p_scb->p_cap->num_protect;
@@ -2178,9 +2189,9 @@ void bta_av_reconfig (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
bta_sys_stop_timer(&p_scb->timer);
memcpy(p_cfg, &p_scb->cfg, sizeof(tAVDT_CFG));
p_cfg->num_protect = p_rcfg->num_protect;
p_cfg->num_protect = (p_rcfg->num_protect <= AVDT_PROTECT_SIZE) ? p_rcfg->num_protect : AVDT_PROTECT_SIZE;
memcpy(p_cfg->codec_info, p_rcfg->codec_info, AVDT_CODEC_SIZE);
memcpy(p_cfg->protect_info, p_rcfg->p_protect_info, p_rcfg->num_protect);
memcpy(p_cfg->protect_info, p_rcfg->p_protect_info, p_cfg->num_protect);
p_scb->rcfg_idx = p_rcfg->sep_info_idx;
p_scb->p_cap->psc_mask = p_scb->cur_psc_mask;
@@ -2393,7 +2404,12 @@ void bta_av_start_ok (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
* If the code were to be re-arranged for some reasons, this number may need to be changed
*/
p_scb->co_started = bta_av_cb.audio_open_cnt;
flush_to = p_bta_av_cfg->p_audio_flush_to[p_scb->co_started - 1];
if (p_scb->co_started > 0) {
flush_to = p_bta_av_cfg->p_audio_flush_to[p_scb->co_started - 1];
} else {
APPL_TRACE_ERROR("bta_av_start_ok: co_started is 0");
flush_to = p_bta_av_cfg->p_audio_flush_to[0];
}
} else {
flush_to = p_bta_av_cfg->video_flush_to;
}
@@ -2785,7 +2801,11 @@ void bta_av_suspend_cont (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
if (AVDT_ERR_CONNECT == err_code) {
/* report failure */
evt.status = BTA_AV_FAIL;
(*bta_av_cb.p_cback)(BTA_AV_RECONFIG_EVT, (tBTA_AV *)&evt);
evt.chnl = p_scb->chnl;
evt.hndl = p_scb->hndl;
if (bta_av_cb.p_cback) {
(*bta_av_cb.p_cback)(BTA_AV_RECONFIG_EVT, (tBTA_AV *)&evt);
}
bta_av_ssm_execute(p_scb, BTA_AV_STR_DISC_FAIL_EVT, NULL);
} else {
APPL_TRACE_ERROR("suspend rejected, try close");
@@ -2801,9 +2821,18 @@ void bta_av_suspend_cont (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
} else {
APPL_TRACE_DEBUG("bta_av_suspend_cont calling AVDT_ReconfigReq");
/* reconfig the stream */
AVDT_ReconfigReq(p_scb->avdt_handle, p_scb->p_cap);
p_scb->p_cap->psc_mask = p_scb->cur_psc_mask;
if (p_scb->p_cap == NULL) {
evt.status = BTA_AV_FAIL;
evt.chnl = p_scb->chnl;
evt.hndl = p_scb->hndl;
if (bta_av_cb.p_cback) {
(*bta_av_cb.p_cback)(BTA_AV_RECONFIG_EVT, (tBTA_AV *)&evt);
}
bta_av_ssm_execute(p_scb, BTA_AV_STR_DISC_FAIL_EVT, NULL);
} else {
AVDT_ReconfigReq(p_scb->avdt_handle, p_scb->p_cap);
p_scb->p_cap->psc_mask = p_scb->cur_psc_mask;
}
}
}
@@ -298,12 +298,18 @@ UINT8 bta_av_rc_create(tBTA_AV_CB *p_cb, UINT8 role, UINT8 shdl, UINT8 lidx)
tAVRC_CONN_CB ccb;
BD_ADDR_PTR bda = (BD_ADDR_PTR)bd_addr_any;
UINT8 status = BTA_AV_RC_ROLE_ACP;
tBTA_AV_SCB *p_scb = p_cb->p_scb[shdl - 1];
tBTA_AV_SCB *p_scb = NULL;
int i;
UINT8 rc_handle;
tBTA_AV_RCB *p_rcb;
if (shdl > 0 && shdl <= BTA_AV_NUM_STRS) {
p_scb = p_cb->p_scb[shdl - 1];
}
if (role == AVCT_INT) {
if (p_scb == NULL) {
return BTA_AV_RC_HANDLE_NONE;
}
bda = p_scb->peer_addr;
status = BTA_AV_RC_ROLE_INT;
} else {
@@ -325,6 +331,11 @@ UINT8 bta_av_rc_create(tBTA_AV_CB *p_cb, UINT8 role, UINT8 shdl, UINT8 lidx)
return BTA_AV_RC_HANDLE_NONE;
}
if (rc_handle >= BTA_AV_NUM_RCB) {
APPL_TRACE_ERROR("bta_av_rc_create: EINVAL rc_handle %u", rc_handle);
AVRC_Close(rc_handle);
return BTA_AV_RC_HANDLE_NONE;
}
i = rc_handle;
p_rcb = &p_cb->rcb[i];
@@ -834,7 +845,7 @@ void bta_av_rc_msg(tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data)
tBTA_AV av;
BT_HDR *p_pkt = NULL;
tAVRC_MSG_VENDOR *p_vendor = &p_data->rc_msg.msg.vendor;
BOOLEAN is_inquiry = ((p_data->rc_msg.msg.hdr.ctype == AVRC_CMD_SPEC_INQ) || p_data->rc_msg.msg.hdr.ctype == AVRC_CMD_GEN_INQ);
BOOLEAN is_inquiry = ((p_data->rc_msg.msg.hdr.ctype == AVRC_CMD_SPEC_INQ) || (p_data->rc_msg.msg.hdr.ctype == AVRC_CMD_GEN_INQ));
#if (AVRC_METADATA_INCLUDED == TRUE)
UINT8 ctype = 0;
tAVRC_RESPONSE rc_rsp;
@@ -936,7 +947,9 @@ void bta_av_rc_msg(tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data)
/* else if not configured to support vendor specific and it's a command */
else if (!(p_cb->features & BTA_AV_FEAT_VENDOR) &&
p_data->rc_msg.msg.hdr.ctype <= AVRC_CMD_GEN_INQ) {
if (p_data->rc_msg.msg.vendor.p_vendor_data[0] == AVRC_PDU_INVALID) {
if (p_data->rc_msg.msg.vendor.p_vendor_data != NULL &&
p_data->rc_msg.msg.vendor.vendor_len >= 5 &&
p_data->rc_msg.msg.vendor.p_vendor_data[0] == AVRC_PDU_INVALID) {
/* reject it */
p_data->rc_msg.msg.hdr.ctype = BTA_AV_RSP_REJ;
p_data->rc_msg.msg.vendor.p_vendor_data[4] = AVRC_STS_BAD_CMD;
@@ -1704,11 +1717,16 @@ void bta_av_rc_disc_done(tBTA_AV_DATA *p_data)
/* cannot create valid rc_handle for current device. report failure */
APPL_TRACE_ERROR("%s: no link resources available", __func__);
p_scb->use_rc = FALSE;
rc_open.rc_handle = BTA_AV_RC_HANDLE_NONE;
bdcpy(rc_open.peer_addr, p_scb->peer_addr);
rc_open.peer_features = 0;
rc_open.peer_ct_features = 0;
rc_open.peer_tg_features = 0;
rc_open.sdp_disc_done = FALSE;
rc_open.status = BTA_AV_FAIL_SDP;
(*p_cb->p_cback)(BTA_AV_RC_OPEN_EVT, (tBTA_AV *) &rc_open);
if (p_cb->p_cback) {
(*p_cb->p_cback)(BTA_AV_RC_OPEN_EVT, (tBTA_AV *) &rc_open);
}
}
}
#if (BT_USE_TRACES == TRUE || BT_TRACE_APPL == TRUE)
@@ -1719,11 +1737,16 @@ void bta_av_rc_disc_done(tBTA_AV_DATA *p_data)
} else if (p_scb->use_rc) {
/* can not find AVRC on peer device. report failure */
p_scb->use_rc = FALSE;
rc_open.rc_handle = BTA_AV_RC_HANDLE_NONE;
bdcpy(rc_open.peer_addr, p_scb->peer_addr);
rc_open.peer_features = 0;
rc_open.peer_ct_features = 0;
rc_open.peer_tg_features = 0;
rc_open.sdp_disc_done = FALSE;
rc_open.status = BTA_AV_FAIL_SDP;
(*p_cb->p_cback)(BTA_AV_RC_OPEN_EVT, (tBTA_AV *) &rc_open);
if (p_cb->p_cback) {
(*p_cb->p_cback)(BTA_AV_RC_OPEN_EVT, (tBTA_AV *) &rc_open);
}
}
}
} else {
@@ -1737,7 +1760,9 @@ void bta_av_rc_disc_done(tBTA_AV_DATA *p_data)
rc_feat.peer_features = peer_features;
rc_feat.peer_ct_features = peer_ct_features;
rc_feat.peer_tg_features = peer_tg_features;
(*p_cb->p_cback)(BTA_AV_RC_FEAT_EVT, (tBTA_AV *) &rc_feat);
if (p_cb->p_cback) {
(*p_cb->p_cback)(BTA_AV_RC_FEAT_EVT, (tBTA_AV *) &rc_feat);
}
}
}
@@ -1866,12 +1891,17 @@ void bta_av_rc_disc(UINT8 disc)
if ((disc & BTA_AV_CHNL_MSK) == BTA_AV_CHNL_MSK) {
/* this is the rc handle/index to tBTA_AV_RCB */
rc_handle = disc & (~BTA_AV_CHNL_MSK);
if (p_cb->rcb[rc_handle].lidx) {
if (rc_handle < BTA_AV_NUM_RCB && p_cb->rcb[rc_handle].lidx > 0 &&
p_cb->rcb[rc_handle].lidx <= (BTA_AV_NUM_LINKS + 1)) {
p_addr = p_cb->lcb[p_cb->rcb[rc_handle].lidx - 1].addr;
}
} else {
hdi = (disc & BTA_AV_HNDL_MSK) - 1;
p_scb = p_cb->p_scb[hdi];
hdi = (disc & BTA_AV_HNDL_MSK);
if (hdi > 0 && (hdi - 1) < BTA_AV_NUM_STRS) {
p_scb = p_cb->p_scb[hdi - 1];
} else {
p_scb = NULL;
}
if (p_scb) {
APPL_TRACE_DEBUG("rc_handle %d", p_scb->rc_handle);
@@ -117,6 +117,7 @@ void BTA_AvRegister(tBTA_AV_CHNL chnl, const char *p_service_name, UINT8 app_id,
p_buf->hdr.event = BTA_AV_API_REGISTER_EVT;
if (p_service_name) {
BCM_STRNCPY_S(p_buf->p_service_name, p_service_name, BTA_SERVICE_NAME_LEN);
p_buf->p_service_name[BTA_SERVICE_NAME_LEN] = '\0';
} else {
p_buf->p_service_name[0] = '\0';
}
@@ -133,6 +134,9 @@ void BTA_AvRegSEP(tBTA_AV_CHNL chnl, UINT8 seid, UINT8 tsep, tBTA_AV_CODEC codec
{
tBTA_AV_API_REG_SEP *p_buf;
if (p_codec_info == NULL) {
return;
}
if ((p_buf = (tBTA_AV_API_REG_SEP *) osi_malloc(sizeof(tBTA_AV_API_REG_SEP))) != NULL) {
p_buf->hdr.layer_specific = chnl;
p_buf->hdr.event = BTA_AV_API_REG_SEP_EVT;
@@ -344,8 +348,14 @@ void BTA_AvReconfig(tBTA_AV_HNDL hndl, BOOLEAN suspend, UINT8 sep_info_idx,
void BTA_AvProtectReq(tBTA_AV_HNDL hndl, UINT8 *p_data, UINT16 len)
{
tBTA_AV_API_PROTECT_REQ *p_buf;
size_t alloc_size;
if ((p_buf = (tBTA_AV_API_PROTECT_REQ *) osi_malloc((UINT16) (sizeof(tBTA_AV_API_PROTECT_REQ) + len))) != NULL) {
/* Cap allocation size to avoid UINT16 overflow */
alloc_size = sizeof(tBTA_AV_API_PROTECT_REQ) + len;
if (alloc_size > 0xFFFF) {
return;
}
if ((p_buf = (tBTA_AV_API_PROTECT_REQ *) osi_malloc((UINT16) alloc_size)) != NULL) {
p_buf->hdr.layer_specific = hndl;
p_buf->hdr.event = BTA_AV_API_PROTECT_REQ_EVT;
p_buf->len = len;
@@ -374,8 +384,14 @@ void BTA_AvProtectReq(tBTA_AV_HNDL hndl, UINT8 *p_data, UINT16 len)
void BTA_AvProtectRsp(tBTA_AV_HNDL hndl, UINT8 error_code, UINT8 *p_data, UINT16 len)
{
tBTA_AV_API_PROTECT_RSP *p_buf;
size_t alloc_size;
if ((p_buf = (tBTA_AV_API_PROTECT_RSP *) osi_malloc((UINT16) (sizeof(tBTA_AV_API_PROTECT_RSP) + len))) != NULL) {
/* Cap allocation size to avoid UINT16 overflow */
alloc_size = sizeof(tBTA_AV_API_PROTECT_RSP) + len;
if (alloc_size > UINT16_MAX) {
return;
}
if ((p_buf = (tBTA_AV_API_PROTECT_RSP *) osi_malloc((UINT16) alloc_size)) != NULL) {
p_buf->hdr.layer_specific = hndl;
p_buf->hdr.event = BTA_AV_API_PROTECT_RSP_EVT;
p_buf->len = len;
@@ -469,8 +485,14 @@ void BTA_AvRemoteCmd(UINT8 rc_handle, UINT8 label, tBTA_AV_RC rc_id, tBTA_AV_STA
void BTA_AvVendorCmd(UINT8 rc_handle, UINT8 label, tBTA_AV_CODE cmd_code, UINT8 *p_data, UINT16 len)
{
tBTA_AV_API_VENDOR *p_buf;
size_t alloc_size;
if ((p_buf = (tBTA_AV_API_VENDOR *) osi_malloc((UINT16) (sizeof(tBTA_AV_API_VENDOR) + len))) != NULL) {
/* Cap allocation size to avoid UINT16 overflow */
alloc_size = sizeof(tBTA_AV_API_VENDOR) + len;
if (alloc_size > UINT16_MAX) {
return;
}
if ((p_buf = (tBTA_AV_API_VENDOR *) osi_malloc((UINT16) alloc_size)) != NULL) {
p_buf->hdr.event = BTA_AV_API_VENDOR_CMD_EVT;
p_buf->hdr.layer_specific = rc_handle;
p_buf->msg.hdr.ctype = cmd_code;
@@ -504,8 +526,14 @@ void BTA_AvVendorCmd(UINT8 rc_handle, UINT8 label, tBTA_AV_CODE cmd_code, UINT8
void BTA_AvVendorRsp(UINT8 rc_handle, UINT8 label, tBTA_AV_CODE rsp_code, UINT8 *p_data, UINT16 len, UINT32 company_id)
{
tBTA_AV_API_VENDOR *p_buf;
size_t alloc_size;
if ((p_buf = (tBTA_AV_API_VENDOR *) osi_malloc((UINT16) (sizeof(tBTA_AV_API_VENDOR) + len))) != NULL) {
/* Cap allocation size to avoid UINT16 overflow */
alloc_size = sizeof(tBTA_AV_API_VENDOR) + len;
if (alloc_size > 0xFFFF) {
return;
}
if ((p_buf = (tBTA_AV_API_VENDOR *) osi_malloc((UINT16) alloc_size)) != NULL) {
p_buf->hdr.event = BTA_AV_API_VENDOR_RSP_EVT;
p_buf->hdr.layer_specific = rc_handle;
p_buf->msg.hdr.ctype = rsp_code;
@@ -627,6 +655,8 @@ void BTA_AvMetaCmd(UINT8 rc_handle, UINT8 label, tBTA_AV_CMD cmd_code, BT_HDR *p
p_buf->label = label;
bta_sys_sendmsg(p_buf);
} else if (p_pkt) {
osi_free(p_pkt);
}
}
@@ -689,14 +719,30 @@ void BTA_AvCaClose(UINT8 rc_handle)
void BTA_AvCaGet(UINT8 rc_handle, tBTA_AV_GET_TYPE type, UINT8 *image_handle, UINT8 *image_descriptor, UINT16 image_descriptor_len)
{
tBTA_AV_API_CA_GET *p_buf;
size_t alloc_size;
if ((p_buf = (tBTA_AV_API_CA_GET *) osi_malloc(sizeof(tBTA_AV_API_CA_GET))) != NULL) {
/* NULL image_handle would cause crash in memcpy; reject early */
if (image_handle == NULL) {
return;
}
/* Cap allocation size to avoid overflow */
alloc_size = sizeof(tBTA_AV_API_CA_GET) + image_descriptor_len;
if (alloc_size > 0xFFFF) {
return;
}
if ((p_buf = (tBTA_AV_API_CA_GET *) osi_malloc((UINT16) alloc_size)) != NULL) {
p_buf->hdr.event = BTA_AV_API_CA_GET_EVT;
p_buf->hdr.layer_specific = rc_handle;
p_buf->type = type;
memcpy(p_buf->image_handle, image_handle, BTA_AV_CA_IMG_HDL_LEN);
p_buf->image_descriptor = image_descriptor;
p_buf->image_descriptor_len = image_descriptor_len;
/* Copy image_descriptor into message to avoid use-after-free when message is async */
if (image_descriptor != NULL && image_descriptor_len > 0) {
p_buf->image_descriptor = (UINT8 *) (p_buf + 1);
memcpy(p_buf->image_descriptor, image_descriptor, image_descriptor_len);
} else {
p_buf->image_descriptor = NULL;
}
bta_sys_sendmsg(p_buf);
}
}
@@ -61,7 +61,7 @@ const UINT16 bta_av_audio_flush_to[] = {
0 /* 5 streams */
}; /* AVDTP audio transport channel flush timeout */
/* Note: Android doesnt support AVRC_SUPF_TG_GROUP_NAVI */
/* Note: Android doesn't support AVRC_SUPF_TG_GROUP_NAVI */
/* Note: if AVRC_SUPF_TG_GROUP_NAVI is set, bta_av_cfg.avrc_group should be TRUE */
#if AVRC_METADATA_INCLUDED == TRUE
#define BTA_AV_RC_SNK_SUPF_TG (AVRC_SUPF_TG_CAT2) /* TODO: | AVRC_SUPF_TG_APP_SETTINGS) */
@@ -105,6 +105,6 @@ const tBTA_AV_CFG bta_av_cfg = {
{0}, /* Default AVRCP target name */
};
tBTA_AV_CFG *p_bta_av_cfg = (tBTA_AV_CFG *) &bta_av_cfg;
const tBTA_AV_CFG *p_bta_av_cfg = &bta_av_cfg;
#endif /* if defined(BTA_AV_INCLUDED) && (BTA_AV_INCLUDED == TRUE) */
@@ -82,7 +82,7 @@ void bta_av_ci_setconfig(tBTA_AV_HNDL hndl, UINT8 err_code, UINT8 category,
p_buf->category = category;
p_buf->recfg_needed = recfg_needed;
p_buf->avdt_handle = avdt_handle;
p_buf->num_seid = num_seid;
p_buf->num_seid = (p_seid != NULL) ? num_seid : 0;
if (p_seid && num_seid) {
memcpy(p_buf->p_seid, p_seid, num_seid);
}
@@ -368,7 +368,12 @@ static tBTA_AV_SCB *bta_av_alloc_scb(tBTA_AV_CHNL chnl)
p_ret->hndl = (tBTA_AV_HNDL)((xx + 1) | chnl);
p_ret->hdi = xx;
p_ret->a2d_list = list_new(NULL);
bta_av_cb.p_scb[xx] = p_ret;
if (p_ret->a2d_list == NULL) {
osi_free(p_ret);
p_ret = NULL;
} else {
bta_av_cb.p_scb[xx] = p_ret;
}
}
break;
}
@@ -417,13 +422,15 @@ void bta_av_conn_cback(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CTRL *p
p_scb = bta_av_addr_to_scb(bd_addr);
}
else if (AVDT_CONNECT_IND_EVT == event) {
APPL_TRACE_DEBUG("CONN_IND is ACP:%d\n", p_data->hdr.err_param);
if (p_data) {
APPL_TRACE_DEBUG("CONN_IND is ACP:%d\n", p_data->hdr.err_param);
}
}
if ((p_msg = (tBTA_AV_STR_MSG *) osi_malloc((UINT16) (sizeof(tBTA_AV_STR_MSG)))) != NULL) {
p_msg->hdr.event = evt;
p_msg->hdr.layer_specific = event;
p_msg->hdr.offset = p_data->hdr.err_param;
p_msg->hdr.offset = p_data ? p_data->hdr.err_param : 0;
bdcpy(p_msg->bd_addr, bd_addr);
if (p_scb) {
APPL_TRACE_DEBUG("scb hndl x%x, role x%x\n", p_scb->hndl, p_scb->role);
@@ -1264,9 +1271,9 @@ void bta_av_dup_audio_buf(tBTA_AV_SCB *p_scb, BT_HDR *p_buf)
if (list_length(p_scbi->a2d_list) > p_bta_av_cfg->audio_mqs) {
// Drop the oldest packet
bta_av_co_audio_drop(p_scbi->hndl);
BT_HDR *p_buf = list_front(p_scbi->a2d_list);
list_remove(p_scbi->a2d_list, p_buf);
osi_free(p_buf);
BT_HDR *p_buf_drop = list_front(p_scbi->a2d_list);
list_remove(p_scbi->a2d_list, p_buf_drop);
osi_free(p_buf_drop);
}
}
}
@@ -1290,6 +1297,10 @@ void bta_av_sm_execute(tBTA_AV_CB *p_cb, UINT16 event, tBTA_AV_DATA *p_data)
tBTA_AV_ST_TBL state_table;
UINT8 action;
if (p_cb == NULL || p_cb->state >= (sizeof(bta_av_st_tbl) / sizeof(bta_av_st_tbl[0]))) {
return;
}
APPL_TRACE_EVENT("AV event=0x%x state=%d\n", event, p_cb->state);
/* look up the state table for the current state */
@@ -1297,6 +1308,10 @@ void bta_av_sm_execute(tBTA_AV_CB *p_cb, UINT16 event, tBTA_AV_DATA *p_data)
event &= 0x00FF;
if (event >= (sizeof(bta_av_st_init) / sizeof(bta_av_st_init[0]))) {
return;
}
/* set next state */
p_cb->state = state_table[event][BTA_AV_NEXT_STATE];
APPL_TRACE_EVENT("next state=%d\n", p_cb->state);
@@ -1329,8 +1344,10 @@ BOOLEAN bta_av_hdl_event(BT_HDR *p_msg)
if (event >= first_event) {
APPL_TRACE_VERBOSE("AV nsm event=0x%x(%s)\n", event, bta_av_evt_code(event));
/* non state machine events */
(*bta_av_nsm_act[event - BTA_AV_FIRST_NSM_EVT]) ((tBTA_AV_DATA *) p_msg);
if (event <= BTA_AV_LAST_NSM_EVT) {
/* 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) {
APPL_TRACE_VERBOSE("AV sm event=0x%x(%s)\n", event, bta_av_evt_code(event));
/* state machine events */
@@ -119,7 +119,9 @@ int bta_av_sbc_up_sample (void *p_src, void *p_dst,
dst = dst_samples / bta_av_sbc_ups_cb.div;
return (*bta_av_sbc_ups_cb.p_act)(p_src, p_dst, src, dst, p_ret);
} else {
*p_ret = 0;
if (p_ret) {
*p_ret = 0;
}
return 0;
}
}
@@ -212,7 +214,7 @@ int bta_av_sbc_up_sample_16m (void *p_src, void *p_dst,
UINT32 src_sps = bta_av_sbc_ups_cb.src_sps;
UINT32 dst_sps = bta_av_sbc_ups_cb.dst_sps;
while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples) {
while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples >= 2) {
*p_dst_tmp++ = *p_worker;
*p_dst_tmp++ = *p_worker;
@@ -224,7 +226,7 @@ int bta_av_sbc_up_sample_16m (void *p_src, void *p_dst,
bta_av_sbc_ups_cb.cur_pos = dst_sps;
while (src_samples-- && dst_samples) {
while (src_samples-- && dst_samples >= 2) {
*p_worker = *p_src_tmp++;
do {
@@ -235,7 +237,7 @@ int bta_av_sbc_up_sample_16m (void *p_src, void *p_dst,
dst_samples--;
dst_samples--;
} while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples);
} while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples >= 2);
bta_av_sbc_ups_cb.cur_pos += dst_sps;
}
@@ -276,7 +278,7 @@ int bta_av_sbc_up_sample_8s (void *p_src, void *p_dst,
UINT32 src_sps = bta_av_sbc_ups_cb.src_sps;
UINT32 dst_sps = bta_av_sbc_ups_cb.dst_sps;
while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples) {
while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples >= 2) {
*p_dst_tmp++ = *p_worker1;
*p_dst_tmp++ = *p_worker2;
@@ -287,7 +289,7 @@ int bta_av_sbc_up_sample_8s (void *p_src, void *p_dst,
bta_av_sbc_ups_cb.cur_pos = dst_sps;
while (src_samples -- && dst_samples) {
while (src_samples -- && dst_samples >= 2) {
*p_worker1 = *(UINT8 *)p_src_tmp++;
*p_worker1 -= 0x80;
*p_worker1 <<= 8;
@@ -302,7 +304,7 @@ int bta_av_sbc_up_sample_8s (void *p_src, void *p_dst,
bta_av_sbc_ups_cb.cur_pos -= src_sps;
dst_samples--;
dst_samples--;
} while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples);
} while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples >= 2);
bta_av_sbc_ups_cb.cur_pos += dst_sps;
}
@@ -342,7 +344,7 @@ int bta_av_sbc_up_sample_8m (void *p_src, void *p_dst,
UINT32 src_sps = bta_av_sbc_ups_cb.src_sps;
UINT32 dst_sps = bta_av_sbc_ups_cb.dst_sps;
while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples) {
while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples >= 4) {
*p_dst_tmp++ = *p_worker;
*p_dst_tmp++ = *p_worker;
@@ -353,7 +355,7 @@ int bta_av_sbc_up_sample_8m (void *p_src, void *p_dst,
bta_av_sbc_ups_cb.cur_pos = dst_sps;
while (src_samples-- && dst_samples) {
while (src_samples-- && dst_samples >= 4) {
*p_worker = *(UINT8 *)p_src_tmp++;
*p_worker -= 0x80;
*p_worker <<= 8;
@@ -365,7 +367,7 @@ int bta_av_sbc_up_sample_8m (void *p_src, void *p_dst,
bta_av_sbc_ups_cb.cur_pos -= src_sps;
dst_samples -= 4;
} while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples);
} while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples >= 4);
bta_av_sbc_ups_cb.cur_pos += dst_sps;
}
@@ -455,6 +457,11 @@ UINT8 bta_av_sbc_cfg_for_cap(UINT8 *p_peer, tA2D_SBC_CIE *p_cap, tA2D_SBC_CIE *p
peer_cie.min_bitpool = p_pref->min_bitpool;
}
if (peer_cie.min_bitpool > peer_cie.max_bitpool) {
APPL_TRACE_ERROR("bta_av_sbc_cfg_for_cap: min_bp > max_bp");
return A2D_FAIL;
}
if (status == A2D_SUCCESS) {
/* build configuration */
A2D_BldSbcInfo(A2D_MEDIA_TYPE_AUDIO, &peer_cie, p_peer);
@@ -429,6 +429,11 @@ void bta_av_ssm_execute(tBTA_AV_SCB *p_scb, UINT16 event, tBTA_AV_DATA *p_data)
APPL_TRACE_VERBOSE("AV Sevent(0x%x)=0x%x(%s) state=%d(%s)",
p_scb->hndl, event, bta_av_evt_code(event), p_scb->state, bta_av_sst_code(p_scb->state));
if (p_scb->state >= (sizeof(bta_av_sst_tbl) / sizeof(bta_av_sst_tbl[0])) ||
event < BTA_AV_FIRST_SSM_EVT || event > BTA_AV_LAST_SSM_EVT) {
return;
}
/* look up the state table for the current state */
state_table = bta_av_sst_tbl[p_scb->state];
@@ -133,6 +133,7 @@ enum {
/* events for AV stream control block state machine */
#define BTA_AV_FIRST_SSM_EVT BTA_AV_API_OPEN_EVT
#define BTA_AV_LAST_SSM_EVT BTA_AV_ACP_CONNECT_EVT
/* events that do not go through state machine */
#define BTA_AV_FIRST_NSM_EVT BTA_AV_API_ENABLE_EVT
@@ -678,7 +679,7 @@ extern tBTA_AV_CB *bta_av_cb_ptr;
#endif
/* config struct */
extern tBTA_AV_CFG *p_bta_av_cfg;
extern const tBTA_AV_CFG *p_bta_av_cfg;
extern const tBTA_AV_SACT bta_av_a2d_action[];
extern const tBTA_AV_SACT bta_av_vdp_action[];
@@ -309,6 +309,7 @@ void bta_av_co_audio_disc_res(tBTA_AV_HNDL hndl, UINT8 num_seps, UINT8 num_snk,
/* Sanity check : this should never happen */
if (p_peer->opened) {
APPL_TRACE_ERROR("bta_av_co_audio_disc_res peer already opened");
return;
}
/* Copy the discovery results */
@@ -359,6 +360,7 @@ void bta_av_co_audio_cfg_res(tBTA_AV_HNDL hndl, UINT8 num_seps, UINT8 num_snk,
/* Sanity check : this should never happen */
if (p_peer->opened) {
APPL_TRACE_ERROR("bta_av_co_audio_cfg_res peer already opened");
return;
}
/* Copy the discovery results */
@@ -403,6 +405,8 @@ void bta_av_build_src_cfg (UINT8 *p_pref_cfg, UINT8 *p_src_cap)
return ;
}
memcpy(&pref_cap, &src_cap, sizeof(tA2D_SBC_CIE));
if (src_cap.samp_freq & A2D_SBC_IE_SAMP_FREQ_48) {
pref_cap.samp_freq = A2D_SBC_IE_SAMP_FREQ_48;
} else if (src_cap.samp_freq & A2D_SBC_IE_SAMP_FREQ_44) {
@@ -751,6 +755,8 @@ void bta_av_co_audio_setconfig(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type,
/* Sanity check: should not be opened at this point */
if (p_peer->opened) {
APPL_TRACE_ERROR("bta_av_co_audio_setconfig peer already in use");
bta_av_ci_setconfig(hndl, A2D_BUSY, AVDT_ASC_CODEC, 0, NULL, FALSE, avdt_handle);
return;
}
#if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
@@ -996,7 +1002,7 @@ void *bta_av_co_audio_src_data_path(tBTA_AV_CODEC codec_type, UINT32 *p_len,
#if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
{
UINT8 *p;
if (bta_av_co_cp_is_active()) {
if (bta_av_co_cp_is_active() && p_buf->offset > 0) {
p_buf->len++;
p_buf->offset--;
p = (UINT8 *)(p_buf + 1) + p_buf->offset;
@@ -78,7 +78,9 @@ static void btc_a2dp_datapath_open(void)
}
#endif
#if (BTC_AV_SINK_INCLUDED == TRUE)
btc_aa_ctrl_cb.data_channel_open = TRUE;
if (btc_av_get_peer_sep() == AVDT_TSEP_SRC && btc_av_get_service_id() == BTA_A2DP_SINK_SERVICE_ID) {
btc_aa_ctrl_cb.data_channel_open = TRUE;
}
#endif
}
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -411,6 +411,7 @@ static void btc_a2dp_sink_handle_decoder_reset(tBTC_MEDIA_SINK_CFG_UPDATE *p_msg
a2dp_sink_local_param.btc_aa_snk_cb.channel_count, FALSE, FALSE);
if (!OI_SUCCESS(status)) {
APPL_TRACE_ERROR("OI_CODEC_SBC_DecoderReset failed with error code %d\n", status);
return;
}
btc_a2dp_control_set_datachnl_stat(TRUE);
@@ -521,13 +522,22 @@ static void btc_a2dp_sink_handle_decoder_reset(tBTC_MEDIA_SINK_CFG_UPDATE *p_msg
*******************************************************************************/
static void btc_a2dp_sink_handle_inc_media(BT_HDR *p_msg)
{
UINT8 *sbc_start_frame = ((UINT8 *)(p_msg + 1) + p_msg->offset + 1);
UINT8 *sbc_start_frame;
int count;
UINT32 pcmBytes, availPcmBytes;
OI_INT16 *pcmDataPointer = a2dp_sink_local_param.pcmData; /*Will be overwritten on next packet receipt*/
OI_STATUS status;
int num_sbc_frames = (*((UINT8 *)(p_msg + 1) + p_msg->offset)) & 0x0f;
UINT32 sbc_frame_len = p_msg->len - 1;
int num_sbc_frames;
UINT32 sbc_frame_len;
if (p_msg->len < 1) {
osi_free(p_msg);
return;
}
sbc_start_frame = ((UINT8 *)(p_msg + 1) + p_msg->offset + 1);
num_sbc_frames = (*((UINT8 *)(p_msg + 1) + p_msg->offset)) & 0x0f;
sbc_frame_len = (UINT32)p_msg->len - 1U;
availPcmBytes = sizeof(a2dp_sink_local_param.pcmData);
/* XXX: Check if the below check is correct, we are checking for peer to be sink when we are sink */
@@ -569,8 +579,6 @@ static void btc_a2dp_sink_handle_inc_media(BT_HDR *p_msg)
}
availPcmBytes -= pcmBytes;
pcmDataPointer += pcmBytes / 2;
p_msg->offset += (p_msg->len - 1) - sbc_frame_len;
p_msg->len = sbc_frame_len + 1;
}
if (count != num_sbc_frames || sbc_frame_len) {
APPL_TRACE_WARNING("Potential decoding error, cnt:%d, num:%d, len:%d. Please ignore if playback is normal.",
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -118,6 +118,17 @@ bool btc_a2dp_sink_startup(void)
osi_event_bind(data_event, a2dp_sink_local_param.btc_aa_snk_task_hdl, BTC_A2DP_SNK_DATA_QUEUE_IDX);
a2dp_sink_local_param.btc_aa_snk_cb.data_ready_event = data_event;
a2dp_sink_local_param.btc_aa_snk_cb.audio_rx_q = fixed_queue_new(QUEUE_SIZE_MAX);
if (a2dp_sink_local_param.btc_aa_snk_cb.audio_rx_q == NULL) {
osi_event_delete(data_event);
a2dp_sink_local_param.btc_aa_snk_cb.data_ready_event = NULL;
a2dp_sink_local_param.btc_aa_snk_task_hdl = NULL;
#if A2D_DYNAMIC_MEMORY == TRUE
osi_free(a2dp_sink_local_param_ptr);
a2dp_sink_local_param_ptr = NULL;
#endif
return false;
}
btc_a2dp_sink_state = BTC_A2DP_SINK_STATE_ON;
btc_a2dp_control_init();
@@ -220,9 +231,18 @@ static void btc_a2dp_sink_data_ready(UNUSED_ATTR void *context)
static void btc_a2dp_sink_handle_inc_media(BT_HDR *p_msg)
{
UINT8 *sbc_start_frame = ((UINT8 *)(p_msg + 1) + p_msg->offset + 1);
int num_sbc_frames = (*((UINT8 *)(p_msg + 1) + p_msg->offset)) & 0x0f;
UINT32 sbc_frame_len = p_msg->len - 1;
UINT8 *sbc_start_frame;
int num_sbc_frames;
UINT32 sbc_frame_len;
UINT32 timestamp;
if (p_msg->len < 1) {
osi_free(p_msg);
return;
}
sbc_start_frame = ((UINT8 *)(p_msg + 1) + p_msg->offset + 1);
num_sbc_frames = (*((UINT8 *)(p_msg + 1) + p_msg->offset)) & 0x0f;
sbc_frame_len = (UINT32)p_msg->len - 1U;
if (a2dp_sink_local_param.btc_aa_snk_cb.rx_flush) {
osi_free(p_msg);
@@ -249,7 +269,7 @@ static void btc_a2dp_sink_handle_inc_media(BT_HDR *p_msg)
APPL_TRACE_DEBUG("Number of sbc frames %d, frame_len %d\n", num_sbc_frames, sbc_frame_len);
UINT32 timestamp = *((UINT32 *) (p_msg + 1));
memcpy(&timestamp, (UINT8 *)(p_msg + 1), sizeof(UINT32));
UINT16 conn_hdl = btc_a2d_conn_handle_get();
btc_a2d_audio_data_cb_to_app(conn_hdl, (uint8_t *)p_msg, sbc_start_frame, sbc_frame_len, num_sbc_frames, timestamp);
/* dont free p_msg here */
@@ -262,6 +282,11 @@ UINT8 btc_a2dp_sink_enque_buf(BT_HDR *p_pkt)
return 0;
}
if (a2dp_sink_local_param.btc_aa_snk_cb.audio_rx_q == NULL) {
osi_free(p_pkt);
return 0;
}
if (a2dp_sink_local_param.btc_aa_snk_cb.rx_flush == TRUE) {
/* Flush enabled, do not enqueue */
osi_free(p_pkt);
@@ -371,10 +371,12 @@ void btc_a2dp_source_on_stopped(tBTA_AV_SUSPEND *p_av)
void btc_a2dp_source_on_suspended(tBTA_AV_SUSPEND *p_av)
{
/* check for status failures */
if (p_av->status != BTA_AV_SUCCESS) {
if (p_av->initiator == TRUE) {
btc_a2dp_control_command_ack(ESP_A2D_MEDIA_CTRL_ACK_FAILURE);
if (p_av != NULL) {
/* check for status failures */
if (p_av->status != BTA_AV_SUCCESS) {
if (p_av->initiator == TRUE) {
btc_a2dp_control_command_ack(ESP_A2D_MEDIA_CTRL_ACK_FAILURE);
}
}
}
@@ -699,15 +701,24 @@ static void btc_a2dp_source_encoder_init(void)
/* lookup table to convert freq */
UINT16 freq_block_tbl[5] = { SBC_sf48000, SBC_sf44100, SBC_sf32000, 0, SBC_sf16000 };
UINT8 block_idx, mode_idx, freq_idx;
APPL_TRACE_DEBUG("%s", __FUNCTION__);
/* Retrieve the current SBC configuration (default if currently not used) */
bta_av_co_audio_get_sbc_config(&sbc_config, &minmtu);
msg.NumOfSubBands = (sbc_config.num_subbands == A2D_SBC_IE_SUBBAND_4) ? 4 : 8;
msg.NumOfBlocks = codec_block_tbl[sbc_config.block_len >> 5];
block_idx = sbc_config.block_len >> 5;
msg.NumOfBlocks = (block_idx < 5) ? codec_block_tbl[block_idx] : 16;
msg.AllocationMethod = (sbc_config.alloc_mthd == A2D_SBC_IE_ALLOC_MD_L) ? SBC_LOUDNESS : SBC_SNR;
msg.ChannelMode = codec_mode_tbl[sbc_config.ch_mode >> 1];
msg.SamplingFreq = freq_block_tbl[sbc_config.samp_freq >> 5];
mode_idx = sbc_config.ch_mode >> 1;
msg.ChannelMode = (mode_idx < 5) ? codec_mode_tbl[mode_idx] : SBC_JOINT_STEREO;
freq_idx = sbc_config.samp_freq >> 5;
msg.SamplingFreq = (freq_idx < 5) ? freq_block_tbl[freq_idx] : SBC_sf44100;
msg.MtuSize = minmtu;
APPL_TRACE_EVENT("msg.ChannelMode %x", msg.ChannelMode);
@@ -1140,6 +1151,10 @@ static UINT8 btc_get_num_aa_frame(void)
a2dp_source_local_param.btc_aa_src_cb.media_feeding.cfg.pcm.num_channel *
a2dp_source_local_param.btc_aa_src_cb.media_feeding.cfg.pcm.bit_per_sample / 8;
if (pcm_bytes_per_frame == 0) {
break;
}
UINT32 us_this_tick = BTC_MEDIA_TIME_TICK_MS * 1000;
UINT64 now_us = time_now_us();
if (a2dp_source_local_param.last_frame_us != 0) {
@@ -1334,9 +1349,9 @@ BOOLEAN btc_media_aa_read_feeding(void)
a2dp_source_local_param.btc_aa_src_cb.media_feeding_state.pcm.aa_feed_residue -= bytes_needed;
if (a2dp_source_local_param.btc_aa_src_cb.media_feeding_state.pcm.aa_feed_residue != 0) {
memcpy((UINT8 *)up_sampled_buffer,
(UINT8 *)up_sampled_buffer + bytes_needed,
a2dp_source_local_param.btc_aa_src_cb.media_feeding_state.pcm.aa_feed_residue);
memmove((UINT8 *)up_sampled_buffer,
(UINT8 *)up_sampled_buffer + bytes_needed,
a2dp_source_local_param.btc_aa_src_cb.media_feeding_state.pcm.aa_feed_residue);
}
return TRUE;
}
@@ -1456,7 +1471,10 @@ static void btc_a2dp_source_prep_2_send(UINT8 nb_frame)
}
while (fixed_queue_length(a2dp_source_local_param.btc_aa_src_cb.TxAaQ) > (MAX_OUTPUT_A2DP_SRC_FRAME_QUEUE_SZ - nb_frame)) {
osi_free(fixed_queue_dequeue(a2dp_source_local_param.btc_aa_src_cb.TxAaQ, 0));
void *p_drop = fixed_queue_dequeue(a2dp_source_local_param.btc_aa_src_cb.TxAaQ, 0);
if (p_drop != NULL) {
osi_free(p_drop);
}
}
// Transcode frame
@@ -135,10 +135,15 @@ void btc_a2dp_source_set_tx_flush(BOOLEAN enable)
void btc_a2dp_source_on_suspended(tBTA_AV_SUSPEND *p_av)
{
/* check for status failures */
if (p_av == NULL) {
return;
}
if (p_av->status != BTA_AV_SUCCESS) {
if (p_av->initiator == TRUE) {
btc_a2dp_control_command_ack(ESP_A2D_MEDIA_CTRL_ACK_FAILURE);
}
return;
}
/* stop tx, ack to cmd, flush tx queue */
@@ -202,6 +207,8 @@ bool btc_a2dp_source_startup(void)
error_exit:;
APPL_TRACE_ERROR("%s A2DP source start up failed", __func__);
btc_a2dp_source_state = BTC_A2DP_SOURCE_STATE_OFF;
#if A2D_DYNAMIC_MEMORY == TRUE
osi_free(a2dp_source_local_param_ptr);
a2dp_source_local_param_ptr = NULL;
@@ -330,6 +330,7 @@ static void btc_report_audio_state(esp_a2d_audio_state_t state, bt_bdaddr_t *bd_
static BOOLEAN btc_av_state_idle_handler(btc_sm_event_t event, void *p_data)
{
esp_a2d_cb_param_t param;
memset(&param, 0, sizeof(esp_a2d_cb_param_t));
BTC_TRACE_DEBUG("%s event: %s flags %x\n", __FUNCTION__,
dump_av_sm_event_name(event), btc_av_cb.flags);
@@ -415,6 +416,10 @@ static BOOLEAN btc_av_state_idle_handler(btc_sm_event_t event, void *p_data)
*/
#if BTC_AV_SRC_INCLUDED
BTC_TRACE_DEBUG("BTA_AV_RC_OPEN_EVT received w/o AV");
if (btc_av_cb.tle_av_open_on_rc) {
osi_alarm_free(btc_av_cb.tle_av_open_on_rc);
btc_av_cb.tle_av_open_on_rc = NULL;
}
btc_av_cb.tle_av_open_on_rc = osi_alarm_new("AVconn", btc_initiate_av_open_tmr_hdlr, NULL, BTC_TIMEOUT_AV_OPEN_ON_RC_SECS * 1000);
osi_alarm_set(btc_av_cb.tle_av_open_on_rc, BTC_TIMEOUT_AV_OPEN_ON_RC_SECS * 1000);
#endif /* BTC_AV_SRC_INCLUDED */
@@ -513,7 +518,8 @@ static BOOLEAN btc_av_state_opening_handler(btc_sm_event_t event, void *p_data)
if (p_bta_data->open.status == BTA_AV_SUCCESS) {
btc_av_cb.edr = p_bta_data->open.edr;
btc_av_cb.peer_sep = p_bta_data->open.sep;
mtu = p_bta_data->open.mtu - BTC_AV_AUDIO_MTU_RESERVE;
mtu = (p_bta_data->open.mtu > BTC_AV_AUDIO_MTU_RESERVE) ?
(p_bta_data->open.mtu - BTC_AV_AUDIO_MTU_RESERVE) : 0;
conn_stat = ESP_A2D_CONNECTION_STATE_CONNECTED;
av_state = BTC_AV_STATE_OPENED;
} else {
@@ -573,19 +579,21 @@ static BOOLEAN btc_av_state_opening_handler(btc_sm_event_t event, void *p_data)
btc_a2d_cb_to_app(ESP_A2D_AUDIO_CFG_EVT, &param);
} break;
case BTC_AV_CONNECT_REQ_EVT:
case BTC_AV_CONNECT_REQ_EVT: {
btc_av_connect_req_t *connect_req = (btc_av_connect_req_t *)p_data;
// Check for device, if same device which moved to opening then ignore callback
if (memcmp ((bt_bdaddr_t *)p_data, &(btc_av_cb.peer_bda),
if (memcmp (&connect_req->target_bda, &(btc_av_cb.peer_bda),
sizeof(btc_av_cb.peer_bda)) == 0) {
BTC_TRACE_DEBUG("%s: Same device moved to Opening state,ignore Connect Req\n", __func__);
btc_queue_advance();
break;
} else {
BTC_TRACE_DEBUG("%s: Moved from idle by Incoming Connection request\n", __func__);
btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, (bt_bdaddr_t *)p_data, 0, 0);
btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &connect_req->target_bda, 0, 0);
btc_queue_advance();
break;
}
}
case BTA_AV_PENDING_EVT:
// Check for device, if same device which moved to opening then ignore callback
@@ -644,6 +652,7 @@ static BOOLEAN btc_av_state_opening_handler(btc_sm_event_t event, void *p_data)
static BOOLEAN btc_av_state_closing_handler(btc_sm_event_t event, void *p_data)
{
esp_a2d_cb_param_t param;
memset(&param, 0, sizeof(esp_a2d_cb_param_t));
BTC_TRACE_DEBUG("%s event: %s flags %x\n", __FUNCTION__,
dump_av_sm_event_name(event), btc_av_cb.flags);
@@ -731,6 +740,7 @@ static BOOLEAN btc_av_state_closing_handler(btc_sm_event_t event, void *p_data)
static BOOLEAN btc_av_state_opened_handler(btc_sm_event_t event, void *p_data)
{
esp_a2d_cb_param_t param;
memset(&param, 0, sizeof(esp_a2d_cb_param_t));
tBTA_AV *p_av = (tBTA_AV *)p_data;
BTC_TRACE_DEBUG("%s event: %s flags %x\n", __FUNCTION__,
@@ -882,17 +892,19 @@ static BOOLEAN btc_av_state_opened_handler(btc_sm_event_t event, void *p_data)
}
break;
case BTC_AV_CONNECT_REQ_EVT:
if (memcmp (&((btc_av_connect_req_t *)p_data)->target_bda, &(btc_av_cb.peer_bda),
case BTC_AV_CONNECT_REQ_EVT: {
btc_av_connect_req_t *connect_req = (btc_av_connect_req_t *)p_data;
if (memcmp (&connect_req->target_bda, &(btc_av_cb.peer_bda),
sizeof(btc_av_cb.peer_bda)) == 0) {
BTC_TRACE_DEBUG("%s: Ignore BTC_AVCONNECT_REQ_EVT for same device\n", __func__);
} else {
BTC_TRACE_DEBUG("%s: Moved to opened by Other Incoming Conn req\n", __func__);
btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED,
(bt_bdaddr_t *)p_data, 0, ESP_A2D_DISC_RSN_NORMAL);
&connect_req->target_bda, 0, ESP_A2D_DISC_RSN_NORMAL);
}
btc_queue_advance();
break;
}
CHECK_RC_EVENT(event, p_data);
@@ -936,6 +948,7 @@ static BOOLEAN btc_av_state_started_handler(btc_sm_event_t event, void *p_data)
{
tBTA_AV *p_av = (tBTA_AV *)p_data;
esp_a2d_cb_param_t param;
memset(&param, 0, sizeof(esp_a2d_cb_param_t));
BTC_TRACE_DEBUG("%s event: %s flags %x\n", __FUNCTION__,
dump_av_sm_event_name(event), btc_av_cb.flags);
@@ -2101,6 +2114,13 @@ uint16_t btc_a2d_conn_handle_get(void)
void btc_av_audio_buff_alloc(uint16_t size, uint8_t **pp_buff, uint8_t **pp_data)
{
/* todo */
if (pp_buff == NULL || pp_data == NULL) {
return;
}
*pp_buff = NULL;
*pp_data = NULL;
BT_HDR *p_buf= (BT_HDR *)osi_calloc(sizeof(BT_HDR) + BTC_AUDIO_BUFF_OFFSET + size);
if (p_buf != NULL) {
*pp_buff = (uint8_t *)p_buf;
@@ -66,6 +66,8 @@ static void a2d_sdp_cback(UINT16 status)
A2D_TRACE_API("a2d_sdp_cback status: %d", status);
memset(&a2d_svc, 0, sizeof(tA2D_Service));
if (status == SDP_SUCCESS) {
/* loop through all records we found */
do {
@@ -74,7 +76,6 @@ static void a2d_sdp_cback(UINT16 status)
a2d_cb.find.service_uuid, p_rec)) == NULL) {
break;
}
memset(&a2d_svc, 0, sizeof(tA2D_Service));
/* get service name */
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;
UINT8 losc;
UINT8 media_type;
if ( p_ie == NULL || p_info == NULL) {
status = A2D_INVALID_PARAMS;
} else {
losc = *p_info++;
p_info++;
media_type = *p_info++;
/* 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;
} else {
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;
if (p_ie->min_bitpool < A2D_SBC_IE_MIN_BITPOOL || p_ie->min_bitpool > A2D_SBC_IE_MAX_BITPOOL ) {
status = A2D_BAD_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) {
} 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) {
status = A2D_BAD_MAX_BITPOOL;
}
if (for_caps == FALSE) {
} else if (for_caps == FALSE) {
if (A2D_BitsSet(p_ie->samp_freq) != A2D_SET_ONE_BIT) {
status = A2D_BAD_SAMP_FREQ;
} 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");
/* initialize AVCTP data structures */
memset(&avct_cb, 0, sizeof(tAVCT_CB));
/* register PSM with L2CAP */
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(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)
/* Include the browsing channel which uses eFCR */
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_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);
/* Allocate ccb; if no ccbs, return failure */
@@ -234,7 +238,7 @@ UINT16 AVCT_CreateBrowse (UINT8 handle, UINT8 role)
#if (AVCT_BROWSE_INCLUDED == TRUE)
UINT16 result = AVCT_SUCCESS;
tAVCT_CCB *p_ccb;
tAVCT_BCB *p_bcb;
tAVCT_BCB *p_bcb = NULL;
int index;
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);
} else {
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 */
@@ -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) {
memset(p_ccb, 0, sizeof(tAVCT_CCB));
} 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);
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 {
/* 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->ch_flags = 0;
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 */
p_lcb->ch_state = AVCT_CH_CFG;
p_lcb->ch_flags = 0;
/* Send L2CAP config req */
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) {
/* set channel state */
p_lcb->ch_state = AVCT_CH_CFG;
p_lcb->ch_flags = 0;
/* Send L2CAP config req */
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 */
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);
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 */
if (p_cfg->mtu_present) {
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++) {
if (!p_lcb->allocated) {
memset(p_lcb, 0, sizeof(tAVCT_LCB));
p_lcb->allocated = (UINT8)(i + 1);
memcpy(p_lcb->peer_addr, bd_addr, BD_ADDR_LEN);
AVCT_TRACE_DEBUG("avct_lcb_alloc %d", p_lcb->allocated);
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;
}
}
@@ -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;
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 */
if (p_buf->len < avct_lcb_pkt_type_len[pkt_type]) {
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 */
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 */
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;
osi_free(p_buf);
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 {
/* copy contents of p_buf to p_rx_msg */
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 */
AVCT_TRACE_ERROR ("avct_lcb_send_msg cannot alloc buffer!!");
osi_free(p_data->ul_msg.p_buf);
p_data->ul_msg.p_buf = NULL;
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;
} else {
p_buf = p_data->ul_msg.p_buf;
p_data->ul_msg.p_buf = NULL;
}
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) {
return 0;
} else {
if (p_scb == NULL) {
return 0;
}
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));
@@ -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)
{
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) {
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 (p_tbl->tcid == 0) {
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;
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);
p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx);
if (p_ccb == NULL) {
return;
}
/* use err_param to indicate the role of connection.
* AVDT_ACP, if ACP */
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 (p_tbl->tcid == 0) {
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);
}
/* 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 (p_tbl->tcid == 0) {
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);
}
/* 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) {
p_tbl->state = AVDT_AD_ST_ACP;
}
/* else we're inititator, start the L2CAP connection */
/* else we're initiator, start the L2CAP connection */
else {
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;
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);
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)
{
if (p_reg == NULL || p_cback == NULL) {
return;
}
/* register PSM with L2CAP */
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;
tAVDT_SCB *p_scb;
if (p_handle == NULL) {
return AVDT_BAD_PARAMS;
}
/* Verify parameters; if invalid, return failure */
if (((p_cs->cfg.psc_mask & (~AVDT_PSC)) != 0) || (p_cs->p_ctrl_cback == NULL)) {
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;
UINT16 result = AVDT_SUCCESS;
if (p_pkt == NULL) {
return AVDT_BAD_PARAMS;
}
/* map handle to scb */
if ((p_scb = avdt_scb_by_hdl(handle)) == NULL) {
result = AVDT_BAD_HANDLE;
@@ -1188,7 +1197,7 @@ UINT16 AVDT_SendReport(UINT8 handle, AVDT_REPORT_TYPE type,
/* build SR - assume fit in one packet */
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->offset = L2CAP_MIN_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 */
*p++ = p_data->rr.frag_lost;
AVDT_TRACE_API("packet_lost: %d\n", p_data->rr.packet_lost);
p_data->rr.packet_lost &= 0xFFFFFF;
AVDT_TRACE_API("packet_lost: %d\n", p_data->rr.packet_lost);
UINT24_TO_BE_STREAM(p, p_data->rr.packet_lost);
/* Use local 24-bit value so caller's p_data->rr.packet_lost is not mutated */
{
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.jitter);
UINT32_TO_BE_STREAM(p, p_data->rr.lsr);
@@ -31,6 +31,7 @@
#include "stack/avdtc_api.h"
#include "avdt_int.h"
#include "stack/btu.h"
#include "osi/allocator.h"
#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;
int i;
if (p_ccb == NULL || p_ccb->state > AVDT_CCB_CLOSING_ST || event > AVDT_CCB_LL_CONG_EVT) {
return;
}
#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]);
#endif
@@ -396,7 +401,7 @@ tAVDT_CCB *avdt_ccb_alloc(BD_ADDR bd_addr)
**
** Function avdt_ccb_dealloc
**
** Description Deallocate a stream control block.
** Description Deallocate a channel control block.
**
**
** Returns void.
@@ -406,10 +411,28 @@ void avdt_ccb_dealloc(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
{
UNUSED(p_data);
if (p_ccb == NULL) {
return;
}
AVDT_TRACE_DEBUG("avdt_ccb_dealloc %d\n", avdt_ccb_to_idx(p_ccb));
btu_free_timer(&p_ccb->timer_entry);
fixed_queue_free(p_ccb->cmd_q, NULL);
fixed_queue_free(p_ccb->rsp_q, NULL);
fixed_queue_free(p_ccb->cmd_q, osi_free_func);
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));
}
@@ -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)
{
if (p_ccb == NULL) {
return AVDT_NUM_LINKS;
}
/* use array arithmetic to determine index */
return (UINT8) (p_ccb - avdt_cb.ccb);
}
@@ -446,6 +472,9 @@ tAVDT_CCB *avdt_ccb_by_idx(UINT8 idx)
/* verify index */
if (idx < AVDT_NUM_LINKS) {
p_ccb = &avdt_cb.ccb[idx];
if (!p_ccb->allocated) {
p_ccb = NULL;
}
} else {
p_ccb = NULL;
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)
{
tAVDT_SCB *p_scb;
UINT8 sig_id = AVDT_SIG_GETCAP;
/* look up scb for seid sent to us */
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;
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;
tAVDT_SCB *p_scb;
if (p_ccb->p_curr_cmd == NULL) {
return;
}
/* determine rsp or rej event */
event = (p_data->msg.hdr.err_code == 0) ?
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;
tAVDT_SCB *p_scb;
if (p_ccb->p_curr_cmd == NULL) {
return;
}
/* determine rsp or rej event */
event = (p_data->msg.hdr.err_code == 0) ?
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;
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 */
memcpy(seid_list, p_data->msg.multi.seid_list, p_data->msg.multi.num_seps);
/* 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,
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);
/* 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;
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 */
memcpy(seid_list, p_data->msg.multi.seid_list, p_data->msg.multi.num_seps);
/* 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,
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);
/* send command */
@@ -690,6 +713,12 @@ void avdt_ccb_cmd_fail(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
tAVDT_SCB *p_scb;
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 */
msg.hdr.err_code = p_data->err_code;
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 */
if (p_ccb->p_conn_cback) {
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);
}
}
@@ -79,6 +79,7 @@ static void avdt_sec_check_complete_term (BD_ADDR bd_addr, tBT_TRANSPORT transpo
tL2CAP_CFG_INFO cfg;
tAVDT_TC_TBL *p_tbl;
UNUSED(p_ref_data);
UNUSED(transport);
AVDT_TRACE_DEBUG("avdt_sec_check_complete_term res: %d\n", res);
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. */
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 */
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;
if (p_tbl->lcid >= L2CAP_BASE_APPL_CID && (p_tbl->lcid - L2CAP_BASE_APPL_CID) < MAX_L2CAP_CHANNELS) {
/* store idx in LCID table, store LCID in routing table */
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 */
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;
tAVDT_TC_TBL *p_tbl;
UNUSED(p_ref_data);
UNUSED(transport);
AVDT_TRACE_DEBUG("avdt_sec_check_complete_orig res: %d\n", res);
if (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);
if (p_tbl == NULL) {
return;
@@ -188,6 +193,11 @@ void avdt_l2c_connect_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8
} else {
/* allocate and set up entry; first channel is always signaling */
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_flush_to = L2CAP_DEFAULT_FLUSH_TO;
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 == L2CAP_CONN_OK) {
/* store idx in LCID table, store LCID in routing table */
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;
if (lcid >= L2CAP_BASE_APPL_CID && lcid < (L2CAP_BASE_APPL_CID + MAX_L2CAP_CHANNELS)) {
/* store idx in LCID table, store LCID in routing table */
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 */
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) {
/* send L2CAP disconnect response */
L2CA_DisconnectRsp(lcid);
} else {
if ((p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx)) != NULL) {
UINT16 rsn = L2CA_GetDisconnectReason(p_ccb->peer_addr, BT_TRANSPORT_BR_EDR);
if (rsn != 0 && rsn != HCI_ERR_PEER_USER) {
disc_rsn = AVDT_DISC_RSN_ABNORMAL;
AVDT_TRACE_EVENT("avdt link disc rsn 0x%x", rsn);
}
}
if ((p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx)) != NULL) {
UINT16 rsn = L2CA_GetDisconnectReason(p_ccb->peer_addr, BT_TRANSPORT_BR_EDR);
if (rsn != 0 && rsn != HCI_ERR_PEER_USER) {
disc_rsn = AVDT_DISC_RSN_ABNORMAL;
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)
{
AVDT_MSG_BLD_SEID(*p, p_msg->security_cmd.hdr.seid);
memcpy(*p, p_msg->security_cmd.p_data, p_msg->security_cmd.len);
*p += p_msg->security_cmd.len;
if (p_msg->security_cmd.p_data && p_msg->security_cmd.len > 0) {
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]) ||
(elem_len < avdt_msg_ie_len_min[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;
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
** of seps app has supplied memory for and seps in msg
*/
if (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 */
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);
if (p_msg->svccap.p_cfg) {
p_msg->svccap.p_cfg->psc_mask &= AVDT_LEG_PSC;
} else {
return AVDT_ERR_BAD_STATE;
}
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);
if (p_msg->svccap.p_cfg) {
p_msg->svccap.p_cfg->psc_mask &= AVDT_MSG_PSC_MASK;
} else {
return AVDT_ERR_BAD_STATE;
}
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;
}
if (p_ccb->p_curr_msg == NULL) {
return FALSE;
}
/* store copy of 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);
if (pkt_type == AVDT_PKT_TYPE_END) {
p_ccb->p_rx_msg->offset -= p_ccb->p_rx_msg->len;
p_ccb->p_rx_msg->len += p_buf->len;
p_ret = p_ccb->p_rx_msg;
p_ccb->p_rx_msg = NULL;
if (p_ccb->p_rx_msg->len <= p_ccb->p_rx_msg->offset) {
p_ccb->p_rx_msg->offset -= p_ccb->p_rx_msg->len;
p_ccb->p_rx_msg->len += p_buf->len;
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 {
p_ccb->p_rx_msg->offset += 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_start;
if (sig_id < AVDT_SIG_DISCOVER || sig_id > AVDT_SIG_MAX) {
return;
}
/* get a buffer */
p_buf = (BT_HDR *) osi_malloc(AVDT_CMD_BUF_SIZE);
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_start;
if (sig_id < AVDT_SIG_DISCOVER || sig_id > AVDT_SIG_MAX) {
return;
}
/* get a buffer */
p_buf = (BT_HDR *) osi_malloc(AVDT_CMD_BUF_SIZE);
if (p_buf == NULL) {
@@ -1656,7 +1692,11 @@ void avdt_msg_ind(tAVDT_CCB *p_ccb, BT_HDR *p_buf)
gen_rej = TRUE;
if (p_ccb->p_curr_cmd != NULL) {
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_param = 0;
}
@@ -541,6 +541,10 @@ void avdt_scb_event(tAVDT_SCB *p_scb, UINT8 event, tAVDT_SCB_EVT *p_data)
UINT8 action;
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
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
@@ -558,7 +562,9 @@ void avdt_scb_event(tAVDT_SCB *p_scb, UINT8 event, tAVDT_SCB_EVT *p_data)
/* execute action functions */
for (i = 0; i < AVDT_SCB_ACTIONS; i++) {
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 {
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 */
offset += o_cc * 4;
p += o_cc * 4;
if (len < offset) {
goto length_error;
}
/* check for and skip over extension header */
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;
BE_STREAM_TO_UINT16(ex_len, p);
if ((UINT32)ex_len * 4 > (UINT32)(len - offset)) {
goto length_error;
}
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 ((p_scb->cs.p_media_cback != 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*/
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->media_buf_len, time_stamp, seq, m_pt, marker);
p_data->p_pkt->len, time_stamp, seq, m_pt, marker);
}
#endif
goto length_error;
@@ -355,6 +361,8 @@ UINT8 *avdt_scb_hdl_report(tAVDT_SCB *p_scb, UINT8 *p, UINT16 len)
AVDT_REPORT_TYPE pt;
tAVDT_REPORT_DATA report;
memset(&report, 0, sizeof(report));
AVDT_TRACE_DEBUG( "avdt_scb_hdl_report");
if (p_scb->cs.p_report_cback) {
/* 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;
}
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)) {
result = AVDT_BAD_PARAMS;
} else {
@@ -643,6 +651,11 @@ void avdt_scb_hdl_pkt_frag(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
pad_len = 0;
}
/* 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);
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;
UINT8 event;
tAVDT_CCB *p_ccb = p_scb->p_ccb;
BD_ADDR remote_addr;
BD_ADDR remote_addr;
memcpy (remote_addr, p_ccb->peer_addr, BD_ADDR_LEN);
if (p_ccb != NULL) {
memcpy(remote_addr, p_ccb->peer_addr, BD_ADDR_LEN);
} else {
memset(remote_addr, 0, BD_ADDR_LEN);
}
/* set up hdr */
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) ) {
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->offset -= AVDT_MEDIA_HDR_SIZE;
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_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 */
(*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb),
NULL,