summaryrefslogtreecommitdiffstats
path: root/stack/avdt
diff options
context:
space:
mode:
Diffstat (limited to 'stack/avdt')
-rw-r--r--stack/avdt/avdt_ad.c628
-rw-r--r--stack/avdt/avdt_api.c1383
-rw-r--r--stack/avdt/avdt_ccb.c464
-rw-r--r--stack/avdt/avdt_ccb_act.c1108
-rw-r--r--stack/avdt/avdt_defs.h203
-rw-r--r--stack/avdt/avdt_int.h744
-rw-r--r--stack/avdt/avdt_l2c.c521
-rw-r--r--stack/avdt/avdt_msg.c1891
-rw-r--r--stack/avdt/avdt_scb.c800
-rw-r--r--stack/avdt/avdt_scb_act.c2124
10 files changed, 9866 insertions, 0 deletions
diff --git a/stack/avdt/avdt_ad.c b/stack/avdt/avdt_ad.c
new file mode 100644
index 0000000..92f429a
--- /dev/null
+++ b/stack/avdt/avdt_ad.c
@@ -0,0 +1,628 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2002-2012 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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This module contains the AVDTP adaption layer.
+ *
+ ******************************************************************************/
+
+#include <string.h>
+#include "data_types.h"
+#include "bt_target.h"
+#include "avdt_api.h"
+#include "avdtc_api.h"
+#include "avdt_int.h"
+#include "l2c_api.h"
+#include "l2cdefs.h"
+#include "wcassert.h"
+
+
+/*******************************************************************************
+**
+** Function avdt_ad_type_to_tcid
+**
+** Description Derives the TCID from the channel type and SCB.
+**
+**
+** Returns TCID value.
+**
+*******************************************************************************/
+UINT8 avdt_ad_type_to_tcid(UINT8 type, tAVDT_SCB *p_scb)
+{
+ UINT8 scb_idx;
+
+ if (type == AVDT_CHAN_SIG)
+ {
+ return 0;
+ }
+ else
+ {
+ scb_idx = avdt_scb_to_hdl(p_scb) - 1;
+ /*
+ AVDT_TRACE_DEBUG2("type: %d, tcid: %d", type, ((scb_idx * (AVDT_CHAN_NUM_TYPES - 1)) + type));
+ */
+ return ((scb_idx * (AVDT_CHAN_NUM_TYPES - 1)) + type);
+ }
+}
+
+/*******************************************************************************
+**
+** Function avdt_ad_tcid_to_type
+**
+** Description Derives the channel type from the TCID.
+**
+**
+** Returns Channel type value.
+**
+*******************************************************************************/
+static UINT8 avdt_ad_tcid_to_type(UINT8 tcid)
+{
+ UINT8 type;
+
+ if (tcid == 0)
+ {
+ type = AVDT_CHAN_SIG;
+ }
+ else
+ {
+ /* tcid translates to type based on number of channels, as follows:
+ ** only media channel : tcid=1,2,3,4,5,6... type=1,1,1,1,1,1...
+ ** media and report : tcid=1,2,3,4,5,6... type=1,2,1,2,1,2...
+ ** media, report, recov : tcid=1,2,3,4,5,6... type=1,2,3,1,2,3...
+ */
+ type = ((tcid + AVDT_CHAN_NUM_TYPES - 2) % (AVDT_CHAN_NUM_TYPES - 1)) + 1;
+ }
+ AVDT_TRACE_DEBUG2("tcid: %d, type: %d", tcid, type);
+ return type;
+}
+
+
+/*******************************************************************************
+**
+** Function avdt_ad_init
+**
+** Description Initialize adaption layer.
+**
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_ad_init(void)
+{
+ int i;
+ tAVDT_TC_TBL *p_tbl = avdt_cb.ad.tc_tbl;
+ memset(&avdt_cb.ad, 0, sizeof(tAVDT_AD));
+
+ /* make sure the peer_mtu is a valid value */
+ for (i = 0; i < AVDT_NUM_TC_TBL; i++, p_tbl++)
+ {
+ p_tbl->peer_mtu = L2CAP_DEFAULT_MTU;
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function avdt_ad_tc_tbl_by_st
+**
+** Description Find adaption layer transport channel table entry matching
+** the given state.
+**
+**
+** Returns Pointer to matching entry. For control channel it returns
+** the matching entry. For media or other it returns the
+** first matching entry (there could be more than one).
+**
+*******************************************************************************/
+tAVDT_TC_TBL *avdt_ad_tc_tbl_by_st(UINT8 type, tAVDT_CCB *p_ccb, UINT8 state)
+{
+ int i;
+ tAVDT_TC_TBL *p_tbl = avdt_cb.ad.tc_tbl;
+ UINT8 ccb_idx;
+
+ if (p_ccb == NULL)
+ {
+ /* resending security req */
+ for (i = 0; i < AVDT_NUM_TC_TBL; i++, p_tbl++)
+ {
+ /* must be AVDT_CHAN_SIG - tcid always zero */
+ if ((p_tbl->tcid == 0) &&
+ (p_tbl->state == state))
+ {
+ break;
+ }
+ }
+ }
+ else
+ {
+ ccb_idx = avdt_ccb_to_idx(p_ccb);
+
+ for (i = 0; i < AVDT_NUM_TC_TBL; i++, p_tbl++)
+ {
+ if (type == AVDT_CHAN_SIG)
+ {
+ /* if control channel, tcid always zero */
+ if ((p_tbl->tcid == 0) &&
+ (p_tbl->ccb_idx == ccb_idx) &&
+ (p_tbl->state == state))
+ {
+ break;
+ }
+ }
+ else
+ {
+ /* if other channel, tcid is always > zero */
+ if ((p_tbl->tcid > 0) &&
+ (p_tbl->ccb_idx == ccb_idx) &&
+ (p_tbl->state == state))
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ /* if nothing found return null */
+ if (i == AVDT_NUM_TC_TBL)
+ {
+ p_tbl = NULL;
+ }
+
+ return p_tbl;
+}
+
+
+/*******************************************************************************
+**
+** Function avdt_ad_tc_tbl_by_lcid
+**
+** Description Find adaption layer transport channel table entry by LCID.
+**
+**
+** Returns Pointer to entry.
+**
+*******************************************************************************/
+tAVDT_TC_TBL *avdt_ad_tc_tbl_by_lcid(UINT16 lcid)
+{
+ UINT8 idx;
+
+ idx = avdt_cb.ad.lcid_tbl[lcid - L2CAP_BASE_APPL_CID];
+
+ if (idx < AVDT_NUM_TC_TBL)
+ {
+ return &avdt_cb.ad.tc_tbl[idx];
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function avdt_ad_tc_tbl_by_type
+**
+** Description This function retrieves the transport channel table entry
+** for a particular channel.
+**
+**
+** Returns Pointer to transport channel table entry.
+**
+*******************************************************************************/
+tAVDT_TC_TBL *avdt_ad_tc_tbl_by_type(UINT8 type, tAVDT_CCB *p_ccb, tAVDT_SCB *p_scb)
+{
+ UINT8 tcid;
+ int i;
+ tAVDT_TC_TBL *p_tbl = avdt_cb.ad.tc_tbl;
+ UINT8 ccb_idx = avdt_ccb_to_idx(p_ccb);
+
+ /* get tcid from type, scb */
+ tcid = avdt_ad_type_to_tcid(type, p_scb);
+
+ for (i = 0; i < AVDT_NUM_TC_TBL; i++, p_tbl++)
+ {
+ if ((p_tbl->tcid == tcid) && (p_tbl->ccb_idx == ccb_idx))
+ {
+ break;
+ }
+ }
+
+ WC_ASSERT(i != AVDT_NUM_TC_TBL);
+
+ return p_tbl;
+}
+
+
+/*******************************************************************************
+**
+** Function avdt_ad_tc_tbl_alloc
+**
+** Description Allocate an entry in the traffic channel table.
+**
+**
+** Returns Pointer to entry.
+**
+*******************************************************************************/
+tAVDT_TC_TBL *avdt_ad_tc_tbl_alloc(tAVDT_CCB *p_ccb)
+{
+ int i;
+ tAVDT_TC_TBL *p_tbl = avdt_cb.ad.tc_tbl;
+
+ /* find next free entry in tc table */
+ for (i = 0; i < AVDT_NUM_TC_TBL; i++, p_tbl++)
+ {
+ if (p_tbl->state == AVDT_AD_ST_UNUSED)
+ {
+ break;
+ }
+ }
+
+ /* sanity check */
+ WC_ASSERT(i != AVDT_NUM_TC_TBL);
+
+ /* initialize entry */
+ p_tbl->peer_mtu = L2CAP_DEFAULT_MTU;
+ p_tbl->cfg_flags = 0;
+ p_tbl->ccb_idx = avdt_ccb_to_idx(p_ccb);
+ p_tbl->state = AVDT_AD_ST_IDLE;
+
+ return p_tbl;
+}
+
+/*******************************************************************************
+**
+** Function avdt_ad_tc_tbl_to_idx
+**
+** Description Convert a transport channel table entry to an index.
+**
+**
+** Returns Index value.
+**
+*******************************************************************************/
+UINT8 avdt_ad_tc_tbl_to_idx(tAVDT_TC_TBL *p_tbl)
+{
+ AVDT_TRACE_DEBUG1("avdt_ad_tc_tbl_to_idx: %d", (p_tbl - avdt_cb.ad.tc_tbl));
+ /* use array arithmetic to determine index */
+ return (UINT8) (p_tbl - avdt_cb.ad.tc_tbl);
+}
+
+/*******************************************************************************
+**
+** Function avdt_ad_tc_close_ind
+**
+** Description This function is called by the L2CAP interface when the
+** L2CAP channel is closed. It looks up the CCB or SCB for
+** the channel and sends it a close event. The reason
+** parameter is the same value passed by the L2CAP
+** callback function.
+**
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_ad_tc_close_ind(tAVDT_TC_TBL *p_tbl, UINT16 reason)
+{
+ tAVDT_CCB *p_ccb;
+ tAVDT_SCB *p_scb;
+ tAVDT_SCB_TC_CLOSE close;
+
+ close.old_tc_state = p_tbl->state;
+ /* clear avdt_ad_tc_tbl entry */
+ p_tbl->state = AVDT_AD_ST_UNUSED;
+ p_tbl->cfg_flags = 0;
+ p_tbl->peer_mtu = L2CAP_DEFAULT_MTU;
+
+ AVDT_TRACE_DEBUG2("avdt_ad_tc_close_ind tcid: %d, old: %d",
+ p_tbl->tcid, close.old_tc_state);
+ /* if signaling channel, notify ccb that channel open */
+ if (p_tbl->tcid == 0)
+ {
+ p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx);
+ avdt_ccb_event(p_ccb, AVDT_CCB_LL_CLOSE_EVT, NULL);
+ }
+ /* if media or other channel, notify scb that channel close */
+ else
+ {
+ /* look up scb in stream routing table by ccb, tcid */
+ p_scb = avdt_scb_by_hdl(avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][p_tbl->tcid].scb_hdl);
+ if (p_scb != NULL)
+ {
+ close.tcid = p_tbl->tcid;
+ close.type = avdt_ad_tcid_to_type(p_tbl->tcid);
+ avdt_scb_event(p_scb, AVDT_SCB_TC_CLOSE_EVT, (tAVDT_SCB_EVT *)&close);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function avdt_ad_tc_open_ind
+**
+** Description This function is called by the L2CAP interface when
+** the L2CAP channel is opened. It looks up the CCB or SCB
+** for the channel and sends it an open event.
+**
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_ad_tc_open_ind(tAVDT_TC_TBL *p_tbl)
+{
+ tAVDT_CCB *p_ccb;
+ tAVDT_SCB *p_scb;
+ tAVDT_OPEN open;
+ tAVDT_EVT_HDR evt;
+
+ p_tbl->state = AVDT_AD_ST_OPEN;
+
+ /* if signaling channel, notify ccb that channel open */
+ if (p_tbl->tcid == 0)
+ {
+ /* set the signal channel to use high priority within the ACL link */
+ 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);
+ /* use err_param to indicate the role of connection.
+ * AVDT_ACP, if ACP */
+ evt.err_param = AVDT_INT;
+ if(p_tbl->cfg_flags & AVDT_L2C_CFG_CONN_ACP)
+ {
+ evt.err_param = AVDT_ACP;
+ }
+ avdt_ccb_event(p_ccb, AVDT_CCB_LL_OPEN_EVT, (tAVDT_CCB_EVT *)&evt);
+ }
+ /* if media or other channel, notify scb that channel open */
+ else
+ {
+ /* look up scb in stream routing table by ccb, tcid */
+ p_scb = avdt_scb_by_hdl(avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][p_tbl->tcid].scb_hdl);
+
+ /* put lcid in event data */
+ if (p_scb != NULL)
+ {
+ open.peer_mtu = p_tbl->peer_mtu;
+ open.lcid = avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][p_tbl->tcid].lcid;
+ open.hdr.err_code = avdt_ad_tcid_to_type(p_tbl->tcid);
+ avdt_scb_event(p_scb, AVDT_SCB_TC_OPEN_EVT, (tAVDT_SCB_EVT *) &open);
+ }
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function avdt_ad_tc_cong_ind
+**
+** Description This function is called by the L2CAP interface layer when
+** L2CAP calls the congestion callback. It looks up the CCB
+** or SCB for the channel and sends it a congestion event.
+** The is_congested parameter is the same value passed by
+** the L2CAP callback function.
+**
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_ad_tc_cong_ind(tAVDT_TC_TBL *p_tbl, BOOLEAN is_congested)
+{
+ tAVDT_CCB *p_ccb;
+ tAVDT_SCB *p_scb;
+
+ /* if signaling channel, notify ccb of congestion */
+ if (p_tbl->tcid == 0)
+ {
+ p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx);
+ 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 */
+ else
+ {
+ /* look up scb in stream routing table by ccb, tcid */
+ p_scb = avdt_scb_by_hdl(avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][p_tbl->tcid].scb_hdl);
+ if (p_scb != NULL)
+ {
+ avdt_scb_event(p_scb, AVDT_SCB_TC_CONG_EVT, (tAVDT_SCB_EVT *) &is_congested);
+ }
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function avdt_ad_tc_data_ind
+**
+** Description This function is called by the L2CAP interface layer when
+** incoming data is received from L2CAP. It looks up the CCB
+** or SCB for the channel and routes the data accordingly.
+**
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_ad_tc_data_ind(tAVDT_TC_TBL *p_tbl, BT_HDR *p_buf)
+{
+ tAVDT_CCB *p_ccb;
+ tAVDT_SCB *p_scb;
+
+ /* store type (media, recovery, reporting) */
+ p_buf->layer_specific = avdt_ad_tcid_to_type(p_tbl->tcid);
+
+
+ /* if signaling channel, handle control message */
+ if (p_tbl->tcid == 0)
+ {
+ p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx);
+ avdt_msg_ind(p_ccb, p_buf);
+ }
+ /* if media or other channel, send event to scb */
+ else
+ {
+ p_scb = avdt_scb_by_hdl(avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][p_tbl->tcid].scb_hdl);
+ if (p_scb != NULL)
+ {
+ avdt_scb_event(p_scb, AVDT_SCB_TC_DATA_EVT, (tAVDT_SCB_EVT *) &p_buf);
+ }
+ else
+ GKI_freebuf(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function avdt_ad_write_req
+**
+** Description This function is called by a CCB or SCB to send data to a
+** transport channel. It looks up the LCID of the channel
+** based on the type, CCB, and SCB (if present). Then it
+** passes the data to L2CA_DataWrite().
+**
+**
+** Returns AVDT_AD_SUCCESS, if data accepted, else FALSE
+** AVDT_AD_CONGESTED, if data accepted and the channel is congested
+** AVDT_AD_FAILED, if error
+**
+*******************************************************************************/
+UINT8 avdt_ad_write_req(UINT8 type, tAVDT_CCB *p_ccb, tAVDT_SCB *p_scb, BT_HDR *p_buf)
+{
+ UINT8 tcid;
+
+ /* get tcid from type, scb */
+ tcid = avdt_ad_type_to_tcid(type, p_scb);
+
+
+ return L2CA_DataWrite(avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid, p_buf);
+}
+
+
+/*******************************************************************************
+**
+** Function avdt_ad_open_req
+**
+** Description This function is called by a CCB or SCB to open a transport
+** channel. This function allocates and initializes a
+** transport channel table entry. The channel can be opened
+** in two roles: as an initiator or acceptor. When opened
+** as an initiator the function will start an L2CAP connection.
+** When opened as an acceptor the function simply configures
+** the table entry to listen for an incoming channel.
+**
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_ad_open_req(UINT8 type, tAVDT_CCB *p_ccb, tAVDT_SCB *p_scb, UINT8 role)
+{
+ tAVDT_TC_TBL *p_tbl;
+ UINT16 lcid;
+
+ p_tbl = avdt_ad_tc_tbl_alloc(p_ccb);
+
+ p_tbl->tcid = avdt_ad_type_to_tcid(type, p_scb);
+ AVDT_TRACE_DEBUG3("avdt_ad_open_req: type: %d, role: %d, tcid:%d",
+ type, role, p_tbl->tcid);
+
+ if (type == AVDT_CHAN_SIG)
+ {
+ /* if signaling, get mtu from registration control block */
+ p_tbl->my_mtu = avdt_cb.rcb.ctrl_mtu;
+ p_tbl->my_flush_to = L2CAP_DEFAULT_FLUSH_TO;
+ }
+ else
+ {
+ /* otherwise get mtu from scb */
+ p_tbl->my_mtu = p_scb->cs.mtu;
+ p_tbl->my_flush_to = p_scb->cs.flush_to;
+
+ /* also set scb_hdl in rt_tbl */
+ avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].scb_hdl = avdt_scb_to_hdl(p_scb);
+ AVDT_TRACE_DEBUG3("avdt_cb.ad.rt_tbl[%d][%d].scb_hdl = %d",
+ avdt_ccb_to_idx(p_ccb), p_tbl->tcid,
+ avdt_scb_to_hdl(p_scb));
+ }
+
+ /* if we're acceptor, we're done; just sit back and listen */
+ if (role == AVDT_ACP)
+ {
+ p_tbl->state = AVDT_AD_ST_ACP;
+ }
+ /* else we're inititator, start the L2CAP connection */
+ else
+ {
+ p_tbl->state = AVDT_AD_ST_CONN;
+
+ /* call l2cap connect req */
+ if ((lcid = L2CA_ConnectReq(AVDT_PSM, p_ccb->peer_addr)) != 0)
+ {
+ /* if connect req ok, store tcid in lcid table */
+ avdt_cb.ad.lcid_tbl[lcid - L2CAP_BASE_APPL_CID] = avdt_ad_tc_tbl_to_idx(p_tbl);
+ AVDT_TRACE_DEBUG2("avdt_cb.ad.lcid_tbl[%d] = %d",
+ (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;
+ AVDT_TRACE_DEBUG3("avdt_cb.ad.rt_tbl[%d][%d].lcid = 0x%x",
+ avdt_ccb_to_idx(p_ccb), p_tbl->tcid,
+ lcid);
+ }
+ else
+ {
+ /* if connect req failed, call avdt_ad_tc_close_ind() */
+ avdt_ad_tc_close_ind(p_tbl, 0);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function avdt_ad_close_req
+**
+** Description This function is called by a CCB or SCB to close a
+** transport channel. The function looks up the LCID for the
+** channel and calls L2CA_DisconnectReq().
+**
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_ad_close_req(UINT8 type, tAVDT_CCB *p_ccb, tAVDT_SCB *p_scb)
+{
+ UINT8 tcid;
+ tAVDT_TC_TBL *p_tbl;
+
+ p_tbl = avdt_ad_tc_tbl_by_type(type, p_ccb, p_scb);
+ AVDT_TRACE_DEBUG1("avdt_ad_close_req state: %d", p_tbl->state);
+
+ switch(p_tbl->state)
+ {
+ case AVDT_AD_ST_UNUSED:
+ /* probably for reporting */
+ break;
+ case AVDT_AD_ST_ACP:
+ /* if we're listening on this channel, send ourselves a close ind */
+ avdt_ad_tc_close_ind(p_tbl, 0);
+ break;
+ default:
+ /* get tcid from type, scb */
+ tcid = avdt_ad_type_to_tcid(type, p_scb);
+
+ /* call l2cap disconnect req */
+ L2CA_DisconnectReq(avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid);
+ }
+}
+
diff --git a/stack/avdt/avdt_api.c b/stack/avdt/avdt_api.c
new file mode 100644
index 0000000..67fe452
--- /dev/null
+++ b/stack/avdt/avdt_api.c
@@ -0,0 +1,1383 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2002-2012 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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This module contains API of the audio/video distribution transport
+ * protocol.
+ *
+ ******************************************************************************/
+
+#include <string.h>
+#include "data_types.h"
+#include "bt_target.h"
+#include "avdt_api.h"
+#include "avdtc_api.h"
+#include "avdt_int.h"
+#include "l2c_api.h"
+#include "btm_api.h"
+#include "btu.h"
+
+
+#if (defined BTTRC_INCLUDED && BTTRC_INCLUDED == TRUE)
+#include "bttrc_str_ids.h"
+#endif
+
+/* Control block for AVDT */
+#if AVDT_DYNAMIC_MEMORY == FALSE
+tAVDT_CB avdt_cb;
+#endif
+
+
+/*******************************************************************************
+**
+** Function avdt_process_timeout
+**
+** Description This function is called by BTU when an AVDTP timer
+** expires. The function sends a timer event to the
+** appropriate CCB or SCB state machine.
+**
+** This function is for use internal to the stack only.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void avdt_process_timeout(TIMER_LIST_ENT *p_tle)
+{
+ UINT8 event = 0;
+ UINT8 err_code = AVDT_ERR_TIMEOUT;
+
+ switch (p_tle->event)
+ {
+ case BTU_TTYPE_AVDT_CCB_RET:
+ event = AVDT_CCB_RET_TOUT_EVT + AVDT_CCB_MKR;
+ break;
+
+ case BTU_TTYPE_AVDT_CCB_RSP:
+ event = AVDT_CCB_RSP_TOUT_EVT + AVDT_CCB_MKR;
+ break;
+
+ case BTU_TTYPE_AVDT_CCB_IDLE:
+ event = AVDT_CCB_IDLE_TOUT_EVT + AVDT_CCB_MKR;
+ break;
+
+ case BTU_TTYPE_AVDT_SCB_TC:
+ event = AVDT_SCB_TC_TOUT_EVT;
+ break;
+
+ default:
+ break;
+ }
+
+ if (event & AVDT_CCB_MKR)
+ {
+ avdt_ccb_event((tAVDT_CCB *) p_tle->param, (UINT8) (event & ~AVDT_CCB_MKR),
+ (tAVDT_CCB_EVT *) &err_code);
+ }
+ else
+ {
+ avdt_scb_event((tAVDT_SCB *) p_tle->param, event, NULL);
+ }
+}
+
+/*******************************************************************************
+**
+** Function AVDT_Register
+**
+** Description This is the system level registration function for the
+** AVDTP protocol. This function initializes AVDTP and
+** prepares the protocol stack for its use. This function
+** must be called once by the system or platform using AVDTP
+** before the other functions of the API an be used.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void AVDT_Register(tAVDT_REG *p_reg, tAVDT_CTRL_CBACK *p_cback)
+{
+
+ BTTRC_AVDT_API0(AVDT_TRACE_API_REGISTER);
+
+ /* register PSM with L2CAP */
+ L2CA_Register(AVDT_PSM, (tL2CAP_APPL_INFO *) &avdt_l2c_appl);
+
+ /* set security level */
+ BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_AVDTP, p_reg->sec_mask,
+ AVDT_PSM, BTM_SEC_PROTO_AVDT, AVDT_CHAN_SIG);
+ BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_AVDTP, p_reg->sec_mask,
+ AVDT_PSM, BTM_SEC_PROTO_AVDT, AVDT_CHAN_SIG);
+
+ /* do not use security on the media channel */
+ BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_AVDTP_NOSEC, BTM_SEC_NONE,
+ AVDT_PSM, BTM_SEC_PROTO_AVDT, AVDT_CHAN_MEDIA);
+ BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_AVDTP_NOSEC, BTM_SEC_NONE,
+ AVDT_PSM, BTM_SEC_PROTO_AVDT, AVDT_CHAN_MEDIA);
+
+#if AVDT_REPORTING == TRUE
+ /* do not use security on the reporting channel */
+ BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_AVDTP_NOSEC, BTM_SEC_NONE,
+ AVDT_PSM, BTM_SEC_PROTO_AVDT, AVDT_CHAN_REPORT);
+ BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_AVDTP_NOSEC, BTM_SEC_NONE,
+ AVDT_PSM, BTM_SEC_PROTO_AVDT, AVDT_CHAN_REPORT);
+#endif
+
+ /* initialize AVDTP data structures */
+ avdt_scb_init();
+ avdt_ccb_init();
+ avdt_ad_init();
+#if defined(AVDT_INITIAL_TRACE_LEVEL)
+ avdt_cb.trace_level = AVDT_INITIAL_TRACE_LEVEL;
+#else
+ avdt_cb.trace_level = BT_TRACE_LEVEL_NONE;
+#endif
+
+ /* copy registration struct */
+ memcpy(&avdt_cb.rcb, p_reg, sizeof(tAVDT_REG));
+ avdt_cb.p_conn_cback = p_cback;
+}
+
+/*******************************************************************************
+**
+** Function AVDT_Deregister
+**
+** Description This function is called to deregister use AVDTP protocol.
+** It is called when AVDTP is no longer being used by any
+** application in the system. Before this function can be
+** called, all streams must be removed with AVDT_RemoveStream().
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void AVDT_Deregister(void)
+{
+ BTTRC_AVDT_API0(AVDT_TRACE_API_DEREGISTER);
+
+ /* deregister PSM with L2CAP */
+ L2CA_Deregister(AVDT_PSM);
+}
+
+/*******************************************************************************
+**
+** Function AVDT_CreateStream
+**
+** Description Create a stream endpoint. After a stream endpoint is
+** created an application can initiate a connection between
+** this endpoint and an endpoint on a peer device. In
+** addition, a peer device can discover, get the capabilities,
+** and connect to this endpoint.
+**
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVDT_CreateStream(UINT8 *p_handle, tAVDT_CS *p_cs)
+{
+ UINT16 result = AVDT_SUCCESS;
+ tAVDT_SCB *p_scb;
+
+ BTTRC_AVDT_API0(AVDT_TRACE_API_CREATESTREAM);
+
+ /* 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;
+ }
+ /* Allocate scb; if no scbs, return failure */
+ else if ((p_scb = avdt_scb_alloc(p_cs)) == NULL)
+ {
+ result = AVDT_NO_RESOURCES;
+ }
+ else
+ {
+ *p_handle = avdt_scb_to_hdl(p_scb);
+ }
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function AVDT_RemoveStream
+**
+** Description Remove a stream endpoint. This function is called when
+** the application is no longer using a stream endpoint.
+** If this function is called when the endpoint is connected
+** the connection is closed and then the stream endpoint
+** is removed.
+**
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVDT_RemoveStream(UINT8 handle)
+{
+ UINT16 result = AVDT_SUCCESS;
+ tAVDT_SCB *p_scb;
+
+
+ BTTRC_AVDT_API0(AVDT_TRACE_API_REMOVESTREAM);
+
+ /* look up scb */
+ if ((p_scb = avdt_scb_by_hdl(handle)) == NULL)
+ {
+ result = AVDT_BAD_HANDLE;
+ }
+ else
+ {
+ /* send remove event to scb */
+ avdt_scb_event(p_scb, AVDT_SCB_API_REMOVE_EVT, NULL);
+ }
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function AVDT_DiscoverReq
+**
+** Description This function initiates a connection to the AVDTP service
+** on the peer device, if not already present, and discovers
+** the stream endpoints on the peer device. (Please note
+** that AVDTP discovery is unrelated to SDP discovery).
+** This function can be called at any time regardless of whether
+** there is an AVDTP connection to the peer device.
+**
+** When discovery is complete, an AVDT_DISCOVER_CFM_EVT
+** is sent to the application via its callback function.
+** The application must not call AVDT_GetCapReq() or
+** AVDT_DiscoverReq() again to the same device until
+** discovery is complete.
+**
+** The memory addressed by sep_info is allocated by the
+** application. This memory is written to by AVDTP as part
+** of the discovery procedure. This memory must remain
+** accessible until the application receives the
+** AVDT_DISCOVER_CFM_EVT.
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVDT_DiscoverReq(BD_ADDR bd_addr, tAVDT_SEP_INFO *p_sep_info,
+ UINT8 max_seps, tAVDT_CTRL_CBACK *p_cback)
+{
+ tAVDT_CCB *p_ccb;
+ UINT16 result = AVDT_SUCCESS;
+ tAVDT_CCB_EVT evt;
+
+ BTTRC_AVDT_API0(AVDT_TRACE_API_DISCOVER_REQ);
+
+ /* find channel control block for this bd addr; if none, allocate one */
+ if ((p_ccb = avdt_ccb_by_bd(bd_addr)) == NULL)
+ {
+ if ((p_ccb = avdt_ccb_alloc(bd_addr)) == NULL)
+ {
+ /* could not allocate channel control block */
+ result = AVDT_NO_RESOURCES;
+ }
+ }
+
+ if (result == AVDT_SUCCESS)
+ {
+ /* make sure no discovery or get capabilities req already in progress */
+ if (p_ccb->proc_busy)
+ {
+ result = AVDT_BUSY;
+ }
+ /* send event to ccb */
+ else
+ {
+ evt.discover.p_sep_info = p_sep_info;
+ evt.discover.num_seps = max_seps;
+ evt.discover.p_cback = p_cback;
+ avdt_ccb_event(p_ccb, AVDT_CCB_API_DISCOVER_REQ_EVT, &evt);
+ }
+ }
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function avdt_get_cap_req
+**
+** Description internal function to serve both AVDT_GetCapReq and
+** AVDT_GetAllCapReq
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+static UINT16 avdt_get_cap_req(BD_ADDR bd_addr, tAVDT_CCB_API_GETCAP *p_evt)
+{
+ tAVDT_CCB *p_ccb = NULL;
+ UINT16 result = AVDT_SUCCESS;
+
+ /* verify SEID */
+ if ((p_evt->single.seid < AVDT_SEID_MIN) || (p_evt->single.seid > AVDT_SEID_MAX))
+ {
+ AVDT_TRACE_ERROR1("seid: %d", p_evt->single.seid);
+ result = AVDT_BAD_PARAMS;
+ }
+ /* find channel control block for this bd addr; if none, allocate one */
+ else if ((p_ccb = avdt_ccb_by_bd(bd_addr)) == NULL)
+ {
+ if ((p_ccb = avdt_ccb_alloc(bd_addr)) == NULL)
+ {
+ /* could not allocate channel control block */
+ result = AVDT_NO_RESOURCES;
+ }
+ }
+
+ if (result == AVDT_SUCCESS)
+ {
+ /* make sure no discovery or get capabilities req already in progress */
+ if (p_ccb->proc_busy)
+ {
+ result = AVDT_BUSY;
+ }
+ /* send event to ccb */
+ else
+ {
+ avdt_ccb_event(p_ccb, AVDT_CCB_API_GETCAP_REQ_EVT, (tAVDT_CCB_EVT *)p_evt);
+ }
+ }
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function AVDT_GetCapReq
+**
+** Description This function initiates a connection to the AVDTP service
+** on the peer device, if not already present, and gets the
+** capabilities of a stream endpoint on the peer device.
+** This function can be called at any time regardless of
+** whether there is an AVDTP connection to the peer device.
+**
+** When the procedure is complete, an AVDT_GETCAP_CFM_EVT is
+** sent to the application via its callback function. The
+** application must not call AVDT_GetCapReq() or
+** AVDT_DiscoverReq() again until the procedure is complete.
+**
+** The memory pointed to by p_cfg is allocated by the
+** application. This memory is written to by AVDTP as part
+** of the get capabilities procedure. This memory must
+** remain accessible until the application receives
+** the AVDT_GETCAP_CFM_EVT.
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVDT_GetCapReq(BD_ADDR bd_addr, UINT8 seid, tAVDT_CFG *p_cfg, tAVDT_CTRL_CBACK *p_cback)
+{
+ tAVDT_CCB_API_GETCAP getcap;
+
+ BTTRC_AVDT_API1(AVDT_TRACE_API_GETCAP_REQ, BTTRC_PARAM_UINT8, seid);
+
+ getcap.single.seid = seid;
+ getcap.single.sig_id = AVDT_SIG_GETCAP;
+ getcap.p_cfg = p_cfg;
+ getcap.p_cback = p_cback;
+ return avdt_get_cap_req (bd_addr, &getcap);
+}
+
+/*******************************************************************************
+**
+** Function AVDT_GetAllCapReq
+**
+** Description This function initiates a connection to the AVDTP service
+** on the peer device, if not already present, and gets the
+** capabilities of a stream endpoint on the peer device.
+** This function can be called at any time regardless of
+** whether there is an AVDTP connection to the peer device.
+**
+** When the procedure is complete, an AVDT_GETCAP_CFM_EVT is
+** sent to the application via its callback function. The
+** application must not call AVDT_GetCapReq() or
+** AVDT_DiscoverReq() again until the procedure is complete.
+**
+** The memory pointed to by p_cfg is allocated by the
+** application. This memory is written to by AVDTP as part
+** of the get capabilities procedure. This memory must
+** remain accessible until the application receives
+** the AVDT_GETCAP_CFM_EVT.
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVDT_GetAllCapReq(BD_ADDR bd_addr, UINT8 seid, tAVDT_CFG *p_cfg, tAVDT_CTRL_CBACK *p_cback)
+{
+ tAVDT_CCB_API_GETCAP getcap;
+
+ BTTRC_AVDT_API1(AVDT_TRACE_API_GET_ALLCAP_REQ, BTTRC_PARAM_UINT8, seid);
+
+ getcap.single.seid = seid;
+ getcap.single.sig_id = AVDT_SIG_GET_ALLCAP;
+ getcap.p_cfg = p_cfg;
+ getcap.p_cback = p_cback;
+ return avdt_get_cap_req (bd_addr, &getcap);
+}
+
+/*******************************************************************************
+**
+** Function AVDT_DelayReport
+**
+** Description This functions sends a Delay Report to the peer device
+** that is associated with a particular SEID.
+** This function is called by SNK device.
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVDT_DelayReport(UINT8 handle, UINT8 seid, UINT16 delay)
+{
+ tAVDT_SCB *p_scb;
+ UINT16 result = AVDT_SUCCESS;
+ tAVDT_SCB_EVT evt;
+
+ BTTRC_AVDT_API0(AVDT_TRACE_API_DELAY_REPORT);
+
+ /* map handle to scb */
+ if ((p_scb = avdt_scb_by_hdl(handle)) == NULL)
+ {
+ result = AVDT_BAD_HANDLE;
+ }
+ else
+ /* send event to scb */
+ {
+ evt.apidelay.hdr.seid = seid;
+ evt.apidelay.delay = delay;
+ avdt_scb_event(p_scb, AVDT_SCB_API_DELAY_RPT_REQ_EVT, &evt);
+ }
+
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function AVDT_OpenReq
+**
+** Description This function initiates a connection to the AVDTP service
+** on the peer device, if not already present, and connects
+** to a stream endpoint on a peer device. When the connection
+** is completed, an AVDT_OPEN_CFM_EVT is sent to the
+** application via the control callback function for this handle.
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVDT_OpenReq(UINT8 handle, BD_ADDR bd_addr, UINT8 seid, tAVDT_CFG *p_cfg)
+{
+ tAVDT_CCB *p_ccb = NULL;
+ tAVDT_SCB *p_scb = NULL;
+ UINT16 result = AVDT_SUCCESS;
+ tAVDT_SCB_EVT evt;
+
+ BTTRC_AVDT_API0(AVDT_TRACE_API_OPEN_REQ);
+
+
+ /* verify SEID */
+ if ((seid < AVDT_SEID_MIN) || (seid > AVDT_SEID_MAX))
+ {
+ result = AVDT_BAD_PARAMS;
+ }
+ /* map handle to scb */
+ else if ((p_scb = avdt_scb_by_hdl(handle)) == NULL)
+ {
+ result = AVDT_BAD_HANDLE;
+ }
+ /* find channel control block for this bd addr; if none, allocate one */
+ else if ((p_ccb = avdt_ccb_by_bd(bd_addr)) == NULL)
+ {
+ if ((p_ccb = avdt_ccb_alloc(bd_addr)) == NULL)
+ {
+ /* could not allocate channel control block */
+ result = AVDT_NO_RESOURCES;
+ }
+ }
+
+ /* send event to scb */
+ if (result == AVDT_SUCCESS)
+ {
+ evt.msg.config_cmd.hdr.seid = seid;
+ evt.msg.config_cmd.hdr.ccb_idx = avdt_ccb_to_idx(p_ccb);
+ evt.msg.config_cmd.int_seid = handle;
+ evt.msg.config_cmd.p_cfg = p_cfg;
+ avdt_scb_event(p_scb, AVDT_SCB_API_SETCONFIG_REQ_EVT, &evt);
+ }
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function AVDT_ConfigRsp
+**
+** Description Respond to a configure request from the peer device. This
+** function must be called if the application receives an
+** AVDT_CONFIG_IND_EVT through its control callback.
+**
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVDT_ConfigRsp(UINT8 handle, UINT8 label, UINT8 error_code, UINT8 category)
+{
+ tAVDT_SCB *p_scb;
+ tAVDT_SCB_EVT evt;
+ UINT16 result = AVDT_SUCCESS;
+ UINT8 event_code;
+
+ BTTRC_AVDT_API0(AVDT_TRACE_API_CONFIG_RSP);
+
+ /* map handle to scb */
+ if ((p_scb = avdt_scb_by_hdl(handle)) == NULL)
+ {
+ result = AVDT_BAD_HANDLE;
+ }
+ /* handle special case when this function is called but peer has not send
+ ** a configuration cmd; ignore and return error result
+ */
+ else if (!p_scb->in_use)
+ {
+ result = AVDT_BAD_HANDLE;
+ }
+ /* send event to scb */
+ else
+ {
+ evt.msg.hdr.err_code = error_code;
+ evt.msg.hdr.err_param = category;
+ evt.msg.hdr.label = label;
+ if (error_code == 0)
+ {
+ event_code = AVDT_SCB_API_SETCONFIG_RSP_EVT;
+ }
+ else
+ {
+ event_code = AVDT_SCB_API_SETCONFIG_REJ_EVT;
+ }
+ avdt_scb_event(p_scb, event_code, &evt);
+ }
+
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function AVDT_StartReq
+**
+** Description Start one or more stream endpoints. This initiates the
+** transfer of media packets for the streams. All stream
+** endpoints must previously be opened. When the streams
+** are started, an AVDT_START_CFM_EVT is sent to the
+** application via the control callback function for each stream.
+**
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVDT_StartReq(UINT8 *p_handles, UINT8 num_handles)
+{
+ tAVDT_SCB *p_scb = NULL;
+ tAVDT_CCB_EVT evt;
+ UINT16 result = AVDT_SUCCESS;
+ int i;
+
+ BTTRC_AVDT_API0(AVDT_TRACE_API_START_REQ);
+
+ if ((num_handles == 0) || (num_handles > AVDT_NUM_SEPS))
+ {
+ result = AVDT_BAD_PARAMS;
+ }
+ else
+ {
+ /* verify handles */
+ for (i = 0; i < num_handles; i++)
+ {
+ if ((p_scb = avdt_scb_by_hdl(p_handles[i])) == NULL)
+ {
+ result = AVDT_BAD_HANDLE;
+ break;
+ }
+ }
+ }
+
+ if (result == AVDT_SUCCESS)
+ {
+ if (p_scb->p_ccb == NULL)
+ {
+ result = AVDT_BAD_HANDLE;
+ }
+ else
+ {
+ /* send event to ccb */
+ memcpy(evt.msg.multi.seid_list, p_handles, num_handles);
+ evt.msg.multi.num_seps = num_handles;
+ avdt_ccb_event(p_scb->p_ccb, AVDT_CCB_API_START_REQ_EVT, &evt);
+ }
+ }
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function AVDT_SuspendReq
+**
+** Description Suspend one or more stream endpoints. This suspends the
+** transfer of media packets for the streams. All stream
+** endpoints must previously be open and started. When the
+** streams are suspended, an AVDT_SUSPEND_CFM_EVT is sent to
+** the application via the control callback function for
+** each stream.
+**
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVDT_SuspendReq(UINT8 *p_handles, UINT8 num_handles)
+{
+ tAVDT_SCB *p_scb = NULL;
+ tAVDT_CCB_EVT evt;
+ UINT16 result = AVDT_SUCCESS;
+ int i;
+
+ BTTRC_AVDT_API0(AVDT_TRACE_API_SUSPEND_REQ);
+
+ if ((num_handles == 0) || (num_handles > AVDT_NUM_SEPS))
+ {
+ result = AVDT_BAD_PARAMS;
+ }
+ else
+ {
+ /* verify handles */
+ for (i = 0; i < num_handles; i++)
+ {
+ if ((p_scb = avdt_scb_by_hdl(p_handles[i])) == NULL)
+ {
+ result = AVDT_BAD_HANDLE;
+ break;
+ }
+ }
+ }
+
+ if (result == AVDT_SUCCESS)
+ {
+ if (p_scb->p_ccb == NULL)
+ {
+ result = AVDT_BAD_HANDLE;
+ }
+ else
+ {
+ /* send event to ccb */
+ memcpy(evt.msg.multi.seid_list, p_handles, num_handles);
+ evt.msg.multi.num_seps = num_handles;
+ avdt_ccb_event(p_scb->p_ccb, AVDT_CCB_API_SUSPEND_REQ_EVT, &evt);
+ }
+ }
+
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function AVDT_CloseReq
+**
+** Description Close a stream endpoint. This stops the transfer of media
+** packets and closes the transport channel associated with
+** this stream endpoint. When the stream is closed, an
+** AVDT_CLOSE_CFM_EVT is sent to the application via the
+** control callback function for this handle.
+**
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVDT_CloseReq(UINT8 handle)
+{
+ tAVDT_SCB *p_scb;
+ UINT16 result = AVDT_SUCCESS;
+
+ BTTRC_AVDT_API0(AVDT_TRACE_API_CLOSE_REQ);
+
+ /* map handle to scb */
+ if ((p_scb = avdt_scb_by_hdl(handle)) == NULL)
+ {
+ result = AVDT_BAD_HANDLE;
+ }
+ else
+ /* send event to scb */
+ {
+ avdt_scb_event(p_scb, AVDT_SCB_API_CLOSE_REQ_EVT, NULL);
+ }
+
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function AVDT_ReconfigReq
+**
+** Description Reconfigure a stream endpoint. This allows the application
+** to change the codec or content protection capabilities of
+** a stream endpoint after it has been opened. This function
+** can only be called if the stream is opened but not started
+** or if the stream has been suspended. When the procedure
+** is completed, an AVDT_RECONFIG_CFM_EVT is sent to the
+** application via the control callback function for this handle.
+**
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVDT_ReconfigReq(UINT8 handle, tAVDT_CFG *p_cfg)
+{
+ tAVDT_SCB *p_scb;
+ UINT16 result = AVDT_SUCCESS;
+ tAVDT_SCB_EVT evt;
+
+ BTTRC_AVDT_API0(AVDT_TRACE_API_RECONFIG_REQ);
+
+ /* map handle to scb */
+ if ((p_scb = avdt_scb_by_hdl(handle)) == NULL)
+ {
+ result = AVDT_BAD_HANDLE;
+ }
+ /* send event to scb */
+ else
+ {
+ /* force psc_mask to zero */
+ p_cfg->psc_mask = 0;
+
+ evt.msg.reconfig_cmd.p_cfg = p_cfg;
+ avdt_scb_event(p_scb, AVDT_SCB_API_RECONFIG_REQ_EVT, &evt);
+ }
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function AVDT_ReconfigRsp
+**
+** Description Respond to a reconfigure request from the peer device.
+** This function must be called if the application receives
+** an AVDT_RECONFIG_IND_EVT through its control callback.
+**
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVDT_ReconfigRsp(UINT8 handle, UINT8 label, UINT8 error_code, UINT8 category)
+{
+ tAVDT_SCB *p_scb;
+ tAVDT_SCB_EVT evt;
+ UINT16 result = AVDT_SUCCESS;
+
+ BTTRC_AVDT_API0(AVDT_TRACE_API_RECONFIG_RSP);
+
+ /* map handle to scb */
+ if ((p_scb = avdt_scb_by_hdl(handle)) == NULL)
+ {
+ result = AVDT_BAD_HANDLE;
+ }
+ /* send event to scb */
+ else
+ {
+ evt.msg.hdr.err_code = error_code;
+ evt.msg.hdr.err_param = category;
+ evt.msg.hdr.label = label;
+ avdt_scb_event(p_scb, AVDT_SCB_API_RECONFIG_RSP_EVT, &evt);
+ }
+
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function AVDT_SecurityReq
+**
+** Description Send a security request to the peer device. When the
+** security procedure is completed, an AVDT_SECURITY_CFM_EVT
+** is sent to the application via the control callback function
+** for this handle. (Please note that AVDTP security procedures
+** are unrelated to Bluetooth link level security.)
+**
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVDT_SecurityReq(UINT8 handle, UINT8 *p_data, UINT16 len)
+{
+ tAVDT_SCB *p_scb;
+ UINT16 result = AVDT_SUCCESS;
+ tAVDT_SCB_EVT evt;
+
+ BTTRC_AVDT_API0(AVDT_TRACE_API_SECURITY_REQ);
+
+ /* map handle to scb */
+ if ((p_scb = avdt_scb_by_hdl(handle)) == NULL)
+ {
+ result = AVDT_BAD_HANDLE;
+ }
+ /* send event to scb */
+ else
+ {
+ evt.msg.security_rsp.p_data = p_data;
+ evt.msg.security_rsp.len = len;
+ avdt_scb_event(p_scb, AVDT_SCB_API_SECURITY_REQ_EVT, &evt);
+ }
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function AVDT_SecurityRsp
+**
+** Description Respond to a security request from the peer device.
+** This function must be called if the application receives
+** an AVDT_SECURITY_IND_EVT through its control callback.
+** (Please note that AVDTP security procedures are unrelated
+** to Bluetooth link level security.)
+**
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVDT_SecurityRsp(UINT8 handle, UINT8 label, UINT8 error_code,
+ UINT8 *p_data, UINT16 len)
+{
+ tAVDT_SCB *p_scb;
+ UINT16 result = AVDT_SUCCESS;
+ tAVDT_SCB_EVT evt;
+
+ BTTRC_AVDT_API0(AVDT_TRACE_API_SECURITY_RSP);
+
+ /* map handle to scb */
+ if ((p_scb = avdt_scb_by_hdl(handle)) == NULL)
+ {
+ result = AVDT_BAD_HANDLE;
+ }
+ /* send event to scb */
+ else
+ {
+ evt.msg.security_rsp.hdr.err_code = error_code;
+ evt.msg.security_rsp.hdr.label = label;
+ evt.msg.security_rsp.p_data = p_data;
+ evt.msg.security_rsp.len = len;
+ avdt_scb_event(p_scb, AVDT_SCB_API_SECURITY_RSP_EVT, &evt);
+ }
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function AVDT_WriteReq
+**
+** Description Send a media packet to the peer device. The stream must
+** be started before this function is called. Also, this
+** function can only be called if the stream is a SRC.
+**
+** When AVDTP has sent the media packet and is ready for the
+** next packet, an AVDT_WRITE_CFM_EVT is sent to the
+** application via the control callback. The application must
+** wait for the AVDT_WRITE_CFM_EVT before it makes the next
+** call to AVDT_WriteReq(). If the applications calls
+** AVDT_WriteReq() before it receives the event the packet
+** will not be sent. The application may make its first call
+** to AVDT_WriteReq() after it receives an AVDT_START_CFM_EVT
+** or AVDT_START_IND_EVT.
+**
+** The application passes the packet using the BT_HDR structure.
+** This structure is described in section 2.1. The offset
+** field must be equal to or greater than AVDT_MEDIA_OFFSET.
+** This allows enough space in the buffer for the L2CAP and
+** AVDTP headers.
+**
+** The memory pointed to by p_pkt must be a GKI buffer
+** allocated by the application. This buffer will be freed
+** by the protocol stack; the application must not free
+** this buffer.
+**
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVDT_WriteReq(UINT8 handle, BT_HDR *p_pkt, UINT32 time_stamp, UINT8 m_pt)
+{
+ tAVDT_SCB *p_scb;
+ tAVDT_SCB_EVT evt;
+ UINT16 result = AVDT_SUCCESS;
+
+ BTTRC_AVDT_API0(AVDT_TRACE_API_WRITE_REQ);
+
+ /* map handle to scb */
+ if ((p_scb = avdt_scb_by_hdl(handle)) == NULL)
+ {
+ result = AVDT_BAD_HANDLE;
+ }
+ else
+ {
+ evt.apiwrite.p_buf = p_pkt;
+ evt.apiwrite.time_stamp = time_stamp;
+ evt.apiwrite.m_pt = m_pt;
+#if AVDT_MULTIPLEXING == TRUE
+ GKI_init_q (&evt.apiwrite.frag_q);
+#endif
+ avdt_scb_event(p_scb, AVDT_SCB_API_WRITE_REQ_EVT, &evt);
+ }
+
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function AVDT_ConnectReq
+**
+** Description This function initiates an AVDTP signaling connection
+** to the peer device. When the connection is completed, an
+** AVDT_CONNECT_IND_EVT is sent to the application via its
+** control callback function. If the connection attempt fails
+** an AVDT_DISCONNECT_IND_EVT is sent. The security mask
+** parameter overrides the outgoing security mask set in
+** AVDT_Register().
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVDT_ConnectReq(BD_ADDR bd_addr, UINT8 sec_mask, tAVDT_CTRL_CBACK *p_cback)
+{
+ tAVDT_CCB *p_ccb = NULL;
+ UINT16 result = AVDT_SUCCESS;
+ tAVDT_CCB_EVT evt;
+
+ BTTRC_AVDT_API0(AVDT_TRACE_API_CONNECT_REQ);
+
+ /* find channel control block for this bd addr; if none, allocate one */
+ if ((p_ccb = avdt_ccb_by_bd(bd_addr)) == NULL)
+ {
+ if ((p_ccb = avdt_ccb_alloc(bd_addr)) == NULL)
+ {
+ /* could not allocate channel control block */
+ result = AVDT_NO_RESOURCES;
+ }
+ }
+ else if (p_ccb->ll_opened == FALSE)
+ {
+ AVDT_TRACE_WARNING0("AVDT_ConnectReq: CCB LL is in the middle of opening");
+
+ /* ccb was already allocated for the incoming signalling. */
+ result = AVDT_BUSY;
+ }
+
+ if (result == AVDT_SUCCESS)
+ {
+ /* send event to ccb */
+ evt.connect.p_cback = p_cback;
+ evt.connect.sec_mask = sec_mask;
+ avdt_ccb_event(p_ccb, AVDT_CCB_API_CONNECT_REQ_EVT, &evt);
+ }
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function AVDT_DisconnectReq
+**
+** Description This function disconnect an AVDTP signaling connection
+** to the peer device. When disconnected an
+** AVDT_DISCONNECT_IND_EVT is sent to the application via its
+** control callback function.
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVDT_DisconnectReq(BD_ADDR bd_addr, tAVDT_CTRL_CBACK *p_cback)
+{
+ tAVDT_CCB *p_ccb = NULL;
+ UINT16 result = AVDT_SUCCESS;
+ tAVDT_CCB_EVT evt;
+
+ BTTRC_AVDT_API0(AVDT_TRACE_API_DISCONNECT_REQ);
+
+
+ /* find channel control block for this bd addr; if none, error */
+ if ((p_ccb = avdt_ccb_by_bd(bd_addr)) == NULL)
+ {
+ result = AVDT_BAD_PARAMS;
+ }
+
+ if (result == AVDT_SUCCESS)
+ {
+ /* send event to ccb */
+ evt.disconnect.p_cback = p_cback;
+ avdt_ccb_event(p_ccb, AVDT_CCB_API_DISCONNECT_REQ_EVT, &evt);
+ }
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function AVDT_GetL2CapChannel
+**
+** Description Get the L2CAP CID used by the handle.
+**
+** Returns CID if successful, otherwise 0.
+**
+*******************************************************************************/
+UINT16 AVDT_GetL2CapChannel(UINT8 handle)
+{
+ tAVDT_SCB *p_scb;
+ tAVDT_CCB *p_ccb;
+ UINT8 tcid;
+ UINT16 lcid = 0;
+
+ /* map handle to scb */
+ if (((p_scb = avdt_scb_by_hdl(handle)) != NULL)
+ && ((p_ccb = p_scb->p_ccb) != NULL))
+ {
+ /* get tcid from type, scb */
+ tcid = avdt_ad_type_to_tcid(AVDT_CHAN_MEDIA, p_scb);
+
+ lcid = avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid;
+ }
+
+ BTTRC_AVDT_API1(AVDT_TRACE_API_GET_L2CAP_CHAN, BTTRC_PARAM_UINT16, lcid);
+
+ return (lcid);
+}
+
+/*******************************************************************************
+**
+** Function AVDT_GetSignalChannel
+**
+** Description Get the L2CAP CID used by the signal channel of the given handle.
+**
+** Returns CID if successful, otherwise 0.
+**
+*******************************************************************************/
+UINT16 AVDT_GetSignalChannel(UINT8 handle, BD_ADDR bd_addr)
+{
+ tAVDT_SCB *p_scb;
+ tAVDT_CCB *p_ccb;
+ UINT8 tcid = 0; /* tcid is always 0 for signal channel */
+ UINT16 lcid = 0;
+
+ /* map handle to scb */
+ if (((p_scb = avdt_scb_by_hdl(handle)) != NULL)
+ && ((p_ccb = p_scb->p_ccb) != NULL))
+ {
+ lcid = avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid;
+ }
+ else if ((p_ccb = avdt_ccb_by_bd(bd_addr)) != NULL)
+ {
+ lcid = avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid;
+ }
+
+ BTTRC_AVDT_API1(AVDT_TRACE_API_GET_SIGNAL_CHAN, BTTRC_PARAM_UINT16, lcid);
+
+ return (lcid);
+}
+
+#if AVDT_MULTIPLEXING == TRUE
+/*******************************************************************************
+**
+** Function AVDT_WriteDataReq
+**
+** Description Send a media packet to the peer device. The stream must
+** be started before this function is called. Also, this
+** function can only be called if the stream is a SRC.
+**
+** When AVDTP has sent the media packet and is ready for the
+** next packet, an AVDT_WRITE_CFM_EVT is sent to the
+** application via the control callback. The application must
+** wait for the AVDT_WRITE_CFM_EVT before it makes the next
+** call to AVDT_WriteDataReq(). If the applications calls
+** AVDT_WriteDataReq() before it receives the event the packet
+** will not be sent. The application may make its first call
+** to AVDT_WriteDataReq() after it receives an
+** AVDT_START_CFM_EVT or AVDT_START_IND_EVT.
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+AVDT_API extern UINT16 AVDT_WriteDataReq(UINT8 handle, UINT8 *p_data, UINT32 data_len,
+ UINT32 time_stamp, UINT8 m_pt, UINT8 marker)
+{
+
+ tAVDT_SCB *p_scb;
+ tAVDT_SCB_EVT evt;
+ UINT16 result = AVDT_SUCCESS;
+
+ BTTRC_AVDT_API1(AVDT_TRACE_API_WRITE_DATA_REQ, BTTRC_PARAM_UINT32, data_len);
+
+ do
+ {
+ /* check length of media frame */
+ if(data_len > AVDT_MAX_MEDIA_SIZE)
+ {
+ result = AVDT_BAD_PARAMS;
+ break;
+ }
+ /* map handle to scb */
+ if ((p_scb = avdt_scb_by_hdl(handle)) == NULL)
+ {
+ result = AVDT_BAD_HANDLE;
+ break;
+ }
+ AVDT_TRACE_WARNING1("mux_tsid_media:%d", p_scb->curr_cfg.mux_tsid_media);
+
+ if (p_scb->p_pkt != NULL
+ || p_scb->p_ccb == NULL
+ || !GKI_queue_is_empty(&p_scb->frag_q)
+ || p_scb->frag_off != 0
+ || p_scb->curr_cfg.mux_tsid_media == 0)
+ {
+ result = AVDT_ERR_BAD_STATE;
+ AVDT_TRACE_WARNING4("p_scb->p_pkt=%x, p_scb->p_ccb=%x, IsQueueEmpty=%x, p_scb->frag_off=%x",
+ p_scb->p_pkt, p_scb->p_ccb, GKI_queue_is_empty(&p_scb->frag_q), p_scb->frag_off);
+ break;
+ }
+ evt.apiwrite.p_buf = 0; /* it will indicate using of fragments queue frag_q */
+ /* create queue of media fragments */
+ GKI_init_q (&evt.apiwrite.frag_q);
+
+ /* compose fragments from media payload and put fragments into gueue */
+ avdt_scb_queue_frags(p_scb, &p_data, &data_len, &evt.apiwrite.frag_q);
+
+ if(GKI_queue_is_empty(&evt.apiwrite.frag_q))
+ {
+ AVDT_TRACE_WARNING0("AVDT_WriteDataReq out of GKI buffers");
+ result = AVDT_ERR_RESOURCE;
+ break;
+ }
+ evt.apiwrite.data_len = data_len;
+ evt.apiwrite.p_data = p_data;
+
+ /* process the fragments queue */
+ evt.apiwrite.time_stamp = time_stamp;
+ evt.apiwrite.m_pt = m_pt | (marker<<7);
+ avdt_scb_event(p_scb, AVDT_SCB_API_WRITE_REQ_EVT, &evt);
+ } while (0);
+
+#if (BT_USE_TRACES == TRUE)
+ if(result != AVDT_SUCCESS)
+ {
+ AVDT_TRACE_WARNING1("*** AVDT_WriteDataReq failed result=%d",result);
+ }
+#endif
+ return result;
+}
+#endif
+
+#if AVDT_MULTIPLEXING == TRUE
+/*******************************************************************************
+**
+** Function AVDT_SetMediaBuf
+**
+** Description Assigns buffer for media packets or forbids using of assigned
+** buffer if argument p_buf is NULL. This function can only
+** be called if the stream is a SNK.
+**
+** AVDTP uses this buffer to reassemble fragmented media packets.
+** When AVDTP receives a complete media packet, it calls the
+** p_media_cback assigned by AVDT_CreateStream().
+** This function can be called during callback to assign a
+** different buffer for next media packet or can leave the current
+** buffer for next packet.
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+AVDT_API extern UINT16 AVDT_SetMediaBuf(UINT8 handle, UINT8 *p_buf, UINT32 buf_len)
+{
+ tAVDT_SCB *p_scb;
+ UINT16 result = AVDT_SUCCESS;
+
+ BTTRC_AVDT_API0(AVDT_TRACE_API_SET_MEDIABUF);
+
+ /* map handle to scb */
+ if ((p_scb = avdt_scb_by_hdl(handle)) == NULL)
+ {
+ result = AVDT_BAD_HANDLE;
+ }
+ else
+ {
+ if(p_buf && p_scb->cs.p_media_cback == NULL)
+ result = AVDT_NO_RESOURCES;
+ else
+ {
+ p_scb->p_media_buf = p_buf;
+ p_scb->media_buf_len = buf_len;
+ }
+ }
+
+ return result;
+}
+#endif
+
+#if AVDT_REPORTING == TRUE
+/*******************************************************************************
+**
+** Function AVDT_SendReport
+**
+** Description
+**
+**
+**
+** Returns
+**
+*******************************************************************************/
+UINT16 AVDT_SendReport(UINT8 handle, AVDT_REPORT_TYPE type,
+ tAVDT_REPORT_DATA *p_data)
+{
+ tAVDT_SCB *p_scb;
+ UINT16 result = AVDT_BAD_PARAMS;
+ BT_HDR *p_pkt;
+ tAVDT_TC_TBL *p_tbl;
+ UINT8 *p, *plen, *pm1, *p_end;
+#if AVDT_MULTIPLEXING == TRUE
+ UINT8 *p_al, u;
+#endif
+ UINT32 ssrc;
+ UINT16 len;
+
+ BTTRC_AVDT_API0(AVDT_TRACE_API_SEND_REPORT);
+
+ /* map handle to scb && verify parameters */
+ if (((p_scb = avdt_scb_by_hdl(handle)) != NULL)
+ && (p_scb->p_ccb != NULL)
+ && (((type == AVDT_RTCP_PT_SR) && (p_scb->cs.tsep == AVDT_TSEP_SRC)) ||
+ ((type == AVDT_RTCP_PT_RR) && (p_scb->cs.tsep == AVDT_TSEP_SNK)) ||
+ (type == AVDT_RTCP_PT_SDES)) )
+ {
+ result = AVDT_NO_RESOURCES;
+
+ /* 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) &&
+ (p_pkt = (BT_HDR *)GKI_getbuf(p_tbl->peer_mtu)) != NULL)
+ {
+ p_pkt->offset = L2CAP_MIN_OFFSET;
+ p = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
+#if AVDT_MULTIPLEXING == TRUE
+ if(p_scb->curr_cfg.psc_mask & AVDT_PSC_MUX)
+ {
+ /* Adaptation Layer header later */
+ p_al = p;
+ p += 2;
+ }
+#endif
+ pm1 = p;
+ *p++ = AVDT_MEDIA_OCTET1 | 1;
+ *p++ = type;
+ /* save the location for length */
+ plen = p;
+ p+= 2;
+ ssrc = avdt_scb_gen_ssrc(p_scb);
+ UINT32_TO_BE_STREAM(p, ssrc);
+
+ switch(type)
+ {
+ case AVDT_RTCP_PT_SR: /* Sender Report */
+ *pm1 = AVDT_MEDIA_OCTET1;
+ UINT32_TO_BE_STREAM(p, p_data->sr.ntp_sec);
+ UINT32_TO_BE_STREAM(p, p_data->sr.ntp_frac);
+ UINT32_TO_BE_STREAM(p, p_data->sr.rtp_time);
+ UINT32_TO_BE_STREAM(p, p_data->sr.pkt_count);
+ UINT32_TO_BE_STREAM(p, p_data->sr.octet_count);
+ break;
+
+ case AVDT_RTCP_PT_RR: /* Receiver Report */
+ *p++ = p_data->rr.frag_lost;
+ AVDT_TRACE_API1("packet_lost: %d", p_data->rr.packet_lost);
+ p_data->rr.packet_lost &= 0xFFFFFF;
+ AVDT_TRACE_API1("packet_lost: %d", p_data->rr.packet_lost);
+ UINT24_TO_BE_STREAM(p, p_data->rr.packet_lost);
+ 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);
+ UINT32_TO_BE_STREAM(p, p_data->rr.dlsr);
+ break;
+
+ case AVDT_RTCP_PT_SDES: /* Source Description */
+ *p++ = AVDT_RTCP_SDES_CNAME;
+ len = strlen((char *)p_data->cname);
+ if(len > AVDT_MAX_CNAME_SIZE)
+ len = AVDT_MAX_CNAME_SIZE;
+ *p++ = (UINT8)len;
+ BCM_STRNCPY_S((char *)p, len+1, (char *)p_data->cname, len+1);
+ p += len;
+ break;
+ }
+ p_end = p;
+ len = p - pm1 - 1;
+ UINT16_TO_BE_STREAM(plen, len);
+
+#if AVDT_MULTIPLEXING == TRUE
+ if(p_scb->curr_cfg.psc_mask & AVDT_PSC_MUX)
+ {
+ /* Adaptation Layer header */
+ p = p_al;
+ len++;
+ UINT16_TO_BE_STREAM(p_al, len );
+ /* TSID, no-fragment bit and coding of length(9-bit length field) */
+ u = *p;
+ *p = (p_scb->curr_cfg.mux_tsid_report<<3) | AVDT_ALH_LCODE_9BITM0;
+ if(u)
+ *p |= AVDT_ALH_LCODE_9BITM1;
+ }
+#endif
+
+ /* set the actual payload length */
+ p_pkt->len = p_end - p;
+ /* send the packet */
+ if(L2CAP_DW_FAILED != avdt_ad_write_req(AVDT_CHAN_REPORT, p_scb->p_ccb, p_scb, p_pkt))
+ result = AVDT_SUCCESS;
+ }
+ }
+
+ return result;
+}
+#endif
+
+/******************************************************************************
+**
+** Function AVDT_SetTraceLevel
+**
+** Description Sets the trace level for AVDT. If 0xff is passed, the
+** current trace level is returned.
+**
+** Input Parameters:
+** new_level: The level to set the AVDT tracing to:
+** 0xff-returns the current setting.
+** 0-turns off tracing.
+** >= 1-Errors.
+** >= 2-Warnings.
+** >= 3-APIs.
+** >= 4-Events.
+** >= 5-Debug.
+**
+** Returns The new trace level or current trace level if
+** the input parameter is 0xff.
+**
+******************************************************************************/
+UINT8 AVDT_SetTraceLevel (UINT8 new_level)
+{
+ if (new_level != 0xFF)
+ avdt_cb.trace_level = new_level;
+
+ return (avdt_cb.trace_level);
+}
+
diff --git a/stack/avdt/avdt_ccb.c b/stack/avdt/avdt_ccb.c
new file mode 100644
index 0000000..9cb40b2
--- /dev/null
+++ b/stack/avdt/avdt_ccb.c
@@ -0,0 +1,464 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2002-2012 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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This module contains the channel control block state machine and
+ * functions which operate on the channel control block.
+ *
+ ******************************************************************************/
+
+#include <string.h>
+#include "data_types.h"
+#include "bt_target.h"
+#include "avdt_api.h"
+#include "avdtc_api.h"
+#include "avdt_int.h"
+#include "gki.h"
+#include "btu.h"
+
+/*****************************************************************************
+** state machine constants and types
+*****************************************************************************/
+#if AVDT_DEBUG == TRUE
+
+/* verbose state strings for trace */
+const char * const avdt_ccb_st_str[] = {
+ "CCB_IDLE_ST",
+ "CCB_OPENING_ST",
+ "CCB_OPEN_ST",
+ "CCB_CLOSING_ST"
+};
+
+/* verbose event strings for trace */
+const char * const avdt_ccb_evt_str[] = {
+ "API_DISCOVER_REQ_EVT",
+ "API_GETCAP_REQ_EVT",
+ "API_START_REQ_EVT",
+ "API_SUSPEND_REQ_EVT",
+ "API_DISCOVER_RSP_EVT",
+ "API_GETCAP_RSP_EVT",
+ "API_START_RSP_EVT",
+ "API_SUSPEND_RSP_EVT",
+ "API_CONNECT_REQ_EVT",
+ "API_DISCONNECT_REQ_EVT",
+ "MSG_DISCOVER_CMD_EVT",
+ "MSG_GETCAP_CMD_EVT",
+ "MSG_START_CMD_EVT",
+ "MSG_SUSPEND_CMD_EVT",
+ "MSG_DISCOVER_RSP_EVT",
+ "MSG_GETCAP_RSP_EVT",
+ "MSG_START_RSP_EVT",
+ "MSG_SUSPEND_RSP_EVT",
+ "RCVRSP_EVT",
+ "SENDMSG_EVT",
+ "RET_TOUT_EVT",
+ "RSP_TOUT_EVT",
+ "IDLE_TOUT_EVT",
+ "UL_OPEN_EVT",
+ "UL_CLOSE_EVT",
+ "LL_OPEN_EVT",
+ "LL_CLOSE_EVT",
+ "LL_CONG_EVT"
+};
+
+#endif
+
+
+/* action function list */
+const tAVDT_CCB_ACTION avdt_ccb_action[] = {
+ avdt_ccb_chan_open,
+ avdt_ccb_chan_close,
+ avdt_ccb_chk_close,
+ avdt_ccb_hdl_discover_cmd,
+ avdt_ccb_hdl_discover_rsp,
+ avdt_ccb_hdl_getcap_cmd,
+ avdt_ccb_hdl_getcap_rsp,
+ avdt_ccb_hdl_start_cmd,
+ avdt_ccb_hdl_start_rsp,
+ avdt_ccb_hdl_suspend_cmd,
+ avdt_ccb_hdl_suspend_rsp,
+ avdt_ccb_snd_discover_cmd,
+ avdt_ccb_snd_discover_rsp,
+ avdt_ccb_snd_getcap_cmd,
+ avdt_ccb_snd_getcap_rsp,
+ avdt_ccb_snd_start_cmd,
+ avdt_ccb_snd_start_rsp,
+ avdt_ccb_snd_suspend_cmd,
+ avdt_ccb_snd_suspend_rsp,
+ avdt_ccb_clear_cmds,
+ avdt_ccb_cmd_fail,
+ avdt_ccb_free_cmd,
+ avdt_ccb_cong_state,
+ avdt_ccb_ret_cmd,
+ avdt_ccb_snd_cmd,
+ avdt_ccb_snd_msg,
+ avdt_ccb_set_reconn,
+ avdt_ccb_clr_reconn,
+ avdt_ccb_chk_reconn,
+ avdt_ccb_chk_timer,
+ avdt_ccb_set_conn,
+ avdt_ccb_set_disconn,
+ avdt_ccb_do_disconn,
+ avdt_ccb_ll_closed,
+ avdt_ccb_ll_opened,
+ avdt_ccb_dealloc
+};
+
+/* state table information */
+#define AVDT_CCB_ACTIONS 2 /* number of actions */
+#define AVDT_CCB_NEXT_STATE 2 /* position of next state */
+#define AVDT_CCB_NUM_COLS 3 /* number of columns in state tables */
+
+/* state table for idle state */
+const UINT8 avdt_ccb_st_idle[][AVDT_CCB_NUM_COLS] = {
+/* Event Action 1 Action 2 Next state */
+/* API_DISCOVER_REQ_EVT */ {AVDT_CCB_SND_DISCOVER_CMD, AVDT_CCB_CHAN_OPEN, AVDT_CCB_OPENING_ST},
+/* API_GETCAP_REQ_EVT */ {AVDT_CCB_SND_GETCAP_CMD, AVDT_CCB_CHAN_OPEN, AVDT_CCB_OPENING_ST},
+/* API_START_REQ_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
+/* API_SUSPEND_REQ_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
+/* API_DISCOVER_RSP_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
+/* API_GETCAP_RSP_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
+/* API_START_RSP_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
+/* API_SUSPEND_RSP_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
+/* API_CONNECT_REQ_EVT */ {AVDT_CCB_SET_CONN, AVDT_CCB_CHAN_OPEN, AVDT_CCB_OPENING_ST},
+/* API_DISCONNECT_REQ_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
+/* MSG_DISCOVER_CMD_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
+/* MSG_GETCAP_CMD_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
+/* MSG_START_CMD_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
+/* MSG_SUSPEND_CMD_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
+/* MSG_DISCOVER_RSP_EVT */ {AVDT_CCB_HDL_DISCOVER_RSP, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
+/* MSG_GETCAP_RSP_EVT */ {AVDT_CCB_HDL_GETCAP_RSP, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
+/* MSG_START_RSP_EVT */ {AVDT_CCB_HDL_START_RSP, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
+/* MSG_SUSPEND_RSP_EVT */ {AVDT_CCB_HDL_SUSPEND_RSP, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
+/* RCVRSP_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
+/* SENDMSG_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
+/* RET_TOUT_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
+/* RSP_TOUT_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
+/* IDLE_TOUT_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
+/* UL_OPEN_EVT */ {AVDT_CCB_CHAN_OPEN, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
+/* UL_CLOSE_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
+/* LL_OPEN_EVT */ {AVDT_CCB_LL_OPENED, AVDT_CCB_IGNORE, AVDT_CCB_OPEN_ST},
+/* LL_CLOSE_EVT */ {AVDT_CCB_LL_CLOSED, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
+/* LL_CONG_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST}
+};
+
+/* state table for opening state */
+const UINT8 avdt_ccb_st_opening[][AVDT_CCB_NUM_COLS] = {
+/* Event Action 1 Action 2 Next state */
+/* API_DISCOVER_REQ_EVT */ {AVDT_CCB_SND_DISCOVER_CMD, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
+/* API_GETCAP_REQ_EVT */ {AVDT_CCB_SND_GETCAP_CMD, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
+/* API_START_REQ_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
+/* API_SUSPEND_REQ_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
+/* API_DISCOVER_RSP_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
+/* API_GETCAP_RSP_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
+/* API_START_RSP_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
+/* API_SUSPEND_RSP_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
+/* API_CONNECT_REQ_EVT */ {AVDT_CCB_SET_CONN, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
+/* API_DISCONNECT_REQ_EVT */ {AVDT_CCB_SET_DISCONN, AVDT_CCB_DO_DISCONN, AVDT_CCB_CLOSING_ST},
+/* MSG_DISCOVER_CMD_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
+/* MSG_GETCAP_CMD_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
+/* MSG_START_CMD_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
+/* MSG_SUSPEND_CMD_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
+/* MSG_DISCOVER_RSP_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
+/* MSG_GETCAP_RSP_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
+/* MSG_START_RSP_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
+/* MSG_SUSPEND_RSP_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
+/* RCVRSP_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
+/* SENDMSG_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
+/* RET_TOUT_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
+/* RSP_TOUT_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
+/* IDLE_TOUT_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
+/* UL_OPEN_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
+/* UL_CLOSE_EVT */ {AVDT_CCB_CLEAR_CMDS, AVDT_CCB_CHAN_CLOSE, AVDT_CCB_CLOSING_ST},
+/* LL_OPEN_EVT */ {AVDT_CCB_SND_CMD, AVDT_CCB_LL_OPENED, AVDT_CCB_OPEN_ST},
+/* LL_CLOSE_EVT */ {AVDT_CCB_LL_CLOSED, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
+/* LL_CONG_EVT */ {AVDT_CCB_CONG_STATE, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST}
+};
+
+/* state table for open state */
+const UINT8 avdt_ccb_st_open[][AVDT_CCB_NUM_COLS] = {
+/* Event Action 1 Action 2 Next state */
+/* API_DISCOVER_REQ_EVT */ {AVDT_CCB_SND_DISCOVER_CMD, AVDT_CCB_SND_CMD, AVDT_CCB_OPEN_ST},
+/* API_GETCAP_REQ_EVT */ {AVDT_CCB_SND_GETCAP_CMD, AVDT_CCB_SND_CMD, AVDT_CCB_OPEN_ST},
+/* API_START_REQ_EVT */ {AVDT_CCB_SND_START_CMD, AVDT_CCB_SND_CMD, AVDT_CCB_OPEN_ST},
+/* API_SUSPEND_REQ_EVT */ {AVDT_CCB_SND_SUSPEND_CMD, AVDT_CCB_SND_CMD, AVDT_CCB_OPEN_ST},
+/* API_DISCOVER_RSP_EVT */ {AVDT_CCB_SND_DISCOVER_RSP, AVDT_CCB_SND_CMD, AVDT_CCB_OPEN_ST},
+/* API_GETCAP_RSP_EVT */ {AVDT_CCB_SND_GETCAP_RSP, AVDT_CCB_SND_CMD, AVDT_CCB_OPEN_ST},
+/* API_START_RSP_EVT */ {AVDT_CCB_SND_START_RSP, AVDT_CCB_SND_CMD, AVDT_CCB_OPEN_ST},
+/* API_SUSPEND_RSP_EVT */ {AVDT_CCB_SND_SUSPEND_RSP, AVDT_CCB_SND_CMD, AVDT_CCB_OPEN_ST},
+/* API_CONNECT_REQ_EVT */ {AVDT_CCB_SET_CONN, AVDT_CCB_LL_OPENED, AVDT_CCB_OPEN_ST},
+/* API_DISCONNECT_REQ_EVT */ {AVDT_CCB_SET_DISCONN, AVDT_CCB_DO_DISCONN, AVDT_CCB_CLOSING_ST},
+/* MSG_DISCOVER_CMD_EVT */ {AVDT_CCB_HDL_DISCOVER_CMD, AVDT_CCB_IGNORE, AVDT_CCB_OPEN_ST},
+/* MSG_GETCAP_CMD_EVT */ {AVDT_CCB_HDL_GETCAP_CMD, AVDT_CCB_IGNORE, AVDT_CCB_OPEN_ST},
+/* MSG_START_CMD_EVT */ {AVDT_CCB_HDL_START_CMD, AVDT_CCB_IGNORE, AVDT_CCB_OPEN_ST},
+/* MSG_SUSPEND_CMD_EVT */ {AVDT_CCB_HDL_SUSPEND_CMD, AVDT_CCB_IGNORE, AVDT_CCB_OPEN_ST},
+/* MSG_DISCOVER_RSP_EVT */ {AVDT_CCB_CHK_CLOSE, AVDT_CCB_HDL_DISCOVER_RSP, AVDT_CCB_OPEN_ST},
+/* MSG_GETCAP_RSP_EVT */ {AVDT_CCB_CHK_CLOSE, AVDT_CCB_HDL_GETCAP_RSP, AVDT_CCB_OPEN_ST},
+/* MSG_START_RSP_EVT */ {AVDT_CCB_HDL_START_RSP, AVDT_CCB_IGNORE, AVDT_CCB_OPEN_ST},
+/* MSG_SUSPEND_RSP_EVT */ {AVDT_CCB_HDL_SUSPEND_RSP, AVDT_CCB_IGNORE, AVDT_CCB_OPEN_ST},
+/* RCVRSP_EVT */ {AVDT_CCB_FREE_CMD, AVDT_CCB_SND_CMD, AVDT_CCB_OPEN_ST},
+/* SENDMSG_EVT */ {AVDT_CCB_SND_MSG, AVDT_CCB_IGNORE, AVDT_CCB_OPEN_ST},
+/* RET_TOUT_EVT */ {AVDT_CCB_RET_CMD, AVDT_CCB_IGNORE, AVDT_CCB_OPEN_ST},
+/* RSP_TOUT_EVT */ {AVDT_CCB_CMD_FAIL, AVDT_CCB_SND_CMD, AVDT_CCB_OPEN_ST},
+/* IDLE_TOUT_EVT */ {AVDT_CCB_CLEAR_CMDS, AVDT_CCB_CHAN_CLOSE, AVDT_CCB_CLOSING_ST},
+/* UL_OPEN_EVT */ {AVDT_CCB_CHK_TIMER, AVDT_CCB_IGNORE, AVDT_CCB_OPEN_ST},
+/* UL_CLOSE_EVT */ {AVDT_CCB_CHK_CLOSE, AVDT_CCB_IGNORE, AVDT_CCB_OPEN_ST},
+/* LL_OPEN_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_OPEN_ST},
+/* LL_CLOSE_EVT */ {AVDT_CCB_LL_CLOSED, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
+/* LL_CONG_EVT */ {AVDT_CCB_CONG_STATE, AVDT_CCB_SND_MSG, AVDT_CCB_OPEN_ST}
+};
+
+/* state table for closing state */
+const UINT8 avdt_ccb_st_closing[][AVDT_CCB_NUM_COLS] = {
+/* Event Action 1 Action 2 Next state */
+/* API_DISCOVER_REQ_EVT */ {AVDT_CCB_SET_RECONN, AVDT_CCB_SND_DISCOVER_CMD, AVDT_CCB_CLOSING_ST},
+/* API_GETCAP_REQ_EVT */ {AVDT_CCB_SET_RECONN, AVDT_CCB_SND_GETCAP_CMD, AVDT_CCB_CLOSING_ST},
+/* API_START_REQ_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST},
+/* API_SUSPEND_REQ_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST},
+/* API_DISCOVER_RSP_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST},
+/* API_GETCAP_RSP_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST},
+/* API_START_RSP_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST},
+/* API_SUSPEND_RSP_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST},
+/* API_CONNECT_REQ_EVT */ {AVDT_CCB_SET_RECONN, AVDT_CCB_SET_CONN, AVDT_CCB_CLOSING_ST},
+/* API_DISCONNECT_REQ_EVT */ {AVDT_CCB_CLR_RECONN, AVDT_CCB_SET_DISCONN, AVDT_CCB_CLOSING_ST},
+/* MSG_DISCOVER_CMD_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST},
+/* MSG_GETCAP_CMD_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST},
+/* MSG_START_CMD_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST},
+/* MSG_SUSPEND_CMD_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST},
+/* MSG_DISCOVER_RSP_EVT */ {AVDT_CCB_HDL_DISCOVER_RSP, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST},
+/* MSG_GETCAP_RSP_EVT */ {AVDT_CCB_HDL_GETCAP_RSP, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST},
+/* MSG_START_RSP_EVT */ {AVDT_CCB_HDL_START_RSP, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST},
+/* MSG_SUSPEND_RSP_EVT */ {AVDT_CCB_HDL_SUSPEND_RSP, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST},
+/* RCVRSP_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST},
+/* SENDMSG_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST},
+/* RET_TOUT_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST},
+/* RSP_TOUT_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST},
+/* IDLE_TOUT_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST},
+/* UL_OPEN_EVT */ {AVDT_CCB_SET_RECONN, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST},
+/* UL_CLOSE_EVT */ {AVDT_CCB_CLR_RECONN, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST},
+/* LL_OPEN_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST},
+/* LL_CLOSE_EVT */ {AVDT_CCB_CHK_RECONN, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
+/* LL_CONG_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST}
+};
+
+/* type for state table */
+typedef const UINT8 (*tAVDT_CCB_ST_TBL)[AVDT_CCB_NUM_COLS];
+
+/* state table */
+const tAVDT_CCB_ST_TBL avdt_ccb_st_tbl[] = {
+ avdt_ccb_st_idle,
+ avdt_ccb_st_opening,
+ avdt_ccb_st_open,
+ avdt_ccb_st_closing
+};
+
+/*******************************************************************************
+**
+** Function avdt_ccb_init
+**
+** Description Initialize channel control block module.
+**
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_ccb_init(void)
+{
+ memset(&avdt_cb.ccb[0], 0, sizeof(tAVDT_CCB) * AVDT_NUM_LINKS);
+ avdt_cb.p_ccb_act = (tAVDT_CCB_ACTION *) avdt_ccb_action;
+}
+
+/*******************************************************************************
+**
+** Function avdt_ccb_event
+**
+** Description State machine event handling function for ccb
+**
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_ccb_event(tAVDT_CCB *p_ccb, UINT8 event, tAVDT_CCB_EVT *p_data)
+{
+ tAVDT_CCB_ST_TBL state_table;
+ UINT8 action;
+ int i;
+
+#if AVDT_DEBUG == TRUE
+ AVDT_TRACE_EVENT3("CCB ccb=%d event=%s state=%s", avdt_ccb_to_idx(p_ccb), avdt_ccb_evt_str[event], avdt_ccb_st_str[p_ccb->state]);
+#endif
+ BTTRC_AVDT_CCB_EVENT(event, p_ccb->state);
+
+ /* look up the state table for the current state */
+ state_table = avdt_ccb_st_tbl[p_ccb->state];
+
+ /* set next state */
+ if (p_ccb->state != state_table[event][AVDT_CCB_NEXT_STATE])
+ BTTRC_AVDT_CCB_STATE(state_table[event][AVDT_CCB_NEXT_STATE]);
+ p_ccb->state = state_table[event][AVDT_CCB_NEXT_STATE];
+
+ /* execute action functions */
+ for (i = 0; i < AVDT_CCB_ACTIONS; i++)
+ {
+ if ((action = state_table[event][i]) != AVDT_CCB_IGNORE)
+ {
+ BTTRC_AVDT_CCB_ACTION(action);
+ (*avdt_cb.p_ccb_act[action])(p_ccb, p_data);
+ }
+ else
+ {
+ break;
+ }
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function avdt_ccb_by_bd
+**
+** Description This lookup function finds the ccb for a BD address.
+**
+**
+** Returns pointer to the ccb, or NULL if none found.
+**
+*******************************************************************************/
+tAVDT_CCB *avdt_ccb_by_bd(BD_ADDR bd_addr)
+{
+ tAVDT_CCB *p_ccb = &avdt_cb.ccb[0];
+ int i;
+
+ for (i = 0; i < AVDT_NUM_LINKS; i++, p_ccb++)
+ {
+ /* if allocated ccb has matching ccb */
+ if (p_ccb->allocated && (!memcmp(p_ccb->peer_addr, bd_addr, BD_ADDR_LEN)))
+ {
+ break;
+ }
+ }
+
+ if (i == AVDT_NUM_LINKS)
+ {
+ /* if no ccb found */
+ p_ccb = NULL;
+
+ AVDT_TRACE_DEBUG6("No ccb for addr %02x-%02x-%02x-%02x-%02x-%02x",
+ bd_addr[0], bd_addr[1], bd_addr[2], bd_addr[3], bd_addr[4], bd_addr[5]);
+ }
+ return p_ccb;
+}
+
+/*******************************************************************************
+**
+** Function avdt_ccb_alloc
+**
+** Description Allocate a channel control block.
+**
+**
+** Returns pointer to the ccb, or NULL if none could be allocated.
+**
+*******************************************************************************/
+tAVDT_CCB *avdt_ccb_alloc(BD_ADDR bd_addr)
+{
+ tAVDT_CCB *p_ccb = &avdt_cb.ccb[0];
+ int i;
+
+ for (i = 0; i < AVDT_NUM_LINKS; i++, p_ccb++)
+ {
+ if (!p_ccb->allocated)
+ {
+ p_ccb->allocated = TRUE;
+ memcpy(p_ccb->peer_addr, bd_addr, BD_ADDR_LEN);
+ GKI_init_q(&p_ccb->cmd_q);
+ GKI_init_q(&p_ccb->rsp_q);
+ p_ccb->timer_entry.param = (UINT32) p_ccb;
+ AVDT_TRACE_DEBUG1("avdt_ccb_alloc %d", i);
+ break;
+ }
+ }
+
+ if (i == AVDT_NUM_LINKS)
+ {
+ /* out of ccbs */
+ p_ccb = NULL;
+ AVDT_TRACE_WARNING0("Out of ccbs");
+ }
+ return p_ccb;
+}
+
+/*******************************************************************************
+**
+** Function avdt_ccb_dealloc
+**
+** Description Deallocate a stream control block.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+void avdt_ccb_dealloc(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
+{
+ AVDT_TRACE_DEBUG1("avdt_ccb_dealloc %d", avdt_ccb_to_idx(p_ccb));
+ btu_stop_timer(&p_ccb->timer_entry);
+ memset(p_ccb, 0, sizeof(tAVDT_CCB));
+}
+
+/*******************************************************************************
+**
+** Function avdt_ccb_to_idx
+**
+** Description Given a pointer to an ccb, return its index.
+**
+**
+** Returns Index of ccb.
+**
+*******************************************************************************/
+UINT8 avdt_ccb_to_idx(tAVDT_CCB *p_ccb)
+{
+ /* use array arithmetic to determine index */
+ return (UINT8) (p_ccb - avdt_cb.ccb);
+}
+
+/*******************************************************************************
+**
+** Function avdt_ccb_by_idx
+**
+** Description Return ccb pointer based on ccb index.
+**
+**
+** Returns pointer to the ccb, or NULL if none found.
+**
+*******************************************************************************/
+tAVDT_CCB *avdt_ccb_by_idx(UINT8 idx)
+{
+ tAVDT_CCB *p_ccb;
+
+ /* verify index */
+ if (idx < AVDT_NUM_LINKS)
+ {
+ p_ccb = &avdt_cb.ccb[idx];
+ }
+ else
+ {
+ p_ccb = NULL;
+ AVDT_TRACE_WARNING1("No ccb for idx %d", idx);
+ }
+ return p_ccb;
+}
+
diff --git a/stack/avdt/avdt_ccb_act.c b/stack/avdt/avdt_ccb_act.c
new file mode 100644
index 0000000..5719be9
--- /dev/null
+++ b/stack/avdt/avdt_ccb_act.c
@@ -0,0 +1,1108 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2006-2012 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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This module contains the action functions associated with the channel
+ * control block state machine.
+ *
+ ******************************************************************************/
+
+#include <string.h>
+#include "data_types.h"
+#include "bt_target.h"
+#include "avdt_api.h"
+#include "avdtc_api.h"
+#include "avdt_int.h"
+#include "gki.h"
+#include "btu.h"
+#include "btm_api.h"
+
+/*******************************************************************************
+**
+** Function avdt_ccb_clear_ccb
+**
+** Description This function clears out certain buffers, queues, and
+** other data elements of a ccb.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+static void avdt_ccb_clear_ccb(tAVDT_CCB *p_ccb)
+{
+ BT_HDR *p_buf;
+
+ /* clear certain ccb variables */
+ p_ccb->cong = FALSE;
+ p_ccb->ret_count = 0;
+
+ /* free message being fragmented */
+ if (p_ccb->p_curr_msg != NULL)
+ {
+ GKI_freebuf(p_ccb->p_curr_msg);
+ p_ccb->p_curr_msg = NULL;
+ }
+
+ /* free message being reassembled */
+ if (p_ccb->p_rx_msg != NULL)
+ {
+ GKI_freebuf(p_ccb->p_rx_msg);
+ p_ccb->p_rx_msg = NULL;
+ }
+
+ /* clear out response queue */
+ while ((p_buf = (BT_HDR *) GKI_dequeue(&p_ccb->rsp_q)) != NULL)
+ {
+ GKI_freebuf(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function avdt_ccb_chan_open
+**
+** Description This function calls avdt_ad_open_req() to
+** initiate a signaling channel connection.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+void avdt_ccb_chan_open(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
+{
+ BTM_SetOutService(p_ccb->peer_addr, BTM_SEC_SERVICE_AVDTP, AVDT_CHAN_SIG);
+ avdt_ad_open_req(AVDT_CHAN_SIG, p_ccb, NULL, AVDT_INT);
+}
+
+/*******************************************************************************
+**
+** Function avdt_ccb_chan_close
+**
+** Description This function calls avdt_ad_close_req() to close a
+** signaling channel connection.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+void avdt_ccb_chan_close(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
+{
+ /* close the transport channel used by this CCB */
+ avdt_ad_close_req(AVDT_CHAN_SIG, p_ccb, NULL);
+}
+
+/*******************************************************************************
+**
+** Function avdt_ccb_chk_close
+**
+** Description This function checks for active streams on this CCB.
+** If there are none, it starts an idle timer.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+void avdt_ccb_chk_close(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
+{
+ int i;
+ tAVDT_SCB *p_scb = &avdt_cb.scb[0];
+
+ /* see if there are any active scbs associated with this ccb */
+ for (i = 0; i < AVDT_NUM_SEPS; i++, p_scb++)
+ {
+ if ((p_scb->allocated) && (p_scb->p_ccb == p_ccb))
+ {
+ break;
+ }
+ }
+
+ /* if no active scbs start idle timer */
+ if (i == AVDT_NUM_SEPS)
+ {
+ btu_start_timer(&p_ccb->timer_entry, BTU_TTYPE_AVDT_CCB_IDLE, avdt_cb.rcb.idle_tout);
+ }
+}
+
+/*******************************************************************************
+**
+** Function avdt_ccb_hdl_discover_cmd
+**
+** Description This function is called when a discover command is
+** received from the peer. It gathers up the stream
+** information for all allocated streams and initiates
+** sending of a discover response.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+void avdt_ccb_hdl_discover_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
+{
+ tAVDT_SEP_INFO sep_info[AVDT_NUM_SEPS];
+ tAVDT_SCB *p_scb = &avdt_cb.scb[0];
+ int i;
+
+ p_data->msg.discover_rsp.p_sep_info = sep_info;
+ p_data->msg.discover_rsp.num_seps = 0;
+
+ /* for all allocated scbs */
+ for (i = 0; i < AVDT_NUM_SEPS; i++, p_scb++)
+ {
+ if (p_scb->allocated)
+ {
+ /* copy sep info */
+ sep_info[i].in_use = p_scb->in_use;
+ sep_info[i].seid = i + 1;
+ sep_info[i].media_type = p_scb->cs.media_type;
+ sep_info[i].tsep = p_scb->cs.tsep;
+
+ p_data->msg.discover_rsp.num_seps++;
+ }
+ }
+
+ /* send response */
+ avdt_ccb_event(p_ccb, AVDT_CCB_API_DISCOVER_RSP_EVT, p_data);
+}
+
+/*******************************************************************************
+**
+** Function avdt_ccb_hdl_discover_rsp
+**
+** Description This function is called when a discover response or
+** reject is received from the peer. It calls the application
+** callback function with the results.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+void avdt_ccb_hdl_discover_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
+{
+ /* we're done with procedure */
+ p_ccb->proc_busy = FALSE;
+
+ /* call app callback with results */
+ (*p_ccb->proc_cback)(0, p_ccb->peer_addr, AVDT_DISCOVER_CFM_EVT,
+ (tAVDT_CTRL *)(&p_data->msg.discover_rsp));
+}
+
+/*******************************************************************************
+**
+** Function avdt_ccb_hdl_getcap_cmd
+**
+** Description This function is called when a get capabilities command
+** is received from the peer. It retrieves the stream
+** configuration for the requested stream and initiates
+** sending of a get capabilities response.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+void avdt_ccb_hdl_getcap_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
+{
+ tAVDT_SCB *p_scb;
+
+ /* look up scb for seid sent to us */
+ p_scb = avdt_scb_by_hdl(p_data->msg.single.seid);
+
+ p_data->msg.svccap.p_cfg = &p_scb->cs.cfg;
+
+ avdt_ccb_event(p_ccb, AVDT_CCB_API_GETCAP_RSP_EVT, p_data);
+}
+
+/*******************************************************************************
+**
+** Function avdt_ccb_hdl_getcap_rsp
+**
+** Description This function is called with a get capabilities response
+** or reject is received from the peer. It calls the
+** application callback function with the results.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+void avdt_ccb_hdl_getcap_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
+{
+ /* we're done with procedure */
+ p_ccb->proc_busy = FALSE;
+
+ /* call app callback with results */
+ (*p_ccb->proc_cback)(0, p_ccb->peer_addr, AVDT_GETCAP_CFM_EVT,
+ (tAVDT_CTRL *)(&p_data->msg.svccap));
+}
+
+/*******************************************************************************
+**
+** Function avdt_ccb_hdl_start_cmd
+**
+** Description This function is called when a start command is received
+** from the peer. It verifies that all requested streams
+** are in the proper state. If so, it initiates sending of
+** a start response. Otherwise it sends a start reject.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+void avdt_ccb_hdl_start_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
+{
+ UINT8 seid;
+ UINT8 err_code;
+
+ /* verify all streams in the right state */
+ if ((seid = avdt_scb_verify(p_ccb, AVDT_VERIFY_START, p_data->msg.multi.seid_list,
+ p_data->msg.multi.num_seps, &err_code)) == 0)
+ {
+ /* we're ok, send response */
+ avdt_ccb_event(p_ccb, AVDT_CCB_API_START_RSP_EVT, p_data);
+ }
+ else
+ {
+ /* not ok, send reject */
+ p_data->msg.hdr.err_code = err_code;
+ p_data->msg.hdr.err_param = seid;
+ avdt_msg_send_rej(p_ccb, AVDT_SIG_START, &p_data->msg);
+ }
+}
+
+/*******************************************************************************
+**
+** Function avdt_ccb_hdl_start_rsp
+**
+** Description This function is called when a start response or reject
+** is received from the peer. Using the SEIDs stored in the
+** current command message, it sends a start response or start
+** reject event to each SCB associated with the command.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+void avdt_ccb_hdl_start_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
+{
+ UINT8 event;
+ int i;
+ UINT8 *p;
+ tAVDT_SCB *p_scb;
+
+ /* 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;
+
+ /* get to where seid's are stashed in current cmd */
+ p = (UINT8 *)(p_ccb->p_curr_cmd + 1);
+
+ /* little trick here; length of current command equals number of streams */
+ for (i = 0; i < p_ccb->p_curr_cmd->len; i++)
+ {
+ if ((p_scb = avdt_scb_by_hdl(p[i])) != NULL)
+ {
+ avdt_scb_event(p_scb, event, (tAVDT_SCB_EVT *) &p_data->msg);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function avdt_ccb_hdl_suspend_cmd
+**
+** Description This function is called when a suspend command is received
+** from the peer. It verifies that all requested streams are
+** in the proper state. If so, it initiates sending of a
+** suspend response. Otherwise it sends a suspend reject.
+
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+void avdt_ccb_hdl_suspend_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
+{
+ UINT8 seid;
+ UINT8 err_code;
+
+ /* verify all streams in the right state */
+ if ((seid = avdt_scb_verify(p_ccb, AVDT_VERIFY_SUSPEND, p_data->msg.multi.seid_list,
+ p_data->msg.multi.num_seps, &err_code)) == 0)
+ {
+ /* we're ok, send response */
+ avdt_ccb_event(p_ccb, AVDT_CCB_API_SUSPEND_RSP_EVT, p_data);
+ }
+ else
+ {
+ /* not ok, send reject */
+ p_data->msg.hdr.err_code = err_code;
+ p_data->msg.hdr.err_param = seid;
+ avdt_msg_send_rej(p_ccb, AVDT_SIG_SUSPEND, &p_data->msg);
+ }
+}
+
+/*******************************************************************************
+**
+** Function avdt_ccb_hdl_suspend_rsp
+**
+** Description This function is called when a suspend response or reject
+** is received from the peer. Using the SEIDs stored in the
+** current command message, it sends a suspend response or
+** suspend reject event to each SCB associated with the command.
+**
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+void avdt_ccb_hdl_suspend_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
+{
+ UINT8 event;
+ int i;
+ UINT8 *p;
+ tAVDT_SCB *p_scb;
+
+ /* 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;
+
+ /* get to where seid's are stashed in current cmd */
+ p = (UINT8 *)(p_ccb->p_curr_cmd + 1);
+
+ /* little trick here; length of current command equals number of streams */
+ for (i = 0; i < p_ccb->p_curr_cmd->len; i++)
+ {
+ if ((p_scb = avdt_scb_by_hdl(p[i])) != NULL)
+ {
+ avdt_scb_event(p_scb, event, (tAVDT_SCB_EVT *) &p_data->msg);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function avdt_ccb_snd_discover_cmd
+**
+** Description This function is called to send a discover command to the
+** peer. It copies variables needed for the procedure from
+** the event to the CCB. It marks the CCB as busy and then
+** sends a discover command.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+void avdt_ccb_snd_discover_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
+{
+ /* store info in ccb struct */
+ p_ccb->p_proc_data = p_data->discover.p_sep_info;
+ p_ccb->proc_cback = p_data->discover.p_cback;
+ p_ccb->proc_param = p_data->discover.num_seps;
+
+ /* we're busy */
+ p_ccb->proc_busy = TRUE;
+
+ /* build and queue discover req */
+ avdt_msg_send_cmd(p_ccb, NULL, AVDT_SIG_DISCOVER, NULL);
+}
+
+/*******************************************************************************
+**
+** Function avdt_ccb_snd_discover_rsp
+**
+** Description This function is called to send a discover response to
+** the peer. It takes the stream information passed in the
+** event and sends a discover response.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+void avdt_ccb_snd_discover_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
+{
+ /* send response */
+ avdt_msg_send_rsp(p_ccb, AVDT_SIG_DISCOVER, &p_data->msg);
+}
+
+/*******************************************************************************
+**
+** Function avdt_ccb_snd_getcap_cmd
+**
+** Description This function is called to send a get capabilities command
+** to the peer. It copies variables needed for the procedure
+** from the event to the CCB. It marks the CCB as busy and
+** then sends a get capabilities command.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+void avdt_ccb_snd_getcap_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
+{
+ UINT8 sig_id = AVDT_SIG_GETCAP;
+
+ /* store info in ccb struct */
+ p_ccb->p_proc_data = p_data->getcap.p_cfg;
+ p_ccb->proc_cback = p_data->getcap.p_cback;
+
+ /* we're busy */
+ p_ccb->proc_busy = TRUE;
+
+ /* build and queue discover req */
+ if (p_data->msg.hdr.sig_id == AVDT_SIG_GET_ALLCAP)
+ sig_id = AVDT_SIG_GET_ALLCAP;
+
+ avdt_msg_send_cmd(p_ccb, NULL, sig_id, (tAVDT_MSG *) &p_data->getcap.single);
+}
+
+/*******************************************************************************
+**
+** Function avdt_ccb_snd_getcap_rsp
+**
+** Description This function is called to send a get capabilities response
+** to the peer. It takes the stream information passed in the
+** event and sends a get capabilities response.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+void avdt_ccb_snd_getcap_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
+{
+ UINT8 sig_id = AVDT_SIG_GETCAP;
+
+ if (p_data->msg.hdr.sig_id == AVDT_SIG_GET_ALLCAP)
+ sig_id = AVDT_SIG_GET_ALLCAP;
+
+ /* send response */
+ avdt_msg_send_rsp(p_ccb, sig_id, &p_data->msg);
+}
+
+/*******************************************************************************
+**
+** Function avdt_ccb_snd_start_cmd
+**
+** Description This function is called to send a start command to the
+** peer. It verifies that all requested streams are in the
+** proper state. If so, it sends a start command. Otherwise
+** send ourselves back a start reject.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+void avdt_ccb_snd_start_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
+{
+ int i;
+ tAVDT_SCB *p_scb;
+ tAVDT_MSG avdt_msg;
+ UINT8 seid_list[AVDT_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 */
+ avdt_scb_peer_seid_list(&p_data->msg.multi);
+
+ /* send command */
+ avdt_msg_send_cmd(p_ccb, seid_list, AVDT_SIG_START, &p_data->msg);
+ }
+ else
+ {
+ /* failed; send ourselves a reject for each stream */
+ for (i = 0; i < p_data->msg.multi.num_seps; i++)
+ {
+ if ((p_scb = avdt_scb_by_hdl(seid_list[i])) != NULL)
+ {
+ avdt_scb_event(p_scb, AVDT_SCB_MSG_START_REJ_EVT, (tAVDT_SCB_EVT *) &avdt_msg.hdr);
+ }
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function avdt_ccb_snd_start_rsp
+**
+** Description This function is called to send a start response to the
+** peer. It takes the stream information passed in the event
+** and sends a start response. Then it sends a start event
+** to the SCB for each stream.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+void avdt_ccb_snd_start_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
+{
+ tAVDT_SCB *p_scb;
+ int i;
+
+ /* send response message */
+ avdt_msg_send_rsp(p_ccb, AVDT_SIG_START, &p_data->msg);
+
+ /* send start event to each scb */
+ for (i = 0; i < p_data->msg.multi.num_seps; i++)
+ {
+ if ((p_scb = avdt_scb_by_hdl(p_data->msg.multi.seid_list[i])) != NULL)
+ {
+ avdt_scb_event(p_scb, AVDT_SCB_MSG_START_CMD_EVT, NULL);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function avdt_ccb_snd_suspend_cmd
+**
+** Description This function is called to send a suspend command to the
+** peer. It verifies that all requested streams are in the
+** proper state. If so, it sends a suspend command.
+** Otherwise it calls the callback function for each requested
+** stream and sends a suspend confirmation with failure.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+void avdt_ccb_snd_suspend_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
+{
+ int i;
+ tAVDT_SCB *p_scb;
+ tAVDT_MSG avdt_msg;
+ UINT8 seid_list[AVDT_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 */
+ avdt_scb_peer_seid_list(&p_data->msg.multi);
+
+ /* send command */
+ avdt_msg_send_cmd(p_ccb, seid_list, AVDT_SIG_SUSPEND, &p_data->msg);
+ }
+ else
+ {
+ /* failed; send ourselves a reject for each stream */
+ for (i = 0; i < p_data->msg.multi.num_seps; i++)
+ {
+ if ((p_scb = avdt_scb_by_hdl(seid_list[i])) != NULL)
+ {
+ avdt_scb_event(p_scb, AVDT_SCB_MSG_SUSPEND_REJ_EVT, (tAVDT_SCB_EVT *) &avdt_msg.hdr);
+ }
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function avdt_ccb_snd_suspend_rsp
+**
+** Description This function is called to send a suspend response to the
+** peer. It takes the stream information passed in the event
+** and sends a suspend response. Then it sends a suspend event
+** to the SCB for each stream.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+void avdt_ccb_snd_suspend_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
+{
+ tAVDT_SCB *p_scb;
+ int i;
+
+ /* send response message */
+ avdt_msg_send_rsp(p_ccb, AVDT_SIG_SUSPEND, &p_data->msg);
+
+ /* send start event to each scb */
+ for (i = 0; i < p_data->msg.multi.num_seps; i++)
+ {
+ if ((p_scb = avdt_scb_by_hdl(p_data->msg.multi.seid_list[i])) != NULL)
+ {
+ avdt_scb_event(p_scb, AVDT_SCB_MSG_SUSPEND_CMD_EVT, NULL);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function avdt_ccb_clear_cmds
+**
+** Description This function is called when the signaling channel is
+** closed to clean up any pending commands. For each pending
+** command in the command queue, it frees the command and
+** calls the application callback function indicating failure.
+** Certain CCB variables are also initialized.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+void avdt_ccb_clear_cmds(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
+{
+ int i;
+ tAVDT_SCB *p_scb = &avdt_cb.scb[0];
+ UINT8 err_code = AVDT_ERR_CONNECT;
+
+ /* clear the ccb */
+ avdt_ccb_clear_ccb(p_ccb);
+
+ /* clear out command queue; this is a little tricky here; we need
+ ** to handle the case where there is a command on deck in p_curr_cmd,
+ ** plus we need to clear out the queue
+ */
+ do
+ {
+ /* we know p_curr_cmd = NULL after this */
+ avdt_ccb_cmd_fail(p_ccb, (tAVDT_CCB_EVT *) &err_code);
+
+ /* set up next message */
+ p_ccb->p_curr_cmd = (BT_HDR *) GKI_dequeue(&p_ccb->cmd_q);
+
+ } while (p_ccb->p_curr_cmd != NULL);
+
+ /* send a CC_CLOSE_EVT any active scbs associated with this ccb */
+ for (i = 0; i < AVDT_NUM_SEPS; i++, p_scb++)
+ {
+ if ((p_scb->allocated) && (p_scb->p_ccb == p_ccb))
+ {
+ avdt_scb_event(p_scb, AVDT_SCB_CC_CLOSE_EVT, NULL);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function avdt_ccb_cmd_fail
+**
+** Description This function is called when there is a response timeout.
+** The currently pending command is freed and we fake a
+** reject message back to ourselves.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+void avdt_ccb_cmd_fail(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
+{
+ tAVDT_MSG msg;
+ UINT8 evt;
+ tAVDT_SCB *p_scb;
+
+ if (p_ccb->p_curr_cmd != NULL)
+ {
+ /* set up data */
+ msg.hdr.err_code = p_data->err_code;
+ msg.hdr.err_param = 0;
+ msg.hdr.ccb_idx = avdt_ccb_to_idx(p_ccb);
+
+ /* pretend that we received a rej message */
+ evt = avdt_msg_rej_2_evt[p_ccb->p_curr_cmd->event - 1];
+
+ if (evt & AVDT_CCB_MKR)
+ {
+ avdt_ccb_event(p_ccb, (UINT8) (evt & ~AVDT_CCB_MKR), (tAVDT_CCB_EVT *) &msg);
+ }
+ else
+ {
+ /* we get the scb out of the current cmd */
+ p_scb = avdt_scb_by_hdl(*((UINT8 *)(p_ccb->p_curr_cmd + 1)));
+ if (p_scb != NULL)
+ {
+ avdt_scb_event(p_scb, evt, (tAVDT_SCB_EVT *) &msg);
+ }
+ }
+
+ GKI_freebuf(p_ccb->p_curr_cmd);
+ p_ccb->p_curr_cmd = NULL;
+ }
+}
+
+/*******************************************************************************
+**
+** Function avdt_ccb_free_cmd
+**
+** Description This function is called when a response is received for a
+** currently pending command. The command is freed.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+void avdt_ccb_free_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
+{
+ if (p_ccb->p_curr_cmd != NULL)
+ {
+ GKI_freebuf(p_ccb->p_curr_cmd);
+ p_ccb->p_curr_cmd = NULL;
+ }
+}
+
+/*******************************************************************************
+**
+** Function avdt_ccb_cong_state
+**
+** Description This function is called to set the congestion state for
+** the CCB.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+void avdt_ccb_cong_state(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
+{
+ p_ccb->cong = p_data->llcong;
+}
+
+/*******************************************************************************
+**
+** Function avdt_ccb_ret_cmd
+**
+** Description This function is called to retransmit the currently
+** pending command. The retransmission count is incremented.
+** If the count reaches the maximum number of retransmissions,
+** the event is treated as a response timeout.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+void avdt_ccb_ret_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
+{
+ UINT8 err_code = AVDT_ERR_TIMEOUT;
+ BT_HDR *p_msg;
+
+ p_ccb->ret_count++;
+ if (p_ccb->ret_count == AVDT_RET_MAX)
+ {
+ /* command failed */
+ p_ccb->ret_count = 0;
+ avdt_ccb_cmd_fail(p_ccb, (tAVDT_CCB_EVT *) &err_code);
+
+ /* go to next queued command */
+ avdt_ccb_snd_cmd(p_ccb, p_data);
+ }
+ else
+ {
+ /* if command pending and we're not congested and not sending a fragment */
+ if ((!p_ccb->cong) && (p_ccb->p_curr_msg == NULL) && (p_ccb->p_curr_cmd != NULL))
+ {
+ /* make copy of message in p_curr_cmd and send it */
+ if ((p_msg = (BT_HDR *) GKI_getpoolbuf(AVDT_CMD_POOL_ID)) != NULL)
+ {
+ memcpy(p_msg, p_ccb->p_curr_cmd,
+ (sizeof(BT_HDR) + p_ccb->p_curr_cmd->offset + p_ccb->p_curr_cmd->len));
+ avdt_msg_send(p_ccb, p_msg);
+ }
+ }
+
+ /* restart timer */
+ btu_start_timer(&p_ccb->timer_entry, BTU_TTYPE_AVDT_CCB_RET, avdt_cb.rcb.ret_tout);
+ }
+}
+
+/*******************************************************************************
+**
+** Function avdt_ccb_snd_cmd
+**
+** Description This function is called the send the next command,
+** if any, in the command queue.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+void avdt_ccb_snd_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
+{
+ BT_HDR *p_msg;
+
+ /* do we have commands to send? send next command; make sure we're clear;
+ ** not congested, not sending fragment, not waiting for response
+ */
+ if ((!p_ccb->cong) && (p_ccb->p_curr_msg == NULL) && (p_ccb->p_curr_cmd == NULL))
+ {
+ if ((p_msg = (BT_HDR *) GKI_dequeue(&p_ccb->cmd_q)) != NULL)
+ {
+ /* make a copy of buffer in p_curr_cmd */
+ if ((p_ccb->p_curr_cmd = (BT_HDR *) GKI_getpoolbuf(AVDT_CMD_POOL_ID)) != NULL)
+ {
+ memcpy(p_ccb->p_curr_cmd, p_msg, (sizeof(BT_HDR) + p_msg->offset + p_msg->len));
+
+ avdt_msg_send(p_ccb, p_msg);
+ }
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function avdt_ccb_snd_msg
+**
+** Description
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+void avdt_ccb_snd_msg(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
+{
+ BT_HDR *p_msg;
+
+ /* if not congested */
+ if (!p_ccb->cong)
+ {
+ /* are we sending a fragmented message? continue sending fragment */
+ if (p_ccb->p_curr_msg != NULL)
+ {
+ avdt_msg_send(p_ccb, NULL);
+ }
+ /* do we have responses to send? send them */
+ else if (!GKI_queue_is_empty(&p_ccb->rsp_q))
+ {
+ while ((p_msg = (BT_HDR *) GKI_dequeue(&p_ccb->rsp_q)) != NULL)
+ {
+ if (avdt_msg_send(p_ccb, p_msg) == TRUE)
+ {
+ /* break out if congested */
+ break;
+ }
+ }
+ }
+
+ /* do we have commands to send? send next command */
+ avdt_ccb_snd_cmd(p_ccb, NULL);
+ }
+}
+
+/*******************************************************************************
+**
+** Function avdt_ccb_set_reconn
+**
+** Description This function is called to enable a reconnect attempt when
+** a channel transitions from closing to idle state. It sets
+** the reconn variable to TRUE.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+void avdt_ccb_set_reconn(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
+{
+ p_ccb->reconn = TRUE;
+}
+
+/*******************************************************************************
+**
+** Function avdt_ccb_clr_reconn
+**
+** Description This function is called to clear the reconn variable.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+void avdt_ccb_clr_reconn(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
+{
+ p_ccb->reconn = FALSE;
+}
+
+/*******************************************************************************
+**
+** Function avdt_ccb_chk_reconn
+**
+** Description This function is called to check if a reconnect attempt
+** is enabled. If enabled, it sends an AVDT_CCB_UL_OPEN_EVT
+** to the CCB. If disabled, the CCB is deallocated.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+void avdt_ccb_chk_reconn(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
+{
+ UINT8 err_code = AVDT_ERR_CONNECT;
+
+ if (p_ccb->reconn)
+ {
+ p_ccb->reconn = FALSE;
+
+ /* clear out ccb */
+ avdt_ccb_clear_ccb(p_ccb);
+
+ /* clear out current command, if any */
+ avdt_ccb_cmd_fail(p_ccb, (tAVDT_CCB_EVT *) &err_code);
+
+ /* reopen the signaling channel */
+ avdt_ccb_event(p_ccb, AVDT_CCB_UL_OPEN_EVT, NULL);
+ }
+ else
+ {
+ avdt_ccb_ll_closed(p_ccb, NULL);
+ }
+}
+
+/*******************************************************************************
+**
+** Function avdt_ccb_chk_timer
+**
+** Description This function stops the CCB timer if the idle timer is
+** running.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+void avdt_ccb_chk_timer(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
+{
+ if (p_ccb->timer_entry.event == BTU_TTYPE_AVDT_CCB_IDLE)
+ {
+ btu_stop_timer(&p_ccb->timer_entry);
+ }
+}
+
+/*******************************************************************************
+**
+** Function avdt_ccb_set_conn
+**
+** Description Set CCB variables associated with AVDT_ConnectReq().
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+void avdt_ccb_set_conn(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
+{
+ /* save callback */
+ p_ccb->p_conn_cback = p_data->connect.p_cback;
+
+ /* set security level */
+ BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_AVDTP, p_data->connect.sec_mask,
+ AVDT_PSM, BTM_SEC_PROTO_AVDT, AVDT_CHAN_SIG);
+}
+
+/*******************************************************************************
+**
+** Function avdt_ccb_set_disconn
+**
+** Description Set CCB variables associated with AVDT_DisconnectReq().
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+void avdt_ccb_set_disconn(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
+{
+ /*
+ AVDT_TRACE_EVENT2("avdt_ccb_set_disconn:conn:x%x, api:x%x",
+ p_ccb->p_conn_cback, p_data->disconnect.p_cback);
+ */
+ /* save callback */
+ if (p_data->disconnect.p_cback)
+ p_ccb->p_conn_cback = p_data->disconnect.p_cback;
+}
+
+/*******************************************************************************
+**
+** Function avdt_ccb_do_disconn
+**
+** Description Do action associated with AVDT_DisconnectReq().
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+void avdt_ccb_do_disconn(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
+{
+ /* clear any pending commands */
+ avdt_ccb_clear_cmds(p_ccb, NULL);
+
+ /* close channel */
+ avdt_ccb_chan_close(p_ccb, NULL);
+}
+
+/*******************************************************************************
+**
+** Function avdt_ccb_ll_closed
+**
+** Description Clear commands from and deallocate CCB.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+void avdt_ccb_ll_closed(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
+{
+ tAVDT_CTRL_CBACK *p_cback;
+ BD_ADDR bd_addr;
+ tAVDT_CTRL avdt_ctrl;
+
+ /* clear any pending commands */
+ avdt_ccb_clear_cmds(p_ccb, NULL);
+
+ /* save callback pointer, bd addr */
+ p_cback = p_ccb->p_conn_cback;
+ if (!p_cback)
+ p_cback = avdt_cb.p_conn_cback;
+ memcpy(bd_addr, p_ccb->peer_addr, BD_ADDR_LEN);
+
+ /* dealloc ccb */
+ avdt_ccb_dealloc(p_ccb, NULL);
+
+ /* call callback */
+ if (p_cback)
+ {
+ avdt_ctrl.hdr.err_code = 0;
+ (*p_cback)(0, bd_addr, AVDT_DISCONNECT_IND_EVT, &avdt_ctrl);
+ }
+}
+
+/*******************************************************************************
+**
+** Function avdt_ccb_ll_opened
+**
+** Description Call callback on open.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+void avdt_ccb_ll_opened(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
+{
+ tAVDT_CTRL avdt_ctrl;
+
+ p_ccb->ll_opened = TRUE;
+
+ if (!p_ccb->p_conn_cback)
+ p_ccb->p_conn_cback = avdt_cb.p_conn_cback;
+
+ /* 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;
+ (*p_ccb->p_conn_cback)(0, p_ccb->peer_addr, AVDT_CONNECT_IND_EVT, &avdt_ctrl);
+ }
+}
diff --git a/stack/avdt/avdt_defs.h b/stack/avdt/avdt_defs.h
new file mode 100644
index 0000000..b6dbbc4
--- /dev/null
+++ b/stack/avdt/avdt_defs.h
@@ -0,0 +1,203 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2002-2012 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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This contains constants definitions and other information from the AVDTP
+ * specification. This file is intended for use internal to AVDT only.
+ *
+ ******************************************************************************/
+#ifndef AVDT_DEFS_H
+#define AVDT_DEFS_H
+
+/*****************************************************************************
+** constants
+*****************************************************************************/
+
+/* signalling packet type */
+#define AVDT_PKT_TYPE_SINGLE 0 /* single packet */
+#define AVDT_PKT_TYPE_START 1 /* start packet */
+#define AVDT_PKT_TYPE_CONT 2 /* continue packet */
+#define AVDT_PKT_TYPE_END 3 /* end packet */
+
+/* signalling message type */
+#define AVDT_MSG_TYPE_CMD 0 /* command */
+#define AVDT_MSG_TYPE_GRJ 1 /* general reject */
+#define AVDT_MSG_TYPE_RSP 2 /* response accept */
+#define AVDT_MSG_TYPE_REJ 3 /* response reject */
+
+/* signalling messages */
+#define AVDT_SIG_DISCOVER 1 /* discover */
+#define AVDT_SIG_GETCAP 2 /* get capabilities */
+#define AVDT_SIG_SETCONFIG 3 /* set configuration */
+#define AVDT_SIG_GETCONFIG 4 /* get configuration */
+#define AVDT_SIG_RECONFIG 5 /* reconfigure */
+#define AVDT_SIG_OPEN 6 /* open */
+#define AVDT_SIG_START 7 /* start */
+#define AVDT_SIG_CLOSE 8 /* close */
+#define AVDT_SIG_SUSPEND 9 /* suspend */
+#define AVDT_SIG_ABORT 10 /* abort */
+#define AVDT_SIG_SECURITY 11 /* security control */
+#define AVDT_SIG_GET_ALLCAP 12 /* get all capabilities */
+#define AVDT_SIG_DELAY_RPT 13 /* delay report */
+
+/* maximum signal value */
+#define AVDT_SIG_MAX AVDT_SIG_DELAY_RPT
+
+/* used for general reject */
+#define AVDT_SIG_NONE 0
+
+/* some maximum and minimum sizes of signalling messages */
+#define AVDT_DISCOVER_REQ_MIN 1
+#define AVDT_DISCOVER_REQ_MAX 124
+
+/* service category information element field values */
+#define AVDT_CAT_TRANS 1 /* Media Transport */
+#define AVDT_CAT_REPORT 2 /* Reporting */
+#define AVDT_CAT_RECOV 3 /* Recovery */
+#define AVDT_CAT_PROTECT 4 /* Content Protection */
+#define AVDT_CAT_HDRCMP 5 /* Header Compression */
+#define AVDT_CAT_MUX 6 /* Multiplexing */
+#define AVDT_CAT_CODEC 7 /* Media Codec */
+#define AVDT_CAT_DELAY_RPT 8 /* Delay Reporting */
+#define AVDT_CAT_MAX_CUR AVDT_CAT_DELAY_RPT
+
+/* min/max lengths of service category information elements */
+#define AVDT_LEN_TRANS_MIN 0
+#define AVDT_LEN_REPORT_MIN 0
+#define AVDT_LEN_RECOV_MIN 3
+#define AVDT_LEN_PROTECT_MIN 2
+#define AVDT_LEN_HDRCMP_MIN 1
+#define AVDT_LEN_MUX_MIN 3
+#define AVDT_LEN_CODEC_MIN 2
+#define AVDT_LEN_DELAY_RPT_MIN 0
+
+#define AVDT_LEN_TRANS_MAX 0
+#define AVDT_LEN_REPORT_MAX 0
+#define AVDT_LEN_RECOV_MAX 3
+#define AVDT_LEN_PROTECT_MAX 255
+#define AVDT_LEN_HDRCMP_MAX 1
+#define AVDT_LEN_MUX_MAX 7
+#define AVDT_LEN_CODEC_MAX 255
+#define AVDT_LEN_DELAY_RPT_MAX 0
+
+/* minimum possible size of configuration or capabilities data */
+#define AVDT_LEN_CFG_MIN 2
+
+/* minimum and maximum lengths for different message types */
+#define AVDT_LEN_SINGLE 1
+#define AVDT_LEN_SETCONFIG_MIN 2
+#define AVDT_LEN_RECONFIG_MIN 1
+#define AVDT_LEN_MULTI_MIN 1
+#define AVDT_LEN_SECURITY_MIN 1
+#define AVDT_LEN_DELAY_RPT 3
+
+/* header lengths for different packet types */
+#define AVDT_LEN_TYPE_SINGLE 2 /* single packet */
+#define AVDT_LEN_TYPE_START 3 /* start packet */
+#define AVDT_LEN_TYPE_CONT 1 /* continue packet */
+#define AVDT_LEN_TYPE_END 1 /* end packet */
+
+/* length of general reject message */
+#define AVDT_LEN_GEN_REJ 2
+
+/* recovery service capabilities information elements */
+#define AVDT_RECOV_MRWS_MIN 0x01 /* min value for maximum recovery window */
+#define AVDT_RECOV_MRWS_MAX 0x18 /* max value for maximum recovery window */
+#define AVDT_RECOV_MNMP_MIN 0x01 /* min value for maximum number of media packets */
+#define AVDT_RECOV_MNMP_MAX 0x18 /* max value for maximum number of media packets */
+
+/* SEID value range */
+#define AVDT_SEID_MIN 0x01
+#define AVDT_SEID_MAX 0x3E
+
+/* first byte of media packet header */
+#define AVDT_MEDIA_OCTET1 0x80
+
+/* for adaptation layer header */
+#define AVDT_ALH_LCODE_MASK 0x03 /* coding of length field */
+#define AVDT_ALH_LCODE_NONE 0x00 /* No length field present. Take length from l2cap */
+#define AVDT_ALH_LCODE_16BIT 0x01 /* 16bit length field */
+#define AVDT_ALH_LCODE_9BITM0 0x02 /* 9 bit length field, MSB = 0, 8 LSBs in 1 octet following */
+#define AVDT_ALH_LCODE_9BITM1 0x03 /* 9 bit length field, MSB = 1, 8 LSBs in 1 octet following */
+
+#define AVDT_ALH_FRAG_MASK 0x04 /* set this for continuation packet */
+
+/*****************************************************************************
+** message parsing and building macros
+*****************************************************************************/
+
+#define AVDT_MSG_PRS_HDR(p, lbl, pkt, msg) \
+ lbl = *(p) >> 4; \
+ pkt = (*(p) >> 2) & 0x03; \
+ msg = *(p)++ & 0x03;
+
+#define AVDT_MSG_PRS_DISC(p, seid, in_use, type, tsep) \
+ seid = *(p) >> 2; \
+ in_use = (*(p)++ >> 1) & 0x01; \
+ type = *(p) >> 4; \
+ tsep = (*(p)++ >> 3) & 0x01;
+
+#define AVDT_MSG_PRS_SIG(p, sig) \
+ sig = *(p)++ & 0x3F;
+
+#define AVDT_MSG_PRS_SEID(p, seid) \
+ seid = *(p)++ >> 2;
+
+#define AVDT_MSG_PRS_PKT_TYPE(p, pkt) \
+ pkt = (*(p) >> 2) & 0x03;
+
+#define AVDT_MSG_PRS_OCTET1(p, o_v, o_p, o_x, o_cc) \
+ o_v = *(p) >> 6; \
+ o_p = (*(p) >> 5) & 0x01; \
+ o_x = (*(p) >> 4) & 0x01; \
+ o_cc = *(p)++ & 0x0F;
+
+#define AVDT_MSG_PRS_RPT_OCTET1(p, o_v, o_p, o_cc) \
+ o_v = *(p) >> 6; \
+ o_p = (*(p) >> 5) & 0x01; \
+ o_cc = *(p)++ & 0x1F;
+
+#define AVDT_MSG_PRS_M_PT(p, m_pt, marker) \
+ marker = *(p) >> 7; \
+ m_pt = *(p)++ & 0x7F;
+
+#define AVDT_MSG_BLD_HDR(p, lbl, pkt, msg) \
+ *(p)++ = (UINT8) ((lbl) << 4) | ((pkt) << 2) | (msg);
+
+#define AVDT_MSG_BLD_DISC(p, seid, in_use, type, tsep) \
+ *(p)++ = (UINT8) (((seid) << 2) | ((in_use) << 1)); \
+ *(p)++ = (UINT8) (((type) << 4) | ((tsep) << 3));
+
+#define AVDT_MSG_BLD_SIG(p, sig) \
+ *(p)++ = (UINT8) (sig);
+
+#define AVDT_MSG_BLD_SEID(p, seid) \
+ *(p)++ = (UINT8) ((seid) << 2);
+
+#define AVDT_MSG_BLD_ERR(p, err) \
+ *(p)++ = (UINT8) (err);
+
+#define AVDT_MSG_BLD_PARAM(p, param) \
+ *(p)++ = (UINT8) (param);
+
+#define AVDT_MSG_BLD_NOSP(p, nosp) \
+ *(p)++ = (UINT8) (nosp);
+
+#endif /* AVDT_DEFS_H */
+
diff --git a/stack/avdt/avdt_int.h b/stack/avdt/avdt_int.h
new file mode 100644
index 0000000..9b101fc
--- /dev/null
+++ b/stack/avdt/avdt_int.h
@@ -0,0 +1,744 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2002-2012 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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This file contains interfaces which are internal to AVDTP.
+ *
+ ******************************************************************************/
+#ifndef AVDT_INT_H
+#define AVDT_INT_H
+
+#include "gki.h"
+#include "avdt_api.h"
+#include "avdtc_api.h"
+#include "avdt_defs.h"
+#include "l2c_api.h"
+#include "btm_api.h"
+
+#ifndef AVDT_DEBUG
+#if (!defined BTTRC_INCLUDED || BTTRC_INCLUDED == FALSE)
+#define AVDT_DEBUG TRUE
+#else
+#define AVDT_DEBUG FALSE
+#endif
+#endif
+
+/*****************************************************************************
+** constants
+*****************************************************************************/
+
+/* channel types */
+enum {
+ AVDT_CHAN_SIG, /* signaling channel */
+ AVDT_CHAN_MEDIA, /* media channel */
+#if AVDT_REPORTING == TRUE
+ AVDT_CHAN_REPORT, /* reporting channel */
+#endif
+ AVDT_CHAN_NUM_TYPES
+};
+
+/* protocol service capabilities of this AVDTP implementation */
+/* for now multiplexing will be used only for fragmentation */
+#if ((AVDT_MULTIPLEXING == TRUE) && (AVDT_REPORTING == TRUE))
+#define AVDT_PSC (AVDT_PSC_TRANS | AVDT_PSC_MUX | AVDT_PSC_REPORT | AVDT_PSC_DELAY_RPT)
+#define AVDT_LEG_PSC (AVDT_PSC_TRANS | AVDT_PSC_MUX | AVDT_PSC_REPORT)
+#else /* AVDT_MULTIPLEXING && AVDT_REPORTING */
+
+#if (AVDT_MULTIPLEXING == TRUE)
+#define AVDT_PSC (AVDT_PSC_TRANS | AVDT_PSC_MUX | AVDT_PSC_DELAY_RPT)
+#define AVDT_LEG_PSC (AVDT_PSC_TRANS | AVDT_PSC_MUX)
+#else /* AVDT_MULTIPLEXING */
+
+#if (AVDT_REPORTING == TRUE)
+#define AVDT_PSC (AVDT_PSC_TRANS | AVDT_PSC_REPORT | AVDT_PSC_DELAY_RPT)
+#define AVDT_LEG_PSC (AVDT_PSC_TRANS | AVDT_PSC_REPORT)
+#else /* AVDT_REPORTING */
+#define AVDT_PSC (AVDT_PSC_TRANS | AVDT_PSC_DELAY_RPT)
+#define AVDT_LEG_PSC (AVDT_PSC_TRANS)
+#endif /* AVDT_REPORTING */
+
+#endif /* AVDT_MULTIPLEXING */
+
+#endif /* AVDT_MULTIPLEXING && AVDT_REPORTING */
+
+/* initiator/acceptor signaling roles */
+#define AVDT_CLOSE_ACP 0
+#define AVDT_CLOSE_INT 1
+#define AVDT_OPEN_ACP 2
+#define AVDT_OPEN_INT 3
+
+/* states for avdt_scb_verify */
+#define AVDT_VERIFY_OPEN 0
+#define AVDT_VERIFY_STREAMING 1
+#define AVDT_VERIFY_SUSPEND 2
+#define AVDT_VERIFY_START 3
+
+/* to distinguish CCB events from SCB events */
+#define AVDT_CCB_MKR 0x80
+
+/* offset where AVDTP signaling message header starts in message */
+#define AVDT_HDR_OFFSET (L2CAP_MIN_OFFSET + AVDT_NUM_SEPS)
+
+/* offset where AVDTP signaling message content starts;
+** use the size of a start header since it's the largest possible
+** layout of signaling message in a buffer is:
+**
+** | BT_HDR | SCB handles | L2CAP + HCI header | AVDTP header | data ... |
+**
+** Note that we "hide" the scb handles at the top of the message buffer.
+*/
+#define AVDT_MSG_OFFSET (L2CAP_MIN_OFFSET + AVDT_NUM_SEPS + AVDT_LEN_TYPE_START)
+
+/* scb transport channel connect timeout value */
+#define AVDT_SCB_TC_CONN_TOUT 10
+
+/* scb transport channel disconnect timeout value */
+#define AVDT_SCB_TC_DISC_TOUT 10
+
+/* maximum number of command retransmissions */
+#ifndef AVDT_RET_MAX
+#define AVDT_RET_MAX 1
+#endif
+
+
+/* ccb state machine states */
+enum {
+ AVDT_CCB_IDLE_ST,
+ AVDT_CCB_OPENING_ST,
+ AVDT_CCB_OPEN_ST,
+ AVDT_CCB_CLOSING_ST
+};
+
+/* state machine action enumeration list */
+enum {
+ AVDT_CCB_CHAN_OPEN,
+ AVDT_CCB_CHAN_CLOSE,
+ AVDT_CCB_CHK_CLOSE,
+ AVDT_CCB_HDL_DISCOVER_CMD,
+ AVDT_CCB_HDL_DISCOVER_RSP,
+ AVDT_CCB_HDL_GETCAP_CMD,
+ AVDT_CCB_HDL_GETCAP_RSP,
+ AVDT_CCB_HDL_START_CMD,
+ AVDT_CCB_HDL_START_RSP,
+ AVDT_CCB_HDL_SUSPEND_CMD,
+ AVDT_CCB_HDL_SUSPEND_RSP,
+ AVDT_CCB_SND_DISCOVER_CMD,
+ AVDT_CCB_SND_DISCOVER_RSP,
+ AVDT_CCB_SND_GETCAP_CMD,
+ AVDT_CCB_SND_GETCAP_RSP,
+ AVDT_CCB_SND_START_CMD,
+ AVDT_CCB_SND_START_RSP,
+ AVDT_CCB_SND_SUSPEND_CMD,
+ AVDT_CCB_SND_SUSPEND_RSP,
+ AVDT_CCB_CLEAR_CMDS,
+ AVDT_CCB_CMD_FAIL,
+ AVDT_CCB_FREE_CMD,
+ AVDT_CCB_CONG_STATE,
+ AVDT_CCB_RET_CMD,
+ AVDT_CCB_SND_CMD,
+ AVDT_CCB_SND_MSG,
+ AVDT_CCB_SET_RECONN,
+ AVDT_CCB_CLR_RECONN,
+ AVDT_CCB_CHK_RECONN,
+ AVDT_CCB_CHK_TIMER,
+ AVDT_CCB_SET_CONN,
+ AVDT_CCB_SET_DISCONN,
+ AVDT_CCB_DO_DISCONN,
+ AVDT_CCB_LL_CLOSED,
+ AVDT_CCB_LL_OPENED,
+ AVDT_CCB_DEALLOC,
+ AVDT_CCB_NUM_ACTIONS
+};
+
+#define AVDT_CCB_IGNORE AVDT_CCB_NUM_ACTIONS
+
+/* ccb state machine events */
+enum {
+ AVDT_CCB_API_DISCOVER_REQ_EVT,
+ AVDT_CCB_API_GETCAP_REQ_EVT,
+ AVDT_CCB_API_START_REQ_EVT,
+ AVDT_CCB_API_SUSPEND_REQ_EVT,
+ AVDT_CCB_API_DISCOVER_RSP_EVT,
+ AVDT_CCB_API_GETCAP_RSP_EVT,
+ AVDT_CCB_API_START_RSP_EVT,
+ AVDT_CCB_API_SUSPEND_RSP_EVT,
+ AVDT_CCB_API_CONNECT_REQ_EVT,
+ AVDT_CCB_API_DISCONNECT_REQ_EVT,
+ AVDT_CCB_MSG_DISCOVER_CMD_EVT,
+ AVDT_CCB_MSG_GETCAP_CMD_EVT,
+ AVDT_CCB_MSG_START_CMD_EVT,
+ AVDT_CCB_MSG_SUSPEND_CMD_EVT,
+ AVDT_CCB_MSG_DISCOVER_RSP_EVT,
+ AVDT_CCB_MSG_GETCAP_RSP_EVT,
+ AVDT_CCB_MSG_START_RSP_EVT,
+ AVDT_CCB_MSG_SUSPEND_RSP_EVT,
+ AVDT_CCB_RCVRSP_EVT,
+ AVDT_CCB_SENDMSG_EVT,
+ AVDT_CCB_RET_TOUT_EVT,
+ AVDT_CCB_RSP_TOUT_EVT,
+ AVDT_CCB_IDLE_TOUT_EVT,
+ AVDT_CCB_UL_OPEN_EVT,
+ AVDT_CCB_UL_CLOSE_EVT,
+ AVDT_CCB_LL_OPEN_EVT,
+ AVDT_CCB_LL_CLOSE_EVT,
+ AVDT_CCB_LL_CONG_EVT
+};
+
+
+/* scb state machine states; these state values are private to this module so
+** the scb state cannot be read or set by actions functions
+*/
+enum {
+ AVDT_SCB_IDLE_ST,
+ AVDT_SCB_CONF_ST,
+ AVDT_SCB_OPENING_ST,
+ AVDT_SCB_OPEN_ST,
+ AVDT_SCB_STREAM_ST,
+ AVDT_SCB_CLOSING_ST
+};
+
+/* state machine action enumeration list */
+enum {
+ AVDT_SCB_HDL_ABORT_CMD,
+ AVDT_SCB_HDL_ABORT_RSP,
+ AVDT_SCB_HDL_CLOSE_CMD,
+ AVDT_SCB_HDL_CLOSE_RSP,
+ AVDT_SCB_HDL_GETCONFIG_CMD,
+ AVDT_SCB_HDL_GETCONFIG_RSP,
+ AVDT_SCB_HDL_OPEN_CMD,
+ AVDT_SCB_HDL_OPEN_REJ,
+ AVDT_SCB_HDL_OPEN_RSP,
+ AVDT_SCB_HDL_PKT,
+ AVDT_SCB_DROP_PKT,
+ AVDT_SCB_HDL_RECONFIG_CMD,
+ AVDT_SCB_HDL_RECONFIG_RSP,
+ AVDT_SCB_HDL_SECURITY_CMD,
+ AVDT_SCB_HDL_SECURITY_RSP,
+ AVDT_SCB_HDL_SETCONFIG_CMD,
+ AVDT_SCB_HDL_SETCONFIG_REJ,
+ AVDT_SCB_HDL_SETCONFIG_RSP,
+ AVDT_SCB_HDL_START_CMD,
+ AVDT_SCB_HDL_START_RSP,
+ AVDT_SCB_HDL_SUSPEND_CMD,
+ AVDT_SCB_HDL_SUSPEND_RSP,
+ AVDT_SCB_HDL_TC_CLOSE,
+#if AVDT_REPORTING == TRUE
+ AVDT_SCB_HDL_TC_CLOSE_STO,
+#endif
+ AVDT_SCB_HDL_TC_OPEN,
+#if AVDT_REPORTING == TRUE
+ AVDT_SCB_HDL_TC_OPEN_STO,
+#endif
+ AVDT_SCB_SND_DELAY_RPT_REQ,
+ AVDT_SCB_HDL_DELAY_RPT_CMD,
+ AVDT_SCB_HDL_DELAY_RPT_RSP,
+ AVDT_SCB_HDL_WRITE_REQ,
+ AVDT_SCB_SND_ABORT_REQ,
+ AVDT_SCB_SND_ABORT_RSP,
+ AVDT_SCB_SND_CLOSE_REQ,
+ AVDT_SCB_SND_STREAM_CLOSE,
+ AVDT_SCB_SND_CLOSE_RSP,
+ AVDT_SCB_SND_GETCONFIG_REQ,
+ AVDT_SCB_SND_GETCONFIG_RSP,
+ AVDT_SCB_SND_OPEN_REQ,
+ AVDT_SCB_SND_OPEN_RSP,
+ AVDT_SCB_SND_RECONFIG_REQ,
+ AVDT_SCB_SND_RECONFIG_RSP,
+ AVDT_SCB_SND_SECURITY_REQ,
+ AVDT_SCB_SND_SECURITY_RSP,
+ AVDT_SCB_SND_SETCONFIG_REQ,
+ AVDT_SCB_SND_SETCONFIG_REJ,
+ AVDT_SCB_SND_SETCONFIG_RSP,
+ AVDT_SCB_SND_TC_CLOSE,
+ AVDT_SCB_CB_ERR,
+ AVDT_SCB_CONG_STATE,
+ AVDT_SCB_REJ_STATE,
+ AVDT_SCB_REJ_IN_USE,
+ AVDT_SCB_REJ_NOT_IN_USE,
+ AVDT_SCB_SET_REMOVE,
+ AVDT_SCB_FREE_PKT,
+ AVDT_SCB_CLR_PKT,
+ AVDT_SCB_CHK_SND_PKT,
+ AVDT_SCB_TC_TIMER,
+ AVDT_SCB_CLR_VARS,
+ AVDT_SCB_DEALLOC,
+ AVDT_SCB_NUM_ACTIONS
+};
+
+#define AVDT_SCB_IGNORE AVDT_SCB_NUM_ACTIONS
+
+/* scb state machine events */
+enum {
+ AVDT_SCB_API_REMOVE_EVT,
+ AVDT_SCB_API_WRITE_REQ_EVT,
+ AVDT_SCB_API_GETCONFIG_REQ_EVT,
+ AVDT_SCB_API_DELAY_RPT_REQ_EVT,
+ AVDT_SCB_API_SETCONFIG_REQ_EVT,
+ AVDT_SCB_API_OPEN_REQ_EVT,
+ AVDT_SCB_API_CLOSE_REQ_EVT,
+ AVDT_SCB_API_RECONFIG_REQ_EVT,
+ AVDT_SCB_API_SECURITY_REQ_EVT,
+ AVDT_SCB_API_ABORT_REQ_EVT,
+ AVDT_SCB_API_GETCONFIG_RSP_EVT,
+ AVDT_SCB_API_SETCONFIG_RSP_EVT,
+ AVDT_SCB_API_SETCONFIG_REJ_EVT,
+ AVDT_SCB_API_OPEN_RSP_EVT,
+ AVDT_SCB_API_CLOSE_RSP_EVT,
+ AVDT_SCB_API_RECONFIG_RSP_EVT,
+ AVDT_SCB_API_SECURITY_RSP_EVT,
+ AVDT_SCB_API_ABORT_RSP_EVT,
+ AVDT_SCB_MSG_SETCONFIG_CMD_EVT,
+ AVDT_SCB_MSG_GETCONFIG_CMD_EVT,
+ AVDT_SCB_MSG_OPEN_CMD_EVT,
+ AVDT_SCB_MSG_START_CMD_EVT,
+ AVDT_SCB_MSG_SUSPEND_CMD_EVT,
+ AVDT_SCB_MSG_CLOSE_CMD_EVT,
+ AVDT_SCB_MSG_ABORT_CMD_EVT,
+ AVDT_SCB_MSG_RECONFIG_CMD_EVT,
+ AVDT_SCB_MSG_SECURITY_CMD_EVT,
+ AVDT_SCB_MSG_DELAY_RPT_CMD_EVT,
+ AVDT_SCB_MSG_DELAY_RPT_RSP_EVT,
+ AVDT_SCB_MSG_SETCONFIG_RSP_EVT,
+ AVDT_SCB_MSG_GETCONFIG_RSP_EVT,
+ AVDT_SCB_MSG_OPEN_RSP_EVT,
+ AVDT_SCB_MSG_START_RSP_EVT,
+ AVDT_SCB_MSG_SUSPEND_RSP_EVT,
+ AVDT_SCB_MSG_CLOSE_RSP_EVT,
+ AVDT_SCB_MSG_ABORT_RSP_EVT,
+ AVDT_SCB_MSG_RECONFIG_RSP_EVT,
+ AVDT_SCB_MSG_SECURITY_RSP_EVT,
+ AVDT_SCB_MSG_SETCONFIG_REJ_EVT,
+ AVDT_SCB_MSG_OPEN_REJ_EVT,
+ AVDT_SCB_MSG_START_REJ_EVT,
+ AVDT_SCB_MSG_SUSPEND_REJ_EVT,
+ AVDT_SCB_TC_TOUT_EVT,
+ AVDT_SCB_TC_OPEN_EVT,
+ AVDT_SCB_TC_CLOSE_EVT,
+ AVDT_SCB_TC_CONG_EVT,
+ AVDT_SCB_TC_DATA_EVT,
+ AVDT_SCB_CC_CLOSE_EVT
+};
+
+/* adaption layer number of stream routing table entries */
+#if AVDT_REPORTING == TRUE
+/* 2 channels(1 media, 1 report) for each SEP and one for signalling */
+#define AVDT_NUM_RT_TBL ((AVDT_NUM_SEPS<<1) + 1)
+#else
+#define AVDT_NUM_RT_TBL (AVDT_NUM_SEPS + 1)
+#endif
+
+/* adaption layer number of transport channel table entries - moved to target.h
+#define AVDT_NUM_TC_TBL (AVDT_NUM_SEPS + AVDT_NUM_LINKS) */
+
+/* "states" used in transport channel table */
+#define AVDT_AD_ST_UNUSED 0 /* Unused - unallocated */
+#define AVDT_AD_ST_IDLE 1 /* No connection */
+#define AVDT_AD_ST_ACP 2 /* Waiting to accept a connection */
+#define AVDT_AD_ST_INT 3 /* Initiating a connection */
+#define AVDT_AD_ST_CONN 4 /* Waiting for connection confirm */
+#define AVDT_AD_ST_CFG 5 /* Waiting for configuration complete */
+#define AVDT_AD_ST_OPEN 6 /* Channel opened */
+#define AVDT_AD_ST_SEC_INT 7 /* Security process as INT */
+#define AVDT_AD_ST_SEC_ACP 8 /* Security process as ACP */
+
+/* Configuration flags. tAVDT_TC_TBL.cfg_flags */
+#define AVDT_L2C_CFG_IND_DONE (1<<0)
+#define AVDT_L2C_CFG_CFM_DONE (1<<1)
+#define AVDT_L2C_CFG_CONN_INT (1<<2)
+#define AVDT_L2C_CFG_CONN_ACP (1<<3)
+
+
+/* result code for avdt_ad_write_req() (L2CA_DataWrite()) */
+#define AVDT_AD_FAILED L2CAP_DW_FAILED /* FALSE */
+#define AVDT_AD_SUCCESS L2CAP_DW_SUCCESS /* TRUE */
+#define AVDT_AD_CONGESTED L2CAP_DW_CONGESTED /* 2 */
+
+/*****************************************************************************
+** data types
+*****************************************************************************/
+
+/* msg union of all message parameter types */
+typedef union {
+ tAVDT_EVT_HDR hdr;
+ tAVDT_EVT_HDR single;
+ tAVDT_SETCONFIG config_cmd;
+ tAVDT_CONFIG reconfig_cmd;
+ tAVDT_MULTI multi;
+ tAVDT_SECURITY security_cmd;
+ tAVDT_DISCOVER discover_rsp;
+ tAVDT_CONFIG svccap;
+ tAVDT_SECURITY security_rsp;
+ tAVDT_DELAY_RPT delay_rpt_cmd;
+} tAVDT_MSG;
+
+/* data type for AVDT_CCB_API_DISCOVER_REQ_EVT */
+typedef struct {
+ tAVDT_CTRL_CBACK *p_cback;
+ tAVDT_SEP_INFO *p_sep_info;
+ UINT8 num_seps;
+} tAVDT_CCB_API_DISCOVER;
+
+/* data type for AVDT_CCB_API_GETCAP_REQ_EVT */
+typedef struct {
+ tAVDT_EVT_HDR single;
+ tAVDT_CTRL_CBACK *p_cback;
+ tAVDT_CFG *p_cfg;
+} tAVDT_CCB_API_GETCAP;
+
+/* data type for AVDT_CCB_API_CONNECT_REQ_EVT */
+typedef struct {
+ tAVDT_CTRL_CBACK *p_cback;
+ UINT8 sec_mask;
+} tAVDT_CCB_API_CONNECT;
+
+/* data type for AVDT_CCB_API_DISCONNECT_REQ_EVT */
+typedef struct {
+ tAVDT_CTRL_CBACK *p_cback;
+} tAVDT_CCB_API_DISCONNECT;
+
+/* union associated with ccb state machine events */
+typedef union {
+ tAVDT_CCB_API_DISCOVER discover;
+ tAVDT_CCB_API_GETCAP getcap;
+ tAVDT_CCB_API_CONNECT connect;
+ tAVDT_CCB_API_DISCONNECT disconnect;
+ tAVDT_MSG msg;
+ BOOLEAN llcong;
+ UINT8 err_code;
+} tAVDT_CCB_EVT;
+
+/* channel control block type */
+typedef struct {
+ BD_ADDR peer_addr; /* BD address of peer */
+ TIMER_LIST_ENT timer_entry; /* CCB timer list entry */
+ BUFFER_Q cmd_q; /* Queue for outgoing command messages */
+ BUFFER_Q rsp_q; /* Queue for outgoing response and reject messages */
+ tAVDT_CTRL_CBACK *proc_cback; /* Procedure callback function */
+ tAVDT_CTRL_CBACK *p_conn_cback; /* Connection/disconnection callback function */
+ void *p_proc_data; /* Pointer to data storage for procedure */
+ BT_HDR *p_curr_cmd; /* Current command being sent awaiting response */
+ BT_HDR *p_curr_msg; /* Current message being sent */
+ BT_HDR *p_rx_msg; /* Current message being received */
+ BOOLEAN allocated; /* Whether ccb is allocated */
+ UINT8 state; /* The CCB state machine state */
+ BOOLEAN ll_opened; /* TRUE if LL is opened */
+ BOOLEAN proc_busy; /* TRUE when a discover or get capabilities procedure in progress */
+ UINT8 proc_param; /* Procedure parameter; either SEID for get capabilities or number of SEPS for discover */
+ BOOLEAN cong; /* Whether signaling channel is congested */
+ UINT8 label; /* Message header "label" (sequence number) */
+ BOOLEAN reconn; /* If TRUE, reinitiate connection after transitioning from CLOSING to IDLE state */
+ UINT8 ret_count; /* Command retransmission count */
+} tAVDT_CCB;
+
+/* type for action functions */
+typedef void (*tAVDT_CCB_ACTION)(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
+
+/* type for AVDT_SCB_API_WRITE_REQ_EVT */
+typedef struct {
+ BT_HDR *p_buf;
+ UINT32 time_stamp;
+#if AVDT_MULTIPLEXING == TRUE
+ BUFFER_Q frag_q; /* Queue for outgoing media fragments. p_buf should be 0 */
+ UINT8 *p_data;
+ UINT32 data_len;
+#endif
+ UINT8 m_pt;
+} tAVDT_SCB_APIWRITE;
+
+/* type for AVDT_SCB_TC_CLOSE_EVT */
+typedef struct {
+ UINT8 old_tc_state; /* channel state before closed */
+ UINT8 tcid; /* TCID */
+ UINT8 type; /* channel type */
+} tAVDT_SCB_TC_CLOSE;
+
+/* type for scb event data */
+typedef union {
+ tAVDT_MSG msg;
+ tAVDT_SCB_APIWRITE apiwrite;
+ tAVDT_DELAY_RPT apidelay;
+ tAVDT_OPEN open;
+ tAVDT_SCB_TC_CLOSE close;
+ BOOLEAN llcong;
+ BT_HDR *p_pkt;
+} tAVDT_SCB_EVT;
+
+/* stream control block type */
+typedef struct {
+ tAVDT_CS cs; /* stream creation struct */
+ tAVDT_CFG curr_cfg; /* current configuration */
+ tAVDT_CFG req_cfg; /* requested configuration */
+ TIMER_LIST_ENT timer_entry; /* timer entry */
+ BT_HDR *p_pkt; /* packet waiting to be sent */
+ tAVDT_CCB *p_ccb; /* ccb associated with this scb */
+ UINT16 media_seq; /* media packet sequence number */
+ BOOLEAN allocated; /* whether scb is allocated or unused */
+ BOOLEAN in_use; /* whether stream being used by peer */
+ UINT8 role; /* initiator/acceptor role in current procedure */
+ BOOLEAN remove; /* whether CB is marked for removal */
+ UINT8 state; /* state machine state */
+ UINT8 peer_seid; /* SEID of peer stream */
+ UINT8 curr_evt; /* current event; set only by state machine */
+ BOOLEAN cong; /* Whether media transport channel is congested */
+ UINT8 close_code; /* Error code received in close response */
+#if AVDT_MULTIPLEXING == TRUE
+ BUFFER_Q frag_q; /* Queue for outgoing media fragments */
+ UINT32 frag_off; /* length of already received media fragments */
+ UINT32 frag_org_len; /* original length before fragmentation of receiving media packet */
+ UINT8 *p_next_frag; /* next fragment to send */
+ UINT8 *p_media_buf; /* buffer for media packet assigned by AVDT_SetMediaBuf */
+ UINT32 media_buf_len; /* length of buffer for media packet assigned by AVDT_SetMediaBuf */
+#endif
+} tAVDT_SCB;
+
+/* type for action functions */
+typedef void (*tAVDT_SCB_ACTION)(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+
+/* adaption layer type for transport channel table */
+typedef struct {
+ UINT16 peer_mtu; /* L2CAP mtu of the peer device */
+ UINT16 my_mtu; /* Our MTU for this channel */
+ UINT16 my_flush_to; /* Our flush timeout for this channel */
+ UINT16 lcid;
+ UINT8 tcid; /* transport channel id */
+ UINT8 ccb_idx; /* channel control block associated with this tc */
+ UINT8 state; /* transport channel state */
+ UINT8 cfg_flags; /* L2CAP configuration flags */
+ UINT8 id;
+} tAVDT_TC_TBL;
+
+/* adaption layer type for stream routing table */
+typedef struct {
+ UINT16 lcid; /* L2CAP LCID of the associated transport channel */
+ UINT8 scb_hdl; /* stream control block associated with this tc */
+} tAVDT_RT_TBL;
+
+
+/* adaption layer control block */
+typedef struct {
+ tAVDT_RT_TBL rt_tbl[AVDT_NUM_LINKS][AVDT_NUM_RT_TBL];
+ tAVDT_TC_TBL tc_tbl[AVDT_NUM_TC_TBL];
+ UINT8 lcid_tbl[MAX_L2CAP_CHANNELS]; /* map LCID to tc_tbl index */
+} tAVDT_AD;
+
+/* Control block for AVDT */
+typedef struct {
+ tAVDT_REG rcb; /* registration control block */
+ tAVDT_CCB ccb[AVDT_NUM_LINKS]; /* channel control blocks */
+ tAVDT_SCB scb[AVDT_NUM_SEPS]; /* stream control blocks */
+ tAVDT_AD ad; /* adaption layer control block */
+ tAVDTC_CTRL_CBACK *p_conf_cback; /* conformance callback function */
+ tAVDT_CCB_ACTION *p_ccb_act; /* pointer to CCB action functions */
+ tAVDT_SCB_ACTION *p_scb_act; /* pointer to SCB action functions */
+ tAVDT_CTRL_CBACK *p_conn_cback; /* connection callback function */
+ UINT8 trace_level; /* trace level */
+} tAVDT_CB;
+
+
+/*****************************************************************************
+** function declarations
+*****************************************************************************/
+
+/* CCB function declarations */
+extern void avdt_ccb_init(void);
+extern void avdt_ccb_event(tAVDT_CCB *p_ccb, UINT8 event, tAVDT_CCB_EVT *p_data);
+extern tAVDT_CCB *avdt_ccb_by_bd(BD_ADDR bd_addr);
+extern tAVDT_CCB *avdt_ccb_alloc(BD_ADDR bd_addr);
+extern void avdt_ccb_dealloc(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
+extern UINT8 avdt_ccb_to_idx(tAVDT_CCB *p_ccb);
+extern tAVDT_CCB *avdt_ccb_by_idx(UINT8 idx);
+
+/* CCB action functions */
+extern void avdt_ccb_chan_open(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
+extern void avdt_ccb_chan_close(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
+extern void avdt_ccb_chk_close(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
+extern void avdt_ccb_hdl_discover_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
+extern void avdt_ccb_hdl_discover_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
+extern void avdt_ccb_hdl_getcap_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
+extern void avdt_ccb_hdl_getcap_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
+extern void avdt_ccb_hdl_start_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
+extern void avdt_ccb_hdl_start_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
+extern void avdt_ccb_hdl_suspend_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
+extern void avdt_ccb_hdl_suspend_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
+extern void avdt_ccb_snd_discover_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
+extern void avdt_ccb_snd_discover_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
+extern void avdt_ccb_snd_getcap_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
+extern void avdt_ccb_snd_getcap_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
+extern void avdt_ccb_snd_start_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
+extern void avdt_ccb_snd_start_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
+extern void avdt_ccb_snd_suspend_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
+extern void avdt_ccb_snd_suspend_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
+extern void avdt_ccb_clear_cmds(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
+extern void avdt_ccb_cmd_fail(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
+extern void avdt_ccb_free_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
+extern void avdt_ccb_cong_state(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
+extern void avdt_ccb_ret_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
+extern void avdt_ccb_snd_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
+extern void avdt_ccb_snd_msg(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
+extern void avdt_ccb_set_reconn(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
+extern void avdt_ccb_clr_reconn(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
+extern void avdt_ccb_chk_reconn(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
+extern void avdt_ccb_chk_timer(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
+extern void avdt_ccb_set_conn(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
+extern void avdt_ccb_set_disconn(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
+extern void avdt_ccb_do_disconn(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
+extern void avdt_ccb_ll_closed(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
+extern void avdt_ccb_ll_opened(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
+
+/* SCB function prototypes */
+extern void avdt_scb_event(tAVDT_SCB *p_scb, UINT8 event, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_init(void);
+extern tAVDT_SCB *avdt_scb_alloc(tAVDT_CS *p_cs);
+extern void avdt_scb_dealloc(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern UINT8 avdt_scb_to_hdl(tAVDT_SCB *p_scb);
+extern tAVDT_SCB *avdt_scb_by_hdl(UINT8 hdl);
+extern UINT8 avdt_scb_verify(tAVDT_CCB *p_ccb, UINT8 state, UINT8 *p_seid, UINT16 num_seid, UINT8 *p_err_code);
+extern void avdt_scb_peer_seid_list(tAVDT_MULTI *p_multi);
+extern UINT32 avdt_scb_gen_ssrc(tAVDT_SCB *p_scb);
+
+/* SCB action functions */
+extern void avdt_scb_hdl_abort_cmd(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_hdl_abort_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_hdl_close_cmd(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_hdl_close_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_hdl_getconfig_cmd(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_hdl_getconfig_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_hdl_open_cmd(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_hdl_open_rej(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_hdl_open_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_hdl_pkt(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_drop_pkt(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_hdl_reconfig_cmd(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_hdl_reconfig_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_hdl_security_cmd(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_hdl_security_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_hdl_setconfig_cmd(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_hdl_setconfig_rej(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_hdl_setconfig_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_hdl_start_cmd(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_hdl_start_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_hdl_suspend_cmd(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_hdl_suspend_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_snd_delay_rpt_req(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_hdl_delay_rpt_cmd(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_hdl_delay_rpt_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_hdl_tc_close(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_hdl_tc_open(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_hdl_tc_close_sto(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_hdl_tc_open_sto(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_hdl_write_req(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_snd_abort_req(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_snd_abort_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_snd_close_req(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_snd_stream_close(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_snd_close_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_snd_getconfig_req(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_snd_getconfig_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_snd_open_req(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_snd_open_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_snd_reconfig_req(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_snd_reconfig_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_snd_security_req(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_snd_security_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_snd_setconfig_req(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_snd_setconfig_rej(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_snd_setconfig_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_snd_tc_close(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_cb_err(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_cong_state(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_rej_state(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_rej_in_use(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_rej_not_in_use(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_set_remove(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_free_pkt(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_chk_snd_pkt(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_clr_pkt(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_tc_timer(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_clr_vars(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
+extern void avdt_scb_queue_frags(tAVDT_SCB *p_scb, UINT8 **pp_data, UINT32 *p_data_len, BUFFER_Q *pq);
+
+/* msg function declarations */
+extern BOOLEAN avdt_msg_send(tAVDT_CCB *p_ccb, BT_HDR *p_msg);
+extern void avdt_msg_send_cmd(tAVDT_CCB *p_ccb, void *p_scb, UINT8 sig_id, tAVDT_MSG *p_params);
+extern void avdt_msg_send_rsp(tAVDT_CCB *p_ccb, UINT8 sig_id, tAVDT_MSG *p_params);
+extern void avdt_msg_send_rej(tAVDT_CCB *p_ccb, UINT8 sig_id, tAVDT_MSG *p_params);
+extern void avdt_msg_send_grej(tAVDT_CCB *p_ccb, UINT8 sig_id, tAVDT_MSG *p_params);
+extern void avdt_msg_ind(tAVDT_CCB *p_ccb, BT_HDR *p_buf);
+
+/* adaption layer function declarations */
+extern void avdt_ad_init(void);
+extern UINT8 avdt_ad_type_to_tcid(UINT8 type, tAVDT_SCB *p_scb);
+extern tAVDT_TC_TBL *avdt_ad_tc_tbl_by_st(UINT8 type, tAVDT_CCB *p_ccb, UINT8 state);
+extern tAVDT_TC_TBL *avdt_ad_tc_tbl_by_lcid(UINT16 lcid);
+extern tAVDT_TC_TBL *avdt_ad_tc_tbl_alloc(tAVDT_CCB *p_ccb);
+extern UINT8 avdt_ad_tc_tbl_to_idx(tAVDT_TC_TBL *p_tbl);
+extern void avdt_ad_tc_close_ind(tAVDT_TC_TBL *p_tbl, UINT16 reason);
+extern void avdt_ad_tc_open_ind(tAVDT_TC_TBL *p_tbl);
+extern void avdt_ad_tc_cong_ind(tAVDT_TC_TBL *p_tbl, BOOLEAN is_congested);
+extern void avdt_ad_tc_data_ind(tAVDT_TC_TBL *p_tbl, BT_HDR *p_buf);
+extern tAVDT_TC_TBL *avdt_ad_tc_tbl_by_type(UINT8 type, tAVDT_CCB *p_ccb, tAVDT_SCB *p_scb);
+extern UINT8 avdt_ad_write_req(UINT8 type, tAVDT_CCB *p_ccb, tAVDT_SCB *p_scb, BT_HDR *p_buf);
+extern void avdt_ad_open_req(UINT8 type, tAVDT_CCB *p_ccb, tAVDT_SCB *p_scb, UINT8 role);
+extern void avdt_ad_close_req(UINT8 type, tAVDT_CCB *p_ccb, tAVDT_SCB *p_scb);
+
+extern void avdt_process_timeout(TIMER_LIST_ENT *p_tle);
+
+/*****************************************************************************
+** macros
+*****************************************************************************/
+
+/* we store the scb and the label in the layer_specific field of the
+** current cmd
+*/
+#define AVDT_BLD_LAYERSPEC(ls, msg, label) \
+ ls = (((label) << 4) | (msg))
+
+#define AVDT_LAYERSPEC_LABEL(ls) ((UINT8)((ls) >> 4))
+
+#define AVDT_LAYERSPEC_MSG(ls) ((UINT8)((ls) & 0x000F))
+
+/*****************************************************************************
+** global data
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/******************************************************************************
+** Main Control Block
+*******************************************************************************/
+#if AVDT_DYNAMIC_MEMORY == FALSE
+AVDT_API extern tAVDT_CB avdt_cb;
+#else
+AVDT_API extern tAVDT_CB *avdt_cb_ptr;
+#define avdt_cb (*avdt_cb_ptr)
+#endif
+
+
+/* L2CAP callback registration structure */
+extern const tL2CAP_APPL_INFO avdt_l2c_appl;
+
+/* reject message event lookup table */
+extern const UINT8 avdt_msg_rej_2_evt[];
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVDT_INT_H */
diff --git a/stack/avdt/avdt_l2c.c b/stack/avdt/avdt_l2c.c
new file mode 100644
index 0000000..20979b4
--- /dev/null
+++ b/stack/avdt/avdt_l2c.c
@@ -0,0 +1,521 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2002-2012 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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This AVDTP adaption layer module interfaces to L2CAP
+ *
+ ******************************************************************************/
+
+#include <string.h>
+#include "data_types.h"
+#include "bt_target.h"
+#include "avdt_api.h"
+#include "avdtc_api.h"
+#include "avdt_int.h"
+#include "l2c_api.h"
+#include "l2cdefs.h"
+#include "btm_api.h"
+#include "btm_int.h"
+
+
+/* callback function declarations */
+void avdt_l2c_connect_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 id);
+void avdt_l2c_connect_cfm_cback(UINT16 lcid, UINT16 result);
+void avdt_l2c_config_cfm_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg);
+void avdt_l2c_config_ind_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg);
+void avdt_l2c_disconnect_ind_cback(UINT16 lcid, BOOLEAN ack_needed);
+void avdt_l2c_disconnect_cfm_cback(UINT16 lcid, UINT16 result);
+void avdt_l2c_congestion_ind_cback(UINT16 lcid, BOOLEAN is_congested);
+void avdt_l2c_data_ind_cback(UINT16 lcid, BT_HDR *p_buf);
+
+/* L2CAP callback function structure */
+const tL2CAP_APPL_INFO avdt_l2c_appl = {
+ avdt_l2c_connect_ind_cback,
+ avdt_l2c_connect_cfm_cback,
+ NULL,
+ avdt_l2c_config_ind_cback,
+ avdt_l2c_config_cfm_cback,
+ avdt_l2c_disconnect_ind_cback,
+ avdt_l2c_disconnect_cfm_cback,
+ NULL,
+ avdt_l2c_data_ind_cback,
+ avdt_l2c_congestion_ind_cback,
+ NULL /* tL2CA_TX_COMPLETE_CB */
+};
+
+/*******************************************************************************
+**
+** Function avdt_sec_check_complete_term
+**
+** Description The function called when Security Manager finishes
+** verification of the service side connection
+**
+** Returns void
+**
+*******************************************************************************/
+static void avdt_sec_check_complete_term (BD_ADDR bd_addr, void *p_ref_data, UINT8 res)
+{
+ tAVDT_CCB *p_ccb = NULL;
+ tL2CAP_CFG_INFO cfg;
+ tAVDT_TC_TBL *p_tbl;
+
+ AVDT_TRACE_DEBUG1("avdt_sec_check_complete_term res: %d", res);
+ if (!bd_addr)
+ {
+ AVDT_TRACE_WARNING0("avdt_sec_check_complete_term: NULL BD_ADDR");
+ return;
+
+ }
+ 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_ACP);
+ if (p_tbl == NULL)
+ return;
+
+ if (res == BTM_SUCCESS)
+ {
+ /* 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;
+
+ /* transition to configuration state */
+ p_tbl->state = AVDT_AD_ST_CFG;
+
+ /* Send L2CAP config req */
+ memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
+ cfg.mtu_present = TRUE;
+ cfg.mtu = p_tbl->my_mtu;
+ cfg.flush_to_present = TRUE;
+ cfg.flush_to = p_tbl->my_flush_to;
+ L2CA_ConfigReq(p_tbl->lcid, &cfg);
+ }
+ else
+ {
+ L2CA_ConnectRsp (bd_addr, p_tbl->id, p_tbl->lcid, L2CAP_CONN_SECURITY_BLOCK, L2CAP_CONN_OK);
+ avdt_ad_tc_close_ind(p_tbl, L2CAP_CONN_SECURITY_BLOCK);
+ }
+}
+
+/*******************************************************************************
+**
+** Function avdt_sec_check_complete_orig
+**
+** Description The function called when Security Manager finishes
+** verification of the service side connection
+**
+** Returns void
+**
+*******************************************************************************/
+static void avdt_sec_check_complete_orig (BD_ADDR bd_addr, void *p_ref_data, UINT8 res)
+{
+ tAVDT_CCB *p_ccb = NULL;
+ tL2CAP_CFG_INFO cfg;
+ tAVDT_TC_TBL *p_tbl;
+
+ AVDT_TRACE_DEBUG1("avdt_sec_check_complete_orig res: %d", 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;
+
+ if( res == BTM_SUCCESS )
+ {
+ /* set channel state */
+ p_tbl->state = AVDT_AD_ST_CFG;
+
+ /* Send L2CAP config req */
+ memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
+ cfg.mtu_present = TRUE;
+ cfg.mtu = p_tbl->my_mtu;
+ cfg.flush_to_present = TRUE;
+ cfg.flush_to = p_tbl->my_flush_to;
+ L2CA_ConfigReq(p_tbl->lcid, &cfg);
+ }
+ else
+ {
+ L2CA_DisconnectReq (p_tbl->lcid);
+ avdt_ad_tc_close_ind(p_tbl, L2CAP_CONN_SECURITY_BLOCK);
+ }
+}
+/*******************************************************************************
+**
+** Function avdt_l2c_connect_ind_cback
+**
+** Description This is the L2CAP connect indication callback function.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void avdt_l2c_connect_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 id)
+{
+ tAVDT_CCB *p_ccb;
+ tAVDT_TC_TBL *p_tbl = NULL;
+ UINT16 result;
+ tL2CAP_CFG_INFO cfg;
+ tBTM_STATUS rc;
+
+ /* do we already have a control channel for this peer? */
+ if ((p_ccb = avdt_ccb_by_bd(bd_addr)) == NULL)
+ {
+ /* no, allocate ccb */
+ if ((p_ccb = avdt_ccb_alloc(bd_addr)) == NULL)
+ {
+ /* no ccb available, reject L2CAP connection */
+ result = L2CAP_CONN_NO_RESOURCES;
+ }
+ else
+ {
+ /* allocate and set up entry; first channel is always signaling */
+ p_tbl = avdt_ad_tc_tbl_alloc(p_ccb);
+ p_tbl->my_mtu = avdt_cb.rcb.ctrl_mtu;
+ p_tbl->my_flush_to = L2CAP_DEFAULT_FLUSH_TO;
+ p_tbl->tcid = AVDT_CHAN_SIG;
+ p_tbl->lcid = lcid;
+ p_tbl->id = id;
+ p_tbl->state = AVDT_AD_ST_SEC_ACP;
+ p_tbl->cfg_flags = AVDT_L2C_CFG_CONN_ACP;
+
+ /* Check the security */
+ rc = btm_sec_mx_access_request (bd_addr, AVDT_PSM,
+ FALSE, BTM_SEC_PROTO_AVDT,
+ AVDT_CHAN_SIG,
+ &avdt_sec_check_complete_term, NULL);
+ if(rc == BTM_CMD_STARTED)
+ {
+ L2CA_ConnectRsp (p_ccb->peer_addr, p_tbl->id, lcid, L2CAP_CONN_PENDING, L2CAP_CONN_OK);
+ }
+ return;
+ }
+ }
+ /* deal with simultaneous control channel connect case */
+ else if ((p_tbl = avdt_ad_tc_tbl_by_st(AVDT_CHAN_SIG, p_ccb, AVDT_AD_ST_CONN)) != NULL)
+ {
+ /* reject their connection */
+ result = L2CAP_CONN_NO_RESOURCES;
+ }
+ /* this must be a traffic channel; are we accepting a traffic channel
+ ** for this ccb?
+ */
+ else if ((p_tbl = avdt_ad_tc_tbl_by_st(AVDT_CHAN_MEDIA, p_ccb, AVDT_AD_ST_ACP)) != NULL)
+ {
+ /* yes; proceed with connection */
+ result = L2CAP_CONN_OK;
+ }
+#if AVDT_REPORTING == TRUE
+ /* this must be a reporting channel; are we accepting a reporting channel
+ ** for this ccb?
+ */
+ else if ((p_tbl = avdt_ad_tc_tbl_by_st(AVDT_CHAN_REPORT, p_ccb, AVDT_AD_ST_ACP)) != NULL)
+ {
+ /* yes; proceed with connection */
+ result = L2CAP_CONN_OK;
+ }
+#endif
+ /* else we're not listening for traffic channel; reject */
+ else
+ {
+ result = L2CAP_CONN_NO_PSM;
+ }
+
+ /* Send L2CAP connect rsp */
+ L2CA_ConnectRsp(bd_addr, id, lcid, result, 0);
+
+ /* 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;
+
+ /* transition to configuration state */
+ p_tbl->state = AVDT_AD_ST_CFG;
+
+ /* Send L2CAP config req */
+ memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
+ cfg.mtu_present = TRUE;
+ cfg.mtu = p_tbl->my_mtu;
+ cfg.flush_to_present = TRUE;
+ cfg.flush_to = p_tbl->my_flush_to;
+ L2CA_ConfigReq(lcid, &cfg);
+ }
+}
+
+/*******************************************************************************
+**
+** Function avdt_l2c_connect_cfm_cback
+**
+** Description This is the L2CAP connect confirm callback function.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void avdt_l2c_connect_cfm_cback(UINT16 lcid, UINT16 result)
+{
+ tAVDT_TC_TBL *p_tbl;
+ tL2CAP_CFG_INFO cfg;
+ tAVDT_CCB *p_ccb;
+
+ AVDT_TRACE_DEBUG2("avdt_l2c_connect_cfm_cback lcid: %d, result: %d",
+ lcid, result);
+ /* look up info for this channel */
+ if ((p_tbl = avdt_ad_tc_tbl_by_lcid(lcid)) != NULL)
+ {
+ /* if in correct state */
+ if (p_tbl->state == AVDT_AD_ST_CONN)
+ {
+ /* if result successful */
+ if (result == L2CAP_CONN_OK)
+ {
+ if(p_tbl->tcid != AVDT_CHAN_SIG)
+ {
+ /* set channel state */
+ p_tbl->state = AVDT_AD_ST_CFG;
+
+ /* Send L2CAP config req */
+ memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
+ cfg.mtu_present = TRUE;
+ cfg.mtu = p_tbl->my_mtu;
+ cfg.flush_to_present = TRUE;
+ cfg.flush_to = p_tbl->my_flush_to;
+ L2CA_ConfigReq(lcid, &cfg);
+ }
+ else
+ {
+ p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx);
+ if(p_ccb == NULL)
+ {
+ result = L2CAP_CONN_NO_RESOURCES;
+ }
+ else
+ {
+ /* set channel state */
+ p_tbl->state = AVDT_AD_ST_SEC_INT;
+ p_tbl->lcid = lcid;
+ p_tbl->cfg_flags = AVDT_L2C_CFG_CONN_INT;
+
+ /* Check the security */
+ btm_sec_mx_access_request (p_ccb->peer_addr, AVDT_PSM,
+ TRUE, BTM_SEC_PROTO_AVDT,
+ AVDT_CHAN_SIG,
+ &avdt_sec_check_complete_orig, NULL);
+ }
+ }
+ }
+
+ /* failure; notify adaption that channel closed */
+ if (result != L2CAP_CONN_OK)
+ {
+ avdt_ad_tc_close_ind(p_tbl, result);
+ }
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function avdt_l2c_config_cfm_cback
+**
+** Description This is the L2CAP config confirm callback function.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void avdt_l2c_config_cfm_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg)
+{
+ tAVDT_TC_TBL *p_tbl;
+
+ /* look up info for this channel */
+ if ((p_tbl = avdt_ad_tc_tbl_by_lcid(lcid)) != NULL)
+ {
+ /* if in correct state */
+ if (p_tbl->state == AVDT_AD_ST_CFG)
+ {
+ /* if result successful */
+ if (p_cfg->result == L2CAP_CONN_OK)
+ {
+ /* update cfg_flags */
+ p_tbl->cfg_flags |= AVDT_L2C_CFG_CFM_DONE;
+
+ /* if configuration complete */
+ if (p_tbl->cfg_flags & AVDT_L2C_CFG_IND_DONE)
+ {
+ avdt_ad_tc_open_ind(p_tbl);
+ }
+ }
+ /* else failure */
+ else
+ {
+ /* Send L2CAP disconnect req */
+ L2CA_DisconnectReq(lcid);
+ }
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function avdt_l2c_config_ind_cback
+**
+** Description This is the L2CAP config indication callback function.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void avdt_l2c_config_ind_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg)
+{
+ tAVDT_TC_TBL *p_tbl;
+
+ /* look up info for this channel */
+ if ((p_tbl = avdt_ad_tc_tbl_by_lcid(lcid)) != NULL)
+ {
+ /* store the mtu in tbl */
+ if (p_cfg->mtu_present)
+ {
+ p_tbl->peer_mtu = p_cfg->mtu;
+ }
+ else
+ {
+ p_tbl->peer_mtu = L2CAP_DEFAULT_MTU;
+ }
+ AVDT_TRACE_DEBUG2("peer_mtu: %d, lcid: x%x",p_tbl->peer_mtu, lcid);
+
+ /* send L2CAP configure response */
+ memset(p_cfg, 0, sizeof(tL2CAP_CFG_INFO));
+ p_cfg->result = L2CAP_CFG_OK;
+ L2CA_ConfigRsp(lcid, p_cfg);
+
+ /* if first config ind */
+ if ((p_tbl->cfg_flags & AVDT_L2C_CFG_IND_DONE) == 0)
+ {
+ /* update cfg_flags */
+ p_tbl->cfg_flags |= AVDT_L2C_CFG_IND_DONE;
+
+ /* if configuration complete */
+ if (p_tbl->cfg_flags & AVDT_L2C_CFG_CFM_DONE)
+ {
+ avdt_ad_tc_open_ind(p_tbl);
+ }
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function avdt_l2c_disconnect_ind_cback
+**
+** Description This is the L2CAP disconnect indication callback function.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void avdt_l2c_disconnect_ind_cback(UINT16 lcid, BOOLEAN ack_needed)
+{
+ tAVDT_TC_TBL *p_tbl;
+
+ AVDT_TRACE_DEBUG2("avdt_l2c_disconnect_ind_cback lcid: %d, ack_needed: %d",
+ lcid, ack_needed);
+ /* look up info for this channel */
+ if ((p_tbl = avdt_ad_tc_tbl_by_lcid(lcid)) != NULL)
+ {
+ if (ack_needed)
+ {
+ /* send L2CAP disconnect response */
+ L2CA_DisconnectRsp(lcid);
+ }
+
+ avdt_ad_tc_close_ind(p_tbl, 0);
+ }
+}
+
+/*******************************************************************************
+**
+** Function avdt_l2c_disconnect_cfm_cback
+**
+** Description This is the L2CAP disconnect confirm callback function.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void avdt_l2c_disconnect_cfm_cback(UINT16 lcid, UINT16 result)
+{
+ tAVDT_TC_TBL *p_tbl;
+
+ AVDT_TRACE_DEBUG2("avdt_l2c_disconnect_cfm_cback lcid: %d, result: %d",
+ lcid, result);
+ /* look up info for this channel */
+ if ((p_tbl = avdt_ad_tc_tbl_by_lcid(lcid)) != NULL)
+ {
+ avdt_ad_tc_close_ind(p_tbl, result);
+ }
+}
+
+/*******************************************************************************
+**
+** Function avdt_l2c_congestion_ind_cback
+**
+** Description This is the L2CAP congestion indication callback function.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void avdt_l2c_congestion_ind_cback(UINT16 lcid, BOOLEAN is_congested)
+{
+ tAVDT_TC_TBL *p_tbl;
+
+ /* look up info for this channel */
+ if ((p_tbl = avdt_ad_tc_tbl_by_lcid(lcid)) != NULL)
+ {
+ avdt_ad_tc_cong_ind(p_tbl, is_congested);
+ }
+}
+
+/*******************************************************************************
+**
+** Function avdt_l2c_data_ind_cback
+**
+** Description This is the L2CAP data indication callback function.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void avdt_l2c_data_ind_cback(UINT16 lcid, BT_HDR *p_buf)
+{
+ tAVDT_TC_TBL *p_tbl;
+
+ /* look up info for this channel */
+ if ((p_tbl = avdt_ad_tc_tbl_by_lcid(lcid)) != NULL)
+ {
+ avdt_ad_tc_data_ind(p_tbl, p_buf);
+ }
+ else /* prevent buffer leak */
+ GKI_freebuf(p_buf);
+}
+
diff --git a/stack/avdt/avdt_msg.c b/stack/avdt/avdt_msg.c
new file mode 100644
index 0000000..5d9c2fb
--- /dev/null
+++ b/stack/avdt/avdt_msg.c
@@ -0,0 +1,1891 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2002-2012 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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This module contains functions for parsing and building AVDTP signaling
+ * messages. It also contains functions called by the SCB or CCB state
+ * machines for sending command, response, and reject messages. It also
+ * contains a function that processes incoming messages and dispatches them
+ * to the appropriate SCB or CCB.
+ *
+ ******************************************************************************/
+
+#include <string.h>
+#include "data_types.h"
+#include "bt_target.h"
+#include "avdt_api.h"
+#include "avdtc_api.h"
+#include "avdt_int.h"
+#include "gki.h"
+#include "btu.h"
+
+/*****************************************************************************
+** constants
+*****************************************************************************/
+
+/* mask of all psc values */
+#define AVDT_MSG_PSC_MASK (AVDT_PSC_TRANS | AVDT_PSC_REPORT | AVDT_PSC_DELAY_RPT | \
+ AVDT_PSC_RECOV | AVDT_PSC_HDRCMP | AVDT_PSC_MUX)
+#define AVDT_PSC_PROTECT (1<<4) /* Content Protection */
+#define AVDT_PSC_CODEC (1<<7) /* codec */
+
+
+/*****************************************************************************
+** type definitions
+*****************************************************************************/
+
+/* type for message building functions */
+typedef void (*tAVDT_MSG_BLD)(UINT8 **p, tAVDT_MSG *p_msg);
+
+/* type for message parsing functions */
+typedef UINT8 (*tAVDT_MSG_PRS)(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len);
+
+
+/*****************************************************************************
+** local function declarations
+*****************************************************************************/
+
+static void avdt_msg_bld_none(UINT8 **p, tAVDT_MSG *p_msg);
+static void avdt_msg_bld_single(UINT8 **p, tAVDT_MSG *p_msg);
+static void avdt_msg_bld_setconfig_cmd(UINT8 **p, tAVDT_MSG *p_msg);
+static void avdt_msg_bld_reconfig_cmd(UINT8 **p, tAVDT_MSG *p_msg);
+static void avdt_msg_bld_multi(UINT8 **p, tAVDT_MSG *p_msg);
+static void avdt_msg_bld_security_cmd(UINT8 **p, tAVDT_MSG *p_msg);
+static void avdt_msg_bld_discover_rsp(UINT8 **p, tAVDT_MSG *p_msg);
+static void avdt_msg_bld_svccap(UINT8 **p, tAVDT_MSG *p_msg);
+static void avdt_msg_bld_security_rsp(UINT8 **p, tAVDT_MSG *p_msg);
+static void avdt_msg_bld_all_svccap(UINT8 **p, tAVDT_MSG *p_msg);
+static void avdt_msg_bld_delay_rpt(UINT8 **p, tAVDT_MSG *p_msg);
+
+static UINT8 avdt_msg_prs_none(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len);
+static UINT8 avdt_msg_prs_single(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len);
+static UINT8 avdt_msg_prs_setconfig_cmd(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len);
+static UINT8 avdt_msg_prs_reconfig_cmd(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len);
+static UINT8 avdt_msg_prs_multi(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len);
+static UINT8 avdt_msg_prs_security_cmd(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len);
+static UINT8 avdt_msg_prs_discover_rsp(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len);
+static UINT8 avdt_msg_prs_svccap(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len);
+static UINT8 avdt_msg_prs_all_svccap(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len);
+static UINT8 avdt_msg_prs_security_rsp(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len);
+static UINT8 avdt_msg_prs_delay_rpt (tAVDT_MSG *p_msg, UINT8 *p, UINT16 len);
+
+/*****************************************************************************
+** constants
+*****************************************************************************/
+
+/* table of information element minimum lengths used for parsing */
+const UINT8 avdt_msg_ie_len_min[] = {
+ 0, /* unused */
+ AVDT_LEN_TRANS_MIN, /* media transport */
+ AVDT_LEN_REPORT_MIN, /* reporting */
+ AVDT_LEN_RECOV_MIN, /* recovery */
+ AVDT_LEN_PROTECT_MIN, /* content protection */
+ AVDT_LEN_HDRCMP_MIN, /* header compression */
+ AVDT_LEN_MUX_MIN, /* multiplexing */
+ AVDT_LEN_CODEC_MIN, /* codec */
+ AVDT_LEN_DELAY_RPT_MIN /* delay report */
+};
+
+/* table of information element minimum lengths used for parsing */
+const UINT8 avdt_msg_ie_len_max[] = {
+ 0, /* unused */
+ AVDT_LEN_TRANS_MAX, /* media transport */
+ AVDT_LEN_REPORT_MAX, /* reporting */
+ AVDT_LEN_RECOV_MAX, /* recovery */
+ AVDT_LEN_PROTECT_MAX, /* content protection */
+ AVDT_LEN_HDRCMP_MAX, /* header compression */
+ AVDT_LEN_MUX_MAX, /* multiplexing */
+ AVDT_LEN_CODEC_MAX, /* codec */
+ AVDT_LEN_DELAY_RPT_MAX /* delay report */
+};
+
+/* table of error codes used when decoding information elements */
+const UINT8 avdt_msg_ie_err[] = {
+ 0, /* unused */
+ AVDT_ERR_MEDIA_TRANS, /* media transport */
+ AVDT_ERR_LENGTH, /* reporting */
+ AVDT_ERR_RECOV_FMT, /* recovery */
+ AVDT_ERR_CP_FMT, /* content protection */
+ AVDT_ERR_ROHC_FMT, /* header compression */
+ AVDT_ERR_MUX_FMT, /* multiplexing */
+ AVDT_ERR_SERVICE, /* codec */
+ AVDT_ERR_SERVICE /* delay report ?? */
+};
+
+/* table of packet type minimum lengths */
+static const UINT8 avdt_msg_pkt_type_len[] = {
+ AVDT_LEN_TYPE_SINGLE,
+ AVDT_LEN_TYPE_START,
+ AVDT_LEN_TYPE_CONT,
+ AVDT_LEN_TYPE_END
+};
+
+/* function table for building command messages */
+const tAVDT_MSG_BLD avdt_msg_bld_cmd[] = {
+ avdt_msg_bld_none, /* discover */
+ avdt_msg_bld_single, /* get capabilities */
+ avdt_msg_bld_setconfig_cmd, /* set configuration */
+ avdt_msg_bld_single, /* get configuration */
+ avdt_msg_bld_reconfig_cmd, /* reconfigure */
+ avdt_msg_bld_single, /* open */
+ avdt_msg_bld_multi, /* start */
+ avdt_msg_bld_single, /* close */
+ avdt_msg_bld_multi, /* suspend */
+ avdt_msg_bld_single, /* abort */
+ avdt_msg_bld_security_cmd, /* security control */
+ avdt_msg_bld_single, /* get all capabilities */
+ avdt_msg_bld_delay_rpt /* delay report */
+};
+
+/* function table for building response messages */
+const tAVDT_MSG_BLD avdt_msg_bld_rsp[] = {
+ avdt_msg_bld_discover_rsp, /* discover */
+ avdt_msg_bld_svccap, /* get capabilities */
+ avdt_msg_bld_none, /* set configuration */
+ avdt_msg_bld_all_svccap, /* get configuration */
+ avdt_msg_bld_none, /* reconfigure */
+ avdt_msg_bld_none, /* open */
+ avdt_msg_bld_none, /* start */
+ avdt_msg_bld_none, /* close */
+ avdt_msg_bld_none, /* suspend */
+ avdt_msg_bld_none, /* abort */
+ avdt_msg_bld_security_rsp, /* security control */
+ avdt_msg_bld_all_svccap, /* get all capabilities */
+ avdt_msg_bld_none /* delay report */
+};
+
+/* function table for parsing command messages */
+const tAVDT_MSG_PRS avdt_msg_prs_cmd[] = {
+ avdt_msg_prs_none, /* discover */
+ avdt_msg_prs_single, /* get capabilities */
+ avdt_msg_prs_setconfig_cmd, /* set configuration */
+ avdt_msg_prs_single, /* get configuration */
+ avdt_msg_prs_reconfig_cmd, /* reconfigure */
+ avdt_msg_prs_single, /* open */
+ avdt_msg_prs_multi, /* start */
+ avdt_msg_prs_single, /* close */
+ avdt_msg_prs_multi, /* suspend */
+ avdt_msg_prs_single, /* abort */
+ avdt_msg_prs_security_cmd, /* security control */
+ avdt_msg_prs_single, /* get all capabilities */
+ avdt_msg_prs_delay_rpt /* delay report */
+};
+
+/* function table for parsing response messages */
+const tAVDT_MSG_PRS avdt_msg_prs_rsp[] = {
+ avdt_msg_prs_discover_rsp, /* discover */
+ avdt_msg_prs_svccap, /* get capabilities */
+ avdt_msg_prs_none, /* set configuration */
+ avdt_msg_prs_all_svccap, /* get configuration */
+ avdt_msg_prs_none, /* reconfigure */
+ avdt_msg_prs_none, /* open */
+ avdt_msg_prs_none, /* start */
+ avdt_msg_prs_none, /* close */
+ avdt_msg_prs_none, /* suspend */
+ avdt_msg_prs_none, /* abort */
+ avdt_msg_prs_security_rsp, /* security control */
+ avdt_msg_prs_all_svccap, /* get all capabilities */
+ avdt_msg_prs_none /* delay report */
+};
+
+/* command message-to-event lookup table */
+const UINT8 avdt_msg_cmd_2_evt[] = {
+ AVDT_CCB_MSG_DISCOVER_CMD_EVT + AVDT_CCB_MKR, /* discover */
+ AVDT_CCB_MSG_GETCAP_CMD_EVT + AVDT_CCB_MKR, /* get capabilities */
+ AVDT_SCB_MSG_SETCONFIG_CMD_EVT, /* set configuration */
+ AVDT_SCB_MSG_GETCONFIG_CMD_EVT, /* get configuration */
+ AVDT_SCB_MSG_RECONFIG_CMD_EVT, /* reconfigure */
+ AVDT_SCB_MSG_OPEN_CMD_EVT, /* open */
+ AVDT_CCB_MSG_START_CMD_EVT + AVDT_CCB_MKR, /* start */
+ AVDT_SCB_MSG_CLOSE_CMD_EVT, /* close */
+ AVDT_CCB_MSG_SUSPEND_CMD_EVT + AVDT_CCB_MKR, /* suspend */
+ AVDT_SCB_MSG_ABORT_CMD_EVT, /* abort */
+ AVDT_SCB_MSG_SECURITY_CMD_EVT, /* security control */
+ AVDT_CCB_MSG_GETCAP_CMD_EVT + AVDT_CCB_MKR, /* get all capabilities */
+ AVDT_SCB_MSG_DELAY_RPT_CMD_EVT /* delay report */
+};
+
+/* response message-to-event lookup table */
+const UINT8 avdt_msg_rsp_2_evt[] = {
+ AVDT_CCB_MSG_DISCOVER_RSP_EVT + AVDT_CCB_MKR, /* discover */
+ AVDT_CCB_MSG_GETCAP_RSP_EVT + AVDT_CCB_MKR, /* get capabilities */
+ AVDT_SCB_MSG_SETCONFIG_RSP_EVT, /* set configuration */
+ AVDT_SCB_MSG_GETCONFIG_RSP_EVT, /* get configuration */
+ AVDT_SCB_MSG_RECONFIG_RSP_EVT, /* reconfigure */
+ AVDT_SCB_MSG_OPEN_RSP_EVT, /* open */
+ AVDT_CCB_MSG_START_RSP_EVT + AVDT_CCB_MKR, /* start */
+ AVDT_SCB_MSG_CLOSE_RSP_EVT, /* close */
+ AVDT_CCB_MSG_SUSPEND_RSP_EVT + AVDT_CCB_MKR, /* suspend */
+ AVDT_SCB_MSG_ABORT_RSP_EVT, /* abort */
+ AVDT_SCB_MSG_SECURITY_RSP_EVT, /* security control */
+ AVDT_CCB_MSG_GETCAP_RSP_EVT + AVDT_CCB_MKR, /* get all capabilities */
+ AVDT_SCB_MSG_DELAY_RPT_RSP_EVT /* delay report */
+};
+
+/* reject message-to-event lookup table */
+const UINT8 avdt_msg_rej_2_evt[] = {
+ AVDT_CCB_MSG_DISCOVER_RSP_EVT + AVDT_CCB_MKR, /* discover */
+ AVDT_CCB_MSG_GETCAP_RSP_EVT + AVDT_CCB_MKR, /* get capabilities */
+ AVDT_SCB_MSG_SETCONFIG_REJ_EVT, /* set configuration */
+ AVDT_SCB_MSG_GETCONFIG_RSP_EVT, /* get configuration */
+ AVDT_SCB_MSG_RECONFIG_RSP_EVT, /* reconfigure */
+ AVDT_SCB_MSG_OPEN_REJ_EVT, /* open */
+ AVDT_CCB_MSG_START_RSP_EVT + AVDT_CCB_MKR, /* start */
+ AVDT_SCB_MSG_CLOSE_RSP_EVT, /* close */
+ AVDT_CCB_MSG_SUSPEND_RSP_EVT + AVDT_CCB_MKR, /* suspend */
+ AVDT_SCB_MSG_ABORT_RSP_EVT, /* abort */
+ AVDT_SCB_MSG_SECURITY_RSP_EVT, /* security control */
+ AVDT_CCB_MSG_GETCAP_RSP_EVT + AVDT_CCB_MKR, /* get all capabilities */
+ 0 /* delay report */
+};
+
+/*******************************************************************************
+**
+** Function avdt_msg_bld_cfg
+**
+** Description This function builds the configuration parameters contained
+** in a command or response message.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+static void avdt_msg_bld_cfg(UINT8 **p, tAVDT_CFG *p_cfg)
+{
+ UINT8 len;
+
+ /* for now, just build media transport, codec, and content protection, and multiplexing */
+
+ /* media transport */
+ if (p_cfg->psc_mask & AVDT_PSC_TRANS)
+ {
+ *(*p)++ = AVDT_CAT_TRANS;
+ *(*p)++ = 0; /* length */
+ }
+
+#if AVDT_REPORTING == TRUE
+ /* reporting transport */
+ if (p_cfg->psc_mask & AVDT_PSC_REPORT)
+ {
+ *(*p)++ = AVDT_CAT_REPORT;
+ *(*p)++ = 0; /* length */
+ }
+#endif
+
+ /* codec */
+ if (p_cfg->num_codec != 0)
+ {
+ *(*p)++ = AVDT_CAT_CODEC;
+ len = p_cfg->codec_info[0] + 1;
+ if( len > AVDT_CODEC_SIZE )
+ len = AVDT_CODEC_SIZE;
+
+ memcpy(*p, p_cfg->codec_info, len);
+ *p += len;
+ }
+
+ /* content protection */
+ if (p_cfg->num_protect != 0)
+ {
+ *(*p)++ = AVDT_CAT_PROTECT;
+ len = p_cfg->protect_info[0] + 1;
+ if( len > AVDT_PROTECT_SIZE )
+ len = AVDT_PROTECT_SIZE;
+
+ memcpy(*p, p_cfg->protect_info, len);
+ *p += len;
+ }
+
+#if AVDT_MULTIPLEXING == TRUE
+ /* multiplexing */
+ if (p_cfg->psc_mask & AVDT_PSC_MUX)
+ {
+ *(*p)++ = AVDT_CAT_MUX;
+ /* length */
+ if (p_cfg->psc_mask & AVDT_PSC_RECOV)
+ *(*p)++ = 7; /* frag (1) + media + report + recovery */
+ else if (p_cfg->psc_mask & AVDT_PSC_REPORT)
+ *(*p)++ = 5; /* frag (1) + media + report */
+ else
+ *(*p)++ = 3; /* frag (1) + media */
+
+ /* allow fragmentation */
+ if(p_cfg->mux_mask & AVDT_MUX_FRAG)
+ *(*p)++ = 0x80;
+ else
+ *(*p)++ = 0;
+
+ /* media transport session */
+ *(*p)++ = p_cfg->mux_tsid_media<<3; /* TSID */
+ *(*p)++ = p_cfg->mux_tcid_media<<3; /* TCID */
+
+ if (p_cfg->psc_mask & AVDT_PSC_RECOV)
+ {
+ /* reporting transport session */
+ *(*p)++ = p_cfg->mux_tsid_report<<3; /* TSID */
+ *(*p)++ = p_cfg->mux_tcid_report<<3; /* TCID */
+ /* recovery transport session */
+ *(*p)++ = p_cfg->mux_tsid_recov<<3; /* TSID */
+ *(*p)++ = p_cfg->mux_tcid_recov<<3; /* TCID */
+ }
+ else if (p_cfg->psc_mask & AVDT_PSC_REPORT)
+ {
+ /* reporting transport session */
+ *(*p)++ = p_cfg->mux_tsid_report<<3; /* TSID */
+ *(*p)++ = p_cfg->mux_tcid_report<<3; /* TCID */
+ }
+ }
+#endif
+
+ /* delay report */
+ if (p_cfg->psc_mask & AVDT_PSC_DELAY_RPT)
+ {
+ *(*p)++ = AVDT_CAT_DELAY_RPT;
+ *(*p)++ = 0; /* length */
+ }
+}
+
+/*******************************************************************************
+**
+** Function avdt_msg_bld_none
+**
+** Description This message building function builds an empty message.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+static void avdt_msg_bld_none(UINT8 **p, tAVDT_MSG *p_msg)
+{
+ return;
+}
+
+/*******************************************************************************
+**
+** Function avdt_msg_bld_single
+**
+** Description This message building function builds a message containing
+** a single SEID.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+static void avdt_msg_bld_single(UINT8 **p, tAVDT_MSG *p_msg)
+{
+ AVDT_MSG_BLD_SEID(*p, p_msg->single.seid);
+}
+
+/*******************************************************************************
+**
+** Function avdt_msg_bld_setconfig_cmd
+**
+** Description This message building function builds a set configuration
+** command message.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+static void avdt_msg_bld_setconfig_cmd(UINT8 **p, tAVDT_MSG *p_msg)
+{
+ AVDT_MSG_BLD_SEID(*p, p_msg->config_cmd.hdr.seid);
+ AVDT_MSG_BLD_SEID(*p, p_msg->config_cmd.int_seid);
+ avdt_msg_bld_cfg(p, p_msg->config_cmd.p_cfg);
+}
+
+/*******************************************************************************
+**
+** Function avdt_msg_bld_reconfig_cmd
+**
+** Description This message building function builds a reconfiguration
+** command message.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+static void avdt_msg_bld_reconfig_cmd(UINT8 **p, tAVDT_MSG *p_msg)
+{
+ AVDT_MSG_BLD_SEID(*p, p_msg->reconfig_cmd.hdr.seid);
+
+ /* force psc mask zero to build only codec and security */
+ p_msg->reconfig_cmd.p_cfg->psc_mask = 0;
+ avdt_msg_bld_cfg(p, p_msg->reconfig_cmd.p_cfg);
+}
+
+/*******************************************************************************
+**
+** Function avdt_msg_bld_multi
+**
+** Description This message building function builds a message containing
+** multiple SEID's.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+static void avdt_msg_bld_multi(UINT8 **p, tAVDT_MSG *p_msg)
+{
+ int i;
+
+ for (i = 0; i < p_msg->multi.num_seps; i++)
+ {
+ AVDT_MSG_BLD_SEID(*p, p_msg->multi.seid_list[i]);
+ }
+}
+
+/*******************************************************************************
+**
+** Function avdt_msg_bld_security_cmd
+**
+** Description This message building function builds a security
+** command message.
+**
+** Returns void.
+**
+*******************************************************************************/
+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;
+}
+
+/*******************************************************************************
+**
+** Function avdt_msg_bld_delay_rpt
+**
+** Description This message building function builds a delay report
+** command message.
+**
+** Returns void.
+**
+*******************************************************************************/
+static void avdt_msg_bld_delay_rpt(UINT8 **p, tAVDT_MSG *p_msg)
+{
+ AVDT_MSG_BLD_SEID(*p, p_msg->delay_rpt_cmd.hdr.seid);
+ UINT16_TO_BE_STREAM(*p, p_msg->delay_rpt_cmd.delay);
+}
+
+/*******************************************************************************
+**
+** Function avdt_msg_bld_discover_rsp
+**
+** Description This message building function builds a discover
+** response message.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+static void avdt_msg_bld_discover_rsp(UINT8 **p, tAVDT_MSG *p_msg)
+{
+ int i;
+
+ for (i = 0; i < p_msg->discover_rsp.num_seps; i++)
+ {
+ /* build discover rsp info */
+ AVDT_MSG_BLD_DISC(*p, p_msg->discover_rsp.p_sep_info[i].seid,
+ p_msg->discover_rsp.p_sep_info[i].in_use,
+ p_msg->discover_rsp.p_sep_info[i].media_type,
+ p_msg->discover_rsp.p_sep_info[i].tsep);
+ }
+}
+
+/*******************************************************************************
+**
+** Function avdt_msg_bld_svccap
+**
+** Description This message building function builds a message containing
+** service capabilities parameters.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+static void avdt_msg_bld_svccap(UINT8 **p, tAVDT_MSG *p_msg)
+{
+ tAVDT_CFG cfg;
+
+ /* make sure the delay report category is not reported */
+ memcpy (&cfg, p_msg->svccap.p_cfg, sizeof(tAVDT_CFG));
+ cfg.psc_mask &= ~AVDT_PSC_DELAY_RPT;
+ avdt_msg_bld_cfg(p, &cfg);
+}
+
+/*******************************************************************************
+**
+** Function avdt_msg_bld_all_svccap
+**
+** Description This message building function builds a message containing
+** service capabilities parameters.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+static void avdt_msg_bld_all_svccap(UINT8 **p, tAVDT_MSG *p_msg)
+{
+ avdt_msg_bld_cfg(p, p_msg->svccap.p_cfg);
+}
+
+/*******************************************************************************
+**
+** Function avdt_msg_bld_security_rsp
+**
+** Description This message building function builds a security
+** response message.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+static void avdt_msg_bld_security_rsp(UINT8 **p, tAVDT_MSG *p_msg)
+{
+ memcpy(*p, p_msg->security_rsp.p_data, p_msg->security_rsp.len);
+ *p += p_msg->security_rsp.len;
+}
+
+/*******************************************************************************
+**
+** Function avdt_msg_prs_cfg
+**
+** Description This message parsing function parses the configuration
+** parameters field of a message.
+**
+**
+** Returns Error code or zero if no error, and element that failed
+** in p_elem.
+**
+*******************************************************************************/
+static UINT8 avdt_msg_prs_cfg(tAVDT_CFG *p_cfg, UINT8 *p, UINT16 len, UINT8* p_elem, UINT8 sig_id)
+{
+ UINT8 *p_end;
+ UINT8 elem = 0;
+ UINT8 elem_len;
+ UINT8 tmp;
+ UINT8 err = 0;
+ UINT8 protect_offset = 0;
+
+ if (!p_cfg)
+ {
+ AVDT_TRACE_ERROR0 ("not expecting this cfg");
+ return AVDT_ERR_BAD_STATE;
+ }
+
+ p_cfg->psc_mask = 0;
+ p_cfg->num_codec = 0;
+ p_cfg->num_protect = 0;
+#if AVDT_MULTIPLEXING == TRUE
+ p_cfg->mux_mask = 0;
+#endif
+
+ /* while there is still data to parse */
+ p_end = p + len;
+ while ((p < p_end) && (err == 0))
+ {
+ /* verify overall length */
+ if ((p_end - p) < AVDT_LEN_CFG_MIN)
+ {
+ err = AVDT_ERR_PAYLOAD;
+ break;
+ }
+
+ /* get and verify info elem id, length */
+ elem = *p++;
+ elem_len = *p++;
+
+ if ((elem == 0) || (elem > AVDT_CAT_MAX_CUR))
+ {
+ /* this may not be really bad.
+ * It may be a service category that is too new for us.
+ * allow these to be parsed without reporting an error.
+ * If this is a "capability" (as in GetCapRsp & GetConfigRsp), this is filtered out.
+ * If this is a Configuration (as in SetConfigCmd & ReconfigCmd),
+ * this will be marked as an error in the caller of this function */
+ if ((sig_id == AVDT_SIG_SETCONFIG) || (sig_id == AVDT_SIG_RECONFIG))
+ {
+ /* Cannot accept unknown category. */
+ err = AVDT_ERR_CATEGORY;
+ break;
+ }
+ else /* GETCAP or GET_ALLCAP */
+ {
+ /* Skip unknown categories. */
+ p += elem_len;
+ AVDT_TRACE_DEBUG2("skipping unknown service category=%d len: %d", elem, elem_len);
+ continue;
+ }
+ }
+
+ if ((elem_len > avdt_msg_ie_len_max[elem]) ||
+ (elem_len < avdt_msg_ie_len_min[elem]))
+ {
+ err = avdt_msg_ie_err[elem];
+ break;
+ }
+
+ /* add element to psc mask, but mask out codec or protect */
+ p_cfg->psc_mask |= (1 << elem);
+ AVDT_TRACE_DEBUG3("elem=%d elem_len: %d psc_mask=0x%x", elem, elem_len, p_cfg->psc_mask);
+
+ /* parse individual information elements with additional parameters */
+ switch (elem)
+ {
+ case AVDT_CAT_RECOV:
+ p_cfg->recov_type = *p++;
+ p_cfg->recov_mrws = *p++;
+ p_cfg->recov_mnmp = *p++;
+ if (p_cfg->recov_type != AVDT_RECOV_RFC2733)
+ {
+ err = AVDT_ERR_RECOV_TYPE;
+ }
+ else if ((p_cfg->recov_mrws < AVDT_RECOV_MRWS_MIN) ||
+ (p_cfg->recov_mrws > AVDT_RECOV_MRWS_MAX) ||
+ (p_cfg->recov_mnmp < AVDT_RECOV_MNMP_MIN) ||
+ (p_cfg->recov_mnmp > AVDT_RECOV_MNMP_MAX))
+ {
+ err = AVDT_ERR_RECOV_FMT;
+ }
+ break;
+
+ case AVDT_CAT_PROTECT:
+ p_cfg->psc_mask &= ~AVDT_PSC_PROTECT;
+ if ((elem_len + protect_offset) < AVDT_PROTECT_SIZE)
+ {
+ p_cfg->num_protect++;
+ p_cfg->protect_info[protect_offset] = elem_len;
+ protect_offset++;
+ memcpy(&p_cfg->protect_info[protect_offset], p, elem_len);
+ protect_offset += elem_len;
+ }
+ p += elem_len;
+ break;
+
+ case AVDT_CAT_HDRCMP:
+ p_cfg->hdrcmp_mask = *p++;
+ break;
+
+#if AVDT_MULTIPLEXING == TRUE
+ case AVDT_CAT_MUX:
+ /* verify length */
+ AVDT_TRACE_WARNING2("psc_mask=0x%x elem_len=%d", p_cfg->psc_mask, elem_len);
+ if( ((0 == (p_cfg->psc_mask & (AVDT_PSC_RECOV|AVDT_PSC_REPORT))) && (elem_len != 3))
+ || ((p_cfg->psc_mask & AVDT_PSC_RECOV) && (elem_len != 7))
+ || ((p_cfg->psc_mask & AVDT_PSC_REPORT) && (elem_len != 5)) )
+ {
+ err = AVDT_ERR_MUX_FMT;
+ break;
+ }
+
+ /* parse fragmentation */
+ p_cfg->mux_mask = *p++ & (UINT8)AVDT_MUX_FRAG;
+
+ /* parse TSIDs and TCIDs */
+ if(--elem_len)
+ p_cfg->mux_tsid_media = (*p++)>>3;
+ else
+ break;
+
+ if(--elem_len)
+ p_cfg->mux_tcid_media = (*p++)>>3;
+ else
+ break;
+
+ if(--elem_len)
+ p_cfg->mux_tsid_report = (*p++)>>3;
+ else
+ break;
+
+ if(--elem_len)
+ p_cfg->mux_tcid_report = (*p++)>>3;
+ else
+ break;
+
+ if(--elem_len)
+ p_cfg->mux_tsid_recov = (*p++)>>3;
+ else
+ break;
+
+ if(--elem_len)
+ p_cfg->mux_tcid_recov = (*p++)>>3;
+ else
+ break;
+ break;
+#endif
+
+ case AVDT_CAT_CODEC:
+ p_cfg->psc_mask &= ~AVDT_PSC_CODEC;
+ tmp = elem_len;
+ if (elem_len >= AVDT_CODEC_SIZE)
+ {
+ tmp = AVDT_CODEC_SIZE - 1;
+ }
+ p_cfg->num_codec++;
+ p_cfg->codec_info[0] = elem_len;
+ memcpy(&p_cfg->codec_info[1], p, tmp);
+ p += elem_len;
+ break;
+
+ case AVDT_CAT_DELAY_RPT:
+ break;
+
+ default:
+ p += elem_len;
+ break;
+ } /* switch */
+ } /* while ! err, !end*/
+ *p_elem = elem;
+ AVDT_TRACE_DEBUG3("err=0x%x, elem:0x%x psc_mask=0x%x", err, elem, p_cfg->psc_mask);
+
+ return err;
+}
+
+/*******************************************************************************
+**
+** Function avdt_msg_prs_none
+**
+** Description This message parsing function parses a message with no parameters.
+
+**
+**
+** Returns Error code or zero if no error.
+**
+*******************************************************************************/
+static UINT8 avdt_msg_prs_none(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len)
+{
+ return 0;
+}
+
+/*******************************************************************************
+**
+** Function avdt_msg_prs_single
+**
+** Description This message parsing function parses a message with a
+** single SEID.
+**
+**
+** Returns Error code or zero if no error.
+**
+*******************************************************************************/
+static UINT8 avdt_msg_prs_single(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len)
+{
+ UINT8 err = 0;
+
+ /* verify len */
+ if (len != AVDT_LEN_SINGLE)
+ {
+ err = AVDT_ERR_LENGTH;
+ }
+ else
+ {
+ AVDT_MSG_PRS_SEID(p, p_msg->single.seid);
+
+ if (avdt_scb_by_hdl(p_msg->single.seid) == NULL)
+ {
+ err = AVDT_ERR_SEID;
+ }
+ }
+ return err;
+}
+
+/*******************************************************************************
+**
+** Function avdt_msg_prs_setconfig_cmd
+**
+** Description This message parsing function parses a set configuration
+** command message.
+**
+**
+** Returns Error code or zero if no error.
+**
+*******************************************************************************/
+static UINT8 avdt_msg_prs_setconfig_cmd(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len)
+{
+ UINT8 err = 0;
+
+ p_msg->hdr.err_param = 0;
+
+ /* verify len */
+ if (len < AVDT_LEN_SETCONFIG_MIN)
+ {
+ err = AVDT_ERR_LENGTH;
+ }
+ else
+ {
+ /* get seids */
+ AVDT_MSG_PRS_SEID(p, p_msg->config_cmd.hdr.seid);
+ if (avdt_scb_by_hdl(p_msg->config_cmd.hdr.seid) == NULL)
+ {
+ err = AVDT_ERR_SEID;
+ }
+
+ AVDT_MSG_PRS_SEID(p, p_msg->config_cmd.int_seid);
+ if ((p_msg->config_cmd.int_seid < AVDT_SEID_MIN) ||
+ (p_msg->config_cmd.int_seid > AVDT_SEID_MAX))
+ {
+ err = AVDT_ERR_SEID;
+ }
+ }
+
+ if (!err)
+ {
+ /* parse configuration parameters */
+ len -= 2;
+ err = avdt_msg_prs_cfg(p_msg->config_cmd.p_cfg, p, len, &p_msg->hdr.err_param, AVDT_SIG_SETCONFIG);
+
+ if (!err)
+ {
+ /* verify protocol service capabilities are supported */
+ if (((p_msg->config_cmd.p_cfg->psc_mask & (~AVDT_PSC)) != 0) ||
+ (p_msg->config_cmd.p_cfg->num_codec == 0))
+ {
+ err = AVDT_ERR_INVALID_CAP;
+ }
+ }
+ }
+
+ return err;
+}
+
+/*******************************************************************************
+**
+** Function avdt_msg_prs_reconfig_cmd
+**
+** Description This message parsing function parses a reconfiguration
+** command message.
+**
+**
+** Returns Error code or zero if no error.
+**
+*******************************************************************************/
+static UINT8 avdt_msg_prs_reconfig_cmd(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len)
+{
+ UINT8 err = 0;
+
+ p_msg->hdr.err_param = 0;
+
+ /* verify len */
+ if (len < AVDT_LEN_RECONFIG_MIN)
+ {
+ err = AVDT_ERR_LENGTH;
+ }
+ else
+ {
+ /* get seid */
+ AVDT_MSG_PRS_SEID(p, p_msg->reconfig_cmd.hdr.seid);
+ if (avdt_scb_by_hdl(p_msg->reconfig_cmd.hdr.seid) == NULL)
+ {
+ err = AVDT_ERR_SEID;
+ }
+ else
+ {
+ /* parse config parameters */
+ len--;
+ err = avdt_msg_prs_cfg(p_msg->config_cmd.p_cfg, p, len, &p_msg->hdr.err_param, AVDT_SIG_RECONFIG);
+
+ /* verify no protocol service capabilities in parameters */
+ if (!err)
+ {
+ AVDT_TRACE_DEBUG2("avdt_msg_prs_reconfig_cmd psc_mask=0x%x/0x%x", p_msg->config_cmd.p_cfg->psc_mask, AVDT_MSG_PSC_MASK);
+ if ((p_msg->config_cmd.p_cfg->psc_mask != 0) ||
+ (p_msg->config_cmd.p_cfg->num_codec == 0 && p_msg->config_cmd.p_cfg->num_protect == 0))
+ {
+ err = AVDT_ERR_INVALID_CAP;
+ }
+ }
+ }
+ }
+ return err;
+}
+
+/*******************************************************************************
+**
+** Function avdt_msg_prs_multi
+**
+** Description This message parsing function parses a message containing
+** multiple SEID's.
+**
+**
+** Returns Error code or zero if no error.
+**
+*******************************************************************************/
+static UINT8 avdt_msg_prs_multi(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len)
+{
+ int i;
+ UINT8 err = 0;
+
+ p_msg->hdr.err_param = 0;
+
+ /* verify len */
+ if (len < AVDT_LEN_MULTI_MIN || (len > AVDT_NUM_SEPS))
+ {
+ err = AVDT_ERR_LENGTH;
+ }
+ else
+ {
+ /* get and verify all seps */
+ for (i = 0; i < len; i++)
+ {
+ AVDT_MSG_PRS_SEID(p, p_msg->multi.seid_list[i]);
+ if (avdt_scb_by_hdl(p_msg->multi.seid_list[i]) == NULL)
+ {
+ err = AVDT_ERR_SEID;
+ p_msg->hdr.err_param = p_msg->multi.seid_list[i];
+ break;
+ }
+ }
+ p_msg->multi.num_seps = (UINT8)i;
+ }
+
+ return err;
+}
+
+/*******************************************************************************
+**
+** Function avdt_msg_prs_security_cmd
+**
+** Description This message parsing function parses a security
+** command message.
+**
+**
+** Returns Error code or zero if no error.
+**
+*******************************************************************************/
+static UINT8 avdt_msg_prs_security_cmd(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len)
+{
+ UINT8 err = 0;
+
+ /* verify len */
+ if (len < AVDT_LEN_SECURITY_MIN)
+ {
+ err = AVDT_ERR_LENGTH;
+ }
+ else
+ {
+ /* get seid */
+ AVDT_MSG_PRS_SEID(p, p_msg->security_cmd.hdr.seid);
+ if (avdt_scb_by_hdl(p_msg->security_cmd.hdr.seid) == NULL)
+ {
+ err = AVDT_ERR_SEID;
+ }
+ else
+ {
+ p_msg->security_cmd.p_data = p;
+ p_msg->security_cmd.len = len - 1;
+ }
+ }
+ return err;
+}
+
+/*******************************************************************************
+**
+** Function avdt_msg_prs_discover_rsp
+**
+** Description This message parsing function parses a discover
+** response message.
+**
+**
+** Returns Error code or zero if no error.
+**
+*******************************************************************************/
+static UINT8 avdt_msg_prs_discover_rsp(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len)
+{
+ int i;
+ UINT8 err = 0;
+
+ /* 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);
+ }
+
+ /* parse out sep info */
+ for (i = 0; i < p_msg->discover_rsp.num_seps; i++)
+ {
+ /* parse discover rsp info */
+ AVDT_MSG_PRS_DISC(p, p_msg->discover_rsp.p_sep_info[i].seid,
+ p_msg->discover_rsp.p_sep_info[i].in_use,
+ p_msg->discover_rsp.p_sep_info[i].media_type,
+ p_msg->discover_rsp.p_sep_info[i].tsep);
+
+ /* verify that seid is valid */
+ if ((p_msg->discover_rsp.p_sep_info[i].seid < AVDT_SEID_MIN) ||
+ (p_msg->discover_rsp.p_sep_info[i].seid > AVDT_SEID_MAX))
+ {
+ err = AVDT_ERR_SEID;
+ break;
+ }
+ }
+
+ return err;
+}
+
+/*******************************************************************************
+**
+** Function avdt_msg_prs_svccap
+**
+** Description This message parsing function parses a message containing
+** service capabilities parameters.
+**
+**
+** Returns Error code or zero if no error.
+**
+*******************************************************************************/
+static UINT8 avdt_msg_prs_svccap(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len)
+{
+ /* parse parameters */
+ 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;
+ }
+
+ return (err);
+}
+
+/*******************************************************************************
+**
+** Function avdt_msg_prs_all_svccap
+**
+** Description This message parsing function parses a message containing
+** service capabilities parameters.
+**
+**
+** Returns Error code or zero if no error.
+**
+*******************************************************************************/
+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;
+ }
+ return (err);
+}
+
+/*******************************************************************************
+**
+** Function avdt_msg_prs_security_rsp
+**
+** Description This message parsing function parsing a security
+** response message.
+**
+**
+** Returns Error code or zero if no error.
+**
+*******************************************************************************/
+static UINT8 avdt_msg_prs_security_rsp(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len)
+{
+ p_msg->security_rsp.p_data = p;
+ p_msg->security_rsp.len = len;
+
+ return 0;
+}
+
+/*******************************************************************************
+**
+** Function avdt_msg_prs_rej
+**
+** Description
+**
+**
+** Returns Error code or zero if no error.
+**
+*******************************************************************************/
+static UINT8 avdt_msg_prs_rej(tAVDT_MSG *p_msg, UINT8 *p, UINT8 sig)
+{
+ if ((sig == AVDT_SIG_SETCONFIG) || (sig == AVDT_SIG_RECONFIG))
+ {
+ p_msg->hdr.err_param = *p++;
+ p_msg->hdr.err_code = *p;
+ }
+ else if ((sig == AVDT_SIG_START) || (sig == AVDT_SIG_SUSPEND))
+ {
+ AVDT_MSG_PRS_SEID(p, p_msg->hdr.err_param);
+ p_msg->hdr.err_code = *p;
+ }
+ else
+ {
+ p_msg->hdr.err_code = *p;
+ }
+
+ return 0;
+}
+
+/*******************************************************************************
+**
+** Function avdt_msg_prs_delay_rpt
+**
+** Description This message parsing function parses a security
+** command message.
+**
+**
+** Returns Error code or zero if no error.
+**
+*******************************************************************************/
+static UINT8 avdt_msg_prs_delay_rpt (tAVDT_MSG *p_msg, UINT8 *p, UINT16 len)
+{
+ UINT8 err = 0;
+
+ /* verify len */
+ if (len != AVDT_LEN_DELAY_RPT)
+ {
+ AVDT_TRACE_WARNING2("avdt_msg_prs_delay_rpt expected len: %u got: %u", AVDT_LEN_DELAY_RPT, len);
+ err = AVDT_ERR_LENGTH;
+ }
+ else
+ {
+ /* get seid */
+ AVDT_MSG_PRS_SEID (p, p_msg->delay_rpt_cmd.hdr.seid);
+
+ if (avdt_scb_by_hdl(p_msg->delay_rpt_cmd.hdr.seid) == NULL)
+ {
+ err = AVDT_ERR_SEID;
+ }
+ else
+ {
+ BE_STREAM_TO_UINT16 (p_msg->delay_rpt_cmd.delay, p);
+ AVDT_TRACE_DEBUG1("avdt_msg_prs_delay_rpt delay: %u", p_msg->delay_rpt_cmd.delay);
+ }
+ }
+ return err;
+}
+
+
+/*******************************************************************************
+**
+** Function avdt_msg_send
+**
+** Description Send, and if necessary fragment the next message.
+**
+**
+** Returns Congested state; TRUE if CCB congested, FALSE if not.
+**
+*******************************************************************************/
+BOOLEAN avdt_msg_send(tAVDT_CCB *p_ccb, BT_HDR *p_msg)
+{
+ UINT16 curr_msg_len;
+ UINT8 pkt_type;
+ UINT8 hdr_len;
+ tAVDT_TC_TBL *p_tbl;
+ BT_HDR *p_buf;
+ UINT8 *p;
+ UINT8 label;
+ UINT8 msg;
+ UINT8 sig;
+ UINT8 nosp = 0; /* number of subsequent packets */
+
+ /* look up transport channel table entry to get peer mtu */
+ p_tbl = avdt_ad_tc_tbl_by_type(AVDT_CHAN_SIG, p_ccb, NULL);
+
+ /* set the current message if there is a message passed in */
+ if (p_msg != NULL)
+ {
+ p_ccb->p_curr_msg = p_msg;
+ }
+
+ /* store copy of curr_msg->len */
+ curr_msg_len = p_ccb->p_curr_msg->len;
+
+ /* while not congested and we haven't sent it all */
+ while ((!p_ccb->cong) && (p_ccb->p_curr_msg != NULL))
+ {
+ /* check what kind of message we've got here; we are using the offset
+ ** to indicate that a message is being fragmented
+ */
+
+ /* if message isn't being fragmented and it fits in mtu */
+ if ((p_ccb->p_curr_msg->offset == AVDT_MSG_OFFSET) &&
+ (p_ccb->p_curr_msg->len <= p_tbl->peer_mtu - AVDT_LEN_TYPE_SINGLE))
+ {
+ pkt_type = AVDT_PKT_TYPE_SINGLE;
+ hdr_len = AVDT_LEN_TYPE_SINGLE;
+ p_buf = p_ccb->p_curr_msg;
+ }
+ /* if message isn't being fragmented and it doesn't fit in mtu */
+ else if ((p_ccb->p_curr_msg->offset == AVDT_MSG_OFFSET) &&
+ (p_ccb->p_curr_msg->len > p_tbl->peer_mtu - AVDT_LEN_TYPE_SINGLE))
+ {
+ pkt_type = AVDT_PKT_TYPE_START;
+ hdr_len = AVDT_LEN_TYPE_START;
+ nosp = (p_ccb->p_curr_msg->len + AVDT_LEN_TYPE_START - p_tbl->peer_mtu) /
+ (p_tbl->peer_mtu - 1) + 2;
+
+ /* get a new buffer for fragment we are sending */
+ if ((p_buf = (BT_HDR *) GKI_getpoolbuf(AVDT_CMD_POOL_ID)) == NULL)
+ {
+ /* do we even want to try and recover from this? could do so
+ by setting retransmission timer */
+ return TRUE;
+ }
+
+ /* copy portion of data from current message to new buffer */
+ p_buf->offset = L2CAP_MIN_OFFSET + hdr_len;
+ p_buf->len = p_tbl->peer_mtu - hdr_len;
+ memcpy((UINT8 *)(p_buf + 1) + p_buf->offset,
+ (UINT8 *)(p_ccb->p_curr_msg + 1) + p_ccb->p_curr_msg->offset, p_buf->len);
+ }
+ /* if message is being fragmented and remaining bytes don't fit in mtu */
+ else if ((p_ccb->p_curr_msg->offset > AVDT_MSG_OFFSET) &&
+ (p_ccb->p_curr_msg->len > (p_tbl->peer_mtu - AVDT_LEN_TYPE_CONT)))
+ {
+ pkt_type = AVDT_PKT_TYPE_CONT;
+ hdr_len = AVDT_LEN_TYPE_CONT;
+
+ /* get a new buffer for fragment we are sending */
+ if ((p_buf = (BT_HDR *) GKI_getpoolbuf(AVDT_CMD_POOL_ID)) == NULL)
+ {
+ /* do we even want to try and recover from this? could do so
+ by setting retransmission timer */
+ return TRUE;
+ }
+
+ /* copy portion of data from current message to new buffer */
+ p_buf->offset = L2CAP_MIN_OFFSET + hdr_len;
+ p_buf->len = p_tbl->peer_mtu - hdr_len;
+ memcpy((UINT8 *)(p_buf + 1) + p_buf->offset,
+ (UINT8 *)(p_ccb->p_curr_msg + 1) + p_ccb->p_curr_msg->offset, p_buf->len);
+ }
+ /* if message is being fragmented and remaining bytes do fit in mtu */
+ else
+ {
+ pkt_type = AVDT_PKT_TYPE_END;
+ hdr_len = AVDT_LEN_TYPE_END;
+ p_buf = p_ccb->p_curr_msg;
+ }
+
+ /* label, sig id, msg type are in hdr of p_curr_msg */
+ label = AVDT_LAYERSPEC_LABEL(p_ccb->p_curr_msg->layer_specific);
+ msg = AVDT_LAYERSPEC_MSG(p_ccb->p_curr_msg->layer_specific);
+ sig = (UINT8) p_ccb->p_curr_msg->event;
+ AVDT_TRACE_DEBUG3("avdt_msg_send label:%d, msg:%d, sig:%d", label, msg, sig);
+
+ /* keep track of how much of msg we've sent */
+ curr_msg_len -= p_buf->len;
+ if (curr_msg_len == 0)
+ {
+ /* entire message sent; mark as finished */
+ p_ccb->p_curr_msg = NULL;
+
+ /* start timer here for commands */
+ if (msg == AVDT_MSG_TYPE_CMD)
+ {
+ /* if retransmit timeout set to zero, sig doesn't use retransmit */
+ if ((sig == AVDT_SIG_DISCOVER) || (sig == AVDT_SIG_GETCAP) ||
+ (sig == AVDT_SIG_SECURITY) || (avdt_cb.rcb.ret_tout == 0))
+ {
+ btu_start_timer(&p_ccb->timer_entry, BTU_TTYPE_AVDT_CCB_RSP, avdt_cb.rcb.sig_tout);
+ }
+ else if (sig != AVDT_SIG_DELAY_RPT)
+ {
+ btu_start_timer(&p_ccb->timer_entry, BTU_TTYPE_AVDT_CCB_RET, avdt_cb.rcb.ret_tout);
+ }
+ }
+ }
+ else
+ {
+ /* message being fragmented and not completely sent */
+ p_ccb->p_curr_msg->len -= p_buf->len;
+ p_ccb->p_curr_msg->offset += p_buf->len;
+ }
+
+ /* set up to build header */
+ p_buf->len += hdr_len;
+ p_buf->offset -= hdr_len;
+ p = (UINT8 *)(p_buf + 1) + p_buf->offset;
+
+ /* build header */
+ AVDT_MSG_BLD_HDR(p, label, pkt_type, msg);
+ if (pkt_type == AVDT_PKT_TYPE_START)
+ {
+ AVDT_MSG_BLD_NOSP(p, nosp);
+ }
+ if ((pkt_type == AVDT_PKT_TYPE_START) || (pkt_type == AVDT_PKT_TYPE_SINGLE))
+ {
+ AVDT_MSG_BLD_SIG(p, sig);
+ }
+
+ /* send msg buffer down */
+ avdt_ad_write_req(AVDT_CHAN_SIG, p_ccb, NULL, p_buf);
+ }
+ return (p_ccb->cong);
+}
+
+/*******************************************************************************
+**
+** Function avdt_msg_asmbl
+**
+** Description Reassemble incoming message.
+**
+**
+** Returns Pointer to reassembled message; NULL if no message
+** available.
+**
+*******************************************************************************/
+BT_HDR *avdt_msg_asmbl(tAVDT_CCB *p_ccb, BT_HDR *p_buf)
+{
+ UINT8 *p;
+ UINT8 pkt_type;
+ BT_HDR *p_ret;
+ UINT16 buf_len;
+
+ /* parse the message header */
+ p = (UINT8 *)(p_buf + 1) + p_buf->offset;
+ AVDT_MSG_PRS_PKT_TYPE(p, pkt_type);
+
+ /* quick sanity check on length */
+ if (p_buf->len < avdt_msg_pkt_type_len[pkt_type])
+ {
+ GKI_freebuf(p_buf);
+ AVDT_TRACE_WARNING0("Bad length during reassembly");
+ p_ret = NULL;
+ }
+ /* single packet */
+ else if (pkt_type == AVDT_PKT_TYPE_SINGLE)
+ {
+ /* if reassembly in progress drop message and process new single */
+ if (p_ccb->p_rx_msg != NULL)
+ {
+ GKI_freebuf(p_ccb->p_rx_msg);
+ p_ccb->p_rx_msg = NULL;
+ AVDT_TRACE_WARNING0("Got single during reassembly");
+ }
+ p_ret = p_buf;
+ }
+ /* start packet */
+ else if (pkt_type == AVDT_PKT_TYPE_START)
+ {
+ /* if reassembly in progress drop message and process new single */
+ if (p_ccb->p_rx_msg != NULL)
+ {
+ GKI_freebuf(p_ccb->p_rx_msg);
+ AVDT_TRACE_WARNING0("Got start during reassembly");
+ }
+ p_ccb->p_rx_msg = p_buf;
+
+ /* copy first header byte over nosp */
+ *(p + 1) = *p;
+
+ /* set offset to point to where to copy next */
+ p_ccb->p_rx_msg->offset += p_ccb->p_rx_msg->len;
+
+ /* adjust length for packet header */
+ p_ccb->p_rx_msg->len -= 1;
+
+ p_ret = NULL;
+ }
+ /* continue or end */
+ else
+ {
+ /* if no reassembly in progress drop message */
+ if (p_ccb->p_rx_msg == NULL)
+ {
+ GKI_freebuf(p_buf);
+ AVDT_TRACE_WARNING1("Pkt type=%d out of order", pkt_type);
+ p_ret = NULL;
+ }
+ else
+ {
+ /* get size of buffer holding assembled message */
+ buf_len = GKI_get_buf_size(p_ccb->p_rx_msg) - sizeof(BT_HDR);
+
+ /* adjust offset and len of fragment for header byte */
+ p_buf->offset += AVDT_LEN_TYPE_CONT;
+ p_buf->len -= AVDT_LEN_TYPE_CONT;
+
+ /* verify length */
+ if ((p_ccb->p_rx_msg->offset + p_buf->len) > buf_len)
+ {
+ /* won't fit; free everything */
+ GKI_freebuf(p_ccb->p_rx_msg);
+ p_ccb->p_rx_msg = NULL;
+ GKI_freebuf(p_buf);
+ p_ret = NULL;
+ }
+ else
+ {
+ /* copy contents of p_buf to p_rx_msg */
+ memcpy((UINT8 *)(p_ccb->p_rx_msg + 1) + p_ccb->p_rx_msg->offset,
+ (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;
+ }
+ else
+ {
+ p_ccb->p_rx_msg->offset += p_buf->len;
+ p_ccb->p_rx_msg->len += p_buf->len;
+ p_ret = NULL;
+ }
+ GKI_freebuf(p_buf);
+ }
+ }
+ }
+ return p_ret;
+}
+
+/*******************************************************************************
+**
+** Function avdt_msg_send_cmd
+**
+** Description This function is called to send a command message. The
+** sig_id parameter indicates the message type, p_params
+** points to the message parameters, if any. It gets a buffer
+** from the AVDTP command pool, executes the message building
+** function for this message type. It then queues the message
+** in the command queue for this CCB.
+**
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_msg_send_cmd(tAVDT_CCB *p_ccb, void *p_scb, UINT8 sig_id, tAVDT_MSG *p_params)
+{
+ BT_HDR *p_buf;
+ UINT8 *p;
+ UINT8 *p_start;
+
+ /* get a buffer */
+ p_buf = (BT_HDR *) GKI_getpoolbuf(AVDT_CMD_POOL_ID);
+ if (p_buf == NULL)
+ {
+ AVDT_TRACE_ERROR0("avdt_msg_send_cmd out of buffer!!");
+ return;
+ }
+
+ /* set up gki buf pointer and offset */
+ p_buf->offset = AVDT_MSG_OFFSET;
+ p_start = p = (UINT8 *)(p_buf + 1) + p_buf->offset;
+
+ /* execute parameter building function to build message */
+ (*avdt_msg_bld_cmd[sig_id - 1])(&p, p_params);
+
+ /* set len */
+ p_buf->len = (UINT16) (p - p_start);
+
+ /* now store scb hdls, if any, in buf */
+ if (p_scb != NULL)
+ {
+ p = (UINT8 *)(p_buf + 1);
+
+ /* for start and suspend, p_scb points to array of handles */
+ if ((sig_id == AVDT_SIG_START) || (sig_id == AVDT_SIG_SUSPEND))
+ {
+ memcpy(p, (UINT8 *) p_scb, p_buf->len);
+ }
+ /* for all others, p_scb points to scb as usual */
+ else
+ {
+ *p = avdt_scb_to_hdl((tAVDT_SCB *) p_scb);
+ }
+ }
+
+ /* stash sig, label, and message type in buf */
+ p_buf->event = sig_id;
+ AVDT_BLD_LAYERSPEC(p_buf->layer_specific, AVDT_MSG_TYPE_CMD, p_ccb->label);
+
+ /* increment label */
+ p_ccb->label = (p_ccb->label + 1) % 16;
+
+ /* queue message and trigger ccb to send it */
+ GKI_enqueue(&p_ccb->cmd_q, p_buf);
+ avdt_ccb_event(p_ccb, AVDT_CCB_SENDMSG_EVT, NULL);
+}
+
+
+/*******************************************************************************
+**
+** Function avdt_msg_send_rsp
+**
+** Description This function is called to send a response message. The
+** sig_id parameter indicates the message type, p_params
+** points to the message parameters, if any. It gets a buffer
+** from the AVDTP command pool, executes the message building
+** function for this message type. It then queues the message
+** in the response queue for this CCB.
+**
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_msg_send_rsp(tAVDT_CCB *p_ccb, UINT8 sig_id, tAVDT_MSG *p_params)
+{
+ BT_HDR *p_buf;
+ UINT8 *p;
+ UINT8 *p_start;
+
+ /* get a buffer */
+ p_buf = (BT_HDR *) GKI_getpoolbuf(AVDT_CMD_POOL_ID);
+ if (p_buf == NULL) return;
+
+ /* set up gki buf pointer and offset */
+ p_buf->offset = AVDT_MSG_OFFSET;
+ p_start = p = (UINT8 *)(p_buf + 1) + p_buf->offset;
+
+ /* execute parameter building function to build message */
+ (*avdt_msg_bld_rsp[sig_id - 1])(&p, p_params);
+
+ /* set length */
+ p_buf->len = (UINT16) (p - p_start);
+
+ /* stash sig, label, and message type in buf */
+ p_buf->event = sig_id;
+ AVDT_BLD_LAYERSPEC(p_buf->layer_specific, AVDT_MSG_TYPE_RSP, p_params->hdr.label);
+
+ /* queue message and trigger ccb to send it */
+ GKI_enqueue(&p_ccb->rsp_q, p_buf);
+ avdt_ccb_event(p_ccb, AVDT_CCB_SENDMSG_EVT, NULL);
+}
+
+
+/*******************************************************************************
+**
+** Function avdt_msg_send_rej
+**
+** Description This function is called to send a reject message. The
+** sig_id parameter indicates the message type. It gets
+** a buffer from the AVDTP command pool and builds the
+** message based on the message type and the error code.
+** It then queues the message in the response queue for
+** this CCB.
+**
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_msg_send_rej(tAVDT_CCB *p_ccb, UINT8 sig_id, tAVDT_MSG *p_params)
+{
+ BT_HDR *p_buf;
+ UINT8 *p;
+ UINT8 *p_start;
+
+ /* get a buffer */
+ p_buf = (BT_HDR *) GKI_getpoolbuf(AVDT_CMD_POOL_ID);
+ if (p_buf == NULL) return;
+
+ /* set up gki buf pointer and offset */
+ p_buf->offset = AVDT_MSG_OFFSET;
+ p_start = p = (UINT8 *)(p_buf + 1) + p_buf->offset;
+
+ /* if sig id included, build into message */
+ if (sig_id != AVDT_SIG_NONE)
+ {
+ /* if this sig has a parameter, add the parameter */
+ if ((sig_id == AVDT_SIG_SETCONFIG) ||
+ (sig_id == AVDT_SIG_RECONFIG))
+ {
+ AVDT_MSG_BLD_PARAM(p, p_params->hdr.err_param);
+ }
+ else if ((sig_id == AVDT_SIG_START) ||
+ (sig_id == AVDT_SIG_SUSPEND))
+ {
+ AVDT_MSG_BLD_SEID(p, p_params->hdr.err_param);
+ }
+
+ /* add the error code */
+ AVDT_MSG_BLD_ERR(p, p_params->hdr.err_code);
+ }
+ AVDT_TRACE_DEBUG0("avdt_msg_send_rej");
+
+ /* calculate length */
+ p_buf->len = (UINT16) (p - p_start);
+
+ /* stash sig, label, and message type in buf */
+ p_buf->event = sig_id;
+ AVDT_BLD_LAYERSPEC(p_buf->layer_specific, AVDT_MSG_TYPE_REJ, p_params->hdr.label);
+
+ /* queue message and trigger ccb to send it */
+ GKI_enqueue(&p_ccb->rsp_q, p_buf);
+ avdt_ccb_event(p_ccb, AVDT_CCB_SENDMSG_EVT, NULL);
+}
+
+/*******************************************************************************
+**
+** Function avdt_msg_send_grej
+**
+** Description This function is called to send a general reject message. The
+** sig_id parameter indicates the message type. It gets
+** a buffer from the AVDTP command pool and builds the
+** message based on the message type and the error code.
+** It then queues the message in the response queue for
+** this CCB.
+**
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_msg_send_grej(tAVDT_CCB *p_ccb, UINT8 sig_id, tAVDT_MSG *p_params)
+{
+ BT_HDR *p_buf;
+ UINT8 *p;
+ UINT8 *p_start;
+
+ /* get a buffer */
+ p_buf = (BT_HDR *) GKI_getpoolbuf(AVDT_CMD_POOL_ID);
+ if (p_buf == NULL) return;
+
+ /* set up gki buf pointer and offset */
+ p_buf->offset = AVDT_MSG_OFFSET;
+ p_start = p = (UINT8 *)(p_buf + 1) + p_buf->offset;
+
+ /* calculate length */
+ p_buf->len = (UINT16) (p - p_start);
+
+ /* stash sig, label, and message type in buf */
+ p_buf->event = sig_id;
+ AVDT_BLD_LAYERSPEC(p_buf->layer_specific, AVDT_MSG_TYPE_GRJ, p_params->hdr.label);
+ //p_buf->event = 0;
+ //AVDT_BLD_LAYERSPEC(p_buf->layer_specific, 0, p_params->hdr.label);
+ AVDT_TRACE_DEBUG0("avdt_msg_send_grej");
+
+ /* queue message and trigger ccb to send it */
+ GKI_enqueue(&p_ccb->rsp_q, p_buf);
+ avdt_ccb_event(p_ccb, AVDT_CCB_SENDMSG_EVT, NULL);
+}
+
+/*******************************************************************************
+**
+** Function avdt_msg_ind
+**
+** Description This function is called by the adaption layer when an
+** incoming message is received on the signaling channel.
+** It parses the message and sends an event to the appropriate
+** SCB or CCB for the message.
+**
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_msg_ind(tAVDT_CCB *p_ccb, BT_HDR *p_buf)
+{
+ tAVDT_SCB *p_scb;
+ UINT8 *p;
+ BOOLEAN ok = TRUE;
+ BOOLEAN handle_rsp = FALSE;
+ BOOLEAN gen_rej = FALSE;
+ UINT8 label;
+ UINT8 pkt_type;
+ UINT8 msg_type;
+ UINT8 sig = 0;
+ tAVDT_MSG msg;
+ tAVDT_CFG cfg;
+ UINT8 err;
+ UINT8 evt = 0;
+ UINT8 scb_hdl;
+
+ /* reassemble message; if no message available (we received a fragment) return */
+ if ((p_buf = avdt_msg_asmbl(p_ccb, p_buf)) == NULL)
+ {
+ return;
+ }
+
+ p = (UINT8 *)(p_buf + 1) + p_buf->offset;
+
+ /* parse the message header */
+ AVDT_MSG_PRS_HDR(p, label, pkt_type, msg_type);
+
+ /* AVDT_TRACE_DEBUG1("msg_type=%d", msg_type); */
+ /* set up label and ccb_idx in message hdr */
+ msg.hdr.label = label;
+ msg.hdr.ccb_idx = avdt_ccb_to_idx(p_ccb);
+
+ /* verify msg type */
+ if (msg_type == AVDT_MSG_TYPE_GRJ)
+ {
+ AVDT_TRACE_WARNING1("Dropping msg msg_type=%d", msg_type);
+ ok = FALSE;
+ }
+ /* check for general reject */
+ else if ((msg_type == AVDT_MSG_TYPE_REJ) && (p_buf->len == AVDT_LEN_GEN_REJ))
+ {
+ 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];
+ msg.hdr.err_code = AVDT_ERR_NSC;
+ msg.hdr.err_param = 0;
+ }
+ }
+ else /* not a general reject */
+ {
+ /* get and verify signal */
+ AVDT_MSG_PRS_SIG(p, sig);
+ msg.hdr.sig_id = sig;
+ if ((sig == 0) || (sig > AVDT_SIG_MAX))
+ {
+ AVDT_TRACE_WARNING2("Dropping msg sig=%d msg_type:%d", sig, msg_type);
+ ok = FALSE;
+
+ /* send a general reject */
+ if (msg_type == AVDT_MSG_TYPE_CMD)
+ {
+ avdt_msg_send_grej(p_ccb, sig, &msg);
+ }
+ }
+ }
+
+ if (ok && !gen_rej)
+ {
+ /* skip over header (msg length already verified during reassembly) */
+ p_buf->len -= AVDT_LEN_TYPE_SINGLE;
+
+ /* set up to parse message */
+ if ((msg_type == AVDT_MSG_TYPE_RSP) && (sig == AVDT_SIG_DISCOVER))
+ {
+ /* parse discover rsp message to struct supplied by app */
+ msg.discover_rsp.p_sep_info = (tAVDT_SEP_INFO *) p_ccb->p_proc_data;
+ msg.discover_rsp.num_seps = p_ccb->proc_param;
+ }
+ else if ((msg_type == AVDT_MSG_TYPE_RSP) &&
+ ((sig == AVDT_SIG_GETCAP) || (sig == AVDT_SIG_GET_ALLCAP)))
+ {
+ /* parse discover rsp message to struct supplied by app */
+ msg.svccap.p_cfg = (tAVDT_CFG *) p_ccb->p_proc_data;
+ }
+ else if ((msg_type == AVDT_MSG_TYPE_RSP) && (sig == AVDT_SIG_GETCONFIG))
+ {
+ /* parse get config rsp message to struct allocated locally */
+ msg.svccap.p_cfg = &cfg;
+ }
+ else if ((msg_type == AVDT_MSG_TYPE_CMD) && (sig == AVDT_SIG_SETCONFIG))
+ {
+ /* parse config cmd message to struct allocated locally */
+ msg.config_cmd.p_cfg = &cfg;
+ }
+ else if ((msg_type == AVDT_MSG_TYPE_CMD) && (sig == AVDT_SIG_RECONFIG))
+ {
+ /* parse reconfig cmd message to struct allocated locally */
+ msg.reconfig_cmd.p_cfg = &cfg;
+ }
+
+ /* parse message; while we're at it map message sig to event */
+ if (msg_type == AVDT_MSG_TYPE_CMD)
+ {
+ msg.hdr.err_code = err = (*avdt_msg_prs_cmd[sig - 1])(&msg, p, p_buf->len);
+ evt = avdt_msg_cmd_2_evt[sig - 1];
+ }
+ else if (msg_type == AVDT_MSG_TYPE_RSP)
+ {
+ msg.hdr.err_code = err = (*avdt_msg_prs_rsp[sig - 1])(&msg, p, p_buf->len);
+ evt = avdt_msg_rsp_2_evt[sig - 1];
+ }
+ else /* msg_type == AVDT_MSG_TYPE_REJ */
+ {
+ err = avdt_msg_prs_rej(&msg, p, sig);
+ evt = avdt_msg_rej_2_evt[sig - 1];
+ }
+
+ /* if parsing failed */
+ if (err != 0)
+ {
+ AVDT_TRACE_WARNING2("Parsing failed sig=%d err=0x%x", sig, err);
+
+ /* if its a rsp or rej, drop it; if its a cmd, send a rej;
+ ** note special case for abort; never send abort reject
+ */
+ ok = FALSE;
+ if ((msg_type == AVDT_MSG_TYPE_CMD) && (sig != AVDT_SIG_ABORT))
+ {
+ avdt_msg_send_rej(p_ccb, sig, &msg);
+ }
+ }
+ }
+
+ /* if its a rsp or rej, check sent cmd to see if we're waiting for
+ ** the rsp or rej. If we didn't send a cmd for it, drop it. If
+ ** it does match a cmd, stop timer for the cmd.
+ */
+ if (ok)
+ {
+ if ((msg_type == AVDT_MSG_TYPE_RSP) || (msg_type == AVDT_MSG_TYPE_REJ))
+ {
+ if ((p_ccb->p_curr_cmd != NULL) &&
+ (p_ccb->p_curr_cmd->event == sig) &&
+ (AVDT_LAYERSPEC_LABEL(p_ccb->p_curr_cmd->layer_specific) == label))
+ {
+ /* stop timer */
+ btu_stop_timer(&p_ccb->timer_entry);
+
+ /* clear retransmission count */
+ p_ccb->ret_count = 0;
+
+ /* later in this function handle ccb event */
+ handle_rsp = TRUE;
+ }
+ else
+ {
+ ok = FALSE;
+ AVDT_TRACE_WARNING2("Cmd not found for rsp sig=%d label=%d", sig, label);
+ }
+ }
+ }
+
+ if (ok)
+ {
+ /* if it's a ccb event send to ccb */
+ if (evt & AVDT_CCB_MKR)
+ {
+ avdt_ccb_event(p_ccb, (UINT8)(evt & ~AVDT_CCB_MKR), (tAVDT_CCB_EVT *) &msg);
+ }
+ /* if it's a scb event */
+ else
+ {
+ /* Scb events always have a single seid. For cmd, get seid from
+ ** message. For rej and rsp, get seid from p_curr_cmd.
+ */
+ if (msg_type == AVDT_MSG_TYPE_CMD)
+ {
+ scb_hdl = msg.single.seid;
+ }
+ else
+ {
+ scb_hdl = *((UINT8 *)(p_ccb->p_curr_cmd + 1));
+ }
+
+ /* Map seid to the scb and send it the event. For cmd, seid has
+ ** already been verified by parsing function.
+ */
+ if (evt && (p_scb = avdt_scb_by_hdl(scb_hdl)) != NULL)
+ {
+ avdt_scb_event(p_scb, evt, (tAVDT_SCB_EVT *) &msg);
+ }
+ }
+ }
+
+ /* free message buffer */
+ GKI_freebuf(p_buf);
+
+ /* if its a rsp or rej, send event to ccb to free associated
+ ** cmd msg buffer and handle cmd queue
+ */
+ if (handle_rsp)
+ {
+ avdt_ccb_event(p_ccb, AVDT_CCB_RCVRSP_EVT, NULL);
+ }
+}
diff --git a/stack/avdt/avdt_scb.c b/stack/avdt/avdt_scb.c
new file mode 100644
index 0000000..b44af06
--- /dev/null
+++ b/stack/avdt/avdt_scb.c
@@ -0,0 +1,800 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2002-2012 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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This module contains the stream control block and functions which
+ * operate on the stream control block.
+ *
+ ******************************************************************************/
+
+#include <string.h>
+#include "data_types.h"
+#include "bt_target.h"
+#include "avdt_api.h"
+#include "avdtc_api.h"
+#include "avdt_int.h"
+#include "gki.h"
+#include "btu.h"
+
+/*****************************************************************************
+** state machine constants and types
+*****************************************************************************/
+#if AVDT_DEBUG == TRUE
+
+/* verbose state strings for trace */
+const char * const avdt_scb_st_str[] = {
+ "SCB_IDLE_ST",
+ "SCB_CONF_ST",
+ "SCB_OPENING_ST",
+ "SCB_OPEN_ST",
+ "SCB_STREAM_ST",
+ "SCB_CLOSING_ST"
+};
+
+/* verbose event strings for trace */
+const char * const avdt_scb_evt_str[] = {
+ "API_REMOVE_EVT",
+ "API_WRITE_REQ_EVT",
+ "API_GETCONFIG_REQ_EVT",
+ "API_DELAY_RPT_REQ",
+ "API_SETCONFIG_REQ_EVT",
+ "API_OPEN_REQ_EVT",
+ "API_CLOSE_REQ_EVT",
+ "API_RECONFIG_REQ_EVT",
+ "API_SECURITY_REQ_EVT",
+ "API_ABORT_REQ_EVT",
+ "API_GETCONFIG_RSP_EVT",
+ "API_SETCONFIG_RSP_EVT",
+ "API_SETCONFIG_REJ_EVT",
+ "API_OPEN_RSP_EVT",
+ "API_CLOSE_RSP_EVT",
+ "API_RECONFIG_RSP_EVT",
+ "API_SECURITY_RSP_EVT",
+ "API_ABORT_RSP_EVT",
+ "MSG_SETCONFIG_CMD_EVT",
+ "MSG_GETCONFIG_CMD_EVT",
+ "MSG_OPEN_CMD_EVT",
+ "MSG_START_CMD_EVT",
+ "MSG_SUSPEND_CMD_EVT",
+ "MSG_CLOSE_CMD_EVT",
+ "MSG_ABORT_CMD_EVT",
+ "MSG_RECONFIG_CMD_EVT",
+ "MSG_SECURITY_CMD_EVT",
+ "MSG_DELAY_RPT_CMD_EVT",
+ "MSG_DELAY_RPT_RSP_EVT",
+ "MSG_SETCONFIG_RSP_EVT",
+ "MSG_GETCONFIG_RSP_EVT",
+ "MSG_OPEN_RSP_EVT",
+ "MSG_START_RSP_EVT",
+ "MSG_SUSPEND_RSP_EVT",
+ "MSG_CLOSE_RSP_EVT",
+ "MSG_ABORT_RSP_EVT",
+ "MSG_RECONFIG_RSP_EVT",
+ "MSG_SECURITY_RSP_EVT",
+ "MSG_SETCONFIG_REJ_EVT",
+ "MSG_OPEN_REJ_EVT",
+ "MSG_START_REJ_EVT",
+ "MSG_SUSPEND_REJ_EVT",
+ "TC_TOUT_EVT",
+ "TC_OPEN_EVT",
+ "TC_CLOSE_EVT",
+ "TC_CONG_EVT",
+ "TC_DATA_EVT",
+ "CC_CLOSE_EVT"
+};
+
+#endif
+
+
+/* action function list */
+const tAVDT_SCB_ACTION avdt_scb_action[] = {
+ avdt_scb_hdl_abort_cmd,
+ avdt_scb_hdl_abort_rsp,
+ avdt_scb_hdl_close_cmd,
+ avdt_scb_hdl_close_rsp,
+ avdt_scb_hdl_getconfig_cmd,
+ avdt_scb_hdl_getconfig_rsp,
+ avdt_scb_hdl_open_cmd,
+ avdt_scb_hdl_open_rej,
+ avdt_scb_hdl_open_rsp,
+ avdt_scb_hdl_pkt,
+ avdt_scb_drop_pkt,
+ avdt_scb_hdl_reconfig_cmd,
+ avdt_scb_hdl_reconfig_rsp,
+ avdt_scb_hdl_security_cmd,
+ avdt_scb_hdl_security_rsp,
+ avdt_scb_hdl_setconfig_cmd,
+ avdt_scb_hdl_setconfig_rej,
+ avdt_scb_hdl_setconfig_rsp,
+ avdt_scb_hdl_start_cmd,
+ avdt_scb_hdl_start_rsp,
+ avdt_scb_hdl_suspend_cmd,
+ avdt_scb_hdl_suspend_rsp,
+ avdt_scb_hdl_tc_close,
+#if AVDT_REPORTING == TRUE
+ avdt_scb_hdl_tc_close_sto,
+#endif
+ avdt_scb_hdl_tc_open,
+#if AVDT_REPORTING == TRUE
+ avdt_scb_hdl_tc_open_sto,
+#endif
+ avdt_scb_snd_delay_rpt_req,
+ avdt_scb_hdl_delay_rpt_cmd,
+ avdt_scb_hdl_delay_rpt_rsp,
+ avdt_scb_hdl_write_req,
+ avdt_scb_snd_abort_req,
+ avdt_scb_snd_abort_rsp,
+ avdt_scb_snd_close_req,
+ avdt_scb_snd_stream_close,
+ avdt_scb_snd_close_rsp,
+ avdt_scb_snd_getconfig_req,
+ avdt_scb_snd_getconfig_rsp,
+ avdt_scb_snd_open_req,
+ avdt_scb_snd_open_rsp,
+ avdt_scb_snd_reconfig_req,
+ avdt_scb_snd_reconfig_rsp,
+ avdt_scb_snd_security_req,
+ avdt_scb_snd_security_rsp,
+ avdt_scb_snd_setconfig_req,
+ avdt_scb_snd_setconfig_rej,
+ avdt_scb_snd_setconfig_rsp,
+ avdt_scb_snd_tc_close,
+ avdt_scb_cb_err,
+ avdt_scb_cong_state,
+ avdt_scb_rej_state,
+ avdt_scb_rej_in_use,
+ avdt_scb_rej_not_in_use,
+ avdt_scb_set_remove,
+ avdt_scb_free_pkt,
+ avdt_scb_clr_pkt,
+ avdt_scb_chk_snd_pkt,
+ avdt_scb_tc_timer,
+ avdt_scb_clr_vars,
+ avdt_scb_dealloc
+};
+
+/* state table information */
+#define AVDT_SCB_ACTIONS 2 /* number of actions */
+#define AVDT_SCB_NEXT_STATE 2 /* position of next state */
+#define AVDT_SCB_NUM_COLS 3 /* number of columns in state tables */
+
+/* state table for idle state */
+const UINT8 avdt_scb_st_idle[][AVDT_SCB_NUM_COLS] = {
+/* Event Action 1 Action 2 Next state */
+/* API_REMOVE_EVT */ {AVDT_SCB_DEALLOC, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* API_WRITE_REQ_EVT */ {AVDT_SCB_FREE_PKT, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* API_GETCONFIG_REQ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* API_DELAY_RPT_REQ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* API_SETCONFIG_REQ_EVT */ {AVDT_SCB_SND_SETCONFIG_REQ, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* API_OPEN_REQ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* API_CLOSE_REQ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* API_RECONFIG_REQ_EVT */ {AVDT_SCB_CB_ERR, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* API_SECURITY_REQ_EVT */ {AVDT_SCB_CB_ERR, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* API_ABORT_REQ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* API_GETCONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* API_SETCONFIG_RSP_EVT */ {AVDT_SCB_SND_SETCONFIG_RSP, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
+/* API_SETCONFIG_REJ_EVT */ {AVDT_SCB_SND_SETCONFIG_REJ, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* API_OPEN_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* API_CLOSE_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* API_RECONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* API_SECURITY_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* API_ABORT_RSP_EVT */ {AVDT_SCB_SND_ABORT_RSP, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* MSG_SETCONFIG_CMD_EVT */ {AVDT_SCB_HDL_SETCONFIG_CMD, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* MSG_GETCONFIG_CMD_EVT */ {AVDT_SCB_REJ_STATE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* MSG_OPEN_CMD_EVT */ {AVDT_SCB_REJ_STATE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* MSG_START_CMD_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* MSG_SUSPEND_CMD_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* MSG_CLOSE_CMD_EVT */ {AVDT_SCB_REJ_STATE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* MSG_ABORT_CMD_EVT */ {AVDT_SCB_HDL_ABORT_CMD, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* MSG_RECONFIG_CMD_EVT */ {AVDT_SCB_REJ_NOT_IN_USE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* MSG_SECURITY_CMD_EVT */ {AVDT_SCB_REJ_STATE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* MSG_DELAY_RPT_CMD_EVT */ {AVDT_SCB_REJ_STATE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* MSG_DELAY_RPT_RSP_EVT */ {AVDT_SCB_HDL_DELAY_RPT_RSP, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* MSG_SETCONFIG_RSP_EVT */ {AVDT_SCB_HDL_SETCONFIG_RSP, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
+/* MSG_GETCONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* MSG_OPEN_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* MSG_START_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* MSG_SUSPEND_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* MSG_CLOSE_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* MSG_ABORT_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* MSG_RECONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* MSG_SECURITY_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* MSG_SETCONFIG_REJ_EVT */ {AVDT_SCB_HDL_SETCONFIG_REJ, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* MSG_OPEN_REJ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* MSG_START_REJ_EVT */ {AVDT_SCB_HDL_START_RSP, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* MSG_SUSPEND_REJ_EVT */ {AVDT_SCB_HDL_SUSPEND_RSP, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* TC_TOUT_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* TC_OPEN_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* TC_CLOSE_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* TC_CONG_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* TC_DATA_EVT */ {AVDT_SCB_DROP_PKT, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* CC_CLOSE_EVT */ {AVDT_SCB_CLR_VARS, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST}
+};
+
+/* state table for configured state */
+const UINT8 avdt_scb_st_conf[][AVDT_SCB_NUM_COLS] = {
+/* Event Action 1 Action 2 Next state */
+/* API_REMOVE_EVT */ {AVDT_SCB_SND_ABORT_REQ, AVDT_SCB_SET_REMOVE, AVDT_SCB_CONF_ST},
+/* API_WRITE_REQ_EVT */ {AVDT_SCB_FREE_PKT, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
+/* API_GETCONFIG_REQ_EVT */ {AVDT_SCB_SND_GETCONFIG_REQ, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
+/* API_DELAY_RPT_REQ_EVT */ {AVDT_SCB_SND_DELAY_RPT_REQ, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
+/* API_SETCONFIG_REQ_EVT */ {AVDT_SCB_CB_ERR, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
+/* API_OPEN_REQ_EVT */ {AVDT_SCB_SND_OPEN_REQ, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
+/* API_CLOSE_REQ_EVT */ {AVDT_SCB_SND_ABORT_REQ, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
+/* API_RECONFIG_REQ_EVT */ {AVDT_SCB_CB_ERR, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
+/* API_SECURITY_REQ_EVT */ {AVDT_SCB_SND_SECURITY_REQ, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
+/* API_ABORT_REQ_EVT */ {AVDT_SCB_SND_ABORT_REQ, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
+/* API_GETCONFIG_RSP_EVT */ {AVDT_SCB_SND_GETCONFIG_RSP, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
+/* API_SETCONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
+/* API_SETCONFIG_REJ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
+/* API_OPEN_RSP_EVT */ {AVDT_SCB_SND_OPEN_RSP, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
+/* API_CLOSE_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
+/* API_RECONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
+/* API_SECURITY_RSP_EVT */ {AVDT_SCB_SND_SECURITY_RSP, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
+/* API_ABORT_RSP_EVT */ {AVDT_SCB_SND_ABORT_RSP, AVDT_SCB_HDL_TC_CLOSE, AVDT_SCB_IDLE_ST},
+/* MSG_SETCONFIG_CMD_EVT */ {AVDT_SCB_REJ_IN_USE, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
+/* MSG_GETCONFIG_CMD_EVT */ {AVDT_SCB_HDL_GETCONFIG_CMD, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
+/* MSG_OPEN_CMD_EVT */ {AVDT_SCB_HDL_OPEN_CMD, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
+/* MSG_START_CMD_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
+/* MSG_SUSPEND_CMD_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
+/* MSG_CLOSE_CMD_EVT */ {AVDT_SCB_REJ_STATE, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
+/* MSG_ABORT_CMD_EVT */ {AVDT_SCB_HDL_ABORT_CMD, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
+/* MSG_RECONFIG_CMD_EVT */ {AVDT_SCB_REJ_STATE, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
+/* MSG_SECURITY_CMD_EVT */ {AVDT_SCB_HDL_SECURITY_CMD, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
+/* MSG_DELAY_RPT_CMD_EVT */ {AVDT_SCB_HDL_DELAY_RPT_CMD, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
+/* MSG_DELAY_RPT_RSP_EVT */ {AVDT_SCB_HDL_DELAY_RPT_RSP, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
+/* MSG_SETCONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
+/* MSG_GETCONFIG_RSP_EVT */ {AVDT_SCB_HDL_GETCONFIG_RSP, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
+/* MSG_OPEN_RSP_EVT */ {AVDT_SCB_HDL_OPEN_RSP, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
+/* MSG_START_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
+/* MSG_SUSPEND_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
+/* MSG_CLOSE_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
+/* MSG_ABORT_RSP_EVT */ {AVDT_SCB_HDL_ABORT_RSP, AVDT_SCB_HDL_TC_CLOSE, AVDT_SCB_IDLE_ST},
+/* MSG_RECONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
+/* MSG_SECURITY_RSP_EVT */ {AVDT_SCB_HDL_SECURITY_RSP, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
+/* MSG_SETCONFIG_REJ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
+/* MSG_OPEN_REJ_EVT */ {AVDT_SCB_HDL_OPEN_REJ, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* MSG_START_REJ_EVT */ {AVDT_SCB_HDL_START_RSP, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
+/* MSG_SUSPEND_REJ_EVT */ {AVDT_SCB_HDL_SUSPEND_RSP, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
+/* TC_TOUT_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
+/* TC_OPEN_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
+/* TC_CLOSE_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
+/* TC_CONG_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
+/* TC_DATA_EVT */ {AVDT_SCB_DROP_PKT, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
+/* CC_CLOSE_EVT */ {AVDT_SCB_HDL_TC_CLOSE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST}
+};
+
+/* state table for opening state */
+const UINT8 avdt_scb_st_opening[][AVDT_SCB_NUM_COLS] = {
+/* Event Action 1 Action 2 Next state */
+/* API_REMOVE_EVT */ {AVDT_SCB_SND_CLOSE_REQ, AVDT_SCB_SET_REMOVE, AVDT_SCB_CLOSING_ST},
+/* API_WRITE_REQ_EVT */ {AVDT_SCB_FREE_PKT, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
+/* API_GETCONFIG_REQ_EVT */ {AVDT_SCB_SND_GETCONFIG_REQ, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
+/* API_DELAY_RPT_REQ_EVT */ {AVDT_SCB_SND_DELAY_RPT_REQ, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
+/* API_SETCONFIG_REQ_EVT */ {AVDT_SCB_CB_ERR, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
+/* API_OPEN_REQ_EVT */ {AVDT_SCB_CB_ERR, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
+/* API_CLOSE_REQ_EVT */ {AVDT_SCB_SND_CLOSE_REQ, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* API_RECONFIG_REQ_EVT */ {AVDT_SCB_CB_ERR, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
+/* API_SECURITY_REQ_EVT */ {AVDT_SCB_SND_SECURITY_REQ, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
+/* API_ABORT_REQ_EVT */ {AVDT_SCB_SND_ABORT_REQ, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* API_GETCONFIG_RSP_EVT */ {AVDT_SCB_SND_GETCONFIG_RSP, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
+/* API_SETCONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
+/* API_SETCONFIG_REJ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
+/* API_OPEN_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
+/* API_CLOSE_RSP_EVT */ {AVDT_SCB_SND_CLOSE_RSP, AVDT_SCB_SND_TC_CLOSE, AVDT_SCB_CLOSING_ST},
+/* API_RECONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
+/* API_SECURITY_RSP_EVT */ {AVDT_SCB_SND_SECURITY_RSP, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
+/* API_ABORT_RSP_EVT */ {AVDT_SCB_SND_ABORT_RSP, AVDT_SCB_SND_TC_CLOSE, AVDT_SCB_CLOSING_ST},
+/* MSG_SETCONFIG_CMD_EVT */ {AVDT_SCB_REJ_STATE, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
+/* MSG_GETCONFIG_CMD_EVT */ {AVDT_SCB_HDL_GETCONFIG_CMD, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
+/* MSG_OPEN_CMD_EVT */ {AVDT_SCB_REJ_STATE, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
+/* MSG_START_CMD_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
+/* MSG_SUSPEND_CMD_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
+/* MSG_CLOSE_CMD_EVT */ {AVDT_SCB_HDL_CLOSE_CMD, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
+/* MSG_ABORT_CMD_EVT */ {AVDT_SCB_HDL_ABORT_CMD, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
+/* MSG_RECONFIG_CMD_EVT */ {AVDT_SCB_REJ_STATE, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
+/* MSG_SECURITY_CMD_EVT */ {AVDT_SCB_HDL_SECURITY_CMD, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
+/* MSG_DELAY_RPT_CMD_EVT */ {AVDT_SCB_HDL_DELAY_RPT_CMD, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
+/* MSG_DELAY_RPT_RSP_EVT */ {AVDT_SCB_HDL_DELAY_RPT_RSP, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
+/* MSG_SETCONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
+/* MSG_GETCONFIG_RSP_EVT */ {AVDT_SCB_HDL_GETCONFIG_RSP, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
+/* MSG_OPEN_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
+/* MSG_START_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
+/* MSG_SUSPEND_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
+/* MSG_CLOSE_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
+/* MSG_ABORT_RSP_EVT */ {AVDT_SCB_SND_TC_CLOSE, AVDT_SCB_HDL_ABORT_RSP, AVDT_SCB_CLOSING_ST},
+/* MSG_RECONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
+/* MSG_SECURITY_RSP_EVT */ {AVDT_SCB_HDL_SECURITY_RSP, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
+/* MSG_SETCONFIG_REJ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
+/* MSG_OPEN_REJ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
+/* MSG_START_REJ_EVT */ {AVDT_SCB_HDL_START_RSP, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
+/* MSG_SUSPEND_REJ_EVT */ {AVDT_SCB_HDL_SUSPEND_RSP, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
+/* TC_TOUT_EVT */ {AVDT_SCB_SND_ABORT_REQ, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* TC_OPEN_EVT */ {AVDT_SCB_HDL_TC_OPEN, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
+/* TC_CLOSE_EVT */ {AVDT_SCB_HDL_TC_CLOSE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* TC_CONG_EVT */ {AVDT_SCB_CONG_STATE, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
+/* TC_DATA_EVT */ {AVDT_SCB_DROP_PKT, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
+/* CC_CLOSE_EVT */ {AVDT_SCB_SND_TC_CLOSE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST}
+};
+
+/* state table for open state */
+const UINT8 avdt_scb_st_open[][AVDT_SCB_NUM_COLS] = {
+/* Event Action 1 Action 2 Next state */
+/* API_REMOVE_EVT */ {AVDT_SCB_SND_CLOSE_REQ, AVDT_SCB_SET_REMOVE, AVDT_SCB_CLOSING_ST},
+/* API_WRITE_REQ_EVT */ {AVDT_SCB_FREE_PKT, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
+/* API_GETCONFIG_REQ_EVT */ {AVDT_SCB_SND_GETCONFIG_REQ, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
+/* API_DELAY_RPT_REQ_EVT */ {AVDT_SCB_SND_DELAY_RPT_REQ, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
+/* API_SETCONFIG_REQ_EVT */ {AVDT_SCB_CB_ERR, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
+/* API_OPEN_REQ_EVT */ {AVDT_SCB_CB_ERR, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
+/* API_CLOSE_REQ_EVT */ {AVDT_SCB_SND_CLOSE_REQ, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* API_RECONFIG_REQ_EVT */ {AVDT_SCB_SND_RECONFIG_REQ, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
+/* API_SECURITY_REQ_EVT */ {AVDT_SCB_SND_SECURITY_REQ, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
+/* API_ABORT_REQ_EVT */ {AVDT_SCB_SND_ABORT_REQ, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* API_GETCONFIG_RSP_EVT */ {AVDT_SCB_SND_GETCONFIG_RSP, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
+/* API_SETCONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
+/* API_SETCONFIG_REJ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
+/* API_OPEN_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
+/* API_CLOSE_RSP_EVT */ {AVDT_SCB_SND_CLOSE_RSP, AVDT_SCB_TC_TIMER, AVDT_SCB_CLOSING_ST},
+/* API_RECONFIG_RSP_EVT */ {AVDT_SCB_SND_RECONFIG_RSP, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
+/* API_SECURITY_RSP_EVT */ {AVDT_SCB_SND_SECURITY_RSP, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
+/* API_ABORT_RSP_EVT */ {AVDT_SCB_SND_ABORT_RSP, AVDT_SCB_TC_TIMER, AVDT_SCB_CLOSING_ST},
+/* MSG_SETCONFIG_CMD_EVT */ {AVDT_SCB_REJ_STATE, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
+/* MSG_GETCONFIG_CMD_EVT */ {AVDT_SCB_HDL_GETCONFIG_CMD, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
+/* MSG_OPEN_CMD_EVT */ {AVDT_SCB_REJ_STATE, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
+/* MSG_START_CMD_EVT */ {AVDT_SCB_HDL_START_CMD, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
+/* MSG_SUSPEND_CMD_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
+/* MSG_CLOSE_CMD_EVT */ {AVDT_SCB_HDL_CLOSE_CMD, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
+/* MSG_ABORT_CMD_EVT */ {AVDT_SCB_HDL_ABORT_CMD, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
+/* MSG_RECONFIG_CMD_EVT */ {AVDT_SCB_HDL_RECONFIG_CMD, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
+/* MSG_SECURITY_CMD_EVT */ {AVDT_SCB_HDL_SECURITY_CMD, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
+/* MSG_DELAY_RPT_CMD_EVT */ {AVDT_SCB_HDL_DELAY_RPT_CMD, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
+/* MSG_DELAY_RPT_RSP_EVT */ {AVDT_SCB_HDL_DELAY_RPT_RSP, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
+/* MSG_SETCONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
+/* MSG_GETCONFIG_RSP_EVT */ {AVDT_SCB_HDL_GETCONFIG_RSP, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
+/* MSG_OPEN_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
+/* MSG_START_RSP_EVT */ {AVDT_SCB_HDL_START_RSP, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
+/* MSG_SUSPEND_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
+/* MSG_CLOSE_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
+/* MSG_ABORT_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* MSG_RECONFIG_RSP_EVT */ {AVDT_SCB_HDL_RECONFIG_RSP, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
+/* MSG_SECURITY_RSP_EVT */ {AVDT_SCB_HDL_SECURITY_RSP, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
+/* MSG_SETCONFIG_REJ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
+/* MSG_OPEN_REJ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
+/* MSG_START_REJ_EVT */ {AVDT_SCB_HDL_START_RSP, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
+/* MSG_SUSPEND_REJ_EVT */ {AVDT_SCB_HDL_SUSPEND_RSP, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
+/* TC_TOUT_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
+#if AVDT_REPORTING == TRUE
+/* TC_OPEN_EVT */ {AVDT_SCB_HDL_TC_OPEN_STO, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
+/* TC_CLOSE_EVT */ {AVDT_SCB_HDL_TC_CLOSE_STO, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
+#else
+/* TC_OPEN_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
+/* TC_CLOSE_EVT */ {AVDT_SCB_HDL_TC_CLOSE, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
+#endif
+/* TC_CONG_EVT */ {AVDT_SCB_CONG_STATE, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
+/* TC_DATA_EVT */ {AVDT_SCB_DROP_PKT, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
+/* CC_CLOSE_EVT */ {AVDT_SCB_SND_TC_CLOSE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST}
+};
+
+/* state table for streaming state */
+const UINT8 avdt_scb_st_stream[][AVDT_SCB_NUM_COLS] = {
+/* Event Action 1 Action 2 Next state */
+/* API_REMOVE_EVT */ {AVDT_SCB_SND_STREAM_CLOSE, AVDT_SCB_SET_REMOVE, AVDT_SCB_CLOSING_ST},
+/* API_WRITE_REQ_EVT */ {AVDT_SCB_HDL_WRITE_REQ, AVDT_SCB_CHK_SND_PKT, AVDT_SCB_STREAM_ST},
+/* API_GETCONFIG_REQ_EVT */ {AVDT_SCB_SND_GETCONFIG_REQ, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
+/* API_DELAY_RPT_REQ_EVT */ {AVDT_SCB_SND_DELAY_RPT_REQ, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
+/* API_SETCONFIG_REQ_EVT */ {AVDT_SCB_CB_ERR, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
+/* API_OPEN_REQ_EVT */ {AVDT_SCB_CB_ERR, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
+/* API_CLOSE_REQ_EVT */ {AVDT_SCB_SND_STREAM_CLOSE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* API_RECONFIG_REQ_EVT */ {AVDT_SCB_CB_ERR, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
+/* API_SECURITY_REQ_EVT */ {AVDT_SCB_SND_SECURITY_REQ, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
+/* API_ABORT_REQ_EVT */ {AVDT_SCB_SND_ABORT_REQ, AVDT_SCB_CLR_PKT, AVDT_SCB_CLOSING_ST},
+/* API_GETCONFIG_RSP_EVT */ {AVDT_SCB_SND_GETCONFIG_RSP, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
+/* API_SETCONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
+/* API_SETCONFIG_REJ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
+/* API_OPEN_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
+/* API_CLOSE_RSP_EVT */ {AVDT_SCB_SND_CLOSE_RSP, AVDT_SCB_TC_TIMER, AVDT_SCB_CLOSING_ST},
+/* API_RECONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
+/* API_SECURITY_RSP_EVT */ {AVDT_SCB_SND_SECURITY_RSP, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
+/* API_ABORT_RSP_EVT */ {AVDT_SCB_SND_ABORT_RSP, AVDT_SCB_TC_TIMER, AVDT_SCB_CLOSING_ST},
+/* MSG_SETCONFIG_CMD_EVT */ {AVDT_SCB_REJ_STATE, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
+/* MSG_GETCONFIG_CMD_EVT */ {AVDT_SCB_HDL_GETCONFIG_CMD, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
+/* MSG_OPEN_CMD_EVT */ {AVDT_SCB_REJ_STATE, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
+/* MSG_START_CMD_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
+/* MSG_SUSPEND_CMD_EVT */ {AVDT_SCB_HDL_SUSPEND_CMD, AVDT_SCB_CLR_PKT, AVDT_SCB_OPEN_ST},
+/* MSG_CLOSE_CMD_EVT */ {AVDT_SCB_HDL_CLOSE_CMD, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
+/* MSG_ABORT_CMD_EVT */ {AVDT_SCB_HDL_ABORT_CMD, AVDT_SCB_CLR_PKT, AVDT_SCB_STREAM_ST},
+/* MSG_RECONFIG_CMD_EVT */ {AVDT_SCB_REJ_STATE, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
+/* MSG_SECURITY_CMD_EVT */ {AVDT_SCB_HDL_SECURITY_CMD, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
+/* MSG_DELAY_RPT_CMD_EVT */ {AVDT_SCB_HDL_DELAY_RPT_CMD, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
+/* MSG_DELAY_RPT_RSP_EVT */ {AVDT_SCB_HDL_DELAY_RPT_RSP, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
+/* MSG_SETCONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
+/* MSG_GETCONFIG_RSP_EVT */ {AVDT_SCB_HDL_GETCONFIG_RSP, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
+/* MSG_OPEN_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
+/* MSG_START_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
+/* MSG_SUSPEND_RSP_EVT */ {AVDT_SCB_HDL_SUSPEND_RSP, AVDT_SCB_CLR_PKT, AVDT_SCB_OPEN_ST},
+/* MSG_CLOSE_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
+/* MSG_ABORT_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
+/* MSG_RECONFIG_RSP_EVT */ {AVDT_SCB_HDL_RECONFIG_RSP, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
+/* MSG_SECURITY_RSP_EVT */ {AVDT_SCB_HDL_SECURITY_RSP, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
+/* MSG_SETCONFIG_REJ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
+/* MSG_OPEN_REJ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
+/* MSG_START_REJ_EVT */ {AVDT_SCB_HDL_START_RSP, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
+/* MSG_SUSPEND_REJ_EVT */ {AVDT_SCB_HDL_SUSPEND_RSP, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
+/* TC_TOUT_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
+/* TC_OPEN_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
+/* TC_CLOSE_EVT */ {AVDT_SCB_HDL_TC_CLOSE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* TC_CONG_EVT */ {AVDT_SCB_CONG_STATE, AVDT_SCB_CHK_SND_PKT, AVDT_SCB_STREAM_ST},
+/* TC_DATA_EVT */ {AVDT_SCB_HDL_PKT, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
+/* CC_CLOSE_EVT */ {AVDT_SCB_SND_TC_CLOSE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST}
+};
+
+/* state table for closing state */
+const UINT8 avdt_scb_st_closing[][AVDT_SCB_NUM_COLS] = {
+/* Event Action 1 Action 2 Next state */
+/* API_REMOVE_EVT */ {AVDT_SCB_SET_REMOVE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* API_WRITE_REQ_EVT */ {AVDT_SCB_FREE_PKT, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* API_GETCONFIG_REQ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* API_DELAY_RPT_REQ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* API_SETCONFIG_REQ_EVT */ {AVDT_SCB_CB_ERR, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* API_OPEN_REQ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* API_CLOSE_REQ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* API_RECONFIG_REQ_EVT */ {AVDT_SCB_CB_ERR, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* API_SECURITY_REQ_EVT */ {AVDT_SCB_CB_ERR, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* API_ABORT_REQ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* API_GETCONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* API_SETCONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* API_SETCONFIG_REJ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* API_OPEN_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* API_CLOSE_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* API_RECONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* API_SECURITY_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* API_ABORT_RSP_EVT */ {AVDT_SCB_SND_ABORT_RSP, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* MSG_SETCONFIG_CMD_EVT */ {AVDT_SCB_REJ_STATE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* MSG_GETCONFIG_CMD_EVT */ {AVDT_SCB_REJ_STATE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* MSG_OPEN_CMD_EVT */ {AVDT_SCB_REJ_STATE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* MSG_START_CMD_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* MSG_SUSPEND_CMD_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* MSG_CLOSE_CMD_EVT */ {AVDT_SCB_REJ_STATE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* MSG_ABORT_CMD_EVT */ {AVDT_SCB_HDL_ABORT_CMD, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* MSG_RECONFIG_CMD_EVT */ {AVDT_SCB_REJ_STATE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* MSG_SECURITY_CMD_EVT */ {AVDT_SCB_REJ_STATE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* MSG_DELAY_RPT_CMD_EVT */ {AVDT_SCB_REJ_STATE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* MSG_DELAY_RPT_RSP_EVT */ {AVDT_SCB_HDL_DELAY_RPT_RSP, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* MSG_SETCONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* MSG_GETCONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* MSG_OPEN_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* MSG_START_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* MSG_SUSPEND_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* MSG_CLOSE_RSP_EVT */ {AVDT_SCB_SND_TC_CLOSE, AVDT_SCB_HDL_CLOSE_RSP, AVDT_SCB_CLOSING_ST},
+/* MSG_ABORT_RSP_EVT */ {AVDT_SCB_SND_TC_CLOSE, AVDT_SCB_HDL_ABORT_RSP, AVDT_SCB_CLOSING_ST},
+/* MSG_RECONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* MSG_SECURITY_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* MSG_SETCONFIG_REJ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* MSG_OPEN_REJ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* MSG_START_REJ_EVT */ {AVDT_SCB_HDL_START_RSP, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* MSG_SUSPEND_REJ_EVT */ {AVDT_SCB_HDL_SUSPEND_RSP, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* TC_TOUT_EVT */ {AVDT_SCB_SND_TC_CLOSE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* TC_OPEN_EVT */ {AVDT_SCB_SND_TC_CLOSE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* TC_CLOSE_EVT */ {AVDT_SCB_HDL_TC_CLOSE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
+/* TC_CONG_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* TC_DATA_EVT */ {AVDT_SCB_DROP_PKT, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
+/* CC_CLOSE_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST}
+};
+
+/* type for state table */
+typedef const UINT8 (*tAVDT_SCB_ST_TBL)[AVDT_SCB_NUM_COLS];
+
+/* state table */
+const tAVDT_SCB_ST_TBL avdt_scb_st_tbl[] = {
+ avdt_scb_st_idle,
+ avdt_scb_st_conf,
+ avdt_scb_st_opening,
+ avdt_scb_st_open,
+ avdt_scb_st_stream,
+ avdt_scb_st_closing
+};
+
+
+/*******************************************************************************
+**
+** Function avdt_scb_event
+**
+** Description State machine event handling function for scb
+**
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_event(tAVDT_SCB *p_scb, UINT8 event, tAVDT_SCB_EVT *p_data)
+{
+ tAVDT_SCB_ST_TBL state_table;
+ UINT8 action;
+ int i;
+
+#if AVDT_DEBUG == TRUE
+ AVDT_TRACE_EVENT4("SCB hdl=%d event=%d/%s state=%s", avdt_scb_to_hdl(p_scb), event, avdt_scb_evt_str[event], avdt_scb_st_str[p_scb->state]);
+#endif
+ BTTRC_AVDT_SCB_EVENT(event, p_scb->state);
+
+ /* set current event */
+ p_scb->curr_evt = event;
+
+ /* look up the state table for the current state */
+ state_table = avdt_scb_st_tbl[p_scb->state];
+
+ /* set next state */
+ if (p_scb->state != state_table[event][AVDT_SCB_NEXT_STATE])
+ BTTRC_AVDT_SCB_STATE(state_table[event][AVDT_SCB_NEXT_STATE]);
+ p_scb->state = state_table[event][AVDT_SCB_NEXT_STATE];
+
+
+ /* execute action functions */
+ for (i = 0; i < AVDT_SCB_ACTIONS; i++)
+ {
+ if ((action = state_table[event][i]) != AVDT_SCB_IGNORE)
+ {
+ BTTRC_AVDT_SCB_ACTION(action);
+ (*avdt_cb.p_scb_act[action])(p_scb, p_data);
+ }
+ else
+ {
+ break;
+ }
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function avdt_scb_init
+**
+** Description Initialize stream control block module.
+**
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_init(void)
+{
+ memset(&avdt_cb.scb[0], 0, sizeof(tAVDT_SCB) * AVDT_NUM_SEPS);
+ avdt_cb.p_scb_act = (tAVDT_SCB_ACTION *) avdt_scb_action;
+}
+
+
+/*******************************************************************************
+**
+** Function avdt_scb_alloc
+**
+** Description Allocate a stream control block.
+**
+**
+** Returns pointer to the scb, or NULL if none could be allocated.
+**
+*******************************************************************************/
+tAVDT_SCB *avdt_scb_alloc(tAVDT_CS *p_cs)
+{
+ tAVDT_SCB *p_scb = &avdt_cb.scb[0];
+ int i;
+
+ /* find available scb */
+ for (i = 0; i < AVDT_NUM_SEPS; i++, p_scb++)
+ {
+ if (!p_scb->allocated)
+ {
+ memset(p_scb,0,sizeof(tAVDT_SCB));
+ p_scb->allocated = TRUE;
+ p_scb->p_ccb = NULL;
+ memcpy(&p_scb->cs, p_cs, sizeof(tAVDT_CS));
+#if AVDT_MULTIPLEXING == TRUE
+ /* initialize fragments gueue */
+ GKI_init_q(&p_scb->frag_q);
+
+ if(p_cs->cfg.psc_mask & AVDT_PSC_MUX)
+ {
+ p_scb->cs.cfg.mux_tcid_media = avdt_ad_type_to_tcid(AVDT_CHAN_MEDIA, p_scb);
+#if AVDT_REPORTING == TRUE
+ if(p_cs->cfg.psc_mask & AVDT_PSC_REPORT)
+ {
+ p_scb->cs.cfg.mux_tcid_report = avdt_ad_type_to_tcid(AVDT_CHAN_REPORT, p_scb);
+ }
+#endif
+ }
+#endif
+ p_scb->timer_entry.param = (UINT32) p_scb;
+ AVDT_TRACE_DEBUG2("avdt_scb_alloc hdl=%d, psc_mask:0x%x", i+1, p_cs->cfg.psc_mask);
+ break;
+ }
+ }
+
+ if (i == AVDT_NUM_SEPS)
+ {
+ /* out of ccbs */
+ p_scb = NULL;
+ AVDT_TRACE_WARNING0("Out of scbs");
+ }
+
+ return p_scb;
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_dealloc
+**
+** Description Deallocate a stream control block.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+void avdt_scb_dealloc(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+#if AVDT_MULTIPLEXING == TRUE
+ void *p_buf;
+#endif
+
+ AVDT_TRACE_DEBUG1("avdt_scb_dealloc hdl=%d", avdt_scb_to_hdl(p_scb));
+ btu_stop_timer(&p_scb->timer_entry);
+
+#if AVDT_MULTIPLEXING == TRUE
+ /* free fragments we're holding, if any; it shouldn't happen */
+ while ((p_buf = GKI_dequeue (&p_scb->frag_q)) != NULL)
+ GKI_freebuf(p_buf);
+#endif
+
+ memset(p_scb, 0, sizeof(tAVDT_SCB));
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_to_hdl
+**
+** Description Given a pointer to an scb, return its handle (or seid).
+**
+**
+** Returns Index of scb.
+**
+*******************************************************************************/
+UINT8 avdt_scb_to_hdl(tAVDT_SCB *p_scb)
+{
+ return (UINT8) (p_scb - avdt_cb.scb + 1);
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_by_hdl
+**
+** Description Given an scb handle (or seid), return a pointer to the scb.
+**
+**
+** Returns Pointer to scb or NULL if index is out of range or scb
+** is not allocated.
+**
+*******************************************************************************/
+tAVDT_SCB *avdt_scb_by_hdl(UINT8 hdl)
+{
+ tAVDT_SCB *p_scb;
+
+ /* verify index */
+ if ((hdl > 0) && (hdl <= AVDT_NUM_SEPS))
+ {
+ p_scb = &avdt_cb.scb[hdl - 1];
+
+ /* verify scb is allocated */
+ if (!p_scb->allocated)
+ {
+ p_scb = NULL;
+ AVDT_TRACE_WARNING1("scb hdl %d not allocated", hdl);
+ }
+ }
+ else
+ {
+ p_scb = NULL;
+ AVDT_TRACE_WARNING1("scb hdl %d out of range", hdl);
+ }
+ return p_scb;
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_verify
+**
+** Description Verify the condition of a list of scbs.
+**
+**
+** Returns SEID that failed, or 0 if success.
+**
+*******************************************************************************/
+UINT8 avdt_scb_verify(tAVDT_CCB *p_ccb, UINT8 state, UINT8 *p_seid, UINT16 num_seid, UINT8 *p_err_code)
+{
+ int i;
+ tAVDT_SCB *p_scb;
+ UINT8 nsc_mask;
+ UINT8 chk_state;
+ UINT8 ret = 0;
+
+ AVDT_TRACE_DEBUG1("avdt_scb_verify state %d", state);
+ /* set nonsupported command mask */
+ /* translate public state into private state */
+ nsc_mask = 0;
+ chk_state = AVDT_SCB_STREAM_ST;
+ switch(state)
+ {
+ case AVDT_VERIFY_SUSPEND:
+ nsc_mask = AVDT_NSC_SUSPEND;
+ break;
+ case AVDT_VERIFY_OPEN:
+ case AVDT_VERIFY_START:
+ chk_state = AVDT_SCB_OPEN_ST;
+ break;
+ }
+
+ /* verify every scb */
+ for (i = 0; i < num_seid; i++)
+ {
+ if ((p_scb = avdt_scb_by_hdl(p_seid[i])) == NULL)
+ {
+ *p_err_code = AVDT_ERR_BAD_STATE;
+ break;
+ }
+ else if ((p_scb->state != chk_state) || (p_scb->p_ccb != p_ccb))
+ {
+ *p_err_code = AVDT_ERR_BAD_STATE;
+ break;
+ }
+ else if (p_scb->cs.nsc_mask & nsc_mask)
+ {
+ *p_err_code = AVDT_ERR_NSC;
+ break;
+ }
+ }
+
+ if (i != num_seid)
+ {
+ ret = p_seid[i];
+ }
+ AVDT_TRACE_DEBUG3("avdt_scb_verify state %d, nsc_mask0x%x, ret: %d",
+ chk_state, nsc_mask, ret);
+ return ret;
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_peer_seid_list
+**
+** Description Given a list of SCB handles, return a list of peer SEIDs
+** for the handles, copied in place into the struct passed in.
+**
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_peer_seid_list(tAVDT_MULTI *p_multi)
+{
+ int i;
+ tAVDT_SCB *p_scb;
+
+ for (i = 0; i < p_multi->num_seps; i++)
+ {
+ if ((p_scb = avdt_scb_by_hdl(p_multi->seid_list[i])) != NULL)
+ {
+ p_multi->seid_list[i] = p_scb->peer_seid;
+ }
+ }
+}
+
diff --git a/stack/avdt/avdt_scb_act.c b/stack/avdt/avdt_scb_act.c
new file mode 100644
index 0000000..c2ced74
--- /dev/null
+++ b/stack/avdt/avdt_scb_act.c
@@ -0,0 +1,2124 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2002-2012 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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This module contains the action functions associated with the stream
+ * control block state machine.
+ *
+ ******************************************************************************/
+
+#include <string.h>
+#include "data_types.h"
+#include "bt_target.h"
+#include "avdt_api.h"
+#include "avdtc_api.h"
+#include "avdt_int.h"
+#include "gki.h"
+#include "btu.h"
+
+/* This table is used to lookup the callback event that matches a particular
+** state machine API request event. Note that state machine API request
+** events are at the beginning of the event list starting at zero, thus
+** allowing for this table.
+*/
+const UINT8 avdt_scb_cback_evt[] = {
+ 0, /* API_REMOVE_EVT (no event) */
+ AVDT_WRITE_CFM_EVT, /* API_WRITE_REQ_EVT */
+ 0, /* API_GETCONFIG_REQ_EVT (no event) */
+ 0, /* API_DELAY_RPT_REQ_EVT (no event) */
+ AVDT_OPEN_CFM_EVT, /* API_SETCONFIG_REQ_EVT */
+ AVDT_OPEN_CFM_EVT, /* API_OPEN_REQ_EVT */
+ AVDT_CLOSE_CFM_EVT, /* API_CLOSE_REQ_EVT */
+ AVDT_RECONFIG_CFM_EVT, /* API_RECONFIG_REQ_EVT */
+ AVDT_SECURITY_CFM_EVT, /* API_SECURITY_REQ_EVT */
+ 0 /* API_ABORT_REQ_EVT (no event) */
+};
+
+/* This table is used to look up the callback event based on the signaling
+** role when the stream is closed.
+*/
+const UINT8 avdt_scb_role_evt[] = {
+ AVDT_CLOSE_IND_EVT, /* AVDT_CLOSE_ACP */
+ AVDT_CLOSE_CFM_EVT, /* AVDT_CLOSE_INT */
+ AVDT_CLOSE_IND_EVT, /* AVDT_OPEN_ACP */
+ AVDT_OPEN_CFM_EVT /* AVDT_OPEN_INT */
+};
+
+/*******************************************************************************
+**
+** Function avdt_scb_gen_ssrc
+**
+** Description This function generates a SSRC number unique to the stream.
+**
+** Returns SSRC value.
+**
+*******************************************************************************/
+UINT32 avdt_scb_gen_ssrc(tAVDT_SCB *p_scb)
+{
+ /* combine the value of the media type and codec type of the SCB */
+ return ((UINT32)(p_scb->cs.cfg.codec_info[1] | p_scb->cs.cfg.codec_info[2]));
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_hdl_abort_cmd
+**
+** Description This function sends the SCB an AVDT_SCB_API_ABORT_RSP_EVT
+** to initiate sending of an abort response message.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_hdl_abort_cmd(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ p_scb->role = AVDT_CLOSE_ACP;
+ avdt_scb_event(p_scb, AVDT_SCB_API_ABORT_RSP_EVT, p_data);
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_hdl_abort_rsp
+**
+** Description This function is an empty function; it serves as a
+** placeholder for a conformance API action function.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_hdl_abort_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ return;
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_hdl_close_cmd
+**
+** Description This function sends the SCB an AVDT_SCB_API_CLOSE_RSP_EVT
+** to initiate sending of a close response message.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_hdl_close_cmd(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ p_scb->role = AVDT_CLOSE_ACP;
+ avdt_scb_event(p_scb, AVDT_SCB_API_CLOSE_RSP_EVT, p_data);
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_hdl_close_rsp
+**
+** Description This function sets the close_code variable to the error
+** code returned in the close response.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_hdl_close_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ p_scb->close_code = p_data->msg.hdr.err_code;
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_hdl_getconfig_cmd
+**
+** Description This function retrieves the configuration parameters of
+** the SCB and sends the SCB an AVDT_SCB_API_GETCONFIG_RSP_EVT
+** to initiate sending of a get configuration response message.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_hdl_getconfig_cmd(tAVDT_SCB *p_scb,tAVDT_SCB_EVT *p_data)
+{
+ p_data->msg.svccap.p_cfg = &p_scb->curr_cfg;
+
+ avdt_scb_event(p_scb, AVDT_SCB_API_GETCONFIG_RSP_EVT, p_data);
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_hdl_getconfig_rsp
+**
+** Description This function is an empty function; it serves as a
+** placeholder for a conformance API action function.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_hdl_getconfig_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ return;
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_hdl_open_cmd
+**
+** Description This function sends the SCB an AVDT_SCB_API_OPEN_RSP_EVT
+** to initiate sending of an open response message.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_hdl_open_cmd(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ avdt_scb_event(p_scb, AVDT_SCB_API_OPEN_RSP_EVT, p_data);
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_hdl_open_rej
+**
+** Description This function calls the application callback function
+** indicating the open request has failed. It initializes
+** certain SCB variables and sends a AVDT_CCB_UL_CLOSE_EVT
+** to the CCB.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_hdl_open_rej(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ /* do exactly same as setconfig reject */
+ avdt_scb_hdl_setconfig_rej(p_scb, p_data);
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_hdl_open_rsp
+**
+** Description This function calls avdt_ad_open_req() to initiate
+** connection of the transport channel for this stream.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_hdl_open_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ /* initiate opening of trans channels for this SEID */
+ p_scb->role = AVDT_OPEN_INT;
+ avdt_ad_open_req(AVDT_CHAN_MEDIA, p_scb->p_ccb, p_scb, AVDT_INT);
+
+ /* start tc connect timer */
+ btu_start_timer(&p_scb->timer_entry, BTU_TTYPE_AVDT_SCB_TC, AVDT_SCB_TC_CONN_TOUT);
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_hdl_pkt_no_frag
+**
+** Description
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_hdl_pkt_no_frag(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ UINT8 *p, *p_start;
+ UINT8 o_v, o_p, o_x, o_cc;
+ UINT8 m_pt;
+ UINT8 marker;
+ UINT16 seq;
+ UINT32 time_stamp;
+ UINT32 ssrc;
+ UINT16 offset;
+ UINT16 ex_len;
+ UINT8 pad_len = 0;
+
+ p = p_start = (UINT8 *)(p_data->p_pkt + 1) + p_data->p_pkt->offset;
+
+ /* parse media packet header */
+ AVDT_MSG_PRS_OCTET1(p, o_v, o_p, o_x, o_cc);
+ AVDT_MSG_PRS_M_PT(p, m_pt, marker);
+ BE_STREAM_TO_UINT16(seq, p);
+ BE_STREAM_TO_UINT32(time_stamp, p);
+ BE_STREAM_TO_UINT32(ssrc, p);
+
+ /* skip over any csrc's in packet */
+ p += o_cc * 4;
+
+ /* check for and skip over extension header */
+ if (o_x)
+ {
+ p += 2;
+ BE_STREAM_TO_UINT16(ex_len, p);
+ p += ex_len * 4;
+ }
+
+ /* save our new offset */
+ offset = (UINT16) (p - p_start);
+
+ /* adjust length for any padding at end of packet */
+ if (o_p)
+ {
+ /* padding length in last byte of packet */
+ pad_len = *(p_start + p_data->p_pkt->len);
+ }
+
+ /* do sanity check */
+ if ((offset > p_data->p_pkt->len) || ((pad_len + offset) > p_data->p_pkt->len))
+ {
+ AVDT_TRACE_WARNING0("Got bad media packet");
+ GKI_freebuf(p_data->p_pkt);
+ }
+ /* adjust offset and length and send it up */
+ else
+ {
+ p_data->p_pkt->len -= (offset + pad_len);
+ p_data->p_pkt->offset += offset;
+
+ if (p_scb->cs.p_data_cback != NULL)
+ {
+ /* report sequence number */
+ p_data->p_pkt->layer_specific = seq;
+ (*p_scb->cs.p_data_cback)(avdt_scb_to_hdl(p_scb), p_data->p_pkt,
+ time_stamp, (UINT8)(m_pt | (marker<<7)));
+ }
+ else
+ {
+#if AVDT_MULTIPLEXING == TRUE
+ if ((p_scb->cs.p_media_cback != NULL)
+ && (p_scb->p_media_buf != NULL)
+ && (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,
+ 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);
+ }
+#endif
+ GKI_freebuf(p_data->p_pkt);
+ }
+ }
+}
+
+#if AVDT_REPORTING == TRUE
+/*******************************************************************************
+**
+** Function avdt_scb_hdl_report
+**
+** Description
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+UINT8 * avdt_scb_hdl_report(tAVDT_SCB *p_scb, UINT8 *p, UINT16 len)
+{
+ UINT16 result = AVDT_SUCCESS;
+ UINT8 *p_start = p;
+ UINT32 ssrc;
+ UINT8 o_v, o_p, o_cc;
+ UINT16 pkt_len;
+ AVDT_REPORT_TYPE pt;
+ tAVDT_REPORT_DATA report, *p_rpt;
+
+ AVDT_TRACE_DEBUG0( "avdt_scb_hdl_report");
+ if(p_scb->cs.p_report_cback)
+ {
+ p_rpt = &report;
+ /* parse report packet header */
+ AVDT_MSG_PRS_RPT_OCTET1(p, o_v, o_p, o_cc);
+ pt = *p++;
+ BE_STREAM_TO_UINT16(pkt_len, p);
+ BE_STREAM_TO_UINT32(ssrc, p);
+
+ switch(pt)
+ {
+ case AVDT_RTCP_PT_SR: /* the packet type - SR (Sender Report) */
+ BE_STREAM_TO_UINT32(report.sr.ntp_sec, p);
+ BE_STREAM_TO_UINT32(report.sr.ntp_frac, p);
+ BE_STREAM_TO_UINT32(report.sr.rtp_time, p);
+ BE_STREAM_TO_UINT32(report.sr.pkt_count, p);
+ BE_STREAM_TO_UINT32(report.sr.octet_count, p);
+ break;
+
+ case AVDT_RTCP_PT_RR: /* the packet type - RR (Receiver Report) */
+ report.rr.frag_lost = *p;
+ BE_STREAM_TO_UINT32(report.rr.packet_lost, p);
+ report.rr.packet_lost &= 0xFFFFFF;
+ BE_STREAM_TO_UINT32(report.rr.seq_num_rcvd, p);
+ BE_STREAM_TO_UINT32(report.rr.jitter, p);
+ BE_STREAM_TO_UINT32(report.rr.lsr, p);
+ BE_STREAM_TO_UINT32(report.rr.dlsr, p);
+ break;
+
+ case AVDT_RTCP_PT_SDES: /* the packet type - SDES (Source Description) */
+ if(*p == AVDT_RTCP_SDES_CNAME)
+ {
+ p_rpt = (tAVDT_REPORT_DATA *)(p+2);
+ }
+ else
+ {
+ AVDT_TRACE_WARNING5( " - SDES SSRC=0x%08x sc=%d %d len=%d %s",
+ ssrc, o_cc, *p, *(p+1), p+2);
+ result = AVDT_BUSY;
+ }
+ break;
+
+ default:
+ AVDT_TRACE_ERROR1( "Bad Report pkt - packet type: %d", pt);
+ result = AVDT_BAD_PARAMS;
+ }
+
+ if(result == AVDT_SUCCESS)
+ (*p_scb->cs.p_report_cback)(avdt_scb_to_hdl(p_scb), pt, p_rpt);
+
+ }
+ p_start += len;
+ return p_start;
+}
+#endif
+
+#if AVDT_MULTIPLEXING == TRUE
+/*******************************************************************************
+**
+** Function avdt_scb_hdl_pkt_frag
+**
+** Description
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_hdl_pkt_frag(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ /* Fields of Adaptation Layer Header */
+ UINT8 al_tsid,al_frag,al_lcode;
+ UINT16 al_len;
+ /* media header fields */
+ UINT8 o_v, o_p, o_x, o_cc;
+ UINT8 m_pt;
+ UINT8 marker;
+ UINT16 seq;
+ UINT32 time_stamp;
+ UINT32 ssrc;
+ UINT16 ex_len;
+ UINT8 pad_len;
+ /* other variables */
+ UINT8 *p; /* current pointer */
+ UINT8 *p_end; /* end of all packet */
+ UINT8 *p_payload; /* pointer to media fragment payload in the buffer */
+ UINT32 payload_len; /* payload length */
+ UINT16 frag_len; /* fragment length */
+
+ p = (UINT8 *)(p_data->p_pkt + 1) + p_data->p_pkt->offset;
+ p_end = p + p_data->p_pkt->len;
+ /* parse all fragments */
+ while(p < p_end)
+ {
+ if (p_end - p < 4) /* length check. maximum length of AL header = 4 */
+ {
+ AVDT_TRACE_WARNING2("p_end: 0x%x - p:0x%x < 4", p_end, p);
+ break;
+ }
+
+ /* parse first byte */
+ al_tsid = (*p)>>3;
+ al_frag = ( (*p) >> 2 ) & 0x01;
+ al_lcode = (*p++) & AVDT_ALH_LCODE_MASK;
+
+ /* in case of TSID=00000, a second AL header byte, before the length field,
+ ** is expected and contains the actual TSID, aligned with MSB */
+ if(al_tsid == 0)
+ al_tsid = *p++;
+
+ /* get remaining media length on base of lcode */
+ switch(al_lcode)
+ {
+ case AVDT_ALH_LCODE_NONE: /* No length field present. Take length from l2cap */
+ al_len = (UINT16)(p_end - p);
+ break;
+ case AVDT_ALH_LCODE_16BIT: /* 16 bit length field */
+ BE_STREAM_TO_UINT16(al_len, p);
+ break;
+ case AVDT_ALH_LCODE_9BITM0: /* 9 bit length field, MSB = 0, 8 LSBs in 1 octet following */
+ al_len = *p++;
+ break;
+ default: /* 9 bit length field, MSB = 1, 8 LSBs in 1 octet following */
+ al_len =(UINT16)*p++ + 0x100;
+ }
+
+ /* max fragment length */
+ frag_len = (UINT16)(p_end - p);
+ /* if it isn't last fragment */
+ if(frag_len >= al_len)
+ frag_len = al_len;
+
+ /* check TSID corresponds to config */
+ if (al_tsid != p_scb->curr_cfg.mux_tsid_media)
+ {
+#if AVDT_REPORTING == TRUE
+ if((p_scb->curr_cfg.psc_mask & AVDT_PSC_REPORT) &&
+ (al_tsid == p_scb->curr_cfg.mux_tsid_report))
+ {
+ /* parse reporting packet */
+ p = avdt_scb_hdl_report(p_scb, p, frag_len);
+ continue;
+ }
+ else
+#endif
+ {
+ AVDT_TRACE_WARNING2("bad tsid: %d, mux_tsid_media:%d", al_tsid, p_scb->curr_cfg.mux_tsid_media);
+ break;
+ }
+ }
+ /* check are buffer for assembling and related callback set */
+ else if ((p_scb->p_media_buf == NULL) || (p_scb->cs.p_media_cback == NULL))
+ {
+ AVDT_TRACE_WARNING0("NULL p_media_buf or p_media_cback");
+ break;
+ }
+
+
+ /* it is media fragment beginning */
+ if(!al_frag) /* is it first fragment of original media packet */
+ {
+ AVDT_TRACE_DEBUG2("al:%d media:%d",
+ al_len, p_scb->media_buf_len);
+
+ p_scb->frag_off = 0;
+ p_scb->frag_org_len = al_len; /* total length of original media packet */
+ /* length check: minimum length of media header is 12 */
+ if (p_scb->frag_org_len < 12)
+ {
+ AVDT_TRACE_WARNING1("bad al_len: %d(<12)", al_len);
+ break;
+ }
+ /* check that data fit into buffer */
+ if (al_len > p_scb->media_buf_len)
+ {
+ AVDT_TRACE_WARNING2("bad al_len: %d(>%d)", al_len, p_scb->media_buf_len);
+ break;
+ }
+ /* make sure it is the last fragment in l2cap packet */
+ if (p + al_len < p_end)
+ {
+ AVDT_TRACE_WARNING2("bad al_len: %d(>%d)", al_len, p_scb->media_buf_len);
+ break;
+ }
+ }
+ else
+ {
+ AVDT_TRACE_DEBUG4("al:%d media:%d frag_org_len:%d frag_off:%d",
+ al_len, p_scb->media_buf_len, p_scb->frag_org_len, p_scb->frag_off);
+
+ /* check that remaining length from AL header equals to original len - length of already received fragments */
+ if(al_len != p_scb->frag_org_len - p_scb->frag_off)
+ {
+ AVDT_TRACE_WARNING4("al_len:%d != (frag_org_len:%d - frag_off:%d) %d",
+ al_len, p_scb->frag_org_len, p_scb->frag_off,
+ (p_scb->frag_org_len- p_scb->frag_off));
+ break;
+ }
+
+ /* do sanity check */
+ if (p_scb->frag_off == 0)
+ {
+ AVDT_TRACE_WARNING0("frag_off=0");
+ break;
+ }
+ }
+ /* do common sanity check */
+ if((p_scb->frag_org_len <= p_scb->frag_off) || (p_scb->frag_org_len >= p_scb->media_buf_len))
+ {
+ AVDT_TRACE_WARNING3("common sanity frag_off:%d frag_org_len:%d media_buf_len:%d",
+ p_scb->frag_off, p_scb->frag_org_len, p_scb->media_buf_len);
+ break;
+ }
+
+ AVDT_TRACE_DEBUG4("Received fragment org_len=%d off=%d al_len=%d frag_len=%d",
+ p_scb->frag_org_len, p_scb->frag_off, al_len, frag_len);
+
+ /* copy fragment into buffer */
+ memcpy(p_scb->p_media_buf + p_scb->frag_off, p, frag_len);
+ p_scb->frag_off += frag_len;
+ /* move to the next fragment */
+ p += frag_len;
+ /* if it is last fragment in original media packet then process total media pocket */
+ if(p_scb->frag_off == p_scb->frag_org_len)
+ {
+ p_payload = p_scb->p_media_buf;
+
+ /* media header */
+ AVDT_MSG_PRS_OCTET1(p_payload, o_v, o_p, o_x, o_cc);
+ AVDT_MSG_PRS_M_PT(p_payload, m_pt, marker);
+ BE_STREAM_TO_UINT16(seq, p_payload);
+ BE_STREAM_TO_UINT32(time_stamp, p_payload);
+ BE_STREAM_TO_UINT32(ssrc, p_payload);
+
+ /* skip over any csrc's in packet */
+ p_payload += o_cc * 4;
+
+ /* check for and skip over extension header */
+ if (o_x)
+ {
+ if(p_scb->p_media_buf + p_scb->frag_off - p_payload < 4)
+ {
+ AVDT_TRACE_WARNING3("length check frag_off:%d p_media_buf:%d p_payload:%d",
+ p_scb->frag_off, p_scb->p_media_buf, p_payload);
+ break;/* length check */
+ }
+ p_payload += 2;
+ BE_STREAM_TO_UINT16(ex_len, p_payload);
+ p_payload += ex_len * 4;
+ }
+
+ if(p_payload >= p_scb->p_media_buf + p_scb->frag_off)
+ {
+ AVDT_TRACE_WARNING3("length check2 frag_off:%d p_media_buf:%d p_payload:%d",
+ p_scb->frag_off, p_scb->p_media_buf, p_payload);
+ break;/* length check */
+ }
+
+ /* adjust length for any padding at end of packet */
+ if (o_p)
+ {
+ /* padding length in last byte of packet */
+ pad_len = *(p_scb->p_media_buf + p_scb->frag_off - 1);
+ }
+ else
+ pad_len = 0;
+ /* payload length */
+ payload_len = (UINT32)(p_scb->p_media_buf + p_scb->frag_off - pad_len - p_payload);
+
+ AVDT_TRACE_DEBUG2("Received last fragment header=%d len=%d",
+ p_payload - p_scb->p_media_buf,payload_len);
+
+ /* send total media packet up */
+ if (p_scb->cs.p_media_cback != NULL)
+ {
+ (*p_scb->cs.p_media_cback)(avdt_scb_to_hdl(p_scb), p_payload,
+ payload_len, time_stamp, seq, m_pt, marker);
+ }
+ }
+ } /* while(p < p_end) */
+
+ if(p < p_end)
+ {
+ AVDT_TRACE_WARNING0("*** Got bad media packet");
+ }
+ GKI_freebuf(p_data->p_pkt);
+}
+#endif
+
+/*******************************************************************************
+**
+** Function avdt_scb_hdl_pkt
+**
+** Description
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_hdl_pkt(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+#if AVDT_REPORTING == TRUE
+ UINT8 *p;
+#endif
+
+#if AVDT_MULTIPLEXING == TRUE
+ /* select right function in dependance of is fragmentation supported or not */
+ if( 0 != (p_scb->curr_cfg.psc_mask & AVDT_PSC_MUX))
+ {
+ avdt_scb_hdl_pkt_frag(p_scb, p_data);
+ }
+ else
+#endif
+#if AVDT_REPORTING == TRUE
+ if(p_data->p_pkt->layer_specific == AVDT_CHAN_REPORT)
+ {
+ p = (UINT8 *)(p_data->p_pkt + 1) + p_data->p_pkt->offset;
+ avdt_scb_hdl_report(p_scb, p, p_data->p_pkt->len);
+ GKI_freebuf(p_data->p_pkt);
+ }
+ else
+#endif
+ avdt_scb_hdl_pkt_no_frag(p_scb, p_data);
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_drop_pkt
+**
+** Description Drop an incoming media packet. This function is called if
+** a media packet is received in any state besides streaming.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_drop_pkt(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ GKI_freebuf(p_data->p_pkt);
+ AVDT_TRACE_WARNING0("Dropped incoming media packet");
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_hdl_reconfig_cmd
+**
+** Description This function calls the application callback function
+** with a reconfiguration indication.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_hdl_reconfig_cmd(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ /* if command not supported */
+ if (p_scb->cs.nsc_mask & AVDT_NSC_RECONFIG)
+ {
+ /* send reject */
+ p_data->msg.hdr.err_code = AVDT_ERR_NSC;
+ p_data->msg.hdr.err_param = 0;
+ avdt_scb_event(p_scb, AVDT_SCB_API_RECONFIG_RSP_EVT, p_data);
+ }
+ else
+ {
+ /* store requested configuration */
+ memcpy(&p_scb->req_cfg, p_data->msg.reconfig_cmd.p_cfg, sizeof(tAVDT_CFG));
+
+ /* call application callback */
+ (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb),
+ NULL,
+ AVDT_RECONFIG_IND_EVT,
+ (tAVDT_CTRL *) &p_data->msg.reconfig_cmd);
+ }
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_hdl_reconfig_rsp
+**
+** Description This function calls the application callback function
+** with a reconfiguration confirm.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_hdl_reconfig_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ if (p_data->msg.hdr.err_code == 0)
+ {
+ /* store new configuration */
+ if (p_scb->req_cfg.num_codec > 0)
+ {
+ p_scb->curr_cfg.num_codec = p_scb->req_cfg.num_codec;
+ memcpy(p_scb->curr_cfg.codec_info, p_scb->req_cfg.codec_info, AVDT_CODEC_SIZE);
+ }
+ if (p_scb->req_cfg.num_protect > 0)
+ {
+ p_scb->curr_cfg.num_protect = p_scb->req_cfg.num_protect;
+ memcpy(p_scb->curr_cfg.protect_info, p_scb->req_cfg.protect_info, AVDT_PROTECT_SIZE);
+ }
+ }
+
+ p_data->msg.svccap.p_cfg = &p_scb->curr_cfg;
+
+ /* call application callback */
+ (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb),
+ NULL,
+ AVDT_RECONFIG_CFM_EVT,
+ (tAVDT_CTRL *) &p_data->msg.svccap);
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_hdl_security_cmd
+**
+** Description This function calls the application callback with a
+** security indication.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_hdl_security_cmd(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ /* if command not supported */
+ if (p_scb->cs.nsc_mask & AVDT_NSC_SECURITY)
+ {
+ /* send reject */
+ p_data->msg.hdr.err_code = AVDT_ERR_NSC;
+ avdt_scb_event(p_scb, AVDT_SCB_API_SECURITY_RSP_EVT, p_data);
+ }
+ else
+ {
+ /* call application callback */
+ (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb),
+ NULL,
+ AVDT_SECURITY_IND_EVT,
+ (tAVDT_CTRL *) &p_data->msg.security_cmd);
+ }
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_hdl_security_rsp
+**
+** Description This function calls the application callback with a
+** security confirm.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_hdl_security_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ /* call application callback */
+ (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb),
+ NULL,
+ AVDT_SECURITY_CFM_EVT,
+ (tAVDT_CTRL *) &p_data->msg.security_cmd);
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_hdl_setconfig_cmd
+**
+** Description This function marks the SCB as in use and copies the
+** configuration and peer SEID to the SCB. It then calls
+** the application callback with a configuration indication.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_hdl_setconfig_cmd(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ tAVDT_CFG *p_cfg;
+
+ if (!p_scb->in_use)
+ {
+ p_cfg = p_data->msg.config_cmd.p_cfg;
+ if(p_scb->cs.cfg.codec_info[AVDT_CODEC_TYPE_INDEX] == p_cfg->codec_info[AVDT_CODEC_TYPE_INDEX])
+ {
+ /* set sep as in use */
+ p_scb->in_use = TRUE;
+
+ /* copy info to scb */
+ p_scb->p_ccb = avdt_ccb_by_idx(p_data->msg.config_cmd.hdr.ccb_idx);
+ p_scb->peer_seid = p_data->msg.config_cmd.int_seid;
+ memcpy(&p_scb->req_cfg, p_cfg, sizeof(tAVDT_CFG));
+ /* call app callback */
+ (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb),
+ p_scb->p_ccb ? p_scb->p_ccb->peer_addr : NULL,
+ AVDT_CONFIG_IND_EVT,
+ (tAVDT_CTRL *) &p_data->msg.config_cmd);
+ }
+ else
+ {
+ p_data->msg.hdr.err_code = AVDT_ERR_UNSUP_CFG;
+ p_data->msg.hdr.err_param = 0;
+ avdt_msg_send_rej(avdt_ccb_by_idx(p_data->msg.hdr.ccb_idx),
+ p_data->msg.hdr.sig_id, &p_data->msg);
+ }
+ }
+ else
+ {
+ avdt_scb_rej_in_use(p_scb, p_data);
+ }
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_hdl_setconfig_rej
+**
+** Description This function marks the SCB as not in use and calls the
+** application callback with an open confirm indicating failure.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_hdl_setconfig_rej(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ /* clear scb variables */
+ avdt_scb_clr_vars(p_scb, p_data);
+
+ /* tell ccb we're done with signaling channel */
+ avdt_ccb_event(avdt_ccb_by_idx(p_data->msg.hdr.ccb_idx), AVDT_CCB_UL_CLOSE_EVT, NULL);
+
+ /* call application callback */
+ (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb),
+ NULL,
+ AVDT_OPEN_CFM_EVT,
+ (tAVDT_CTRL *) &p_data->msg.hdr);
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_hdl_setconfig_rsp
+**
+** Description This function sends the SCB an AVDT_SCB_API_OPEN_REQ_EVT
+** to initiate sending of an open command message.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_hdl_setconfig_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ tAVDT_EVT_HDR single;
+
+ if (p_scb->p_ccb != NULL)
+ {
+ /* save configuration */
+ memcpy(&p_scb->curr_cfg, &p_scb->req_cfg, sizeof(tAVDT_CFG));
+
+ /* initiate open */
+ single.seid = p_scb->peer_seid;
+ avdt_scb_event(p_scb, AVDT_SCB_API_OPEN_REQ_EVT, (tAVDT_SCB_EVT *) &single);
+ }
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_hdl_start_cmd
+**
+** Description This function calls the application callback with a
+** start indication.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_hdl_start_cmd(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb),
+ p_scb->p_ccb ? p_scb->p_ccb->peer_addr : NULL,
+ AVDT_START_IND_EVT,
+ NULL);
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_hdl_start_rsp
+**
+** Description This function calls the application callback with a
+** start confirm.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_hdl_start_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb),
+ p_scb->p_ccb ? p_scb->p_ccb->peer_addr : NULL,
+ AVDT_START_CFM_EVT,
+ (tAVDT_CTRL *) &p_data->msg.hdr);
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_hdl_suspend_cmd
+**
+** Description This function calls the application callback with a suspend
+** indication.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_hdl_suspend_cmd(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb),
+ p_scb->p_ccb ? p_scb->p_ccb->peer_addr : NULL,
+ AVDT_SUSPEND_IND_EVT,
+ NULL);
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_hdl_suspend_rsp
+**
+** Description This function calls the application callback with a suspend
+** confirm.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_hdl_suspend_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb),
+ p_scb->p_ccb ? p_scb->p_ccb->peer_addr : NULL,
+ AVDT_SUSPEND_CFM_EVT,
+ (tAVDT_CTRL *) &p_data->msg.hdr);
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_hdl_tc_close
+**
+** Description This function is called when the transport channel is
+** closed. It marks the SCB as not in use and
+** initializes certain SCB parameters. It then sends
+** an AVDT_CCB_UL_CLOSE_EVT to the CCB if the SCB
+** initiated the close. It then checks to see if the SCB
+** is to be removed. If it is it deallocates the SCB. Finally,
+** it calls the application callback with a close indication.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_hdl_tc_close(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ UINT8 hdl = avdt_scb_to_hdl(p_scb);
+ tAVDT_CTRL_CBACK *p_ctrl_cback = p_scb->cs.p_ctrl_cback;
+ tAVDT_CTRL avdt_ctrl;
+ UINT8 event;
+ tAVDT_CCB *p_ccb = p_scb->p_ccb;
+ BD_ADDR remote_addr;
+
+
+ memcpy (remote_addr, p_ccb->peer_addr, BD_ADDR_LEN);
+
+ /* set up hdr */
+ avdt_ctrl.hdr.err_code = p_scb->close_code;
+
+ /* clear sep variables */
+ avdt_scb_clr_vars(p_scb, p_data);
+ p_scb->media_seq = 0;
+ p_scb->cong = FALSE;
+
+ /* free pkt we're holding, if any */
+ if (p_scb->p_pkt != NULL)
+ {
+ GKI_freebuf(p_scb->p_pkt);
+ p_scb->p_pkt = NULL;
+ }
+
+ /* stop transport channel timer */
+ btu_stop_timer(&p_scb->timer_entry);
+
+ if ((p_scb->role == AVDT_CLOSE_INT) || (p_scb->role == AVDT_OPEN_INT))
+ {
+ /* tell ccb we're done with signaling channel */
+ avdt_ccb_event(p_ccb, AVDT_CCB_UL_CLOSE_EVT, NULL);
+ }
+ event = (p_scb->role == AVDT_CLOSE_INT) ? AVDT_CLOSE_CFM_EVT : AVDT_CLOSE_IND_EVT;
+ p_scb->role = AVDT_CLOSE_ACP;
+
+ if (p_scb->remove)
+ {
+ avdt_scb_dealloc(p_scb, NULL);
+ }
+
+ /* call app callback */
+ (*p_ctrl_cback)(hdl, remote_addr, event, &avdt_ctrl);
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_snd_delay_rpt_req
+**
+** Description This function calls the application callback with a delay
+** report.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_snd_delay_rpt_req (tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ avdt_msg_send_cmd(p_scb->p_ccb, p_scb, AVDT_SIG_DELAY_RPT, (tAVDT_MSG *) &p_data->apidelay);
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_hdl_delay_rpt_cmd
+**
+** Description This function calls the application callback with a delay
+** report.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_hdl_delay_rpt_cmd (tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb),
+ p_scb->p_ccb ? p_scb->p_ccb->peer_addr : NULL,
+ AVDT_DELAY_REPORT_EVT,
+ (tAVDT_CTRL *) &p_data->msg.hdr);
+
+ if (p_scb->p_ccb)
+ avdt_msg_send_rsp(p_scb->p_ccb, AVDT_SIG_DELAY_RPT, &p_data->msg);
+ else
+ avdt_scb_rej_not_in_use(p_scb, p_data);
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_hdl_delay_rpt_rsp
+**
+** Description This function calls the application callback with a delay
+** report.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_hdl_delay_rpt_rsp (tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb),
+ p_scb->p_ccb ? p_scb->p_ccb->peer_addr : NULL,
+ AVDT_DELAY_REPORT_CFM_EVT,
+ (tAVDT_CTRL *) &p_data->msg.hdr);
+}
+
+#if AVDT_REPORTING == TRUE
+/*******************************************************************************
+**
+** Function avdt_scb_hdl_tc_close_sto
+**
+** Description This function is called when a channel is closed in OPEN
+** state. Check the channel type and process accordingly.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_hdl_tc_close_sto(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ tAVDT_CTRL avdt_ctrl;
+ /* AVDT_CHAN_SIG does not visit this action */
+ if(p_data && p_data->close.type != AVDT_CHAN_MEDIA)
+ {
+ /* it's reporting or recovery channel,
+ * the channel close in open state means the peer does not support it */
+ if(p_data->close.old_tc_state == AVDT_AD_ST_OPEN)
+ {
+ avdt_ctrl.hdr.err_code = 0;
+ avdt_ctrl.hdr.err_param = 0;
+ /* call app callback */
+ (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb),
+ p_scb->p_ccb ? p_scb->p_ccb->peer_addr : NULL,
+ AVDT_REPORT_DISCONN_EVT, &avdt_ctrl);
+ }
+ }
+ else
+ {
+ /* must be in OPEN state. need to go back to idle */
+ avdt_scb_event(p_scb, AVDT_SCB_MSG_ABORT_RSP_EVT, NULL);
+ avdt_scb_hdl_tc_close(p_scb, p_data);
+ }
+}
+#endif
+
+/*******************************************************************************
+**
+** Function avdt_scb_hdl_tc_open
+**
+** Description This function is called when the transport channel is
+** opened while in the opening state. It calls the
+** application callback with an open indication or open
+** confirm depending on who initiated the open procedure.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_hdl_tc_open(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ UINT8 event;
+#if AVDT_REPORTING == TRUE
+ UINT8 role;
+#endif
+
+ /* stop transport channel connect timer */
+ btu_stop_timer(&p_scb->timer_entry);
+
+ event = (p_scb->role == AVDT_OPEN_INT) ? AVDT_OPEN_CFM_EVT : AVDT_OPEN_IND_EVT;
+ p_data->open.hdr.err_code = 0;
+
+ AVDT_TRACE_DEBUG3("psc_mask: cfg: 0x%x, req:0x%x, cur: 0x%x",
+ p_scb->cs.cfg.psc_mask, p_scb->req_cfg.psc_mask, p_scb->curr_cfg.psc_mask);
+#if AVDT_REPORTING == TRUE
+ if(p_scb->curr_cfg.psc_mask & AVDT_PSC_REPORT)
+ {
+ /* open the reporting channel, if both devices support it */
+ role = (p_scb->role == AVDT_OPEN_INT) ? AVDT_INT : AVDT_ACP;
+ avdt_ad_open_req(AVDT_CHAN_REPORT, p_scb->p_ccb, p_scb, role);
+ }
+#endif
+
+ /* call app callback */
+ (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb),
+ p_scb->p_ccb ? p_scb->p_ccb->peer_addr : NULL,
+ event,
+ (tAVDT_CTRL *) &p_data->open);
+}
+
+#if AVDT_REPORTING == TRUE
+/*******************************************************************************
+**
+** Function avdt_scb_hdl_tc_open_sto
+**
+** Description This function is called when the transport channel is
+** opened while in the opening state. It calls the
+** application callback with an open indication or open
+** confirm depending on who initiated the open procedure.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_hdl_tc_open_sto(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ tAVDT_CTRL avdt_ctrl;
+ /* open reporting channel here, when it is implemented */
+
+ /* call app callback */
+ if(p_data->open.hdr.err_code == AVDT_CHAN_REPORT)
+ {
+ avdt_ctrl.hdr.err_code = 0;
+ avdt_ctrl.hdr.err_param = 1;
+ (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb),
+ p_scb->p_ccb ? p_scb->p_ccb->peer_addr : NULL,
+ AVDT_REPORT_CONN_EVT, &avdt_ctrl);
+ }
+}
+#endif
+
+/*******************************************************************************
+**
+** Function avdt_scb_hdl_write_req_no_frag
+**
+** Description This function frees the media packet currently stored in
+** the SCB, if any. Then it builds a new media packet from
+** with the passed in buffer and stores it in the SCB.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_hdl_write_req_no_frag(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ UINT8 *p;
+ UINT32 ssrc;
+
+ /* free packet we're holding, if any; to be replaced with new */
+ if (p_scb->p_pkt != NULL)
+ {
+ GKI_freebuf(p_scb->p_pkt);
+
+ /* this shouldn't be happening */
+ AVDT_TRACE_WARNING0("Dropped media packet; congested");
+ }
+
+ /* build a media packet */
+
+ ssrc = avdt_scb_gen_ssrc(p_scb);
+
+ p_data->apiwrite.p_buf->len += AVDT_MEDIA_HDR_SIZE;
+ p_data->apiwrite.p_buf->offset -= AVDT_MEDIA_HDR_SIZE;
+
+ p = (UINT8 *)(p_data->apiwrite.p_buf + 1) + p_data->apiwrite.p_buf->offset;
+
+ UINT8_TO_BE_STREAM(p, AVDT_MEDIA_OCTET1);
+ UINT8_TO_BE_STREAM(p, p_data->apiwrite.m_pt);
+ UINT16_TO_BE_STREAM(p, p_scb->media_seq);
+ UINT32_TO_BE_STREAM(p, p_data->apiwrite.time_stamp);
+ UINT32_TO_BE_STREAM(p, ssrc);
+
+ p_scb->media_seq++;
+
+ /* store it */
+ p_scb->p_pkt = p_data->apiwrite.p_buf;
+}
+
+#if AVDT_MULTIPLEXING == TRUE
+/*******************************************************************************
+**
+** Function avdt_scb_hdl_write_req_frag
+**
+** Description This function builds a new fragments of media packet from
+** the passed in buffers and stores them in the SCB.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_hdl_write_req_frag(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ UINT8 *p;
+ UINT32 ssrc;
+ BT_HDR *p_frag;
+
+ /* free fragments we're holding, if any; it shouldn't happen */
+ if (!GKI_queue_is_empty(&p_scb->frag_q))
+ {
+ while((p_frag = (BT_HDR*)GKI_dequeue (&p_scb->frag_q)) != NULL)
+ GKI_freebuf(p_frag);
+
+ /* this shouldn't be happening */
+ AVDT_TRACE_WARNING0("*** Dropped media packet; congested");
+ }
+
+ /* build a media fragments */
+ p_scb->frag_off = p_data->apiwrite.data_len;
+ p_scb->p_next_frag = p_data->apiwrite.p_data;
+
+ ssrc = avdt_scb_gen_ssrc(p_scb);
+
+ /* get first packet */
+ p_frag = (BT_HDR*)GKI_getfirst (&p_data->apiwrite.frag_q);
+ /* posit on Adaptation Layer header */
+ p_frag->len += AVDT_AL_HDR_SIZE + AVDT_MEDIA_HDR_SIZE;
+ p_frag->offset -= AVDT_AL_HDR_SIZE + AVDT_MEDIA_HDR_SIZE;
+ p = (UINT8 *)(p_frag + 1) + p_frag->offset;
+
+ /* Adaptation Layer header */
+ /* TSID, no-fragment bit and coding of length(in 2 length octets following) */
+ *p++ = (p_scb->curr_cfg.mux_tsid_media<<3) | AVDT_ALH_LCODE_16BIT;
+
+ /* length of all remaining transport packet */
+ UINT16_TO_BE_STREAM(p, p_frag->layer_specific+AVDT_MEDIA_HDR_SIZE );
+ /* media header */
+ UINT8_TO_BE_STREAM(p, AVDT_MEDIA_OCTET1);
+ UINT8_TO_BE_STREAM(p, p_data->apiwrite.m_pt);
+ UINT16_TO_BE_STREAM(p, p_scb->media_seq);
+ UINT32_TO_BE_STREAM(p, p_data->apiwrite.time_stamp);
+ UINT32_TO_BE_STREAM(p, ssrc);
+ p_scb->media_seq++;
+
+ while((p_frag = (BT_HDR*)GKI_getnext (p_frag)) != NULL)
+ {
+ /* posit on Adaptation Layer header */
+ p_frag->len += AVDT_AL_HDR_SIZE;
+ p_frag->offset -= AVDT_AL_HDR_SIZE;
+ p = (UINT8 *)(p_frag + 1) + p_frag->offset;
+ /* Adaptation Layer header */
+ /* TSID, fragment bit and coding of length(in 2 length octets following) */
+ *p++ = (p_scb->curr_cfg.mux_tsid_media<<3) | (AVDT_ALH_FRAG_MASK|AVDT_ALH_LCODE_16BIT);
+
+ /* length of all remaining transport packet */
+ UINT16_TO_BE_STREAM(p, p_frag->layer_specific );
+ }
+
+ /* store it */
+ p_scb->frag_q = p_data->apiwrite.frag_q;
+}
+#endif
+
+
+/*******************************************************************************
+**
+** Function avdt_scb_hdl_write_req
+**
+** Description This function calls one of the two versions of building functions
+** for case with and without fragmentation
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_hdl_write_req(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+#if AVDT_MULTIPLEXING == TRUE
+ if (GKI_queue_is_empty(&p_data->apiwrite.frag_q))
+#endif
+ avdt_scb_hdl_write_req_no_frag(p_scb, p_data);
+#if AVDT_MULTIPLEXING == TRUE
+ else
+ avdt_scb_hdl_write_req_frag(p_scb, p_data);
+#endif
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_snd_abort_req
+**
+** Description This function sends an abort command message.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_snd_abort_req(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ tAVDT_EVT_HDR hdr;
+
+ if (p_scb->p_ccb != NULL)
+ {
+ p_scb->role = AVDT_CLOSE_INT;
+
+ hdr.seid = p_scb->peer_seid;
+
+ avdt_msg_send_cmd(p_scb->p_ccb, p_scb, AVDT_SIG_ABORT, (tAVDT_MSG *) &hdr);
+ }
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_snd_abort_rsp
+**
+** Description This function sends an abort response message.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_snd_abort_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ avdt_msg_send_rsp(avdt_ccb_by_idx(p_data->msg.hdr.ccb_idx), AVDT_SIG_ABORT,
+ &p_data->msg);
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_snd_close_req
+**
+** Description This function sends a close command message.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_snd_close_req(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ tAVDT_EVT_HDR hdr;
+
+ p_scb->role = AVDT_CLOSE_INT;
+
+ hdr.seid = p_scb->peer_seid;
+
+ avdt_msg_send_cmd(p_scb->p_ccb, p_scb, AVDT_SIG_CLOSE, (tAVDT_MSG *) &hdr);
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_snd_stream_close
+**
+** Description This function sends a close command message.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_snd_stream_close(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+#if AVDT_MULTIPLEXING == TRUE
+ BT_HDR *p_frag;
+
+ AVDT_TRACE_WARNING2("avdt_scb_snd_stream_close c:%d, off:%d",
+ p_scb->frag_q.count, p_scb->frag_off);
+ /* clean fragments queue */
+ while((p_frag = (BT_HDR*)GKI_dequeue (&p_scb->frag_q)) != NULL)
+ GKI_freebuf(p_frag);
+ p_scb->frag_off = 0;
+#endif
+ if (p_scb->p_pkt)
+ {
+ GKI_freebuf(p_scb->p_pkt);
+ p_scb->p_pkt = NULL;
+ }
+
+#if 0
+ if(p_scb->cong)
+ p_scb->cong = FALSE;
+
+ /* p_scb->curr_cfg.mux_tsid_media == 0 */
+#endif
+ avdt_scb_snd_close_req(p_scb, p_data);
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_snd_close_rsp
+**
+** Description This function sends a close response message.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_snd_close_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ avdt_msg_send_rsp(p_scb->p_ccb, AVDT_SIG_CLOSE, &p_data->msg);
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_snd_getconfig_req
+**
+** Description This function sends a get configuration command message.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_snd_getconfig_req(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ tAVDT_EVT_HDR hdr;
+
+ hdr.seid = p_scb->peer_seid;
+
+ avdt_msg_send_cmd(p_scb->p_ccb, p_scb, AVDT_SIG_GETCONFIG, (tAVDT_MSG *) &hdr);
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_snd_getconfig_rsp
+**
+** Description This function sends a get configuration response message.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_snd_getconfig_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ avdt_msg_send_rsp(p_scb->p_ccb, AVDT_SIG_GETCONFIG, &p_data->msg);
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_snd_open_req
+**
+** Description This function sends an open command message.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_snd_open_req(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ tAVDT_EVT_HDR hdr;
+
+ hdr.seid = p_scb->peer_seid;
+
+ avdt_msg_send_cmd(p_scb->p_ccb, p_scb, AVDT_SIG_OPEN, (tAVDT_MSG *) &hdr);
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_snd_open_rsp
+**
+** Description This function sends an open response message. It also
+** calls avdt_ad_open_req() to accept a transport channel
+** connection.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_snd_open_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ /* notify adaption that we're waiting for transport channel open */
+ p_scb->role = AVDT_OPEN_ACP;
+ avdt_ad_open_req(AVDT_CHAN_MEDIA, p_scb->p_ccb, p_scb, AVDT_ACP);
+
+ /* send response */
+ avdt_msg_send_rsp(p_scb->p_ccb, AVDT_SIG_OPEN, &p_data->msg);
+
+ /* start tc connect timer */
+ btu_start_timer(&p_scb->timer_entry, BTU_TTYPE_AVDT_SCB_TC, AVDT_SCB_TC_CONN_TOUT);
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_snd_reconfig_req
+**
+** Description This function stores the configuration parameters in the
+** SCB and sends a reconfiguration command message.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_snd_reconfig_req(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ memcpy(&p_scb->req_cfg, p_data->msg.config_cmd.p_cfg, sizeof(tAVDT_CFG));
+ p_data->msg.hdr.seid = p_scb->peer_seid;
+ avdt_msg_send_cmd(p_scb->p_ccb, p_scb, AVDT_SIG_RECONFIG, &p_data->msg);
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_snd_reconfig_rsp
+**
+** Description This function stores the configuration parameters in the
+** SCB and sends a reconfiguration response message.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_snd_reconfig_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ if (p_data->msg.hdr.err_code == 0)
+ {
+ /* store new configuration */
+ if (p_scb->req_cfg.num_codec > 0)
+ {
+ p_scb->curr_cfg.num_codec = p_scb->req_cfg.num_codec;
+ memcpy(p_scb->curr_cfg.codec_info, p_scb->req_cfg.codec_info, AVDT_CODEC_SIZE);
+ }
+ if (p_scb->req_cfg.num_protect > 0)
+ {
+ p_scb->curr_cfg.num_protect = p_scb->req_cfg.num_protect;
+ memcpy(p_scb->curr_cfg.protect_info, p_scb->req_cfg.protect_info, AVDT_PROTECT_SIZE);
+ }
+
+ /* send response */
+ avdt_msg_send_rsp(p_scb->p_ccb, AVDT_SIG_RECONFIG, &p_data->msg);
+ }
+ else
+ {
+ /* send reject */
+ avdt_msg_send_rej(p_scb->p_ccb, AVDT_SIG_RECONFIG, &p_data->msg);
+ }
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_snd_security_req
+**
+** Description This function sends a security command message.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_snd_security_req(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ p_data->msg.hdr.seid = p_scb->peer_seid;
+ avdt_msg_send_cmd(p_scb->p_ccb, p_scb, AVDT_SIG_SECURITY, &p_data->msg);
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_snd_security_rsp
+**
+** Description This function sends a security response message.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_snd_security_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ if (p_data->msg.hdr.err_code == 0)
+ {
+ avdt_msg_send_rsp(p_scb->p_ccb, AVDT_SIG_SECURITY, &p_data->msg);
+ }
+ else
+ {
+ avdt_msg_send_rej(p_scb->p_ccb, AVDT_SIG_SECURITY, &p_data->msg);
+ }
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_snd_setconfig_rej
+**
+** Description This function marks the SCB as not in use and sends a
+** set configuration reject message.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_snd_setconfig_rej(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ if (p_scb->p_ccb != NULL)
+ {
+ avdt_msg_send_rej(p_scb->p_ccb, AVDT_SIG_SETCONFIG, &p_data->msg);
+
+ /* clear scb variables */
+ avdt_scb_clr_vars(p_scb, p_data);
+ }
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_snd_setconfig_req
+**
+** Description This function marks the SCB as in use and copies the
+** configuration parameters to the SCB. Then the function
+** sends a set configuration command message and initiates
+** opening of the signaling channel.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_snd_setconfig_req(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ tAVDT_CFG *p_req, *p_cfg;
+
+ /* copy API parameters to scb, set scb as in use */
+ p_scb->in_use = TRUE;
+ p_scb->p_ccb = avdt_ccb_by_idx(p_data->msg.config_cmd.hdr.ccb_idx);
+ p_scb->peer_seid = p_data->msg.config_cmd.hdr.seid;
+ p_req = p_data->msg.config_cmd.p_cfg;
+ p_cfg = &p_scb->cs.cfg;
+#if AVDT_MULTIPLEXING == TRUE
+ p_req->mux_tsid_media = p_cfg->mux_tsid_media;
+ p_req->mux_tcid_media = p_cfg->mux_tcid_media;
+ if(p_req->psc_mask & AVDT_PSC_REPORT)
+ {
+ p_req->mux_tsid_report = p_cfg->mux_tsid_report;
+ p_req->mux_tcid_report = p_cfg->mux_tcid_report;
+ }
+#endif
+ memcpy(&p_scb->req_cfg, p_data->msg.config_cmd.p_cfg, sizeof(tAVDT_CFG));
+
+ avdt_msg_send_cmd(p_scb->p_ccb, p_scb, AVDT_SIG_SETCONFIG, &p_data->msg);
+
+ /* tell ccb to open channel */
+ avdt_ccb_event(p_scb->p_ccb, AVDT_CCB_UL_OPEN_EVT, NULL);
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_snd_setconfig_rsp
+**
+** Description This function copies the requested configuration into the
+** current configuration and sends a set configuration
+** response message.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_snd_setconfig_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ if (p_scb->p_ccb != NULL)
+ {
+ memcpy(&p_scb->curr_cfg, &p_scb->req_cfg, sizeof(tAVDT_CFG));
+
+ avdt_msg_send_rsp(p_scb->p_ccb, AVDT_SIG_SETCONFIG, &p_data->msg);
+ }
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_snd_tc_close
+**
+** Description This function calls avdt_ad_close_req() to close the
+** transport channel for this SCB.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_snd_tc_close(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+#if AVDT_REPORTING == TRUE
+ if(p_scb->curr_cfg.psc_mask & AVDT_PSC_REPORT)
+ avdt_ad_close_req(AVDT_CHAN_REPORT, p_scb->p_ccb, p_scb);
+#endif
+ avdt_ad_close_req(AVDT_CHAN_MEDIA, p_scb->p_ccb, p_scb);
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_cb_err
+**
+** Description This function calls the application callback function
+** indicating an error.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_cb_err(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ tAVDT_CTRL avdt_ctrl;
+
+ /* set error code and parameter */
+ avdt_ctrl.hdr.err_code = AVDT_ERR_BAD_STATE;
+ avdt_ctrl.hdr.err_param = 0;
+
+ /* call callback, using lookup table to get callback event */
+ (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb),
+ NULL,
+ avdt_scb_cback_evt[p_scb->curr_evt],
+ &avdt_ctrl);
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_cong_state
+**
+** Description This function sets the congestion state of the SCB media
+** transport channel.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_cong_state(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ p_scb->cong = p_data->llcong;
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_rej_state
+**
+** Description This function sends a reject message to the peer indicating
+** incorrect state for the received command message.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_rej_state(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ p_data->msg.hdr.err_code = AVDT_ERR_BAD_STATE;
+ p_data->msg.hdr.err_param = 0;
+ avdt_msg_send_rej(avdt_ccb_by_idx(p_data->msg.hdr.ccb_idx),
+ p_data->msg.hdr.sig_id, &p_data->msg);
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_rej_in_use
+**
+** Description This function sends a reject message to the peer indicating
+** the stream is in use.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_rej_in_use(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ p_data->msg.hdr.err_code = AVDT_ERR_IN_USE;
+ p_data->msg.hdr.err_param = 0;
+ avdt_msg_send_rej(avdt_ccb_by_idx(p_data->msg.hdr.ccb_idx),
+ p_data->msg.hdr.sig_id, &p_data->msg);
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_rej_not_in_use
+**
+** Description This function sends a reject message to the peer indicating
+** the stream is in use.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_rej_not_in_use(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ p_data->msg.hdr.err_code = AVDT_ERR_NOT_IN_USE;
+ p_data->msg.hdr.err_param = 0;
+ avdt_msg_send_rej(avdt_ccb_by_idx(p_data->msg.hdr.ccb_idx),
+ p_data->msg.hdr.sig_id, &p_data->msg);
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_set_remove
+**
+** Description This function marks an SCB to be removed.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_set_remove(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ p_scb->remove = TRUE;
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_free_pkt
+**
+** Description This function frees the media packet passed in.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_free_pkt(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ tAVDT_CTRL avdt_ctrl;
+#if AVDT_MULTIPLEXING == TRUE
+ BT_HDR *p_frag;
+#endif
+
+ /* set error code and parameter */
+ avdt_ctrl.hdr.err_code = AVDT_ERR_BAD_STATE;
+ avdt_ctrl.hdr.err_param = 0;
+
+ /* p_buf can be NULL in case using of fragments queue frag_q */
+ if(p_data->apiwrite.p_buf)
+ GKI_freebuf(p_data->apiwrite.p_buf);
+
+#if AVDT_MULTIPLEXING == TRUE
+ /* clean fragments queue */
+ while((p_frag = (BT_HDR*)GKI_dequeue (&p_data->apiwrite.frag_q)) != NULL)
+ GKI_freebuf(p_frag);
+#endif
+
+ AVDT_TRACE_WARNING0("Dropped media packet");
+
+ /* we need to call callback to keep data flow going */
+ (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb), NULL, AVDT_WRITE_CFM_EVT,
+ &avdt_ctrl);
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_clr_pkt
+**
+** Description This function frees the media packet stored in the SCB.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_clr_pkt(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ tAVDT_CTRL avdt_ctrl;
+ tAVDT_CCB *p_ccb;
+ UINT8 tcid;
+ UINT16 lcid;
+#if AVDT_MULTIPLEXING == TRUE
+ BT_HDR *p_frag;
+#endif
+
+ /* set error code and parameter */
+ avdt_ctrl.hdr.err_code = AVDT_ERR_BAD_STATE;
+ avdt_ctrl.hdr.err_param = 0;
+ /* flush the media data queued at L2CAP */
+ if((p_ccb = p_scb->p_ccb) != NULL)
+ {
+ /* get tcid from type, scb */
+ tcid = avdt_ad_type_to_tcid(AVDT_CHAN_MEDIA, p_scb);
+
+ lcid = avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid;
+ L2CA_FlushChannel (lcid, L2CAP_FLUSH_CHANS_ALL);
+ }
+
+ if (p_scb->p_pkt != NULL)
+ {
+ GKI_freebuf(p_scb->p_pkt);
+ p_scb->p_pkt = NULL;
+
+ AVDT_TRACE_DEBUG0("Dropped stored media packet");
+
+ /* we need to call callback to keep data flow going */
+ (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb), NULL, AVDT_WRITE_CFM_EVT,
+ &avdt_ctrl);
+ }
+#if AVDT_MULTIPLEXING == TRUE
+ else if(!GKI_queue_is_empty (&p_scb->frag_q))
+ {
+ AVDT_TRACE_DEBUG0("Dropped fragments queue");
+ /* clean fragments queue */
+ while((p_frag = (BT_HDR*)GKI_dequeue (&p_scb->frag_q)) != NULL)
+ GKI_freebuf(p_frag);
+
+ p_scb->frag_off = 0;
+
+ /* we need to call callback to keep data flow going */
+ (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb), NULL, AVDT_WRITE_CFM_EVT,
+ &avdt_ctrl);
+ }
+#endif
+}
+
+
+/*******************************************************************************
+**
+** Function avdt_scb_chk_snd_pkt
+**
+** Description This function checks if the SCB is congested, and if not
+** congested it sends a stored media packet, if any. After it
+** sends the packet it calls the application callback function
+** with a write confirm.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_chk_snd_pkt(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ tAVDT_CTRL avdt_ctrl;
+ BT_HDR *p_pkt;
+#if AVDT_MULTIPLEXING == TRUE
+ BOOLEAN sent = FALSE;
+ UINT8 res = AVDT_AD_SUCCESS;
+ tAVDT_SCB_EVT data;
+#endif
+
+ avdt_ctrl.hdr.err_code = 0;
+
+ if (!p_scb->cong)
+ {
+ if (p_scb->p_pkt != NULL)
+ {
+ p_pkt = p_scb->p_pkt;
+ p_scb->p_pkt = NULL;
+ avdt_ad_write_req(AVDT_CHAN_MEDIA, p_scb->p_ccb, p_scb, p_pkt);
+
+ (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb), NULL, AVDT_WRITE_CFM_EVT, &avdt_ctrl);
+ }
+#if AVDT_MULTIPLEXING == TRUE
+ else
+ {
+#if 0
+ AVDT_TRACE_DEBUG1("num_q=%d",
+ L2CA_FlushChannel(avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_scb->p_ccb)][avdt_ad_type_to_tcid(AVDT_CHAN_MEDIA, p_scb)].lcid),
+ L2CAP_FLUSH_CHANS_GET);
+#endif
+ while((p_pkt = (BT_HDR*)GKI_dequeue (&p_scb->frag_q)) != NULL)
+ {
+ sent = TRUE;
+ AVDT_TRACE_DEBUG1("Send fragment len=%d",p_pkt->len);
+ /* fragments queue contains fragment to send */
+ res = avdt_ad_write_req(AVDT_CHAN_MEDIA, p_scb->p_ccb, p_scb, p_pkt);
+ if(AVDT_AD_CONGESTED == res)
+ {
+ p_scb->cong = TRUE;
+ AVDT_TRACE_DEBUG0("avdt/l2c congested!!");
+ break;/* exit loop if channel became congested */
+ }
+ }
+ AVDT_TRACE_DEBUG2("res=%d left=%d",res, p_scb->frag_off);
+
+ if(p_scb->frag_off)
+ {
+ if(AVDT_AD_SUCCESS == res || GKI_queue_is_empty (&p_scb->frag_q))
+ {
+ /* all buffers were sent to L2CAP, compose more to queue */
+ avdt_scb_queue_frags(p_scb, &p_scb->p_next_frag, &p_scb->frag_off, &p_scb->frag_q);
+ if(!GKI_queue_is_empty (&p_scb->frag_q))
+ {
+ data.llcong = p_scb->cong;
+ avdt_scb_event(p_scb, AVDT_SCB_TC_CONG_EVT, &data);
+ }
+ }
+ }
+
+ /* Send event AVDT_WRITE_CFM_EVT if it was last fragment */
+ else if (sent && GKI_queue_is_empty (&p_scb->frag_q))
+ {
+ (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb), NULL, AVDT_WRITE_CFM_EVT, &avdt_ctrl);
+ }
+ }
+#endif
+ }
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_tc_timer
+**
+** Description This function is called to start a timer when the peer
+** initiates closing of the stream. The timer verifies that
+** the peer disconnects the transport channel.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_tc_timer(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ btu_start_timer(&p_scb->timer_entry, BTU_TTYPE_AVDT_SCB_TC, AVDT_SCB_TC_DISC_TOUT);
+}
+
+/*******************************************************************************
+**
+** Function avdt_scb_clr_vars
+**
+** Description This function initializes certain SCB variables.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_clr_vars(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
+{
+ p_scb->in_use = FALSE;
+ p_scb->p_ccb = NULL;
+ p_scb->peer_seid = 0;
+}
+
+#if AVDT_MULTIPLEXING == TRUE
+/*******************************************************************************
+**
+** Function avdt_scb_queue_frags
+**
+** Description This function breaks media payload into fragments
+** and put the fragments in the given queue.
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void avdt_scb_queue_frags(tAVDT_SCB *p_scb, UINT8 **pp_data, UINT32 *p_data_len, BUFFER_Q *pq)
+{
+ UINT16 lcid;
+ UINT16 num_frag;
+ UINT16 mtu_used;
+ UINT8 *p;
+ BOOLEAN al_hdr = FALSE;
+ UINT8 tcid;
+ tAVDT_TC_TBL *p_tbl;
+ UINT16 buf_size;
+ UINT16 offset = AVDT_MEDIA_OFFSET + AVDT_AL_HDR_SIZE;
+ UINT16 cont_offset = offset - AVDT_MEDIA_HDR_SIZE;
+ BT_HDR *p_frag;
+
+ tcid = avdt_ad_type_to_tcid(AVDT_CHAN_MEDIA, p_scb);
+ lcid = avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_scb->p_ccb)][tcid].lcid;
+
+ if( p_scb->frag_off != 0)
+ {
+ /* continuing process is usually triggered by un-congest event.
+ * the number of buffers at L2CAP is very small (if not 0).
+ * we do not need to L2CA_FlushChannel() */
+ offset = cont_offset;
+ al_hdr = TRUE;
+ num_frag = AVDT_MAX_FRAG_COUNT;
+ }
+ else
+ {
+ num_frag = L2CA_FlushChannel(lcid, L2CAP_FLUSH_CHANS_GET);
+ AVDT_TRACE_DEBUG2("num_q=%d lcid=%d", num_frag, lcid);
+ if(num_frag >= AVDT_MAX_FRAG_COUNT)
+ {
+ num_frag = 0;
+ }
+ else
+ {
+ num_frag = AVDT_MAX_FRAG_COUNT - num_frag;
+ }
+ }
+
+ /* look up transport channel table entry to get peer mtu */
+ p_tbl = avdt_ad_tc_tbl_by_type(AVDT_CHAN_MEDIA, p_scb->p_ccb, p_scb);
+ buf_size = p_tbl->peer_mtu + BT_HDR_SIZE;
+ AVDT_TRACE_DEBUG3("peer_mtu: %d, buf_size: %d num_frag=%d",
+ p_tbl->peer_mtu, buf_size, num_frag);
+
+ if(buf_size > AVDT_DATA_POOL_SIZE)
+ buf_size = AVDT_DATA_POOL_SIZE;
+
+ mtu_used = buf_size - BT_HDR_SIZE;
+
+ while(*p_data_len && num_frag)
+ {
+ /* allocate buffer for fragment */
+ if(NULL == (p_frag = (BT_HDR*)GKI_getbuf(buf_size)))
+ {
+ AVDT_TRACE_WARNING1("avdt_scb_queue_frags len=%d(out of GKI buffers)",*p_data_len);
+ break;
+ }
+ /* fill fragment by chunk of media payload */
+ p_frag->layer_specific = *p_data_len;/* length of all remaining transport packet */
+ p_frag->offset = offset;
+ /* adjust packet offset for continuing packets */
+ offset = cont_offset;
+
+ p_frag->len = mtu_used - p_frag->offset;
+ if(p_frag->len > *p_data_len)
+ p_frag->len = *p_data_len;
+ memcpy((UINT8*)(p_frag+1) + p_frag->offset, *pp_data, p_frag->len);
+ *pp_data += p_frag->len;
+ *p_data_len -= p_frag->len;
+ AVDT_TRACE_DEBUG1("Prepared fragment len=%d", p_frag->len);
+
+ if(al_hdr)
+ {
+ /* Adaptation Layer header */
+ p_frag->len += AVDT_AL_HDR_SIZE;
+ p_frag->offset -= AVDT_AL_HDR_SIZE;
+ p = (UINT8 *)(p_frag + 1) + p_frag->offset;
+ /* TSID, fragment bit and coding of length(in 2 length octets following) */
+ *p++ = (p_scb->curr_cfg.mux_tsid_media<<3) | (AVDT_ALH_FRAG_MASK|AVDT_ALH_LCODE_16BIT);
+
+ /* length of all remaining transport packet */
+ UINT16_TO_BE_STREAM(p, p_frag->layer_specific );
+ }
+ /* put fragment into gueue */
+ GKI_enqueue(pq, p_frag);
+ num_frag--;
+ }
+}
+#endif
+