{
/* AVCT CCB is still there. dealloc */
bta_av_del_rc(p_rcb);
-
- /* if the AVRCP is no longer listening, create the listening channel */
- if (bta_av_cb.rc_acp_handle == BTA_AV_RC_HANDLE_NONE && bta_av_cb.features & BTA_AV_FEAT_RCTG)
- bta_av_rc_create(&bta_av_cb, AVCT_ACP, 0, BTA_AV_NUM_LINKS + 1);
}
}
else if ((p_rcb->handle != BTA_AV_RC_HANDLE_NONE) && (p_rcb->status & BTA_AV_RC_CONN_MASK))
/* AVRCP cupported categories */
#if (AVRC_CTLR_INCLUDED == TRUE)
+#define BTA_AV_RC_SUPF_CT (AVRC_SUPF_CT_CAT1 | AVRC_SUPF_CT_CAT2)
+#else
#define BTA_AV_RC_SUPF_CT (AVRC_SUPF_CT_CAT2)
#endif
UINT8 role;
BOOLEAN needed = FALSE;
tBTA_AV_SCB *p_scbi;
+ tBTM_STATUS ret;
int i;
UINT8 mask;
{
if (bta_av_cb.features & BTA_AV_FEAT_MASTER)
bta_sys_clear_policy(BTA_ID_AV, HCI_ENABLE_MASTER_SLAVE_SWITCH, p_scbi->peer_addr);
- if (BTM_CMD_STARTED != BTM_SwitchRole(p_scbi->peer_addr, BTM_ROLE_MASTER, NULL))
+ ret = BTM_SwitchRole(p_scbi->peer_addr, BTM_ROLE_MASTER, NULL);
+ if (ret == BTM_REPEATED_ATTEMPTS)
+ return FALSE;
+
+ if (BTM_CMD_STARTED != ret)
{
/* can not switch role on SCBI
* start the timer on SCB - because this function is ONLY called when SCB gets API_OPEN */
{
UINT8 role;
BOOLEAN is_ok = TRUE;
+ tBTM_STATUS ret;
if (BTM_GetRole(p_scb->peer_addr, &role) == BTM_SUCCESS)
{
- LOG_INFO(LOG_TAG, "%s hndl:x%x role:%d conn_audio:x%x bits:%d features:x%x",
+ LOG_INFO("%s hndl:x%x role:%d conn_audio:x%x bits:%d features:x%x",
__func__, p_scb->hndl, role, bta_av_cb.conn_audio, bits,
bta_av_cb.features);
if (BTM_ROLE_MASTER != role && (A2D_BitsSet(bta_av_cb.conn_audio) > bits || (bta_av_cb.features & BTA_AV_FEAT_MASTER)))
{
if (bta_av_cb.features & BTA_AV_FEAT_MASTER)
bta_sys_clear_policy(BTA_ID_AV, HCI_ENABLE_MASTER_SLAVE_SWITCH, p_scb->peer_addr);
-
- if (BTM_CMD_STARTED != BTM_SwitchRole(p_scb->peer_addr, BTM_ROLE_MASTER, NULL))
+ ret = BTM_SwitchRole(p_scb->peer_addr, BTM_ROLE_MASTER, NULL);
+ /* We have already reached maximum attempts,
+ * If we try again it will anyways fail
+ * return from here
+ * */
+ if (ret == BTM_REPEATED_ATTEMPTS)
+ return TRUE;
+
+ if (BTM_CMD_STARTED != ret)
{
/* can not switch role on SCB - start the timer on SCB */
}
else if ((btif_av_cb[index].peer_sep == AVDT_TSEP_SRC) &&
(p_bta_data->open.status == BTA_AV_SUCCESS))
{
+ /* if queued PLAY command, send it now */
+ btif_rc_check_handle_pending_play(p_bta_data->open.bd_addr, FALSE);
/* Bring up AVRCP connection too */
BTA_AvOpenRc(btif_av_cb[index].bta_handle);
}
switch (event)
{
case BTIF_AV_INIT_REQ_EVT:
- BTIF_TRACE_DEBUG("%s: BTIF_AV_INIT_REQ_EVT", __FUNCTION__);
+ BTIF_TRACE_IMP("%s: BTIF_AV_INIT_REQ_EVT", __FUNCTION__);
if(btif_a2dp_start_media_task())
btif_a2dp_on_init();
break;
/*events from Upper layer and Media Task*/
case BTIF_AV_CLEANUP_REQ_EVT: /*Clean up to be called on default index*/
- BTIF_TRACE_DEBUG("%s: BTIF_AV_CLEANUP_REQ_EVT", __FUNCTION__);
+ BTIF_TRACE_IMP("%s: BTIF_AV_CLEANUP_REQ_EVT", __FUNCTION__);
uuid = (int)*p_param;
if (uuid == BTA_A2DP_SOURCE_SERVICE_ID)
{
static void cleanup(int service_uuid)
{
int i;
- BTIF_TRACE_EVENT("%s", __FUNCTION__);
+ BTIF_TRACE_IMP("AV %s", __FUNCTION__);
btif_transfer_context(btif_av_handle_event, BTIF_AV_CLEANUP_REQ_EVT,
(char*)&service_uuid, sizeof(int), NULL);
static bool absolute_volume_disabled(void);
static void btif_rc_upstreams_evt(UINT16 event, tAVRC_COMMAND* p_param, UINT8 ctype, UINT8 label,
int index);
+#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
static void btif_rc_upstreams_rsp_evt(UINT16 event, tAVRC_RESPONSE *pavrc_resp, UINT8 ctype, UINT8 label,
int index);
+#endif
static bt_status_t set_addrplayer_rsp(btrc_status_t status_code, bt_bdaddr_t *bd_addr);
static int btif_rc_get_idx_by_addr(BD_ADDR address);
******************************************************************************/
extern BOOLEAN btif_hf_call_terminated_recently();
extern BOOLEAN check_cod(const bt_bdaddr_t *remote_bdaddr, uint32_t cod);
-
extern void btif_get_latest_playing_device(BD_ADDR address); //get the Playing device address
extern BOOLEAN btif_av_is_playing();
extern BOOLEAN btif_av_is_device_connected(BD_ADDR address);
close(fd);
return -1;
}
+ BTIF_TRACE_IMP("AVRCP: input device opened.. Delay 30 ms");
+ sleep_ms(30);
return fd;
}
bdaddr_to_string(&avdtp_addr, addr1, sizeof(bdstr_t)),
bdaddr_to_string(&rc_addr, addr2, sizeof(bdstr_t)) );
- //if (interop_match(INTEROP_DISABLE_ABSOLUTE_VOLUME, &rc_addr)
- if (absolute_volume_disabled()
- || bdcmp(avdtp_addr.address, rc_addr.address))
+ if (interop_match_addr(INTEROP_DISABLE_ABSOLUTE_VOLUME, &rc_addr)
+ || absolute_volume_disabled()
+ || bdcmp(avdtp_addr.address, rc_addr.address))
btif_rc_cb[index].rc_features &= ~BTA_AV_FEAT_ADV_CTRL;
if (btif_rc_cb[index].rc_features & BTA_AV_FEAT_BROWSE)
if (btif_rc_cb[index].rc_features & BTA_AV_FEAT_METADATA)
{
rc_features |= BTRC_FEAT_METADATA;
- /* Mark rc features processed to avoid repeating
- * the AVRCP procedure every time on receiving this
- * update.
- */
- btif_rc_cb[index].rc_features_processed = TRUE;
- getcapabilities_cmd (AVRC_CAP_COMPANY_ID);
}
- BTIF_TRACE_DEBUG("%s: rc_features=0x%x", __FUNCTION__, rc_features);
+ if (btif_rc_cb[index].rc_features & BTA_AV_FEAT_AVRC_UI_UPDATE)
+ {
+ rc_features |= BTRC_FEAT_AVRC_UI_UPDATE;
+ }
+ BTIF_TRACE_IMP("%s: rc_features=0x%x", __FUNCTION__, rc_features);
if (btif_rc_cb[index].rc_connected)
{
- BTIF_TRACE_DEBUG("%s: update App on supported features", __FUNCTION__);
+ BTIF_TRACE_IMP("%s: update App on supported features", __FUNCTION__);
HAL_CBACK(bt_rc_callbacks, remote_features_cb, &rc_addr, rc_features)
}
else
{
- BTIF_TRACE_DEBUG("%s: skipping feature update to App", __FUNCTION__);
+ BTIF_TRACE_IMP("%s: skipping feature update to App", __FUNCTION__);
}
#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
BTIF_TRACE_DEBUG("Checking for feature flags in btif_rc_handler with label %d",
UINT32 i;
tAVRC_ATTR_ENTRY element_attrs[MAX_ELEM_ATTR_SIZE];
int valid_attr, rc_index = btif_rc_get_idx_by_addr(bd_addr->address);
+ CHECK_RC_CONNECTED
valid_attr = 0;
if (rc_index == btif_max_rc_clients)
return BT_STATUS_FAIL;
}
BTIF_TRACE_DEBUG("- %s on index = %d", __FUNCTION__, rc_index);
- CHECK_RC_CONNECTED
+
memset(element_attrs, 0, sizeof(tAVRC_ATTR_ENTRY) * num_attr);
if (num_attr == 0)
p_bcb->ch_lcid = lcid; /*Updadate LCID so that on config associated bcb could be found*/
ertm_info.preferred_mode = L2CAP_FCR_ERTM_MODE;
ertm_info.allowed_modes = L2CAP_FCR_CHAN_OPT_ERTM;
- ertm_info.user_rx_buf_size = 4096;//AVCT_BR_USER_RX_BUF_SIZE;
- ertm_info.user_tx_buf_size = 4096;//AVCT_BR_USER_TX_BUF_SIZE;
- ertm_info.fcr_rx_buf_size = 4096;//AVCT_BR_FCR_RX_BUF_SIZE;
- ertm_info.fcr_tx_buf_size = 4096;//AVCT_BR_FCR_TX_BUF_SIZE;
+ ertm_info.user_rx_buf_size = AVCT_BR_USER_RX_BUF_SIZE;
+ ertm_info.user_tx_buf_size = AVCT_BR_USER_TX_BUF_SIZE;
+ ertm_info.fcr_rx_buf_size = AVCT_BR_FCR_RX_BUF_SIZE;
+ ertm_info.fcr_tx_buf_size = AVCT_BR_FCR_TX_BUF_SIZE;
p_ertm_info = &ertm_info;
L2CA_ErtmConnectRsp (bd_addr, id, lcid, result, L2CAP_CONN_OK, p_ertm_info);
}
/******************************************************************************
**
+** Function avrc_get_packet_type
+**
+** Description Gets a packet type for fragmanted packet.
+**
+** Returns Type of fragmenatation packet.
+**
+******************************************************************************/
+static UINT8 avrc_get_packet_type(BT_HDR *pp_pkt)
+{
+ BT_HDR *p_pkt = pp_pkt;
+ UINT8 *p_data;
+ UINT8 pkt_type;
+ p_data = (UINT8 *)(p_pkt+1) + p_pkt->offset;
+ /* Skip over vendor header (ctype, subunit*, opcode, CO_ID) */
+ p_data += AVRC_VENDOR_HDR_SIZE;
+
+ pkt_type = *(p_data + 1) & AVRC_PKT_TYPE_MASK;
+
+ return pkt_type;
+}
+
+/******************************************************************************
+**
** Function avrc_copy_packet
**
** Description Copies an AVRC packet to a new buffer. In the new buffer,
UINT8 *p_data;
UINT8 *p_begin;
UINT8 pkt_type;
+ UINT8 *p_rsp_data;
BOOLEAN abort_frag = FALSE;
tAVRC_STS status = AVRC_STS_NO_ERROR;
tAVRC_FRAG_CB *p_fcb;
if (status != AVRC_STS_NO_ERROR)
{
- /* use the current GKI buffer to build/send the reject message */
- p_data = (UINT8 *)(p_pkt+1) + p_pkt->offset;
- *p_data++ = AVRC_RSP_REJ;
- p_data += AVRC_VENDOR_HDR_SIZE; /* pdu */
- *p_data++ = 0; /* pkt_type */
- UINT16_TO_BE_STREAM(p_data, 1); /* len */
- *p_data++ = status; /* error code */
- p_pkt->len = AVRC_VENDOR_HDR_SIZE + 5;
- p_rsp = p_pkt;
+ /* check for buffer size before modifing it */
+ p_rsp = avrc_copy_packet(p_pkt, AVRC_OP_REJ_MSG_LEN);
+ p_rsp_data = avrc_get_data_ptr(p_rsp);
+ *p_rsp_data++ = AVRC_RSP_REJ;
+ p_rsp_data += AVRC_VENDOR_HDR_SIZE; /* pdu 1 byte*/
+ *p_rsp_data++ = 0; /* pkt_type 1 byte*/
+ UINT16_TO_BE_STREAM(p_rsp_data, 1); /* len 2 byte */
+ *p_rsp_data++ = status; /* error code 1 byte*/
+ p_rsp->len = AVRC_VENDOR_HDR_SIZE + 5;
}
return p_rsp;
msg.hdr.subunit_id = p_data[1] & AVRC_SUBID_MASK;
opcode = p_data[2];
}
-
+ AVRC_TRACE_DEBUG("opcode %d",opcode);
if ( ((avrc_cb.ccb[handle].control & AVRC_CT_TARGET) && (cr == AVCT_CMD)) ||
((avrc_cb.ccb[handle].control & AVRC_CT_CONTROL) && (cr == AVCT_RSP)) )
{
#if (AVRC_METADATA_INCLUDED == TRUE)
UINT8 drop_code = 0;
+ if (p_msg->vendor_len > AVRC_META_CMD_BUF_SIZE)
+ {
+ int packet_type = avrc_get_packet_type(p_pkt);
+ AVRC_TRACE_DEBUG("packet_type %d", packet_type);
+ //single packet size is greater then MTU size, reject it
+ if (packet_type == AVRC_PKT_SINGLE)
+ {
+ AVRC_TRACE_ERROR("Incorrect lenght for single packet");
+ reject = TRUE;
+ break;
+ }
+ }
drop_code = avrc_proc_far_msg(handle, label, cr, &p_pkt, p_msg);
if (drop_code > 0)
drop = TRUE;
opcode = p_data[0];
AVRC_TRACE_DEBUG("opcode:%x, length:%x",opcode, p_pkt->len);
/*Do sanity Check here*/
- if (cr == AVCT_CMD)
+ if ((avrc_cb.ccb[handle].control & AVRC_CT_TARGET) && (cr == AVCT_CMD))
{
opcode = AVRC_OP_BROWSE;
msg.browse.browse_len = p_pkt->len;
status = AVRC_STS_BAD_PARAM;
break;
- case AVRC_EVT_VOLUME_CHANGE:
- len = 2;
- UINT8_TO_BE_STREAM(p_data, (AVRC_MAX_VOLUME & p_rsp->param.volume));
case AVRC_EVT_AVAL_PLAYERS_CHANGE:
len = EVT_AVAIL_PLAYER_CHANGE_RSP_LENGTH;
break;
case AVRC_EVT_NOW_PLAYING_CHANGE:
len = EVT_NOW_PLAYING_CHANGE_RSP_LENGTH;
break;
-
+ case AVRC_EVT_VOLUME_CHANGE:
+ len = 2;
+ UINT8_TO_BE_STREAM(p_data, (AVRC_MAX_VOLUME & p_rsp->param.volume));
+ break;
default:
status = AVRC_STS_BAD_PARAM;
AVRC_TRACE_ERROR("%s unknown event_id", __func__);