Commit 6d488f52 authored by Ajay Panicker's avatar Ajay Panicker Committed by Gerrit Code Review
Browse files

Merge "AVRCP 1.6: media browsing support on Target(1/3)"

parents ee1e3df8 a408eb72
/******************************************************************************
*
* Copyright (C) 2004-2012 Broadcom Corporation
* Copyright (C) 2004-2016 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -227,6 +227,14 @@ static void bta_av_rc_ctrl_cback(uint8_t handle, uint8_t event, uint16_t result,
{
msg_event = BTA_AV_AVRC_CLOSE_EVT;
}
else if (event == AVRC_BROWSE_OPEN_IND_EVT)
{
msg_event = BTA_AV_AVRC_BROWSE_OPEN_EVT;
}
else if (event == AVRC_BROWSE_CLOSE_IND_EVT)
{
msg_event = BTA_AV_AVRC_BROWSE_CLOSE_EVT;
}
if (msg_event) {
tBTA_AV_RC_CONN_CHG *p_msg =
......@@ -255,7 +263,10 @@ static void bta_av_rc_msg_cback(uint8_t handle, uint8_t label, uint8_t opcode, t
APPL_TRACE_DEBUG("%s handle: %u opcode=0x%x", __func__, handle, opcode);
/* Determine the size of the buffer we need */
/* Copy avrc packet into BTA message buffer (for sending to BTA state machine) */
/* Get size of payload data (for vendor and passthrough messages only; for browsing
* messages, use zero-copy) */
if (opcode == AVRC_OP_VENDOR && p_msg->vendor.p_vendor_data != NULL) {
p_data_src = p_msg->vendor.p_vendor_data;
data_len = (uint16_t) p_msg->vendor.vendor_len;
......@@ -267,6 +278,7 @@ static void bta_av_rc_msg_cback(uint8_t handle, uint8_t label, uint8_t opcode, t
/* Create a copy of the message */
tBTA_AV_RC_MSG *p_buf =
(tBTA_AV_RC_MSG *)osi_malloc(sizeof(tBTA_AV_RC_MSG) + data_len);
p_buf->hdr.event = BTA_AV_AVRC_MSG_EVT;
p_buf->handle = handle;
p_buf->label = label;
......@@ -276,13 +288,23 @@ static void bta_av_rc_msg_cback(uint8_t handle, uint8_t label, uint8_t opcode, t
if (p_data_src != NULL) {
uint8_t *p_data_dst = (uint8_t *)(p_buf + 1);
memcpy(p_data_dst, p_data_src, data_len);
/* Update bta message buffer to point to payload data */
/* (Note AVRC_OP_BROWSING uses zero-copy: p_buf->msg.browse.p_browse_data
* already points to original avrc buffer) */
if (opcode == AVRC_OP_VENDOR)
p_buf->msg.vendor.p_vendor_data = p_data_dst;
else if (opcode == AVRC_OP_PASS_THRU)
p_buf->msg.pass.p_pass_data = p_data_dst;
}
if (opcode == AVRC_OP_BROWSE) {
/* set p_pkt to NULL, so avrc would not free the buffer */
p_msg->browse.p_browse_pkt = NULL;
}
bta_sys_sendmsg(p_buf);
}
/*******************************************************************************
......@@ -323,7 +345,8 @@ uint8_t bta_av_rc_create(tBTA_AV_CB *p_cb, uint8_t role, uint8_t shdl, uint8_t l
ccb.company_id = p_bta_av_cfg->company_id;
ccb.conn = role;
/* note: BTA_AV_FEAT_RCTG = AVRC_CT_TARGET, BTA_AV_FEAT_RCCT = AVRC_CT_CONTROL */
ccb.control = p_cb->features & (BTA_AV_FEAT_RCTG | BTA_AV_FEAT_RCCT | AVRC_CT_PASSIVE);
ccb.control = p_cb->features & (BTA_AV_FEAT_RCTG | BTA_AV_FEAT_RCCT | BTA_AV_FEAT_METADATA |
AVRC_CT_PASSIVE);
if (AVRC_Open(&rc_handle, &ccb, bda) != AVRC_SUCCESS)
return BTA_AV_RC_HANDLE_NONE;
......@@ -512,6 +535,14 @@ void bta_av_rc_opened(tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data)
return;
}
if (p_cb->features & BTA_AV_FEAT_RCTG)
{
/* listen to browsing channel when the connection is open,
* if peer initiated AVRCP connection and local device supports browsing channel */
if ((p_cb->features & BTA_AV_FEAT_BROWSE) && (p_cb->rcb[i].peer_features == 0))
AVRC_OpenBrowse(p_data->rc_conn_chg.handle, AVCT_ACP);
}
if (p_cb->rcb[i].lidx == (BTA_AV_NUM_LINKS + 1) && shdl != 0)
{
/* rc is opened on the RC only ACP channel, but is for a specific
......@@ -572,6 +603,15 @@ void bta_av_rc_opened(tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data)
}
(*p_cb->p_cback)(BTA_AV_RC_OPEN_EVT, (tBTA_AV *) &rc_open);
/* if local initiated AVRCP connection and both peer and locals device support
* browsing channel, open the browsing channel now */
if ((p_cb->features & BTA_AV_FEAT_BROWSE) &&
(rc_open.peer_features & BTA_AV_FEAT_BROWSE) &&
((p_cb->rcb[i].status & BTA_AV_RC_ROLE_MASK) == BTA_AV_RC_ROLE_INT))
{
AVRC_OpenBrowse (p_data->rc_conn_chg.handle, AVCT_INT);
}
}
/*******************************************************************************
......@@ -696,17 +736,20 @@ void bta_av_rc_free_rsp (tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data)
/*******************************************************************************
**
** Function bta_av_rc_meta_req
** Function bta_av_rc_free_browse_msg
**
** Description Send an AVRCP metadata command.
** Description free an AVRCP browse message buffer.
**
** Returns void
**
*******************************************************************************/
void bta_av_rc_free_msg (tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data)
void bta_av_rc_free_browse_msg (tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data)
{
UNUSED(p_cb);
UNUSED(p_data);
if (p_data->rc_msg.opcode == AVRC_OP_BROWSE)
{
osi_free_and_reset((void **)&p_data->rc_msg.msg.browse.p_browse_pkt);
}
}
/*******************************************************************************
......@@ -778,7 +821,8 @@ tBTA_AV_EVT bta_av_proc_meta_cmd(tAVRC_RESPONSE *p_rc_rsp, tBTA_AV_RC_MSG *p_ms
/* reject it */
evt=0;
p_vendor->hdr.ctype = BTA_AV_RSP_NOT_IMPL;
AVRC_VendorRsp(p_msg->handle, p_msg->label, &p_msg->msg.vendor);
p_vendor->vendor_len = 0;
p_rc_rsp->rsp.status = AVRC_STS_BAD_PARAM;
}
else if (!AVRC_IsValidAvcType(pdu, p_vendor->hdr.ctype) )
{
......@@ -872,6 +916,15 @@ void bta_av_rc_msg(tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data)
rc_rsp.rsp.status = BTA_AV_STS_NO_RSP;
#endif
if (NULL == p_data)
{
APPL_TRACE_ERROR("Message from peer with no data in %s", __func__);
return;
}
APPL_TRACE_DEBUG("%s: opcode=%x, ctype=%x", __func__, p_data->rc_msg.opcode,
p_data->rc_msg.msg.hdr.ctype);
if (p_data->rc_msg.opcode == AVRC_OP_PASS_THRU)
{
/* if this is a pass thru command */
......@@ -893,7 +946,7 @@ void bta_av_rc_msg(tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data)
p_data->rc_msg.msg.pass.p_pass_data, is_inquiry);
#endif
}
#if (AVRC_CTLR_INCLUDED == TRUE)
#if (AVRC_CTRL_INCLUDED == TRUE)
else if (((p_data->rc_msg.msg.pass.op_id == AVRC_ID_VOL_UP)||
(p_data->rc_msg.msg.pass.op_id == AVRC_ID_VOL_DOWN)) &&
!strcmp(avrcp_ct_support, "true"))
......@@ -974,6 +1027,7 @@ void bta_av_rc_msg(tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data)
(p_vendor->company_id == AVRC_CO_METADATA))
{
av.meta_msg.p_msg = &p_data->rc_msg.msg;
rc_rsp.rsp.status = BTA_AV_STS_NO_RSP;
evt = bta_av_proc_meta_cmd (&rc_rsp, &p_data->rc_msg, &ctype);
}
else
......@@ -1011,6 +1065,19 @@ void bta_av_rc_msg(tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data)
AVRC_VendorRsp(p_data->rc_msg.handle, p_data->rc_msg.label, &p_data->rc_msg.msg.vendor);
}
}
else if (p_data->rc_msg.opcode == AVRC_OP_BROWSE)
{
/* set up for callback */
av.meta_msg.rc_handle = p_data->rc_msg.handle;
av.meta_msg.company_id = p_vendor->company_id;
av.meta_msg.code = p_data->rc_msg.msg.hdr.ctype;
av.meta_msg.label = p_data->rc_msg.label;
av.meta_msg.p_msg = &p_data->rc_msg.msg;
av.meta_msg.p_data = p_data->rc_msg.msg.browse.p_browse_data;
av.meta_msg.len = p_data->rc_msg.msg.browse.browse_len;
evt = BTA_AV_META_MSG_EVT;
}
#if (AVRC_METADATA_INCLUDED == TRUE)
if (evt == 0 && rc_rsp.rsp.status != BTA_AV_STS_NO_RSP)
{
......@@ -1029,6 +1096,8 @@ void bta_av_rc_msg(tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data)
{
av.remote_cmd.rc_handle = p_data->rc_msg.handle;
(*p_cb->p_cback)(evt, &av);
/* If browsing message, then free the browse message buffer */
bta_av_rc_free_browse_msg(p_cb, p_data);
}
}
......@@ -1328,6 +1397,8 @@ void bta_av_conn_chg(tBTA_AV_DATA *p_data)
if (bta_av_cb.rcb[i].shdl == index + 1)
{
bta_av_del_rc(&bta_av_cb.rcb[i]);
/* since the connection is already down and info was removed, clean reference */
bta_av_cb.rcb[i].shdl = 0;
break;
}
}
......@@ -2034,6 +2105,61 @@ void bta_av_rc_closed(tBTA_AV_DATA *p_data)
(*p_cb->p_cback)(BTA_AV_RC_CLOSE_EVT, (tBTA_AV *) &rc_close);
}
/*******************************************************************************
**
** Function bta_av_rc_browse_opened
**
** Description AVRC browsing channel is opened
**
** Returns void
**
*******************************************************************************/
void bta_av_rc_browse_opened(tBTA_AV_DATA *p_data)
{
tBTA_AV_CB *p_cb = &bta_av_cb;
tBTA_AV_RC_CONN_CHG *p_msg = (tBTA_AV_RC_CONN_CHG *)p_data;
tBTA_AV_RC_BROWSE_OPEN rc_browse_open;
APPL_TRACE_DEBUG("bta_av_rc_browse_opened bd_addr:%02x-%02x-%02x-%02x-%02x-%02x",
p_msg->peer_addr[0], p_msg->peer_addr[1],
p_msg->peer_addr[2], p_msg->peer_addr[3],
p_msg->peer_addr[4], p_msg->peer_addr[5]);
APPL_TRACE_DEBUG("bta_av_rc_browse_opened rc_handle:%d", p_msg->handle);
rc_browse_open.status = BTA_AV_SUCCESS;
rc_browse_open.rc_handle = p_msg->handle;
bdcpy(rc_browse_open.peer_addr, p_msg->peer_addr);
(*p_cb->p_cback)(BTA_AV_RC_BROWSE_OPEN_EVT, (tBTA_AV *)&rc_browse_open);
}
/*******************************************************************************
**
** Function bta_av_rc_browse_closed
**
** Description AVRC browsing channel is closed
**
** Returns void
**
*******************************************************************************/
void bta_av_rc_browse_closed(tBTA_AV_DATA *p_data)
{
tBTA_AV_CB *p_cb = &bta_av_cb;
tBTA_AV_RC_CONN_CHG *p_msg = (tBTA_AV_RC_CONN_CHG *)p_data;
tBTA_AV_RC_BROWSE_CLOSE rc_browse_close;
APPL_TRACE_DEBUG("bta_av_rc_browse_closed bd_addr:%02x-%02x-%02x-%02x-%02x-%02x",
p_msg->peer_addr[0], p_msg->peer_addr[1],
p_msg->peer_addr[2], p_msg->peer_addr[3],
p_msg->peer_addr[4], p_msg->peer_addr[5]);
APPL_TRACE_DEBUG("bta_av_rc_browse_closed rc_handle:%d", p_msg->handle);
rc_browse_close.rc_handle = p_msg->handle;
bdcpy(rc_browse_close.peer_addr, p_msg->peer_addr);
(*p_cb->p_cback)(BTA_AV_RC_BROWSE_CLOSE_EVT, (tBTA_AV *)&rc_browse_close);
}
/*******************************************************************************
**
** Function bta_av_rc_disc
......
/******************************************************************************
*
* Copyright (C) 2005-2012 Broadcom Corporation
* Copyright (C) 2005-2016 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -30,6 +30,10 @@
#include "bta_api.h"
#include "bta_av_int.h"
#ifndef BTA_AV_RC_COMP_ID
#define BTA_AV_RC_COMP_ID AVRC_CO_GOOGLE
#endif
#ifndef BTA_AV_RC_PASS_RSP_CODE
#define BTA_AV_RC_PASS_RSP_CODE BTA_AV_RSP_NOT_IMPL
#endif
......@@ -39,13 +43,22 @@ const uint32_t bta_av_meta_caps_co_ids[] = {
AVRC_CO_BROADCOM
};
/* AVRCP cupported categories */
/* AVRCP supported categories */
#if (AVRC_CTRL_INCLUDED == TRUE)
#define BTA_AV_RC_SUPF_CT (AVRC_SUPF_CT_CAT2)
#define BTA_AVK_RC_SUPF_CT (AVRC_SUPF_CT_CAT1)
#define BTA_AVK_RC_SUPF_TG (AVRC_SUPF_TG_CAT2)
#endif
/* AVRCP Controller and Targer default name */
#ifndef BTA_AV_RC_CT_NAME
#define BTA_AV_RC_CT_NAME "AVRC Controller"
#endif
#ifndef BTA_AV_RC_TG_NAME
#define BTA_AV_RC_TG_NAME "AVRC Target"
#endif
/* Added to modify
** 1. flush timeout
** 2. Remove Group navigation support in SupportedFeatures
......@@ -65,7 +78,8 @@ const uint16_t bta_av_audio_flush_to[] = {
/* Note: Android doesnt 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_SUPF_TG (AVRC_SUPF_TG_CAT1) /* TODO: | AVRC_SUPF_TG_APP_SETTINGS) */
#define BTA_AV_RC_SUPF_TG (AVRC_SUPF_TG_CAT1 | AVRC_SUPF_TG_MULTI_PLAYER | \
AVRC_SUPF_TG_BROWSE) /* TODO: | AVRC_SUPF_TG_APP_SETTINGS) */
#else
#define BTA_AV_RC_SUPF_TG (AVRC_SUPF_TG_CAT1)
#endif
......@@ -77,6 +91,10 @@ const uint8_t bta_av_meta_caps_evt_ids[] = {
AVRC_EVT_PLAY_STATUS_CHANGE,
AVRC_EVT_TRACK_CHANGE,
AVRC_EVT_PLAY_POS_CHANGED,
AVRC_EVT_AVAL_PLAYERS_CHANGE,
AVRC_EVT_ADDR_PLAYER_CHANGE,
AVRC_EVT_UIDS_CHANGE,
AVRC_EVT_NOW_PLAYING_CHANGE,
/* TODO: Add support for these events
AVRC_EVT_APP_SETTING_CHANGE,
*/
......@@ -103,7 +121,7 @@ const uint8_t bta_avk_meta_caps_evt_ids[] = {
/* This configuration to be used when we are Src + TG + CT( only for abs vol) */
const tBTA_AV_CFG bta_av_cfg =
{
AVRC_CO_BROADCOM, /* AVRCP Company ID */
BTA_AV_RC_COMP_ID, /* AVRCP Company ID */
#if (AVRC_METADATA_INCLUDED == TRUE)
512, /* AVRCP MTU at L2CAP for control channel */
#else
......@@ -126,8 +144,8 @@ const tBTA_AV_CFG bta_av_cfg =
bta_av_meta_caps_evt_ids,/* the the metadata Get Capabilities response for event id */
NULL, /* the action function table for VDP stream */
NULL, /* action function to register VDP */
{0}, /* Default AVRCP controller name */
{0}, /* Default AVRCP target name */
BTA_AV_RC_CT_NAME, /* Default AVRCP controller name */
BTA_AV_RC_TG_NAME /* Default AVRCP target name */
};
/* This configuration to be used when we are Sink + CT + TG( only for abs vol) */
......
......@@ -97,6 +97,8 @@ enum
BTA_AV_SIGNALLING_TIMER_EVT,
BTA_AV_SDP_AVRC_DISC_EVT,
BTA_AV_AVRC_CLOSE_EVT,
BTA_AV_AVRC_BROWSE_OPEN_EVT,
BTA_AV_AVRC_BROWSE_CLOSE_EVT,
BTA_AV_CONN_CHG_EVT,
BTA_AV_DEREG_COMP_EVT,
#if (AVDT_REPORTING == TRUE)
......@@ -651,6 +653,8 @@ extern void bta_av_sig_chg(tBTA_AV_DATA *p_data);
extern void bta_av_signalling_timer(tBTA_AV_DATA *p_data);
extern void bta_av_rc_disc_done(tBTA_AV_DATA *p_data);
extern void bta_av_rc_closed(tBTA_AV_DATA *p_data);
extern void bta_av_rc_browse_opened(tBTA_AV_DATA *p_data);
extern void bta_av_rc_browse_closed(tBTA_AV_DATA *p_data);
extern void bta_av_rc_disc(uint8_t disc);
extern void bta_av_conn_chg(tBTA_AV_DATA *p_data);
extern void bta_av_dereg_comp(tBTA_AV_DATA *p_data);
......@@ -665,7 +669,7 @@ extern void bta_av_rc_msg (tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data);
extern void bta_av_rc_close (tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data);
extern void bta_av_rc_meta_rsp (tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data);
extern void bta_av_rc_free_rsp (tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data);
extern void bta_av_rc_free_msg (tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data);
extern void bta_av_rc_free_browse_msg (tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data);
extern tBTA_AV_RCB * bta_av_get_rcb_by_shdl(uint8_t shdl);
extern void bta_av_del_rc(tBTA_AV_RCB *p_rcb);
......
......@@ -78,7 +78,7 @@ enum
BTA_AV_RC_VENDOR_CMD,
BTA_AV_RC_VENDOR_RSP,
BTA_AV_RC_FREE_RSP,
BTA_AV_RC_FREE_MSG,
BTA_AV_RC_FREE_BROWSE_MSG,
BTA_AV_RC_META_RSP,
BTA_AV_RC_MSG,
BTA_AV_RC_CLOSE,
......@@ -99,7 +99,7 @@ const tBTA_AV_ACTION bta_av_action[] =
bta_av_rc_vendor_cmd,
bta_av_rc_vendor_rsp,
bta_av_rc_free_rsp,
bta_av_rc_free_msg,
bta_av_rc_free_browse_msg,
bta_av_rc_meta_rsp,
bta_av_rc_msg,
bta_av_rc_close,
......@@ -122,7 +122,7 @@ static const uint8_t bta_av_st_init[][BTA_AV_NUM_COLS] =
/* API_META_RSP_EVT */ {BTA_AV_RC_FREE_RSP, BTA_AV_INIT_ST },
/* API_RC_CLOSE_EVT */ {BTA_AV_IGNORE, BTA_AV_INIT_ST },
/* AVRC_OPEN_EVT */ {BTA_AV_RC_OPENED, BTA_AV_OPEN_ST },
/* AVRC_MSG_EVT */ {BTA_AV_RC_FREE_MSG, BTA_AV_INIT_ST },
/* AVRC_MSG_EVT */ {BTA_AV_RC_FREE_BROWSE_MSG, BTA_AV_INIT_ST },
/* AVRC_NONE_EVT */ {BTA_AV_IGNORE, BTA_AV_INIT_ST },
};
......@@ -176,6 +176,8 @@ const tBTA_AV_NSM_ACT bta_av_nsm_act[] =
bta_av_signalling_timer, /* BTA_AV_SIGNALLING_TIMER_EVT */
bta_av_rc_disc_done, /* BTA_AV_SDP_AVRC_DISC_EVT */
bta_av_rc_closed, /* BTA_AV_AVRC_CLOSE_EVT */
bta_av_rc_browse_opened,/* BTA_AV_AVRC_BROWSE_OPEN_EVT */
bta_av_rc_browse_closed,/* BTA_AV_AVRC_BROWSE_CLOSE_EVT */
bta_av_conn_chg, /* BTA_AV_CONN_CHG_EVT */
bta_av_dereg_comp, /* BTA_AV_DEREG_COMP_EVT */
#if (AVDT_REPORTING == TRUE)
......@@ -456,10 +458,16 @@ static void bta_av_api_register(tBTA_AV_DATA *p_data)
p_bta_av_cfg = (tBTA_AV_CFG *) &bta_av_cfg;
}
if (p_bta_av_cfg == NULL)
{
APPL_TRACE_ERROR("AV configuration is null!");
return;
}
do
{
p_scb = bta_av_alloc_scb(registr.chnl);
if(p_scb == NULL)
if (p_scb == NULL)
{
APPL_TRACE_ERROR("failed to alloc SCB");
break;
......@@ -471,7 +479,7 @@ static void bta_av_api_register(tBTA_AV_DATA *p_data)
/* initialize the stream control block */
registr.status = BTA_AV_SUCCESS;
if((bta_av_cb.reg_audio + bta_av_cb.reg_video) == 0)
if ((bta_av_cb.reg_audio + bta_av_cb.reg_video) == 0)
{
/* the first channel registered. register to AVDTP */
reg.ctrl_mtu = p_bta_av_cfg->sig_mtu;
......@@ -496,19 +504,19 @@ static void bta_av_api_register(tBTA_AV_DATA *p_data)
bta_ar_reg_avct(p_bta_av_cfg->avrc_mtu, p_bta_av_cfg->avrc_br_mtu,
(uint8_t)(bta_av_cb.sec_mask & (~BTA_SEC_AUTHORIZE)), BTA_ID_AV);
#endif
uint16_t profile_version = AVRC_REV_1_0;
if (profile_initialized == UUID_SERVCLASS_AUDIO_SOURCE)
{
bta_ar_reg_avrc(UUID_SERVCLASS_AV_REM_CTRL_TARGET, "AV Remote Control Target",
NULL, p_bta_av_cfg->avrc_tg_cat, BTA_ID_AV,
(bta_av_cb.features & BTA_AV_FEAT_BROWSE), AVRC_REV_1_3);
profile_version = AVRC_REV_1_6;
}
else if (profile_initialized == UUID_SERVCLASS_AUDIO_SINK)
{
// Initialize AVRCP1.4 to provide Absolute Volume control.
bta_ar_reg_avrc(UUID_SERVCLASS_AV_REM_CTRL_TARGET, "AV Remote Control Target",
NULL, p_bta_av_cfg->avrc_tg_cat, BTA_ID_AV,
(bta_av_cb.features & BTA_AV_FEAT_BROWSE), AVRC_REV_1_4);
profile_version = AVRC_REV_1_4;
}
bta_ar_reg_avrc(UUID_SERVCLASS_AV_REM_CTRL_TARGET, "AV Remote Control Target",
NULL, p_bta_av_cfg->avrc_tg_cat, BTA_ID_AV,
(bta_av_cb.features & BTA_AV_FEAT_BROWSE), profile_version);
#endif
}
......@@ -1331,6 +1339,8 @@ char *bta_av_evt_code(uint16_t evt_code)
case BTA_AV_SIGNALLING_TIMER_EVT: return "SIGNALLING_TIMER";
case BTA_AV_SDP_AVRC_DISC_EVT: return "SDP_AVRC_DISC";
case BTA_AV_AVRC_CLOSE_EVT: return "AVRC_CLOSE";
case BTA_AV_AVRC_BROWSE_OPEN_EVT: return "AVRC_BROWSE_OPEN";
case BTA_AV_AVRC_BROWSE_CLOSE_EVT: return "AVRC_BROWSE_CLOSE";
case BTA_AV_CONN_CHG_EVT: return "CONN_CHG";
case BTA_AV_DEREG_COMP_EVT: return "DEREG_COMP";
#if (AVDT_REPORTING == TRUE)
......
......@@ -203,34 +203,36 @@ typedef uint8_t tBTA_AV_ERR;
/* AV callback events */
#define BTA_AV_ENABLE_EVT 0 /* AV enabled */
#define BTA_AV_REGISTER_EVT 1 /* registered to AVDT */
#define BTA_AV_OPEN_EVT 2 /* connection opened */
#define BTA_AV_CLOSE_EVT 3 /* connection closed */
#define BTA_AV_START_EVT 4 /* stream data transfer started */
#define BTA_AV_STOP_EVT 5 /* stream data transfer stopped */
#define BTA_AV_PROTECT_REQ_EVT 6 /* content protection request */
#define BTA_AV_PROTECT_RSP_EVT 7 /* content protection response */
#define BTA_AV_RC_OPEN_EVT 8 /* remote control channel open */
#define BTA_AV_RC_CLOSE_EVT 9 /* remote control channel closed */
#define BTA_AV_REMOTE_CMD_EVT 10 /* remote control command */
#define BTA_AV_REMOTE_RSP_EVT 11 /* remote control response */
#define BTA_AV_VENDOR_CMD_EVT 12 /* vendor dependent remote control command */
#define BTA_AV_VENDOR_RSP_EVT 13 /* vendor dependent remote control response */
#define BTA_AV_RECONFIG_EVT 14 /* reconfigure response */
#define BTA_AV_SUSPEND_EVT 15 /* suspend response */
#define BTA_AV_PENDING_EVT 16 /* incoming connection pending:
* signal channel is open and stream is
* not open after
* BTA_AV_SIGNALLING_TIMEOUT_MS */
#define BTA_AV_META_MSG_EVT 17 /* metadata messages */
#define BTA_AV_REJECT_EVT 18 /* incoming connection rejected */
#define BTA_AV_RC_FEAT_EVT 19 /* remote control channel peer supported features update */
#define BTA_AV_SINK_MEDIA_CFG_EVT 20 /* command to configure sink codec */
#define BTA_AV_SINK_MEDIA_DATA_EVT 21 /* sending sink data to Media Task */
#define BTA_AV_OFFLOAD_START_RSP_EVT 22 /* a2dp offload start response */
#define BTA_AV_ENABLE_EVT 0 /* AV enabled */
#define BTA_AV_REGISTER_EVT 1 /* registered to AVDT */
#define BTA_AV_OPEN_EVT 2 /* connection opened */
#define BTA_AV_CLOSE_EVT 3 /* connection closed */
#define BTA_AV_START_EVT 4 /* stream data transfer started */
#define BTA_AV_STOP_EVT 5 /* stream data transfer stopped */
#define BTA_AV_PROTECT_REQ_EVT 6 /* content protection request */
#define BTA_AV_PROTECT_RSP_EVT 7 /* content protection response */
#define BTA_AV_RC_OPEN_EVT 8 /* remote control channel open */
#define BTA_AV_RC_CLOSE_EVT 9 /* remote control channel closed */
#define BTA_AV_RC_BROWSE_OPEN_EVT 10 /* remote control browse channel open */
#define BTA_AV_RC_BROWSE_CLOSE_EVT 11 /* remote control browse channel closed */
#define BTA_AV_REMOTE_CMD_EVT 12 /* remote control command */
#define BTA_AV_REMOTE_RSP_EVT 13 /* remote control response */
#define BTA_AV_VENDOR_CMD_EVT 14 /* vendor dependent remote control command */
#define BTA_AV_VENDOR_RSP_EVT 15 /* vendor dependent remote control response */
#define BTA_AV_RECONFIG_EVT 16 /* reconfigure response */
#define BTA_AV_SUSPEND_EVT 17 /* suspend response */
#define BTA_AV_PENDING_EVT 18 /* incoming connection pending:
* signal channel is open and stream is
* not open after
* BTA_AV_SIGNALLING_TIMEOUT_MS */
#define BTA_AV_META_MSG_EVT 19 /* metadata messages */
#define BTA_AV_REJECT_EVT 20 /* incoming connection rejected */
#define BTA_AV_RC_FEAT_EVT 21 /* remote control channel peer supported features update */
#define BTA_AV_SINK_MEDIA_CFG_EVT 22 /* command to configure sink codec */
#define BTA_AV_SINK_MEDIA_DATA_EVT 23 /* sending sink data to Media Task */
#define BTA_AV_OFFLOAD_START_RSP_EVT 24 /* a2dp offload start response */
/* Max BTA event */
#define BTA_AV_MAX_EVT 23
#define BTA_AV_MAX_EVT 25
typedef uint8_t tBTA_AV_EVT;
......@@ -305,8 +307,8 @@ typedef struct
{
tBTA_AV_CHNL chnl;
tBTA_AV_HNDL hndl;
uint8_t *p_data;
uint16_t len;
uint8_t *p_data;
uint16_t len;
} tBTA_AV_PROTECT_REQ;
/* data associated with BTA_AV_PROTECT_RSP_EVT */
......@@ -314,15 +316,15 @@ typedef struct
{
tBTA_AV_CHNL chnl;
tBTA_AV_HNDL hndl;
uint8_t *p_data;
uint16_t len;
uint8_t *p_data;
uint16_t len;
tBTA_AV_ERR err_code;
} tBTA_AV_PROTECT_RSP;
/* data associated with BTA_AV_RC_OPEN_EVT */
typedef struct
{
uint8_t rc_handle;
uint8_t rc_handle;
tBTA_AV_FEAT peer_features;
BD_ADDR peer_addr;
tBTA_AV_STATUS status;
......@@ -331,10 +333,25 @@ typedef struct
/* data associated with BTA_AV_RC_CLOSE_EVT */
typedef struct
{
uint8_t rc_handle;
uint8_t rc_handle;
BD_ADDR peer_addr;
} tBTA_AV_RC_CLOSE;
/* data associated with BTA_AV_RC_BROWSE_OPEN_EVT */
typedef struct
{
uint8_t rc_handle;
BD_ADDR peer_addr;
tBTA_AV_STATUS status;
} tBTA_AV_RC_BROWSE_OPEN;
/* data associated with BTA_AV_RC_BROWSE_CLOSE_EVT */
typedef struct
{
uint8_t rc_handle;
BD_ADDR peer_addr;
} tBTA_AV_RC_BROWSE_CLOSE;
/* data associated with BTA_AV_RC_FEAT_EVT */
typedef struct
{
......@@ -417,6 +434,8 @@ typedef union
tBTA_AV_PROTECT_RSP protect_rsp;
tBTA_AV_RC_OPEN rc_open;
tBTA_AV_RC_CLOSE rc_close;
tBTA_AV_RC_BROWSE_OPEN rc_browse_open;
tBTA_AV_RC_BROWSE_CLOSE rc_browse_close;
tBTA_AV_REMOTE_CMD remote_cmd;
tBTA_AV_REMOTE_RSP remote_rsp;
tBTA_AV_VENDOR vendor_cmd;
......
/******************************************************************************
*
* Copyright (C) 2009-2012 Broadcom Corporation
* Copyright (C) 2009-2016 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -26,6 +26,7 @@
#include <system/audio.h>
#include <hardware/bluetooth.h>
#include <hardware/bt_av.h>
#include <hardware/bt_rc.h>
#include "bt_utils.h"
#include "bta_api.h"
......@@ -113,6 +114,8 @@ else\
#define CHECK_RC_EVENT(e, d) \
case BTA_AV_RC_OPEN_EVT: \
case BTA_AV_RC_CLOSE_EVT: \
case BTA_AV_RC_BROWSE_OPEN_EVT: \
case BTA_AV_RC_BROWSE_CLOSE_EVT: \
case BTA_AV_REMOTE_CMD_EVT: \
case BTA_AV_VENDOR_CMD_EVT: \
case BTA_AV_META_MSG_EVT: \
......@@ -144,7 +147,7 @@ static void btif_av_event_free_data(btif_sm_event_t event, void *p_data);
*************************************************************************/
extern void btif_rc_handler(tBTA_AV_EVT event, tBTA_AV *p_data);
extern bool btif_rc_get_connected_peer(BD_ADDR peer_addr);
extern uint8_t btif_rc_get_connected_peer_handle(void);
extern uint8_t btif_rc_get_connected_peer_handle(BD_ADDR peer_addr);
extern void btif_rc_check_handle_pending_play (BD_ADDR peer_addr, bool bSendToApp);
extern fixed_queue_t *btu_general_alarm_queue;
......@@ -180,6 +183,8 @@ const char *dump_av_sm_event_name(btif_av_sm_event_t event)
CASE_RETURN_STR(BTA_AV_PROTECT_RSP_EVT)
CASE_RETURN_STR(BTA_AV_RC_OPEN_EVT)
CASE_RETURN_STR(BTA_AV_RC_CLOSE_EVT)
CASE_RETURN_STR(BTA_AV_RC_BROWSE_OPEN_EVT)
CASE_RETURN_STR(BTA_AV_RC_BROWSE_CLOSE_EVT)
CASE_RETURN_STR(BTA_AV_REMOTE_CMD_EVT)
CASE_RETURN_STR(BTA_AV_REMOTE_RSP_EVT)
CASE_RETURN_STR(BTA_AV_VENDOR_CMD_EVT)
......@@ -369,6 +374,11 @@ static bool btif_av_state_idle_handler(btif_sm_event_t event, void *p_data)
btif_rc_handler(event, (tBTA_AV*)p_data);
break;
case BTA_AV_RC_BROWSE_OPEN_EVT:
BTIF_TRACE_DEBUG("BTA_AV_RC_BROWSE_OPEN_EVT received");
btif_rc_handler(event, (tBTA_AV*)p_data);
break;
/*
* In case Signalling channel is not down
* and remote started Streaming Procedure
......@@ -516,6 +526,7 @@ static bool btif_av_state_opening_handler(btif_sm_event_t event, void *p_data)
BTIF_TRACE_WARNING("BTA_AV_OPEN_EVT::FAILED status: %d",
p_bta_data->open.status );
BD_ADDR peer_addr;
uint8_t peer_handle = BTRC_HANDLE_NONE;
if ((btif_rc_get_connected_peer(peer_addr))
&&(!bdcmp(btif_av_cb.peer_bda.address, peer_addr)))
{
......@@ -524,7 +535,10 @@ static bool btif_av_state_opening_handler(btif_sm_event_t event, void *p_data)
* A2DP conneciton failed, for any reason
*/
BTIF_TRACE_WARNING(" Disconnecting AVRCP ");
BTA_AvCloseRc(btif_rc_get_connected_peer_handle());
peer_handle = btif_rc_get_connected_peer_handle(peer_addr);
if (peer_handle != BTRC_HANDLE_NONE) {
BTA_AvCloseRc(peer_handle);
}
}
state = BTAV_CONNECTION_STATE_DISCONNECTED;
av_state = BTIF_AV_STATE_IDLE;
......@@ -680,6 +694,11 @@ static bool btif_av_state_closing_handler(btif_sm_event_t event, void *p_data)
btif_rc_handler(event, (tBTA_AV*)p_data);
break;
/* Handle the RC_BROWSE_CLOSE event for tetsing*/
case BTA_AV_RC_BROWSE_CLOSE_EVT:
btif_rc_handler(event, (tBTA_AV*)p_data);
break;
case BTIF_AV_OFFLOAD_START_REQ_EVT:
btif_a2dp_on_offload_started(BTA_AV_FAIL);
BTIF_TRACE_ERROR("BTIF_AV_OFFLOAD_START_REQ_EVT: Stream not Started Closing");
......@@ -1086,14 +1105,17 @@ void btif_av_event_deep_copy(uint16_t event, char *p_dest, char *p_src)
memcpy(av_dest->meta_msg.p_msg, av_src->meta_msg.p_msg,
sizeof(tAVRC_MSG));
if (av_src->meta_msg.p_msg->vendor.p_vendor_data &&
av_src->meta_msg.p_msg->vendor.vendor_len)
{
av_dest->meta_msg.p_msg->vendor.p_vendor_data = (uint8_t *)osi_calloc(
av_src->meta_msg.p_msg->vendor.vendor_len);
memcpy(av_dest->meta_msg.p_msg->vendor.p_vendor_data,
av_src->meta_msg.p_msg->vendor.p_vendor_data,
av_src->meta_msg.p_msg->vendor.vendor_len);
tAVRC_MSG *p_msg_src = av_src->meta_msg.p_msg;
tAVRC_MSG *p_msg_dest = av_dest->meta_msg.p_msg;
if ((p_msg_src->hdr.opcode == AVRC_OP_VENDOR) &&
(p_msg_src->vendor.p_vendor_data &&
p_msg_src->vendor.vendor_len)) {
p_msg_dest->vendor.p_vendor_data = (uint8_t *)osi_calloc(
p_msg_src->vendor.vendor_len);
memcpy(p_msg_dest->vendor.p_vendor_data,
p_msg_src->vendor.p_vendor_data,
p_msg_src->vendor.vendor_len);
}
}
break;
......@@ -1113,7 +1135,9 @@ static void btif_av_event_free_data(btif_sm_event_t event, void *p_data)
osi_free_and_reset((void **)&av->meta_msg.p_data);
if (av->meta_msg.p_msg) {
osi_free(av->meta_msg.p_msg->vendor.p_vendor_data);
if (av->meta_msg.p_msg->hdr.opcode == AVRC_OP_VENDOR) {
osi_free(av->meta_msg.p_msg->vendor.p_vendor_data);
}
osi_free_and_reset((void **)&av->meta_msg.p_msg);
}
}
......@@ -1541,6 +1565,7 @@ bt_status_t btif_av_execute_service(bool b_enable)
#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
|BTA_AV_FEAT_RCCT
|BTA_AV_FEAT_ADV_CTRL
|BTA_AV_FEAT_BROWSE
#endif
,bte_av_callback);
#else
......
This diff is collapsed.
/******************************************************************************
*
* Copyright (c) 2014 The Android Open Source Project
* Copyright (C) 2009-2012 Broadcom Corporation
* Copyright (C) 2009-2016 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -485,6 +485,8 @@ const char *dump_rc_event(uint8_t event)
switch(event) {
CASE_RETURN_STR(BTA_AV_RC_OPEN_EVT)
CASE_RETURN_STR(BTA_AV_RC_CLOSE_EVT)
CASE_RETURN_STR(BTA_AV_RC_BROWSE_OPEN_EVT)
CASE_RETURN_STR(BTA_AV_RC_BROWSE_CLOSE_EVT)
CASE_RETURN_STR(BTA_AV_REMOTE_CMD_EVT)
CASE_RETURN_STR(BTA_AV_REMOTE_RSP_EVT)
CASE_RETURN_STR(BTA_AV_VENDOR_CMD_EVT)
......@@ -509,6 +511,10 @@ const char * dump_rc_notification_event_id(uint8_t event_id)
CASE_RETURN_STR(AVRC_EVT_SYSTEM_STATUS_CHANGE)
CASE_RETURN_STR(AVRC_EVT_APP_SETTING_CHANGE)
CASE_RETURN_STR(AVRC_EVT_VOLUME_CHANGE)
CASE_RETURN_STR(AVRC_EVT_ADDR_PLAYER_CHANGE)
CASE_RETURN_STR(AVRC_EVT_AVAL_PLAYERS_CHANGE)
CASE_RETURN_STR(AVRC_EVT_NOW_PLAYING_CHANGE)
CASE_RETURN_STR(AVRC_EVT_UIDS_CHANGE)
default:
return "Unhandled Event ID";
......@@ -536,6 +542,15 @@ const char* dump_rc_pdu(uint8_t pdu)
CASE_RETURN_STR(AVRC_PDU_SET_ADDRESSED_PLAYER)
CASE_RETURN_STR(AVRC_PDU_CHANGE_PATH)
CASE_RETURN_STR(AVRC_PDU_GET_CAPABILITIES)
CASE_RETURN_STR(AVRC_PDU_SET_BROWSED_PLAYER)
CASE_RETURN_STR(AVRC_PDU_GET_FOLDER_ITEMS)
CASE_RETURN_STR(AVRC_PDU_GET_ITEM_ATTRIBUTES)
CASE_RETURN_STR(AVRC_PDU_PLAY_ITEM)
CASE_RETURN_STR(AVRC_PDU_SEARCH)
CASE_RETURN_STR(AVRC_PDU_ADD_TO_NOW_PLAYING)
CASE_RETURN_STR(AVRC_PDU_GET_TOTAL_NUM_OF_ITEMS)
CASE_RETURN_STR(AVRC_PDU_GENERAL_REJECT)
default:
return "Unknown PDU";
}
......
/******************************************************************************
*
* Copyright (c) 2014 The Android Open Source Project
* Copyright (C) 1999-2012 Broadcom Corporation
* Copyright (C) 1999-2016 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......
......@@ -97,6 +97,8 @@ LOCAL_SRC_FILES := \
./gatt/gatt_attr.c \
./gatt/gatt_db.c \
./avct/avct_api.c \
./avct/avct_l2c_br.c \
./avct/avct_bcb_act.c \
./avct/avct_l2c.c \
./avct/avct_lcb.c \
./avct/avct_ccb.c \
......
/******************************************************************************
*
* Copyright (C) 2003-2012 Broadcom Corporation
* Copyright (C) 2003-2016 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -68,17 +68,16 @@ void AVCT_Register(uint16_t mtu, uint16_t mtu_br, uint8_t sec_mask)
/* 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);
BTM_SetSecurityLevel(true, "", BTM_SEC_SERVICE_AVCTP_BROWSE, sec_mask, AVCT_BR_PSM, 0, 0);
BTM_SetSecurityLevel(false, "", BTM_SEC_SERVICE_AVCTP_BROWSE, sec_mask, AVCT_BR_PSM, 0, 0);
/* AVCTP browsing channel uses the same security service as AVCTP control channel */
BTM_SetSecurityLevel(true, "", BTM_SEC_SERVICE_AVCTP, sec_mask, AVCT_BR_PSM, 0, 0);
BTM_SetSecurityLevel(false, "", BTM_SEC_SERVICE_AVCTP, sec_mask, AVCT_BR_PSM, 0, 0);
if (mtu_br < AVCT_MIN_BROWSE_MTU)
mtu_br = AVCT_MIN_BROWSE_MTU;
avct_cb.mtu_br = mtu_br;
#endif
#if defined(AVCT_INITIAL_TRACE_LEVEL)
avct_cb.trace_level = AVCT_INITIAL_TRACE_LEVEL;
......@@ -236,7 +235,6 @@ uint16_t AVCT_RemoveConn(uint8_t handle)
*******************************************************************************/
uint16_t AVCT_CreateBrowse (uint8_t handle, uint8_t role)
{
#if (AVCT_BROWSE_INCLUDED == TRUE)
uint16_t result = AVCT_SUCCESS;
tAVCT_CCB *p_ccb;
tAVCT_BCB *p_bcb;
......@@ -285,17 +283,13 @@ uint16_t AVCT_CreateBrowse (uint8_t handle, uint8_t role)
{
/* bind bcb to ccb */
p_ccb->p_bcb = p_bcb;
memcpy(p_bcb->peer_addr, p_ccb->p_lcb->peer_addr, BD_ADDR_LEN);
AVCT_TRACE_DEBUG("ch_state: %d", p_bcb->ch_state);
avct_bcb_event(p_bcb, AVCT_LCB_UL_BIND_EVT, (tAVCT_LCB_EVT *) &p_ccb);
}
}
return result;
#else
UNUSED(handle);
UNUSED(role);
return AVCT_NO_RESOURCES;
#endif
}
/*******************************************************************************
......@@ -313,7 +307,6 @@ uint16_t AVCT_CreateBrowse (uint8_t handle, uint8_t role)
*******************************************************************************/
uint16_t AVCT_RemoveBrowse (uint8_t handle)
{
#if (AVCT_BROWSE_INCLUDED == TRUE)
uint16_t result = AVCT_SUCCESS;
tAVCT_CCB *p_ccb;
......@@ -329,11 +322,8 @@ uint16_t AVCT_RemoveBrowse (uint8_t handle)
{
avct_bcb_event(p_ccb->p_bcb, AVCT_LCB_UL_UNBIND_EVT, (tAVCT_LCB_EVT *) &p_ccb);
}
return result;
#else
UNUSED(handle);
return AVCT_NO_RESOURCES;
#endif
}
/*******************************************************************************
......@@ -349,16 +339,14 @@ uint16_t AVCT_RemoveBrowse (uint8_t handle)
uint16_t AVCT_GetBrowseMtu (uint8_t handle)
{
uint16_t peer_mtu = AVCT_MIN_BROWSE_MTU;
#if (AVCT_BROWSE_INCLUDED == TRUE)
tAVCT_CCB *p_ccb;
if ((p_ccb = avct_ccb_by_idx(handle)) != NULL && p_ccb->p_bcb != NULL)
{
peer_mtu = p_ccb->p_bcb->peer_mtu;
}
#else
UNUSED(handle);
#endif
return peer_mtu;
}
......@@ -445,7 +433,6 @@ uint16_t AVCT_MsgReq(uint8_t handle, uint8_t label, uint8_t cr, BT_HDR *p_msg)
ul_msg.label = label;
ul_msg.cr = cr;
#if (AVCT_BROWSE_INCLUDED == TRUE)
/* send msg event to bcb */
if (p_msg->layer_specific == AVCT_DATA_BROWSE)
{
......@@ -463,7 +450,6 @@ uint16_t AVCT_MsgReq(uint8_t handle, uint8_t label, uint8_t cr, BT_HDR *p_msg)
}
/* send msg event to lcb */
else
#endif
{
avct_lcb_event(p_ccb->p_lcb, AVCT_LCB_UL_MSG_EVT, (tAVCT_LCB_EVT *) &ul_msg);
}
......
This diff is collapsed.
......@@ -80,18 +80,17 @@ void avct_ccb_dealloc(tAVCT_CCB *p_ccb, uint8_t event, uint16_t result, BD_ADDR
tAVCT_CTRL_CBACK *p_cback = p_ccb->cc.p_ctrl_cback;
AVCT_TRACE_DEBUG("avct_ccb_dealloc %d", avct_ccb_to_idx(p_ccb));
#if (AVCT_BROWSE_INCLUDED == TRUE)
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 */
avct_bcb_event(p_ccb->p_bcb, AVCT_LCB_UL_UNBIND_EVT, (tAVCT_LCB_EVT *) &p_ccb);
p_ccb->p_lcb = NULL;
}
#else
memset(p_ccb, 0, sizeof(tAVCT_CCB));
#endif
if (event != AVCT_NO_EVT)
{
......
......@@ -48,15 +48,17 @@
** message parsing and building macros
*****************************************************************************/
#define AVCT_BLD_HDR(p, label, type, cr_ipid) \
#define AVCT_BUILD_HDR(p, label, type, cr_ipid) \
*(p)++ = ((label) << 4) | ((type) << 2) | (cr_ipid);
#define AVCT_PRS_HDR(p, label, type, cr_ipid) \
#define AVCT_PARSE_HDR(p, label, type, cr_ipid) \
do { \
label = *(p) >> 4; \
(type) = (*(p) >> 2) & 3; \
(cr_ipid) = *(p)++ & 3;
(cr_ipid) = *(p)++ & 3; \
} while (0)
#define AVCT_PRS_PKT_TYPE(p, type) \
type = (*(p) >> 2) & 3;
#define AVCT_PKT_TYPE(p) \
((*(p) >> 2) & 3)
#endif /* AVCT_DEFS_H */
/******************************************************************************
*
* Copyright (C) 2003-2012 Broadcom Corporation
* Copyright (C) 2003-2016 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -101,6 +101,7 @@ typedef struct {
uint8_t ch_flags; /* L2CAP configuration flags */
BT_HDR *p_tx_msg; /* Message to be sent - in case the browsing channel is not open when MsgReg is called */
uint8_t ch_close; /* CCB index+1, if CCB initiated channel close */
BD_ADDR peer_addr; /* BD address of peer */
} tAVCT_BCB;
#define AVCT_ALOC_LCB 0x01
......@@ -148,14 +149,12 @@ typedef struct {
/* LCB function declarations */
extern void avct_lcb_event(tAVCT_LCB *p_lcb, uint8_t event, tAVCT_LCB_EVT *p_data);
#if (AVCT_BROWSE_INCLUDED == TRUE)
extern void avct_bcb_event(tAVCT_BCB *p_bcb, uint8_t event, tAVCT_LCB_EVT *p_data);
extern void avct_close_bcb(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data);
extern tAVCT_LCB *avct_lcb_by_bcb(tAVCT_BCB *p_bcb);
extern tAVCT_BCB *avct_bcb_by_lcb(tAVCT_LCB *p_lcb);
extern bool avct_bcb_last_ccb(tAVCT_BCB *p_bcb, tAVCT_CCB *p_ccb_last);
extern uint8_t avct_bcb_get_last_ccb_index(tAVCT_BCB *p_bcb, tAVCT_CCB *p_ccb_last);
extern tAVCT_BCB *avct_bcb_by_lcid(uint16_t lcid);
#endif
extern tAVCT_LCB *avct_lcb_by_bd(BD_ADDR bd_addr);
extern tAVCT_LCB *avct_lcb_alloc(BD_ADDR bd_addr);
extern void avct_lcb_dealloc(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data);
......@@ -181,7 +180,6 @@ extern void avct_lcb_msg_ind(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data);
extern void avct_lcb_free_msg_ind(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data);
/* BCB action functions */
#if (AVCT_BROWSE_INCLUDED == TRUE)
typedef void (*tAVCT_BCB_ACTION)(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data);
extern void avct_bcb_chnl_open(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data);
extern void avct_bcb_unbind_disc(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data);
......@@ -204,7 +202,6 @@ extern void avct_bcb_dealloc(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data);
extern const tAVCT_BCB_ACTION avct_bcb_action[];
extern const uint8_t avct_lcb_pkt_type_len[];
extern const tL2CAP_FCR_OPTS avct_l2c_br_fcr_opts_def;
#endif
/* CCB function declarations */
extern tAVCT_CCB *avct_ccb_alloc(tAVCT_CC *p_cc);
......@@ -227,9 +224,7 @@ extern tAVCT_CB *avct_cb_ptr;
/* L2CAP callback registration structure */
extern const tL2CAP_APPL_INFO avct_l2c_appl;
#if (AVCT_BROWSE_INCLUDED == TRUE)
extern const tL2CAP_APPL_INFO avct_l2c_br_appl;
#endif
#ifdef __cplusplus
}
......
/******************************************************************************
*
* Copyright (C) 2008-2016 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*****************************************************************************
**
** Name: avct_l2c_br.c
**
** Description: This AVCTP module interfaces to L2CAP
**
******************************************************************************/
#include <string.h>
#include "bt_target.h"
#include "bt_utils.h"
#include "avct_api.h"
#include "avct_int.h"
#include "l2c_api.h"
#include "l2cdefs.h"
/* Configuration flags. */
#define AVCT_L2C_CFG_IND_DONE (1<<0)
#define AVCT_L2C_CFG_CFM_DONE (1<<1)
/* AVCTP Browsing channel FCR Option:
* Size of the transmission window when using enhanced retransmission mode. Not used
* in basic and streaming modes. Range: 1 - 63
*/
#define AVCT_BR_FCR_OPT_TX_WINDOW_SIZE 10
/* AVCTP Browsing channel FCR Option:
* Number of transmission attempts for a single I-Frame before taking
* Down the connection. Used In ERTM mode only. Value is Ignored in basic and
* Streaming modes.
* Range: 0, 1-0xFF
* 0 - infinite retransmissions
* 1 - single transmission
*/
#define AVCT_BR_FCR_OPT_MAX_TX_B4_DISCNT 20
/* AVCTP Browsing channel FCR Option: Retransmission Timeout
* The AVRCP specification set a value in the range of 300 - 2000 ms
* Timeout (in msecs) to detect Lost I-Frames. Only used in Enhanced retransmission mode.
* Range: Minimum 2000 (2 secs) when supporting PBF.
*/
#define AVCT_BR_FCR_OPT_RETX_TOUT 2000
/* AVCTP Browsing channel FCR Option: Monitor Timeout
* The AVRCP specification set a value in the range of 300 - 2000 ms
* Timeout (in msecs) to detect Lost S-Frames. Only used in Enhanced retransmission mode.
* Range: Minimum 12000 (12 secs) when supporting PBF.
*/
#define AVCT_BR_FCR_OPT_MONITOR_TOUT 12000
/* callback function declarations */
void avct_l2c_br_connect_ind_cback(BD_ADDR bd_addr, uint16_t lcid, uint16_t psm, uint8_t id);
void avct_l2c_br_connect_cfm_cback(uint16_t lcid, uint16_t result);
void avct_l2c_br_config_cfm_cback(uint16_t lcid, tL2CAP_CFG_INFO *p_cfg);
void avct_l2c_br_config_ind_cback(uint16_t lcid, tL2CAP_CFG_INFO *p_cfg);
void avct_l2c_br_disconnect_ind_cback(uint16_t lcid, bool ack_needed);
void avct_l2c_br_disconnect_cfm_cback(uint16_t lcid, uint16_t result);
void avct_l2c_br_congestion_ind_cback(uint16_t lcid, bool is_congested);
void avct_l2c_br_data_ind_cback(uint16_t lcid, BT_HDR *p_buf);
/* L2CAP callback function structure */
const tL2CAP_APPL_INFO avct_l2c_br_appl = {
avct_l2c_br_connect_ind_cback,
avct_l2c_br_connect_cfm_cback,
NULL,
avct_l2c_br_config_ind_cback,
avct_l2c_br_config_cfm_cback,
avct_l2c_br_disconnect_ind_cback,
avct_l2c_br_disconnect_cfm_cback,
NULL,
avct_l2c_br_data_ind_cback,
avct_l2c_br_congestion_ind_cback,
NULL /* tL2CA_TX_COMPLETE_CB */
};
/* Browsing channel eL2CAP default options */
const tL2CAP_FCR_OPTS avct_l2c_br_fcr_opts_def = {
L2CAP_FCR_ERTM_MODE, /* Mandatory for Browsing channel */
AVCT_BR_FCR_OPT_TX_WINDOW_SIZE, /* Tx window size */
AVCT_BR_FCR_OPT_MAX_TX_B4_DISCNT, /* Maximum transmissions before disconnecting */
AVCT_BR_FCR_OPT_RETX_TOUT, /* Retransmission timeout (2 secs) */
AVCT_BR_FCR_OPT_MONITOR_TOUT, /* Monitor timeout (12 secs) */
L2CAP_DEFAULT_ERM_MPS /* MPS segment size */
};
/*******************************************************************************
**
** Function avct_l2c_br_connect_ind_cback
**
** Description This is the L2CAP connect indication callback function.
**
**
** Returns void
**
*******************************************************************************/
void avct_l2c_br_connect_ind_cback(BD_ADDR bd_addr, uint16_t lcid, uint16_t psm, uint8_t id)
{
tAVCT_LCB *p_lcb;
uint16_t result = L2CAP_CONN_NO_RESOURCES;
tL2CAP_CFG_INFO cfg;
tAVCT_BCB *p_bcb;
tL2CAP_ERTM_INFO ertm_info;
UNUSED(psm);
memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
cfg.mtu_present = true;
if ((p_lcb = avct_lcb_by_bd(bd_addr)) != NULL)
{
/* control channel exists */
p_bcb = avct_bcb_by_lcb(p_lcb);
memcpy(p_bcb->peer_addr, bd_addr, BD_ADDR_LEN);
if (p_bcb->allocated == 0)
{
/* browsing channel does not exist yet and the browsing channel is registered
* - accept connection */
p_bcb->allocated = p_lcb->allocated; /* copy the index from lcb */
result = L2CAP_CONN_OK;
cfg.mtu = avct_cb.mtu_br;
cfg.fcr_present = true;
cfg.fcr = avct_l2c_br_fcr_opts_def;
}
}
/* else no control channel yet, reject */
/* Set the FCR options: Browsing channel mandates ERTM */
ertm_info.preferred_mode = cfg.fcr.mode;
ertm_info.allowed_modes = L2CAP_FCR_CHAN_OPT_ERTM;
ertm_info.user_rx_buf_size = BT_DEFAULT_BUFFER_SIZE;
ertm_info.user_tx_buf_size = BT_DEFAULT_BUFFER_SIZE;
ertm_info.fcr_rx_buf_size = BT_DEFAULT_BUFFER_SIZE;
ertm_info.fcr_tx_buf_size = BT_DEFAULT_BUFFER_SIZE;
/* Send L2CAP connect rsp */
L2CA_ErtmConnectRsp(bd_addr, id, lcid, result, 0, &ertm_info);
/* if result ok, proceed with connection */
if (result == L2CAP_CONN_OK)
{
/* store LCID */
p_bcb->ch_lcid = lcid;
/* transition to configuration state */
p_bcb->ch_state = AVCT_CH_CFG;
/* Send L2CAP config req */
L2CA_ConfigReq(lcid, &cfg);
}
}
/*******************************************************************************
**
** Function avct_l2c_br_connect_cfm_cback
**
** Description This is the L2CAP connect confirm callback function.
**
**
** Returns void
**
*******************************************************************************/
void avct_l2c_br_connect_cfm_cback(uint16_t lcid, uint16_t result)
{
tAVCT_BCB *p_lcb;
tL2CAP_CFG_INFO cfg;
/* look up lcb for this channel */
p_lcb = avct_bcb_by_lcid(lcid);
if ((p_lcb == NULL) || (p_lcb->ch_state != AVCT_CH_CONN))
return;
if (result != L2CAP_CONN_OK)
{
/* failure */
avct_bcb_event(p_lcb, AVCT_LCB_LL_CLOSE_EVT, (tAVCT_LCB_EVT *) &result);
return;
}
/* result is successful */
/* set channel state */
p_lcb->ch_state = AVCT_CH_CFG;
/* Send L2CAP config req */
memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
cfg.mtu_present = true;
cfg.mtu = avct_cb.mtu_br;
cfg.fcr_present = true;
cfg.fcr = avct_l2c_br_fcr_opts_def;
L2CA_ConfigReq(lcid, &cfg);
}
/*******************************************************************************
**
** Function avct_l2c_br_config_cfm_cback
**
** Description This is the L2CAP config confirm callback function.
**
**
** Returns void
**
*******************************************************************************/
void avct_l2c_br_config_cfm_cback(uint16_t lcid, tL2CAP_CFG_INFO *p_cfg)
{
tAVCT_BCB *p_lcb;
/* look up lcb for this channel */
p_lcb = avct_bcb_by_lcid(lcid);
if ((p_lcb == NULL) || (p_lcb->ch_state != AVCT_CH_CFG))
return;
/* if result successful */
if (p_cfg->result == L2CAP_CFG_OK)
{
/* update flags */
p_lcb->ch_flags |= AVCT_L2C_CFG_CFM_DONE;
/* if configuration complete */
if (p_lcb->ch_flags & AVCT_L2C_CFG_IND_DONE)
{
p_lcb->ch_state = AVCT_CH_OPEN;
avct_bcb_event(p_lcb, AVCT_LCB_LL_OPEN_EVT, NULL);
}
}
/* else failure */
else
{
/* store result value */
p_lcb->ch_result = p_cfg->result;
/* Send L2CAP disconnect req */
L2CA_DisconnectReq(lcid);
}
}
/*******************************************************************************
**
** Function avct_l2c_br_config_ind_cback
**
** Description This is the L2CAP config indication callback function.
**
**
** Returns void
**
*******************************************************************************/
void avct_l2c_br_config_ind_cback(uint16_t lcid, tL2CAP_CFG_INFO *p_cfg)
{
tAVCT_BCB *p_lcb;
uint16_t max_mtu = BT_DEFAULT_BUFFER_SIZE - L2CAP_MIN_OFFSET - BT_HDR_SIZE;
/* Don't include QoS nor flush timeout in the response since we
currently always accept these values. Note: fcr_present is left
untouched since l2cap negotiates this internally
*/
p_cfg->flush_to_present = false;
p_cfg->qos_present = false;
/* look up lcb for this channel */
p_lcb = avct_bcb_by_lcid(lcid);
if (p_lcb == NULL)
return;
/* store the mtu in tbl */
p_lcb->peer_mtu = L2CAP_DEFAULT_MTU;
if (p_cfg->mtu_present)
{
p_lcb->peer_mtu = p_cfg->mtu;
}
if (p_lcb->peer_mtu > max_mtu)
{
p_lcb->peer_mtu = p_cfg->mtu = max_mtu;
/* Must tell the peer what the adjusted value is */
p_cfg->mtu_present = true;
}
else /* Don't include in the response */
p_cfg->mtu_present = false;
AVCT_TRACE_DEBUG ("%s peer_mtu:%d use:%d", __func__,
p_lcb->peer_mtu, max_mtu);
if (p_lcb->peer_mtu >= AVCT_MIN_BROWSE_MTU)
p_cfg->result = L2CAP_CFG_OK;
else
{
p_cfg->result = L2CAP_CFG_UNACCEPTABLE_PARAMS;
p_cfg->mtu_present = true;
p_cfg->mtu = AVCT_MIN_BROWSE_MTU;
}
/* send L2CAP configure response */
L2CA_ConfigRsp(lcid, p_cfg);
if (p_cfg->result != L2CAP_CFG_OK)
{
return;
}
/* if first config ind */
if ((p_lcb->ch_flags & AVCT_L2C_CFG_IND_DONE) == 0)
{
/* update flags */
p_lcb->ch_flags |= AVCT_L2C_CFG_IND_DONE;
/* if configuration complete */
if (p_lcb->ch_flags & AVCT_L2C_CFG_CFM_DONE)
{
p_lcb->ch_state = AVCT_CH_OPEN;
avct_bcb_event(p_lcb, AVCT_LCB_LL_OPEN_EVT, NULL);
}
}
}
/*******************************************************************************
**
** Function avct_l2c_br_disconnect_ind_cback
**
** Description This is the L2CAP disconnect indication callback function.
**
**
** Returns void
**
*******************************************************************************/
void avct_l2c_br_disconnect_ind_cback(uint16_t lcid, bool ack_needed)
{
tAVCT_BCB *p_lcb;
uint16_t result = AVCT_RESULT_FAIL;
/* look up lcb for this channel */
p_lcb = avct_bcb_by_lcid(lcid);
if (p_lcb == NULL)
return;
if (ack_needed)
{
/* send L2CAP disconnect response */
L2CA_DisconnectRsp(lcid);
}
avct_bcb_event(p_lcb, AVCT_LCB_LL_CLOSE_EVT, (tAVCT_LCB_EVT *) &result);
}
/*******************************************************************************
**
** Function avct_l2c_br_disconnect_cfm_cback
**
** Description This is the L2CAP disconnect confirm callback function.
**
**
** Returns void
**
*******************************************************************************/
void avct_l2c_br_disconnect_cfm_cback(uint16_t lcid, uint16_t result)
{
tAVCT_BCB *p_lcb;
uint16_t res;
/* look up lcb for this channel */
p_lcb = avct_bcb_by_lcid(lcid);
if (p_lcb == NULL)
return;
/* result value may be previously stored */
res = (p_lcb->ch_result != 0) ? p_lcb->ch_result : result;
p_lcb->ch_result = 0;
avct_bcb_event(p_lcb, AVCT_LCB_LL_CLOSE_EVT, (tAVCT_LCB_EVT *) &res);
}
/*******************************************************************************
**
** Function avct_l2c_br_congestion_ind_cback
**
** Description This is the L2CAP congestion indication callback function.
**
**
** Returns void
**
*******************************************************************************/
void avct_l2c_br_congestion_ind_cback(uint16_t lcid, bool is_congested)
{
tAVCT_BCB *p_lcb;
/* look up lcb for this channel */
p_lcb = avct_bcb_by_lcid(lcid);
if (p_lcb == NULL)
return;
avct_bcb_event(p_lcb, AVCT_LCB_LL_CONG_EVT, (tAVCT_LCB_EVT *) &is_congested);
}
/*******************************************************************************
**
** Function avct_l2c_br_data_ind_cback
**
** Description This is the L2CAP data indication callback function.
**
**
** Returns void
**
*******************************************************************************/
void avct_l2c_br_data_ind_cback(uint16_t lcid, BT_HDR *p_buf)
{
tAVCT_BCB *p_lcb;
tAVCT_LCB_EVT evt_data;
/* look up lcb for this channel */
p_lcb = avct_bcb_by_lcid(lcid);
if (p_lcb == NULL)
{
/* prevent buffer leak */
osi_free(p_buf);
return;
}
evt_data.p_buf = p_buf;
avct_bcb_event(p_lcb, AVCT_LCB_LL_MSG_EVT, &evt_data);
}
......@@ -233,7 +233,6 @@ void avct_lcb_event(tAVCT_LCB *p_lcb, uint8_t event, tAVCT_LCB_EVT *p_data)
** Returns Nothing.
**
*******************************************************************************/
#if (AVCT_BROWSE_INCLUDED == TRUE)
void avct_bcb_event(tAVCT_BCB *p_bcb, uint8_t event, tAVCT_LCB_EVT *p_data)
{
tAVCT_LCB_ST_TBL state_table;
......@@ -265,7 +264,6 @@ void avct_bcb_event(tAVCT_BCB *p_bcb, uint8_t event, tAVCT_LCB_EVT *p_data)
}
}
}
#endif
/*******************************************************************************
**
......
......@@ -58,7 +58,7 @@ static BT_HDR *avct_lcb_msg_asmbl(tAVCT_LCB *p_lcb, BT_HDR *p_buf)
/* parse the message header */
p = (uint8_t *)(p_buf + 1) + p_buf->offset;
AVCT_PRS_PKT_TYPE(p, pkt_type);
pkt_type = AVCT_PKT_TYPE(p);
/* quick sanity check on length */
if (p_buf->len < avct_lcb_pkt_type_len[pkt_type])
......@@ -187,7 +187,8 @@ void avct_lcb_chnl_open(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
BTM_SetOutService(p_lcb->peer_addr, BTM_SEC_SERVICE_AVCTP, 0);
/* call l2cap connect req */
p_lcb->ch_state = AVCT_CH_CONN;
if ((p_lcb->ch_lcid = L2CA_ConnectReq(AVCT_PSM, p_lcb->peer_addr)) == 0)
p_lcb->ch_lcid = L2CA_ConnectReq(AVCT_PSM, p_lcb->peer_addr);
if (p_lcb->ch_lcid == 0)
{
/* if connect req failed, send ourselves close event */
avct_lcb_event(p_lcb, AVCT_LCB_LL_CLOSE_EVT, (tAVCT_LCB_EVT *) &result);
......@@ -404,9 +405,8 @@ void avct_lcb_bind_conn(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
void avct_lcb_chk_disc(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
{
AVCT_TRACE_WARNING("%s", __func__);
#if (AVCT_BROWSE_INCLUDED == TRUE)
avct_close_bcb(p_lcb, p_data);
#endif
if (avct_lcb_last_ccb(p_lcb, p_data->p_ccb))
{
AVCT_TRACE_WARNING("%s: closing", __func__);
......@@ -511,7 +511,7 @@ void avct_lcb_discard_msg(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
{
UNUSED(p_lcb);
AVCT_TRACE_WARNING("Dropping message");
AVCT_TRACE_WARNING("%s Dropping message", __func__);
osi_free_and_reset((void **)&p_data->ul_msg.p_buf);
}
......@@ -589,7 +589,7 @@ void avct_lcb_send_msg(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
p = (uint8_t *)(p_buf + 1) + p_buf->offset;
/* build header */
AVCT_BLD_HDR(p, p_data->ul_msg.label, pkt_type, p_data->ul_msg.cr);
AVCT_BUILD_HDR(p, p_data->ul_msg.label, pkt_type, p_data->ul_msg.cr);
if (pkt_type == AVCT_PKT_TYPE_START)
{
UINT8_TO_STREAM(p, nosp);
......@@ -623,7 +623,7 @@ void avct_lcb_send_msg(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
pkt_type = AVCT_PKT_TYPE_END;
}
}
AVCT_TRACE_DEBUG ("avct_lcb_send_msg tx_q_count:%d",
AVCT_TRACE_DEBUG ("%s tx_q_count:%d", __func__,
fixed_queue_length(p_lcb->tx_q));
return;
}
......@@ -679,7 +679,7 @@ void avct_lcb_msg_ind(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
p = (uint8_t *)(p_data->p_buf + 1) + p_data->p_buf->offset;
/* parse header byte */
AVCT_PRS_HDR(p, label, type, cr_ipid);
AVCT_PARSE_HDR(p, label, type, cr_ipid);
UNUSED(type);
/* check for invalid cr_ipid */
......@@ -692,29 +692,29 @@ void avct_lcb_msg_ind(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
/* parse and lookup PID */
BE_STREAM_TO_UINT16(pid, p);
if ((p_ccb = avct_lcb_has_pid(p_lcb, pid)) != NULL)
p_ccb = avct_lcb_has_pid(p_lcb, pid);
if (p_ccb)
{
/* PID found; send msg up, adjust bt hdr and call msg callback */
p_data->p_buf->offset += AVCT_HDR_LEN_SINGLE;
p_data->p_buf->len -= AVCT_HDR_LEN_SINGLE;
(*p_ccb->cc.p_msg_cback)(avct_ccb_to_idx(p_ccb), label, cr_ipid, p_data->p_buf);
return;
}
else
{
/* PID not found; drop message */
AVCT_TRACE_WARNING("No ccb for PID=%x", pid);
osi_free_and_reset((void **)&p_data->p_buf);
/* if command send reject */
if (cr_ipid == AVCT_CMD)
{
BT_HDR *p_buf = (BT_HDR *)osi_malloc(AVCT_CMD_BUF_SIZE);
p_buf->len = AVCT_HDR_LEN_SINGLE;
p_buf->offset = AVCT_MSG_OFFSET - AVCT_HDR_LEN_SINGLE;
p = (uint8_t *)(p_buf + 1) + p_buf->offset;
AVCT_BLD_HDR(p, label, AVCT_PKT_TYPE_SINGLE, AVCT_REJ);
UINT16_TO_BE_STREAM(p, pid);
L2CA_DataWrite(p_lcb->ch_lcid, p_buf);
}
/* PID not found; drop message */
AVCT_TRACE_WARNING("No ccb for PID=%x", pid);
osi_free_and_reset((void **)&p_data->p_buf);
/* if command send reject */
if (cr_ipid == AVCT_CMD)
{
BT_HDR *p_buf = (BT_HDR *)osi_malloc(AVCT_CMD_BUF_SIZE);
p_buf->len = AVCT_HDR_LEN_SINGLE;
p_buf->offset = AVCT_MSG_OFFSET - AVCT_HDR_LEN_SINGLE;
p = (uint8_t *)(p_buf + 1) + p_buf->offset;
AVCT_BUILD_HDR(p, label, AVCT_PKT_TYPE_SINGLE, AVCT_REJ);
UINT16_TO_BE_STREAM(p, pid);
L2CA_DataWrite(p_lcb->ch_lcid, p_buf);
}
}
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment