Merge branch 'bugfix/ai_review_a2dp_v5.4' into 'release/v5.4'

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

See merge request espressif/esp-idf!47756
This commit is contained in:
Wang Meng Yang
2026-04-24 18:54:36 +08:00
31 changed files with 532 additions and 135 deletions
@@ -125,6 +125,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);
@@ -213,6 +214,10 @@ esp_err_t esp_a2d_media_ctrl(esp_a2d_media_ctrl_t ctrl)
ctrl = ESP_A2D_MEDIA_CTRL_SUSPEND;
}
if (ctrl <= ESP_A2D_MEDIA_CTRL_NONE || ctrl > ESP_A2D_MEDIA_CTRL_SUSPEND) {
return ESP_ERR_INVALID_ARG;
}
bt_status_t stat;
btc_av_args_t arg;
btc_msg_t msg;
+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;
}
}
@@ -722,6 +727,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);
}
}
}
@@ -1633,7 +1639,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)) {
@@ -1873,6 +1879,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;
@@ -2167,9 +2178,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;
@@ -2382,7 +2393,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;
}
@@ -2774,7 +2790,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");
@@ -2790,9 +2810,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';
}
@@ -327,8 +328,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;
@@ -357,8 +364,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;
@@ -452,8 +465,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;
@@ -487,8 +506,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;
@@ -610,6 +635,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);
}
}
@@ -672,14 +699,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);
}
@@ -366,7 +366,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;
}
@@ -415,13 +420,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);
@@ -1177,9 +1184,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);
}
}
}
@@ -1203,6 +1210,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 */
@@ -1210,6 +1221,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);
@@ -1242,8 +1257,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];
@@ -132,6 +132,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
@@ -667,7 +668,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[];
@@ -297,6 +297,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 */
@@ -347,6 +348,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 */
@@ -391,6 +393,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) {
@@ -739,6 +743,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)
@@ -984,7 +990,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;
@@ -76,7 +76,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
}
@@ -418,6 +418,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);
@@ -528,7 +529,7 @@ static void btc_a2dp_sink_handle_decoder_reset(tBTC_MEDIA_SINK_CFG_UPDATE *p_msg
*******************************************************************************/
static void btc_a2dp_sink_handle_inc_media(tBT_SBC_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*/
@@ -574,8 +575,6 @@ static void btc_a2dp_sink_handle_inc_media(tBT_SBC_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.",
@@ -377,10 +377,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);
}
}
}
@@ -678,15 +680,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);
@@ -1108,6 +1119,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) {
@@ -1302,9 +1317,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;
}
@@ -1424,7 +1439,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
@@ -1539,8 +1557,8 @@ static void btc_a2dp_source_aa_stop_tx(void)
when the DUT and the remote device issue SUSPEND simultaneously
and due to the processing of the SUSPEND request from the remote,
the media path is torn down. If the A2DP HAL happens to wait
for ACK for the initiated SUSPEND, it would never receive it casuing
a block/wait. Due to this acknowledgement, the A2DP HAL is guranteed
for ACK for the initiated SUSPEND, it would never receive it causing
a block/wait. Due to this acknowledgement, the A2DP HAL is guaranteed
to get the ACK for any pending command in such cases. */
if (send_ack) {
@@ -308,6 +308,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);
@@ -387,6 +388,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 */
@@ -521,9 +526,10 @@ static BOOLEAN btc_av_state_opening_handler(btc_sm_event_t event, void *p_data)
}
} 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();
@@ -534,6 +540,7 @@ static BOOLEAN btc_av_state_opening_handler(btc_sm_event_t event, void *p_data)
btc_queue_advance();
break;
}
}
case BTA_AV_PENDING_EVT:
// Check for device, if same device which moved to opening then ignore callback
@@ -592,6 +599,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);
@@ -679,6 +687,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__,
@@ -801,8 +810,9 @@ 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 {
@@ -812,6 +822,7 @@ static BOOLEAN btc_av_state_opened_handler(btc_sm_event_t event, void *p_data)
}
btc_queue_advance();
break;
}
CHECK_RC_EVENT(event, p_data);
@@ -855,6 +866,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);
@@ -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;
@@ -898,6 +904,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;
@@ -1157,7 +1166,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;
@@ -1190,9 +1199,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,