]> granicus.if.org Git - esp-idf/commitdiff
component/bt: transport bluedroid avct, avdt, avrc and a2dp module to stack
authorwangmengyang <wangmengyang@espressif.com>
Wed, 2 Nov 2016 09:42:26 +0000 (17:42 +0800)
committerwangmengyang <wangmengyang@espressif.com>
Wed, 2 Nov 2016 09:42:26 +0000 (17:42 +0800)
38 files changed:
components/bt/bluedroid/stack/a2dp/a2d_api.c [new file with mode: 0755]
components/bt/bluedroid/stack/a2dp/a2d_sbc.c [new file with mode: 0755]
components/bt/bluedroid/stack/a2dp/include/a2d_int.h [new file with mode: 0755]
components/bt/bluedroid/stack/avct/avct_api.c [new file with mode: 0755]
components/bt/bluedroid/stack/avct/avct_ccb.c [new file with mode: 0755]
components/bt/bluedroid/stack/avct/avct_l2c.c [new file with mode: 0755]
components/bt/bluedroid/stack/avct/avct_lcb.c [new file with mode: 0755]
components/bt/bluedroid/stack/avct/avct_lcb_act.c [new file with mode: 0755]
components/bt/bluedroid/stack/avct/include/avct_defs.h [new file with mode: 0755]
components/bt/bluedroid/stack/avct/include/avct_int.h [new file with mode: 0755]
components/bt/bluedroid/stack/avdt/avdt_ad.c [new file with mode: 0755]
components/bt/bluedroid/stack/avdt/avdt_api.c [new file with mode: 0755]
components/bt/bluedroid/stack/avdt/avdt_ccb.c [new file with mode: 0755]
components/bt/bluedroid/stack/avdt/avdt_ccb_act.c [new file with mode: 0755]
components/bt/bluedroid/stack/avdt/avdt_l2c.c [new file with mode: 0755]
components/bt/bluedroid/stack/avdt/avdt_msg.c [new file with mode: 0755]
components/bt/bluedroid/stack/avdt/avdt_scb.c [new file with mode: 0755]
components/bt/bluedroid/stack/avdt/avdt_scb_act.c [new file with mode: 0755]
components/bt/bluedroid/stack/avdt/include/avdt_defs.h [moved from components/bt/bluedroid/profiles/std/include/avdt_defs.h with 100% similarity]
components/bt/bluedroid/stack/avdt/include/avdt_int.h [new file with mode: 0755]
components/bt/bluedroid/stack/avrc/avrc_api.c [moved from components/bt/bluedroid/profiles/std/avrc/avrc_api.c with 99% similarity]
components/bt/bluedroid/stack/avrc/avrc_bld_ct.c [moved from components/bt/bluedroid/profiles/std/avrc/avrc_bld_ct.c with 100% similarity]
components/bt/bluedroid/stack/avrc/avrc_bld_tg.c [moved from components/bt/bluedroid/profiles/std/avrc/avrc_bld_tg.c with 99% similarity]
components/bt/bluedroid/stack/avrc/avrc_opt.c [moved from components/bt/bluedroid/profiles/std/avrc/avrc_opt.c with 99% similarity]
components/bt/bluedroid/stack/avrc/avrc_pars_ct.c [moved from components/bt/bluedroid/profiles/std/avrc/avrc_pars_ct.c with 99% similarity]
components/bt/bluedroid/stack/avrc/avrc_pars_tg.c [moved from components/bt/bluedroid/profiles/std/avrc/avrc_pars_tg.c with 100% similarity]
components/bt/bluedroid/stack/avrc/avrc_sdp.c [moved from components/bt/bluedroid/profiles/std/avrc/avrc_sdp.c with 100% similarity]
components/bt/bluedroid/stack/avrc/avrc_utils.c [moved from components/bt/bluedroid/profiles/std/avrc/avrc_utils.c with 100% similarity]
components/bt/bluedroid/stack/avrc/include/avrc_int.h [moved from components/bt/bluedroid/profiles/std/avrc/include/avrc_int.h with 99% similarity]
components/bt/bluedroid/stack/include/a2d_api.h [new file with mode: 0755]
components/bt/bluedroid/stack/include/a2d_sbc.h [new file with mode: 0755]
components/bt/bluedroid/stack/include/avct_api.h [moved from components/bt/bluedroid/profiles/std/include/avct_api.h with 100% similarity]
components/bt/bluedroid/stack/include/avdt_api.h [moved from components/bt/bluedroid/profiles/std/include/avdt_api.h with 100% similarity]
components/bt/bluedroid/stack/include/avdtc_api.h [moved from components/bt/bluedroid/profiles/std/include/avdtc_api.h with 100% similarity]
components/bt/bluedroid/stack/include/avrc_api.h [moved from components/bt/bluedroid/profiles/std/include/avrc_api.h with 100% similarity]
components/bt/bluedroid/stack/include/avrc_defs.h [moved from components/bt/bluedroid/profiles/std/include/avrc_defs.h with 100% similarity]
components/bt/bluedroid/utils/include/bt_utils.h [new file with mode: 0755]
components/bt/component.mk

diff --git a/components/bt/bluedroid/stack/a2dp/a2d_api.c b/components/bt/bluedroid/stack/a2dp/a2d_api.c
new file mode 100755 (executable)
index 0000000..f0f4a83
--- /dev/null
@@ -0,0 +1,395 @@
+/******************************************************************************
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  ommon API for the Advanced Audio Distribution Profile (A2DP)
+ *
+ ******************************************************************************/
+#include <string.h>
+#include "bt_target.h"
+#include "sdpdefs.h"
+#include "a2d_api.h"
+#include "a2d_int.h"
+#include "avdt_api.h"
+
+/*****************************************************************************
+**  Global data
+*****************************************************************************/
+#if A2D_DYNAMIC_MEMORY == FALSE
+tA2D_CB a2d_cb;
+#endif
+
+
+/******************************************************************************
+**
+** Function         a2d_sdp_cback
+**
+** Description      This is the SDP callback function used by A2D_FindService.
+**                  This function will be executed by SDP when the service
+**                  search is completed.  If the search is successful, it
+**                  finds the first record in the database that matches the
+**                  UUID of the search.  Then retrieves various parameters
+**                  from the record.  When it is finished it calls the
+**                  application callback function.
+**
+** Returns          Nothing.
+**
+******************************************************************************/
+static void a2d_sdp_cback(UINT16 status)
+{
+    tSDP_DISC_REC       *p_rec = NULL;
+    tSDP_DISC_ATTR      *p_attr;
+    BOOLEAN             found = FALSE;
+    tA2D_Service        a2d_svc;
+    tSDP_PROTOCOL_ELEM  elem;
+
+    A2D_TRACE_API("a2d_sdp_cback status: %d", status);
+
+    if (status == SDP_SUCCESS)
+    {
+        /* loop through all records we found */
+        do
+        {
+            /* get next record; if none found, we're done */
+            if ((p_rec = SDP_FindServiceInDb(a2d_cb.find.p_db,
+                            a2d_cb.find.service_uuid, p_rec)) == NULL)
+            {
+                break;
+            }
+            memset(&a2d_svc, 0, sizeof(tA2D_Service));
+
+            /* get service name */
+            if ((p_attr = SDP_FindAttributeInRec(p_rec,
+                            ATTR_ID_SERVICE_NAME)) != NULL)
+            {
+                a2d_svc.p_service_name = (char *) p_attr->attr_value.v.array;
+                a2d_svc.service_len    = SDP_DISC_ATTR_LEN(p_attr->attr_len_type);
+            }
+
+            /* get provider name */
+            if ((p_attr = SDP_FindAttributeInRec(p_rec,
+                            ATTR_ID_PROVIDER_NAME)) != NULL)
+            {
+                a2d_svc.p_provider_name = (char *) p_attr->attr_value.v.array;
+                a2d_svc.provider_len    = SDP_DISC_ATTR_LEN(p_attr->attr_len_type);
+            }
+
+            /* get supported features */
+            if ((p_attr = SDP_FindAttributeInRec(p_rec,
+                            ATTR_ID_SUPPORTED_FEATURES)) != NULL)
+            {
+                a2d_svc.features = p_attr->attr_value.v.u16;
+            }
+
+            /* get AVDTP version */
+            if (SDP_FindProtocolListElemInRec(p_rec, UUID_PROTOCOL_AVDTP, &elem))
+            {
+                a2d_svc.avdt_version = elem.params[0];
+                A2D_TRACE_DEBUG("avdt_version: 0x%x", a2d_svc.avdt_version);
+            }
+
+            /* we've got everything, we're done */
+            found = TRUE;
+            break;
+
+        } while (TRUE);
+    }
+
+    a2d_cb.find.service_uuid = 0;
+    /* return info from sdp record in app callback function */
+    if (a2d_cb.find.p_cback != NULL)
+    {
+        (*a2d_cb.find.p_cback)(found, &a2d_svc);
+    }
+
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         a2d_set_avdt_sdp_ver
+**
+** Description      This function allows the script wrapper to change the
+**                  avdt version of a2dp.
+**
+** Returns          None
+**
+*******************************************************************************/
+void a2d_set_avdt_sdp_ver (UINT16 avdt_sdp_ver)
+{
+    a2d_cb.avdt_sdp_ver = avdt_sdp_ver;
+}
+
+/******************************************************************************
+**
+** Function         A2D_AddRecord
+**
+** Description      This function is called by a server application to add
+**                  SRC or SNK information to an SDP record.  Prior to
+**                  calling this function the application must call
+**                  SDP_CreateRecord() to create an SDP record.
+**
+**                  Input Parameters:
+**                      service_uuid:  Indicates SRC or SNK.
+**
+**                      p_service_name:  Pointer to a null-terminated character
+**                      string containing the service name.
+**
+**                      p_provider_name:  Pointer to a null-terminated character
+**                      string containing the provider name.
+**
+**                      features:  Profile supported features.
+**
+**                      sdp_handle:  SDP handle returned by SDP_CreateRecord().
+**
+**                  Output Parameters:
+**                      None.
+**
+** Returns          A2D_SUCCESS if function execution succeeded,
+**                  A2D_INVALID_PARAMS if bad parameters are given.
+**                  A2D_FAIL if function execution failed.
+**
+******************************************************************************/
+tA2D_STATUS A2D_AddRecord(UINT16 service_uuid, char *p_service_name, char *p_provider_name,
+        UINT16 features, UINT32 sdp_handle)
+{
+    UINT16      browse_list[1];
+    BOOLEAN     result = TRUE;
+    UINT8       temp[8];
+    UINT8       *p;
+    tSDP_PROTOCOL_ELEM  proto_list [A2D_NUM_PROTO_ELEMS];
+
+    A2D_TRACE_API("A2D_AddRecord uuid: %x", service_uuid);
+
+    if( (sdp_handle == 0) ||
+        (service_uuid != UUID_SERVCLASS_AUDIO_SOURCE && service_uuid != UUID_SERVCLASS_AUDIO_SINK) )
+        return A2D_INVALID_PARAMS;
+
+    /* add service class id list */
+    result &= SDP_AddServiceClassIdList(sdp_handle, 1, &service_uuid);
+
+    memset((void*) proto_list, 0 , A2D_NUM_PROTO_ELEMS*sizeof(tSDP_PROTOCOL_ELEM));
+
+    /* add protocol descriptor list   */
+    proto_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
+    proto_list[0].num_params = 1;
+    proto_list[0].params[0] = AVDT_PSM;
+    proto_list[1].protocol_uuid = UUID_PROTOCOL_AVDTP;
+    proto_list[1].num_params = 1;
+    proto_list[1].params[0] = a2d_cb.avdt_sdp_ver;
+
+    result &= SDP_AddProtocolList(sdp_handle, A2D_NUM_PROTO_ELEMS, proto_list);
+
+    /* add profile descriptor list   */
+    result &= SDP_AddProfileDescriptorList(sdp_handle, UUID_SERVCLASS_ADV_AUDIO_DISTRIBUTION, A2D_VERSION);
+
+    /* add supported feature */
+    if (features != 0)
+    {
+        p = temp;
+        UINT16_TO_BE_STREAM(p, features);
+        result &= SDP_AddAttribute(sdp_handle, ATTR_ID_SUPPORTED_FEATURES, UINT_DESC_TYPE,
+                  (UINT32)2, (UINT8*)temp);
+    }
+
+    /* add provider name */
+    if (p_provider_name != NULL)
+    {
+        result &= SDP_AddAttribute(sdp_handle, ATTR_ID_PROVIDER_NAME, TEXT_STR_DESC_TYPE,
+                    (UINT32)(strlen(p_provider_name)+1), (UINT8 *) p_provider_name);
+    }
+
+    /* add service name */
+    if (p_service_name != NULL)
+    {
+        result &= SDP_AddAttribute(sdp_handle, ATTR_ID_SERVICE_NAME, TEXT_STR_DESC_TYPE,
+                    (UINT32)(strlen(p_service_name)+1), (UINT8 *) p_service_name);
+    }
+
+    /* add browse group list */
+    browse_list[0] = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
+    result &= SDP_AddUuidSequence(sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, browse_list);
+
+
+    return (result ? A2D_SUCCESS : A2D_FAIL);
+}
+
+/******************************************************************************
+**
+** Function         A2D_FindService
+**
+** Description      This function is called by a client application to
+**                  perform service discovery and retrieve SRC or SNK SDP
+**                  record information from a server.  Information is
+**                  returned for the first service record found on the
+**                  server that matches the service UUID.  The callback
+**                  function will be executed when service discovery is
+**                  complete.  There can only be one outstanding call to
+**                  A2D_FindService() at a time; the application must wait
+**                  for the callback before it makes another call to
+**                  the function.
+**
+**                  Input Parameters:
+**                      service_uuid:  Indicates SRC or SNK.
+**
+**                      bd_addr:  BD address of the peer device.
+**
+**                      p_db:  Pointer to the information to initialize
+**                             the discovery database.
+**
+**                      p_cback:  Pointer to the A2D_FindService()
+**                      callback function.
+**
+**                  Output Parameters:
+**                      None.
+**
+** Returns          A2D_SUCCESS if function execution succeeded,
+**                  A2D_INVALID_PARAMS if bad parameters are given.
+**                  A2D_BUSY if discovery is already in progress.
+**                  A2D_FAIL if function execution failed.
+**
+******************************************************************************/
+tA2D_STATUS A2D_FindService(UINT16 service_uuid, BD_ADDR bd_addr,
+                        tA2D_SDP_DB_PARAMS *p_db, tA2D_FIND_CBACK *p_cback)
+{
+    tSDP_UUID   uuid_list;
+    BOOLEAN     result = TRUE;
+    UINT16      a2d_attr_list[] = {ATTR_ID_SERVICE_CLASS_ID_LIST, /* update A2D_NUM_ATTR, if changed */
+                                   ATTR_ID_BT_PROFILE_DESC_LIST,
+                                   ATTR_ID_SUPPORTED_FEATURES,
+                                   ATTR_ID_SERVICE_NAME,
+                                   ATTR_ID_PROTOCOL_DESC_LIST,
+                                   ATTR_ID_PROVIDER_NAME};
+
+    A2D_TRACE_API("A2D_FindService uuid: %x", service_uuid);
+    if( (service_uuid != UUID_SERVCLASS_AUDIO_SOURCE && service_uuid != UUID_SERVCLASS_AUDIO_SINK) ||
+        p_db == NULL || p_db->p_db == NULL || p_cback == NULL)
+        return A2D_INVALID_PARAMS;
+
+    if( a2d_cb.find.service_uuid == UUID_SERVCLASS_AUDIO_SOURCE ||
+        a2d_cb.find.service_uuid == UUID_SERVCLASS_AUDIO_SINK)
+        return A2D_BUSY;
+
+    /* set up discovery database */
+    uuid_list.len = LEN_UUID_16;
+    uuid_list.uu.uuid16 = service_uuid;
+
+    if(p_db->p_attrs == NULL || p_db->num_attr == 0)
+    {
+        p_db->p_attrs  = a2d_attr_list;
+        p_db->num_attr = A2D_NUM_ATTR;
+    }
+
+    result = SDP_InitDiscoveryDb(p_db->p_db, p_db->db_len, 1, &uuid_list, p_db->num_attr,
+                                 p_db->p_attrs);
+
+    if (result == TRUE)
+    {
+        /* store service_uuid and discovery db pointer */
+        a2d_cb.find.p_db = p_db->p_db;
+        a2d_cb.find.service_uuid = service_uuid;
+        a2d_cb.find.p_cback = p_cback;
+
+        /* perform service search */
+        result = SDP_ServiceSearchAttributeRequest(bd_addr, p_db->p_db, a2d_sdp_cback);
+        if(FALSE == result)
+        {
+            a2d_cb.find.service_uuid = 0;
+        }
+    }
+
+    return (result ? A2D_SUCCESS : A2D_FAIL);
+}
+
+/******************************************************************************
+**
+** Function         A2D_SetTraceLevel
+**
+** Description      Sets the trace level for A2D. If 0xff is passed, the
+**                  current trace level is returned.
+**
+**                  Input Parameters:
+**                      new_level:  The level to set the A2D 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 A2D_SetTraceLevel (UINT8 new_level)
+{
+    if (new_level != 0xFF)
+        a2d_cb.trace_level = new_level;
+
+    return (a2d_cb.trace_level);
+}
+
+/******************************************************************************
+** Function         A2D_BitsSet
+**
+** Description      Check the given num for the number of bits set
+** Returns          A2D_SET_ONE_BIT, if one and only one bit is set
+**                  A2D_SET_ZERO_BIT, if all bits clear
+**                  A2D_SET_MULTL_BIT, if multiple bits are set
+******************************************************************************/
+UINT8 A2D_BitsSet(UINT8 num)
+{
+    UINT8   count;
+    BOOLEAN res;
+    if(num == 0)
+        res = A2D_SET_ZERO_BIT;
+    else
+    {
+        count = (num & (num - 1));
+        res = ((count==0)?A2D_SET_ONE_BIT:A2D_SET_MULTL_BIT);
+    }
+    return res;
+}
+
+/*******************************************************************************
+**
+** Function         A2D_Init
+**
+** Description      This function is called to initialize the control block
+**                  for this layer.  It must be called before accessing any
+**                  other API functions for this layer.  It is typically called
+**                  once during the start up of the stack.
+**
+** Returns          void
+**
+*******************************************************************************/
+void A2D_Init(void)
+{
+    memset(&a2d_cb, 0, sizeof(tA2D_CB));
+
+    a2d_cb.avdt_sdp_ver = AVDT_VERSION;
+
+#if defined(A2D_INITIAL_TRACE_LEVEL)
+    a2d_cb.trace_level  = A2D_INITIAL_TRACE_LEVEL;
+#else
+    a2d_cb.trace_level  = BT_TRACE_LEVEL_NONE;
+#endif
+}
+
diff --git a/components/bt/bluedroid/stack/a2dp/a2d_sbc.c b/components/bt/bluedroid/stack/a2dp/a2d_sbc.c
new file mode 100755 (executable)
index 0000000..6ef76fc
--- /dev/null
@@ -0,0 +1,399 @@
+/******************************************************************************
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  Utility functions to help build and parse SBC Codec Information Element
+ *  and Media Payload.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#include <string.h>
+#include "a2d_api.h"
+#include "a2d_int.h"
+#include "a2d_sbc.h"
+#include "bt_utils.h"
+
+/*************************************************************************************************
+ * SBC descramble code
+ * Purpose: to tie the SBC code with BTE/mobile stack code,
+ *          especially for the case when the SBC is ported into a third-party Multimedia chip
+ *
+ * Algorithm:
+ *  init process: all counters reset to 0,
+ *                calculate base_index: (6 + s16NumOfChannels*s16NumOfSubBands/2)
+ *    scramble side:    the init process happens every time SBC_Encoder_Init() is called.
+ *    descramble side:  it would be nice to know if he "init" process has happened.
+ *                      alter the SBC SYNC word 0x9C (1001 1100) to 0x8C (1000 1100).
+ *
+ *  scramble process:
+ *    The CRC byte:
+ *    Every SBC frame has a frame header.
+ *    The 1st byte is the sync word and the following 2 bytes are about the stream format.
+ *    They are supposed to be "constant" within a "song"
+ *    The 4th byte is the CRC byte. The CRC byte is bound to be random.
+ *    Derive 2 items from the CRC byte; one is the "use" bit, the other is the "index".
+ *
+ *    SBC keeps 2 sets of "use" & "index"; derived the current and the previous frame.
+ *
+ *    The "use" bit is any bit in SBC_PRTC_USE_MASK is set.
+ *    If set, SBC uses the "index" from the current frame.
+ *    If not set, SBC uses the "index" from the previous frame or 0.
+ *
+ *    index = (CRC & 0x3) + ((CRC & 0x30) >> 2) // 8 is the max index
+ *
+ *    if(index > 0)
+ *    {
+ *        p = &u8frame[base_index];
+ *        if((index&1)&&(u16PacketLength > (base_index+index*2)))
+ *        {
+ *            // odd index: swap 2 bytes
+ *            tmp = p[index];
+ *            p[index] = p[index*2];
+ *            p[index*2] = tmp;
+ *        }
+ *        else
+ *        {
+ *            // even index: shift by 3
+ *            tmp = (p[index] >> 3) + (p[index] << 5);
+ *            p[index] = tmp;
+ *        }
+ *    }
+ *    //else index is 0. The frame stays unaltered
+ *
+ */
+#define A2D_SBC_SYNC_WORD       0x9C
+#define A2D_SBC_CRC_IDX         3
+#define A2D_SBC_USE_MASK        0x64
+#define A2D_SBC_SYNC_MASK       0x10
+#define A2D_SBC_CIDX            0
+#define A2D_SBC_LIDX            1
+#define A2D_SBC_CH_M_BITS       0xC /* channel mode bits: 0: mono; 1 ch */
+#define A2D_SBC_SUBBAND_BIT     0x1 /* num of subband bit: 0:4; 1: 8 */
+
+#define A2D_SBC_GET_IDX(sc) (((sc) & 0x3) + (((sc) & 0x30) >> 2))
+
+typedef struct
+{
+    UINT8   use;
+    UINT8   idx;
+} tA2D_SBC_FR_CB;
+
+typedef struct
+{
+    tA2D_SBC_FR_CB  fr[2];
+    UINT8           index;
+    UINT8           base;
+} tA2D_SBC_DS_CB;
+
+static tA2D_SBC_DS_CB a2d_sbc_ds_cb;
+/*int a2d_count = 0;*/
+/******************************************************************************
+**
+** Function         A2D_SbcChkFrInit
+**
+** Description      check if need to init the descramble control block.
+**
+** Returns          nothing.
+******************************************************************************/
+void A2D_SbcChkFrInit(UINT8 *p_pkt)
+{
+    UINT8   fmt;
+    UINT8   num_chnl = 1;
+    UINT8   num_subband = 4;
+
+    if((p_pkt[0] & A2D_SBC_SYNC_MASK) == 0)
+    {
+        a2d_cb.use_desc = TRUE;
+        fmt = p_pkt[1];
+        p_pkt[0] |= A2D_SBC_SYNC_MASK;
+        memset(&a2d_sbc_ds_cb, 0, sizeof(tA2D_SBC_DS_CB));
+        if(fmt & A2D_SBC_CH_M_BITS)
+            num_chnl = 2;
+        if(fmt & A2D_SBC_SUBBAND_BIT)
+            num_subband = 8;
+        a2d_sbc_ds_cb.base = 6 + num_chnl*num_subband/2;
+        /*printf("base: %d\n", a2d_sbc_ds_cb.base);
+        a2d_count = 0;*/
+    }
+}
+
+/******************************************************************************
+**
+** Function         A2D_SbcDescramble
+**
+** Description      descramble the packet.
+**
+** Returns          nothing.
+******************************************************************************/
+void A2D_SbcDescramble(UINT8 *p_pkt, UINT16 len)
+{
+    tA2D_SBC_FR_CB *p_cur, *p_last;
+    UINT32   idx, tmp, tmp2;
+
+    if(a2d_cb.use_desc)
+    {
+        /* c2l */
+        p_last  = &a2d_sbc_ds_cb.fr[A2D_SBC_LIDX];
+        p_cur   = &a2d_sbc_ds_cb.fr[A2D_SBC_CIDX];
+        p_last->idx = p_cur->idx;
+        p_last->use = p_cur->use;
+        /* getc */
+        p_cur->use = p_pkt[A2D_SBC_CRC_IDX] & A2D_SBC_USE_MASK;
+        p_cur->idx = A2D_SBC_GET_IDX(p_pkt[A2D_SBC_CRC_IDX]);
+        a2d_sbc_ds_cb.index = (p_cur->use)?A2D_SBC_CIDX:A2D_SBC_LIDX;
+        /*
+        printf("%05d: ar[%02d]: x%02x, msk: x%02x, use: %s, idx: %02d, ",
+            a2d_count++,
+            A2D_SBC_CRC_IDX, p_pkt[A2D_SBC_CRC_IDX], A2D_SBC_USE_MASK,
+            (p_cur->use)?"cur":"lst", p_cur->idx);
+        */
+        /* descramble */
+        idx = a2d_sbc_ds_cb.fr[a2d_sbc_ds_cb.index].idx;
+        if(idx > 0)
+        {
+            p_pkt = &p_pkt[a2d_sbc_ds_cb.base];
+            if((idx&1) && (len > (a2d_sbc_ds_cb.base+(idx<<1))))
+            {
+                tmp2        = (idx<<1);
+                tmp         = p_pkt[idx];
+                p_pkt[idx]  = p_pkt[tmp2];
+                p_pkt[tmp2]  = tmp;
+                /*
+                printf("tmp2: %02d, len: %d, idx: %d\n",
+                    tmp2, len, a2d_sbc_ds_cb.fr[a2d_sbc_ds_cb.index].idx);
+                    */
+            }
+            else
+            {
+                tmp2        = p_pkt[idx];
+                tmp         = (tmp2>>3)+(tmp2<<5);
+                p_pkt[idx]  = (UINT8)tmp;
+                /*
+                printf("tmp: x%02x, len: %d, idx: %d(cmp:%d)\n",
+                    (UINT8)tmp2, len, a2d_sbc_ds_cb.fr[a2d_sbc_ds_cb.index].idx,
+                    (a2d_sbc_ds_cb.base+(idx<<1)));
+                    */
+            }
+        }
+        /*
+        else
+        {
+            printf("!!!!\n");
+        }
+        */
+    }
+}
+
+/******************************************************************************
+**
+** Function         A2D_BldSbcInfo
+**
+** Description      This function is called by an application to build
+**                  the SBC Media Codec Capabilities byte sequence
+**                  beginning from the LOSC octet.
+**                  Input Parameters:
+**                      media_type:  Indicates Audio, or Multimedia.
+**
+**                      p_ie:  The SBC Codec Information Element information.
+**
+**                  Output Parameters:
+**                      p_result:  the resulting codec info byte sequence.
+**
+** Returns          A2D_SUCCESS if function execution succeeded.
+**                  Error status code, otherwise.
+******************************************************************************/
+tA2D_STATUS A2D_BldSbcInfo(UINT8 media_type, tA2D_SBC_CIE *p_ie, UINT8 *p_result)
+{
+    tA2D_STATUS status;
+
+    if( p_ie == NULL || p_result == NULL ||
+        (p_ie->samp_freq & ~A2D_SBC_IE_SAMP_FREQ_MSK) ||
+        (p_ie->ch_mode & ~A2D_SBC_IE_CH_MD_MSK) ||
+        (p_ie->block_len & ~A2D_SBC_IE_BLOCKS_MSK) ||
+        (p_ie->num_subbands & ~A2D_SBC_IE_SUBBAND_MSK) ||
+        (p_ie->alloc_mthd & ~A2D_SBC_IE_ALLOC_MD_MSK) ||
+        (p_ie->max_bitpool < p_ie->min_bitpool) ||
+        (p_ie->max_bitpool < A2D_SBC_IE_MIN_BITPOOL) ||
+        (p_ie->max_bitpool > A2D_SBC_IE_MAX_BITPOOL) ||
+        (p_ie->min_bitpool < A2D_SBC_IE_MIN_BITPOOL) ||
+        (p_ie->min_bitpool > A2D_SBC_IE_MAX_BITPOOL) )
+    {
+        /* if any unused bit is set */
+        status = A2D_INVALID_PARAMS;
+    }
+    else
+    {
+        status = A2D_SUCCESS;
+        *p_result++ = A2D_SBC_INFO_LEN;
+        *p_result++ = media_type;
+        *p_result++ = A2D_MEDIA_CT_SBC;
+
+        /* Media Codec Specific Information Element */
+        *p_result++ = p_ie->samp_freq | p_ie->ch_mode;
+
+        *p_result++ = p_ie->block_len | p_ie->num_subbands | p_ie->alloc_mthd;
+
+        *p_result++ = p_ie->min_bitpool;
+        *p_result   = p_ie->max_bitpool;
+    }
+    return status;
+}
+
+/******************************************************************************
+**
+** Function         A2D_ParsSbcInfo
+**
+** Description      This function is called by an application to parse
+**                  the SBC Media Codec Capabilities byte sequence
+**                  beginning from the LOSC octet.
+**                  Input Parameters:
+**                      p_info:  the byte sequence to parse.
+**
+**                      for_caps:  TRUE, if the byte sequence is for get capabilities response.
+**
+**                  Output Parameters:
+**                      p_ie:  The SBC Codec Information Element information.
+**
+** Returns          A2D_SUCCESS if function execution succeeded.
+**                  Error status code, otherwise.
+******************************************************************************/
+tA2D_STATUS A2D_ParsSbcInfo(tA2D_SBC_CIE *p_ie, UINT8 *p_info, BOOLEAN for_caps)
+{
+    tA2D_STATUS status;
+    UINT8   losc;
+
+    if( p_ie == NULL || p_info == NULL)
+        status = A2D_INVALID_PARAMS;
+    else
+    {
+        losc    = *p_info++;
+        p_info++;
+        /* If the function is called for the wrong Media Type or Media Codec Type */
+        if(losc != A2D_SBC_INFO_LEN || *p_info != A2D_MEDIA_CT_SBC)
+            status = A2D_WRONG_CODEC;
+        else
+        {
+            p_info++;
+            p_ie->samp_freq = *p_info & A2D_SBC_IE_SAMP_FREQ_MSK;
+            p_ie->ch_mode   = *p_info & A2D_SBC_IE_CH_MD_MSK;
+            p_info++;
+            p_ie->block_len     = *p_info & A2D_SBC_IE_BLOCKS_MSK;
+            p_ie->num_subbands  = *p_info & A2D_SBC_IE_SUBBAND_MSK;
+            p_ie->alloc_mthd    = *p_info & A2D_SBC_IE_ALLOC_MD_MSK;
+            p_info++;
+            p_ie->min_bitpool = *p_info++;
+            p_ie->max_bitpool = *p_info;
+            status = A2D_SUCCESS;
+            if(p_ie->min_bitpool < A2D_SBC_IE_MIN_BITPOOL || p_ie->min_bitpool > A2D_SBC_IE_MAX_BITPOOL )
+                status = A2D_BAD_MIN_BITPOOL;
+
+            if(p_ie->max_bitpool < A2D_SBC_IE_MIN_BITPOOL || p_ie->max_bitpool > A2D_SBC_IE_MAX_BITPOOL ||
+                p_ie->max_bitpool < p_ie->min_bitpool)
+                status = A2D_BAD_MAX_BITPOOL;
+
+            if(for_caps == FALSE)
+            {
+                if(A2D_BitsSet(p_ie->samp_freq) != A2D_SET_ONE_BIT)
+                    status = A2D_BAD_SAMP_FREQ;
+                if(A2D_BitsSet(p_ie->ch_mode) != A2D_SET_ONE_BIT)
+                    status = A2D_BAD_CH_MODE;
+                if(A2D_BitsSet(p_ie->block_len) != A2D_SET_ONE_BIT)
+                    status = A2D_BAD_BLOCK_LEN;
+                if(A2D_BitsSet(p_ie->num_subbands) != A2D_SET_ONE_BIT)
+                    status = A2D_BAD_SUBBANDS;
+                if(A2D_BitsSet(p_ie->alloc_mthd) != A2D_SET_ONE_BIT)
+                    status = A2D_BAD_ALLOC_MTHD;
+            }
+        }
+    }
+    return status;
+}
+
+/******************************************************************************
+**
+** Function         A2D_BldSbcMplHdr
+**
+** Description      This function is called by an application to parse
+**                  the SBC Media Payload header.
+**                  Input Parameters:
+**                      frag:  1, if fragmented. 0, otherwise.
+**
+**                      start:  1, if the starting packet of a fragmented frame.
+**
+**                      last:  1, if the last packet of a fragmented frame.
+**
+**                      num:  If frag is 1, this is the number of remaining fragments
+**                            (including this fragment) of this frame.
+**                            If frag is 0, this is the number of frames in this packet.
+**
+**                  Output Parameters:
+**                      p_dst:  the resulting media payload header byte sequence.
+**
+** Returns          void.
+******************************************************************************/
+void A2D_BldSbcMplHdr(UINT8 *p_dst, BOOLEAN frag, BOOLEAN start, BOOLEAN last, UINT8 num)
+{
+    if(p_dst)
+    {
+        *p_dst  = 0;
+        if(frag)
+            *p_dst  |= A2D_SBC_HDR_F_MSK;
+        if(start)
+            *p_dst  |= A2D_SBC_HDR_S_MSK;
+        if(last)
+            *p_dst  |= A2D_SBC_HDR_L_MSK;
+        *p_dst  |= (A2D_SBC_HDR_NUM_MSK & num);
+    }
+}
+
+/******************************************************************************
+**
+** Function         A2D_ParsSbcMplHdr
+**
+** Description      This function is called by an application to parse
+**                  the SBC Media Payload header.
+**                  Input Parameters:
+**                      p_src:  the byte sequence to parse..
+**
+**                  Output Parameters:
+**                      frag:  1, if fragmented. 0, otherwise.
+**
+**                      start:  1, if the starting packet of a fragmented frame.
+**
+**                      last:  1, if the last packet of a fragmented frame.
+**
+**                      num:  If frag is 1, this is the number of remaining fragments
+**                            (including this fragment) of this frame.
+**                            If frag is 0, this is the number of frames in this packet.
+**
+** Returns          void.
+******************************************************************************/
+void A2D_ParsSbcMplHdr(UINT8 *p_src, BOOLEAN *p_frag, BOOLEAN *p_start, BOOLEAN *p_last, UINT8 *p_num)
+{
+    if(p_src && p_frag && p_start && p_last && p_num)
+    {
+        *p_frag = (*p_src & A2D_SBC_HDR_F_MSK) ? TRUE: FALSE;
+        *p_start= (*p_src & A2D_SBC_HDR_S_MSK) ? TRUE: FALSE;
+        *p_last = (*p_src & A2D_SBC_HDR_L_MSK) ? TRUE: FALSE;
+        *p_num  = (*p_src & A2D_SBC_HDR_NUM_MSK);
+    }
+}
+
diff --git a/components/bt/bluedroid/stack/a2dp/include/a2d_int.h b/components/bt/bluedroid/stack/a2dp/include/a2d_int.h
new file mode 100755 (executable)
index 0000000..84e109b
--- /dev/null
@@ -0,0 +1,83 @@
+/******************************************************************************
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  2DP internal header file
+ *
+ ******************************************************************************/
+#ifndef A2D_INT_H
+#define A2D_INT_H
+
+#include "a2d_api.h"
+
+/*****************************************************************************
+**  Constants
+*****************************************************************************/
+#define A2D_VERSION             0x0102
+
+/* Number of attributes in A2D SDP record. */
+#define A2D_NUM_ATTR            6
+
+/* Number of protocol elements in protocol element list. */
+#define A2D_NUM_PROTO_ELEMS     2
+
+/*****************************************************************************
+**  Type definitions
+*****************************************************************************/
+
+/* Control block used by A2D_FindService(). */
+typedef struct
+{
+    tA2D_FIND_CBACK     *p_cback;       /* pointer to application callback */
+    tSDP_DISCOVERY_DB   *p_db;          /* pointer to discovery database */
+    UINT16              service_uuid;   /* service UUID of search */
+} tA2D_FIND_CB;
+
+typedef struct
+{
+    tA2D_FIND_CB    find;   /* find service control block */
+    UINT8           trace_level;
+    BOOLEAN         use_desc;
+    UINT16          avdt_sdp_ver;   /* AVDTP version */
+} tA2D_CB;
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/******************************************************************************
+** Main Control Block
+*******************************************************************************/
+#if A2D_DYNAMIC_MEMORY == FALSE
+extern tA2D_CB  a2d_cb;
+#else
+extern tA2D_CB *a2d_cb_ptr;
+#define a2d_cb (*a2d_cb_ptr)
+#endif
+
+/* Used only for conformance testing */
+extern void a2d_set_avdt_sdp_ver (UINT16 avdt_sdp_ver);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* A2D_INT_H */
diff --git a/components/bt/bluedroid/stack/avct/avct_api.c b/components/bt/bluedroid/stack/avct/avct_api.c
new file mode 100755 (executable)
index 0000000..bf3dd18
--- /dev/null
@@ -0,0 +1,473 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2003-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 control transport protocol.
+ *
+ ******************************************************************************/
+
+#include <string.h>
+#include "bt_types.h"
+#include "bt_target.h"
+#include "bt_utils.h"
+#include "gki.h"
+#include "l2c_api.h"
+#include "l2cdefs.h"
+#include "btm_api.h"
+#include "avct_api.h"
+#include "avct_int.h"
+
+/* Control block for AVCT */
+#if AVCT_DYNAMIC_MEMORY == FALSE
+tAVCT_CB avct_cb;
+#endif
+
+/*******************************************************************************
+**
+** Function         AVCT_Register
+**
+** Description      This is the system level registration function for the
+**                  AVCTP protocol.  This function initializes AVCTP and
+**                  prepares the protocol stack for its use.  This function
+**                  must be called once by the system or platform using AVCTP
+**                  before the other functions of the API an be used.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void AVCT_Register(UINT16 mtu, UINT16 mtu_br, UINT8 sec_mask)
+{
+    UNUSED(mtu_br);
+
+    AVCT_TRACE_API("AVCT_Register");
+
+    /* register PSM with L2CAP */
+    L2CA_Register(AVCT_PSM, (tL2CAP_APPL_INFO *) &avct_l2c_appl);
+
+    /* set security level */
+    BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_AVCTP, sec_mask, AVCT_PSM, 0, 0);
+    BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_AVCTP, sec_mask, AVCT_PSM, 0, 0);
+
+    /* initialize AVCTP data structures */
+    memset(&avct_cb, 0, sizeof(tAVCT_CB));
+
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+    /* Include the browsing channel which uses eFCR */
+    L2CA_Register(AVCT_BR_PSM, (tL2CAP_APPL_INFO *) &avct_l2c_br_appl);
+
+    BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_AVCTP_BROWSE, sec_mask, AVCT_BR_PSM, 0, 0);
+    BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_AVCTP_BROWSE, sec_mask, AVCT_BR_PSM, 0, 0);
+
+    if (mtu_br < AVCT_MIN_BROWSE_MTU)
+        mtu_br = AVCT_MIN_BROWSE_MTU;
+    avct_cb.mtu_br = mtu_br;
+#endif
+
+#if defined(AVCT_INITIAL_TRACE_LEVEL)
+    avct_cb.trace_level = AVCT_INITIAL_TRACE_LEVEL;
+#else
+    avct_cb.trace_level = BT_TRACE_LEVEL_NONE;
+#endif
+
+    if (mtu < AVCT_MIN_CONTROL_MTU)
+        mtu = AVCT_MIN_CONTROL_MTU;
+    /* store mtu */
+    avct_cb.mtu = mtu;
+}
+
+/*******************************************************************************
+**
+** Function         AVCT_Deregister
+**
+** Description      This function is called to deregister use AVCTP protocol.
+**                  It is called when AVCTP is no longer being used by any
+**                  application in the system.  Before this function can be
+**                  called, all connections must be removed with
+**                  AVCT_RemoveConn().
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void AVCT_Deregister(void)
+{
+    AVCT_TRACE_API("AVCT_Deregister");
+
+    /* deregister PSM with L2CAP */
+    L2CA_Deregister(AVCT_PSM);
+}
+
+/*******************************************************************************
+**
+** Function         AVCT_CreateConn
+**
+** Description      Create an AVCTP connection.  There are two types of
+**                  connections, initiator and acceptor, as determined by
+**                  the p_cc->role parameter.  When this function is called to
+**                  create an initiator connection, an AVCTP connection to
+**                  the peer device is initiated if one does not already exist.
+**                  If an acceptor connection is created, the connection waits
+**                  passively for an incoming AVCTP connection from a peer device.
+**
+**
+** Returns          AVCT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVCT_CreateConn(UINT8 *p_handle, tAVCT_CC *p_cc, BD_ADDR peer_addr)
+{
+    UINT16      result = AVCT_SUCCESS;
+    tAVCT_CCB   *p_ccb;
+    tAVCT_LCB   *p_lcb;
+
+    AVCT_TRACE_API("AVCT_CreateConn: %d, control:%d", p_cc->role, p_cc->control);
+
+    /* Allocate ccb; if no ccbs, return failure */
+    if ((p_ccb = avct_ccb_alloc(p_cc)) == NULL)
+    {
+        result = AVCT_NO_RESOURCES;
+    }
+    else
+    {
+        /* get handle */
+        *p_handle = avct_ccb_to_idx(p_ccb);
+
+        /* if initiator connection */
+        if (p_cc->role == AVCT_INT)
+        {
+            /* find link; if none allocate a new one */
+            if ((p_lcb = avct_lcb_by_bd(peer_addr)) == NULL)
+            {
+                if ((p_lcb = avct_lcb_alloc(peer_addr)) == NULL)
+                {
+                    /* no link resources; free ccb as well */
+                    avct_ccb_dealloc(p_ccb, AVCT_NO_EVT, 0, NULL);
+                    result = AVCT_NO_RESOURCES;
+                }
+            }
+            /* check if PID already in use */
+            else if (avct_lcb_has_pid(p_lcb, p_cc->pid))
+            {
+                avct_ccb_dealloc(p_ccb, AVCT_NO_EVT, 0, NULL);
+                result = AVCT_PID_IN_USE;
+            }
+
+            if (result == AVCT_SUCCESS)
+            {
+                /* bind lcb to ccb */
+                p_ccb->p_lcb = p_lcb;
+                AVCT_TRACE_DEBUG("ch_state: %d", p_lcb->ch_state);
+                avct_lcb_event(p_lcb, AVCT_LCB_UL_BIND_EVT, (tAVCT_LCB_EVT *) &p_ccb);
+            }
+        }
+    }
+    return result;
+}
+
+/*******************************************************************************
+**
+** Function         AVCT_RemoveConn
+**
+** Description      Remove an AVCTP connection.  This function is called when
+**                  the application is no longer using a connection.  If this
+**                  is the last connection to a peer the L2CAP channel for AVCTP
+**                  will be closed.
+**
+**
+** Returns          AVCT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVCT_RemoveConn(UINT8 handle)
+{
+    UINT16              result = AVCT_SUCCESS;
+    tAVCT_CCB           *p_ccb;
+
+    AVCT_TRACE_API("AVCT_RemoveConn");
+
+    /* map handle to ccb */
+    if ((p_ccb = avct_ccb_by_idx(handle)) == NULL)
+    {
+        result = AVCT_BAD_HANDLE;
+    }
+    /* if connection not bound to lcb, dealloc */
+    else if (p_ccb->p_lcb == NULL)
+    {
+        avct_ccb_dealloc(p_ccb, AVCT_NO_EVT, 0, NULL);
+    }
+    /* send unbind event to lcb */
+    else
+    {
+        avct_lcb_event(p_ccb->p_lcb, AVCT_LCB_UL_UNBIND_EVT, (tAVCT_LCB_EVT *) &p_ccb);
+    }
+    return result;
+}
+
+/*******************************************************************************
+**
+** Function         AVCT_CreateBrowse
+**
+** Description      Create an AVCTP Browse channel.  There are two types of
+**                  connections, initiator and acceptor, as determined by
+**                  the role parameter.  When this function is called to
+**                  create an initiator connection, the Browse channel to
+**                  the peer device is initiated if one does not already exist.
+**                  If an acceptor connection is created, the connection waits
+**                  passively for an incoming AVCTP connection from a peer device.
+**
+**
+** Returns          AVCT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVCT_CreateBrowse (UINT8 handle, UINT8 role)
+{
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+    UINT16      result = AVCT_SUCCESS;
+    tAVCT_CCB   *p_ccb;
+    tAVCT_BCB   *p_bcb;
+    int         index;
+
+    AVCT_TRACE_API("AVCT_CreateBrowse: %d", role);
+
+    /* map handle to ccb */
+    if ((p_ccb = avct_ccb_by_idx(handle)) == NULL)
+    {
+        return AVCT_BAD_HANDLE;
+    }
+    else
+    {
+        /* mark this CCB as supporting browsing channel */
+        if ((p_ccb->allocated & AVCT_ALOC_BCB) == 0)
+        {
+            p_ccb->allocated |= AVCT_ALOC_BCB;
+        }
+    }
+
+    /* if initiator connection */
+    if (role == AVCT_INT)
+    {
+        /* the link control block must exist before this function is called as INT. */
+        if ((p_ccb->p_lcb == NULL) || (p_ccb->p_lcb->allocated == 0))
+        {
+            result = AVCT_NOT_OPEN;
+        }
+        else
+        {
+            /* find link; if none allocate a new one */
+            index = p_ccb->p_lcb->allocated;
+            if (index > AVCT_NUM_LINKS)
+            {
+                result = AVCT_BAD_HANDLE;
+            }
+            else
+            {
+                p_bcb = &avct_cb.bcb[index - 1];
+                p_bcb->allocated = index;
+            }
+        }
+
+        if (result == AVCT_SUCCESS)
+        {
+            /* bind bcb to ccb */
+            p_ccb->p_bcb = p_bcb;
+            AVCT_TRACE_DEBUG("ch_state: %d", p_bcb->ch_state);
+            avct_bcb_event(p_bcb, AVCT_LCB_UL_BIND_EVT, (tAVCT_LCB_EVT *) &p_ccb);
+        }
+    }
+
+    return result;
+#else
+    UNUSED(handle);
+    UNUSED(role);
+    return AVCT_NO_RESOURCES;
+#endif
+}
+
+/*******************************************************************************
+**
+** Function         AVCT_RemoveBrowse
+**
+** Description      Remove an AVCTP Browse channel.  This function is called when
+**                  the application is no longer using a connection.  If this
+**                  is the last connection to a peer the L2CAP channel for AVCTP
+**                  will be closed.
+**
+**
+** Returns          AVCT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVCT_RemoveBrowse (UINT8 handle)
+{
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+    UINT16              result = AVCT_SUCCESS;
+    tAVCT_CCB           *p_ccb;
+
+    AVCT_TRACE_API("AVCT_RemoveBrowse");
+
+    /* map handle to ccb */
+    if ((p_ccb = avct_ccb_by_idx(handle)) == NULL)
+    {
+        result = AVCT_BAD_HANDLE;
+    }
+    else if (p_ccb->p_bcb != NULL)
+    /* send unbind event to bcb */
+    {
+        avct_bcb_event(p_ccb->p_bcb, AVCT_LCB_UL_UNBIND_EVT, (tAVCT_LCB_EVT *) &p_ccb);
+    }
+    return result;
+#else
+    UNUSED(handle);
+    return AVCT_NO_RESOURCES;
+#endif
+}
+
+/*******************************************************************************
+**
+** Function         AVCT_GetBrowseMtu
+**
+** Description      Get the peer_mtu for the AVCTP Browse channel of the given
+**                  connection.
+**
+** Returns          the peer browsing channel MTU.
+**
+*******************************************************************************/
+UINT16 AVCT_GetBrowseMtu (UINT8 handle)
+{
+    UINT16  peer_mtu = AVCT_MIN_BROWSE_MTU;
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+    tAVCT_CCB           *p_ccb;
+
+    if ((p_ccb = avct_ccb_by_idx(handle)) != NULL && p_ccb->p_bcb != NULL)
+    {
+        peer_mtu = p_ccb->p_bcb->peer_mtu;
+    }
+#else
+    UNUSED(handle);
+#endif
+    return peer_mtu;
+}
+
+/*******************************************************************************
+**
+** Function         AVCT_GetPeerMtu
+**
+** Description      Get the peer_mtu for the AVCTP channel of the given
+**                  connection.
+**
+** Returns          the peer MTU size.
+**
+*******************************************************************************/
+UINT16 AVCT_GetPeerMtu (UINT8 handle)
+{
+    UINT16      peer_mtu = L2CAP_DEFAULT_MTU;
+    tAVCT_CCB   *p_ccb;
+
+    /* map handle to ccb */
+    if ((p_ccb = avct_ccb_by_idx(handle)) != NULL)
+    {
+        if (p_ccb->p_lcb)
+        {
+            peer_mtu = p_ccb->p_lcb->peer_mtu;
+        }
+    }
+
+    return peer_mtu;
+}
+
+/*******************************************************************************
+**
+** Function         AVCT_MsgReq
+**
+** Description      Send an AVCTP message to a peer device.  In calling
+**                  AVCT_MsgReq(), the application should keep track of the
+**                  congestion state of AVCTP as communicated with events
+**                  AVCT_CONG_IND_EVT and AVCT_UNCONG_IND_EVT.   If the
+**                  application calls AVCT_MsgReq() when AVCTP is congested
+**                  the message may be discarded.  The application may make its
+**                  first call to AVCT_MsgReq() after it receives an
+**                  AVCT_CONNECT_CFM_EVT or AVCT_CONNECT_IND_EVT on control channel or
+**                  AVCT_BROWSE_CONN_CFM_EVT or AVCT_BROWSE_CONN_IND_EVT on browsing channel.
+**
+**                  p_msg->layer_specific must be set to
+**                  AVCT_DATA_CTRL for control channel traffic;
+**                  AVCT_DATA_BROWSE for for browse channel traffic.
+**
+** Returns          AVCT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVCT_MsgReq(UINT8 handle, UINT8 label, UINT8 cr, BT_HDR *p_msg)
+{
+    UINT16          result = AVCT_SUCCESS;
+    tAVCT_CCB       *p_ccb;
+    tAVCT_UL_MSG    ul_msg;
+
+    AVCT_TRACE_API("AVCT_MsgReq");
+
+    /* verify p_msg parameter */
+    if (p_msg == NULL)
+    {
+        return AVCT_NO_RESOURCES;
+    }
+    AVCT_TRACE_API("len: %d", p_msg->len);
+
+    /* map handle to ccb */
+    if ((p_ccb = avct_ccb_by_idx(handle)) == NULL)
+    {
+        result = AVCT_BAD_HANDLE;
+        GKI_freebuf(p_msg);
+    }
+    /* verify channel is bound to link */
+    else if (p_ccb->p_lcb == NULL)
+    {
+        result = AVCT_NOT_OPEN;
+        GKI_freebuf(p_msg);
+    }
+
+    if (result == AVCT_SUCCESS)
+    {
+        ul_msg.p_buf = p_msg;
+        ul_msg.p_ccb = p_ccb;
+        ul_msg.label = label;
+        ul_msg.cr = cr;
+
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+        /* send msg event to bcb */
+        if (p_msg->layer_specific == AVCT_DATA_BROWSE)
+        {
+            if (p_ccb->p_bcb == NULL && (p_ccb->allocated & AVCT_ALOC_BCB) == 0)
+            {
+                /* BCB channel is not open and not allocated */
+                result = AVCT_BAD_HANDLE;
+                GKI_freebuf(p_msg);
+            }
+            else
+            {
+                p_ccb->p_bcb = avct_bcb_by_lcb(p_ccb->p_lcb);
+                avct_bcb_event(p_ccb->p_bcb, AVCT_LCB_UL_MSG_EVT, (tAVCT_LCB_EVT *) &ul_msg);
+            }
+        }
+        /* send msg event to lcb */
+        else
+#endif
+        {
+            avct_lcb_event(p_ccb->p_lcb, AVCT_LCB_UL_MSG_EVT, (tAVCT_LCB_EVT *) &ul_msg);
+        }
+    }
+    return result;
+}
+
diff --git a/components/bt/bluedroid/stack/avct/avct_ccb.c b/components/bt/bluedroid/stack/avct/avct_ccb.c
new file mode 100755 (executable)
index 0000000..e0f87de
--- /dev/null
@@ -0,0 +1,150 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2003-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 which operate on the AVCTP connection
+ *  control block.
+ *
+ ******************************************************************************/
+
+#include <string.h>
+#include "bt_types.h"
+#include "bt_target.h"
+#include "avct_api.h"
+#include "avct_int.h"
+
+/*******************************************************************************
+**
+** Function         avct_ccb_alloc
+**
+** Description      Allocate a connection control block; copy parameters to ccb.
+**
+**
+** Returns          pointer to the ccb, or NULL if none could be allocated.
+**
+*******************************************************************************/
+tAVCT_CCB *avct_ccb_alloc(tAVCT_CC *p_cc)
+{
+    tAVCT_CCB   *p_ccb = &avct_cb.ccb[0];
+    int         i;
+
+    for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++)
+    {
+        if (!p_ccb->allocated)
+        {
+            p_ccb->allocated = AVCT_ALOC_LCB;
+            memcpy(&p_ccb->cc, p_cc, sizeof(tAVCT_CC));
+            AVCT_TRACE_DEBUG("avct_ccb_alloc %d", i);
+            break;
+        }
+    }
+
+    if (i == AVCT_NUM_CONN)
+    {
+        /* out of ccbs */
+        p_ccb = NULL;
+        AVCT_TRACE_WARNING("Out of ccbs");
+    }
+    return p_ccb;
+}
+
+/*******************************************************************************
+**
+** Function         avct_ccb_dealloc
+**
+** Description      Deallocate a connection control block and call application
+**                  callback.
+**
+**
+** Returns          void.
+**
+*******************************************************************************/
+void avct_ccb_dealloc(tAVCT_CCB *p_ccb, UINT8 event, UINT16 result, BD_ADDR bd_addr)
+{
+    tAVCT_CTRL_CBACK    *p_cback = p_ccb->cc.p_ctrl_cback;
+
+    AVCT_TRACE_DEBUG("avct_ccb_dealloc %d", avct_ccb_to_idx(p_ccb));
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+    if(p_ccb->p_bcb == NULL)
+        memset(p_ccb, 0, sizeof(tAVCT_CCB));
+    else
+    {
+        /* control channel is down, but the browsing channel is still connected 0 disconnect it now */
+        avct_bcb_event(p_ccb->p_bcb, AVCT_LCB_UL_UNBIND_EVT, (tAVCT_LCB_EVT *) &p_ccb);
+        p_ccb->p_lcb = NULL;
+    }
+#else
+    memset(p_ccb, 0, sizeof(tAVCT_CCB));
+#endif
+
+    if (event != AVCT_NO_EVT)
+    {
+        (*p_cback)(avct_ccb_to_idx(p_ccb), event, result, bd_addr);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         avct_ccb_to_idx
+**
+** Description      Given a pointer to an ccb, return its index.
+**
+**
+** Returns          Index of ccb.
+**
+*******************************************************************************/
+UINT8 avct_ccb_to_idx(tAVCT_CCB *p_ccb)
+{
+    /* use array arithmetic to determine index */
+    return (UINT8) (p_ccb - avct_cb.ccb);
+}
+
+/*******************************************************************************
+**
+** Function         avct_ccb_by_idx
+**
+** Description      Return ccb pointer based on ccb index (or handle).
+**
+**
+** Returns          pointer to the ccb, or NULL if none found.
+**
+*******************************************************************************/
+tAVCT_CCB *avct_ccb_by_idx(UINT8 idx)
+{
+    tAVCT_CCB   *p_ccb;
+
+    /* verify index */
+    if (idx < AVCT_NUM_CONN)
+    {
+        p_ccb = &avct_cb.ccb[idx];
+
+        /* verify ccb is allocated */
+        if (!p_ccb->allocated)
+        {
+            p_ccb = NULL;
+            AVCT_TRACE_WARNING("ccb %d not allocated", idx);
+        }
+    }
+    else
+    {
+        p_ccb = NULL;
+        AVCT_TRACE_WARNING("No ccb for idx %d", idx);
+    }
+    return p_ccb;
+}
diff --git a/components/bt/bluedroid/stack/avct/avct_l2c.c b/components/bt/bluedroid/stack/avct/avct_l2c.c
new file mode 100755 (executable)
index 0000000..815fa4b
--- /dev/null
@@ -0,0 +1,436 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2003-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 AVCTP module interfaces to L2CAP
+ *
+ ******************************************************************************/
+
+#include <string.h>
+#include "bt_types.h"
+#include "bt_target.h"
+#include "bt_utils.h"
+#include "avct_api.h"
+#include "avct_int.h"
+#include "l2c_api.h"
+#include "l2cdefs.h"
+
+/* Configuration flags. */
+#define AVCT_L2C_CFG_IND_DONE   (1<<0)
+#define AVCT_L2C_CFG_CFM_DONE   (1<<1)
+
+/* callback function declarations */
+void avct_l2c_connect_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 id);
+void avct_l2c_connect_cfm_cback(UINT16 lcid, UINT16 result);
+void avct_l2c_config_cfm_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg);
+void avct_l2c_config_ind_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg);
+void avct_l2c_disconnect_ind_cback(UINT16 lcid, BOOLEAN ack_needed);
+void avct_l2c_disconnect_cfm_cback(UINT16 lcid, UINT16 result);
+void avct_l2c_congestion_ind_cback(UINT16 lcid, BOOLEAN is_congested);
+void avct_l2c_data_ind_cback(UINT16 lcid, BT_HDR *p_buf);
+
+/* L2CAP callback function structure */
+const tL2CAP_APPL_INFO avct_l2c_appl = {
+    avct_l2c_connect_ind_cback,
+    avct_l2c_connect_cfm_cback,
+    NULL,
+    avct_l2c_config_ind_cback,
+    avct_l2c_config_cfm_cback,
+    avct_l2c_disconnect_ind_cback,
+    avct_l2c_disconnect_cfm_cback,
+    NULL,
+    avct_l2c_data_ind_cback,
+    avct_l2c_congestion_ind_cback,
+    NULL                                /* tL2CA_TX_COMPLETE_CB */
+};
+
+/*******************************************************************************
+**
+** Function         avct_l2c_is_passive
+**
+** Description      check is the CCB associated with the given LCB was created
+**                  as passive
+**
+** Returns          TRUE, if the given LCB is created as AVCT_PASSIVE
+**
+*******************************************************************************/
+static BOOLEAN avct_l2c_is_passive (tAVCT_LCB *p_lcb)
+{
+    BOOLEAN     is_passive = FALSE;
+    tAVCT_CCB   *p_ccb = &avct_cb.ccb[0];
+    int         i;
+
+    for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++)
+    {
+        if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb))
+        {
+            AVCT_TRACE_DEBUG("avct_l2c_is_ct control:x%x", p_ccb->cc.control);
+            if (p_ccb->cc.control & AVCT_PASSIVE)
+            {
+                is_passive = TRUE;
+                break;
+            }
+        }
+    }
+    return is_passive;
+}
+
+/*******************************************************************************
+**
+** Function         avct_l2c_connect_ind_cback
+**
+** Description      This is the L2CAP connect indication callback function.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void avct_l2c_connect_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 id)
+{
+    tAVCT_LCB       *p_lcb;
+    UINT16          result = L2CAP_CONN_OK;
+    tL2CAP_CFG_INFO cfg;
+    UNUSED(psm);
+
+    /* do we already have a channel for this peer? */
+    if ((p_lcb = avct_lcb_by_bd(bd_addr)) == NULL)
+    {
+        /* no, allocate lcb */
+        if ((p_lcb = avct_lcb_alloc(bd_addr)) == NULL)
+        {
+            /* no ccb available, reject L2CAP connection */
+            result = L2CAP_CONN_NO_RESOURCES;
+        }
+    }
+    /* else we already have a channel for this peer */
+    else
+    {
+        if (!avct_l2c_is_passive (p_lcb) || (p_lcb->ch_state == AVCT_CH_OPEN))
+        {
+            /* this LCB included CT role - reject */
+            result = L2CAP_CONN_NO_RESOURCES;
+        }
+        else
+        {
+            /* TG role only - accept the connection from CT. move the channel ID to the conflict list */
+            p_lcb->conflict_lcid = p_lcb->ch_lcid;
+            AVCT_TRACE_DEBUG("avct_l2c_connect_ind_cback conflict_lcid:0x%x", p_lcb->conflict_lcid);
+        }
+    }
+
+    if(p_lcb)
+    {
+        AVCT_TRACE_DEBUG("avct_l2c_connect_ind_cback: 0x%x, res: %d, ch_state: %d",
+            lcid, result, p_lcb->ch_state);
+    }
+    /* Send L2CAP connect rsp */
+    L2CA_ConnectRsp(bd_addr, id, lcid, result, 0);
+
+    /* if result ok, proceed with connection */
+    if (result == L2CAP_CONN_OK)
+    {
+        /* store LCID */
+        p_lcb->ch_lcid = lcid;
+
+        /* transition to configuration state */
+        p_lcb->ch_state = AVCT_CH_CFG;
+
+        /* Send L2CAP config req */
+        memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
+        cfg.mtu_present = TRUE;
+        cfg.mtu = avct_cb.mtu;
+        L2CA_ConfigReq(lcid, &cfg);
+        AVCT_TRACE_DEBUG("avct_l2c snd Cfg Req");
+    }
+
+#if (BT_USE_TRACES == TRUE)
+    if(p_lcb)
+        AVCT_TRACE_DEBUG("ch_state cni: %d ", p_lcb->ch_state);
+#endif
+}
+
+/*******************************************************************************
+**
+** Function         avct_l2c_connect_cfm_cback
+**
+** Description      This is the L2CAP connect confirm callback function.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void avct_l2c_connect_cfm_cback(UINT16 lcid, UINT16 result)
+{
+    tAVCT_LCB       *p_lcb;
+    tL2CAP_CFG_INFO cfg;
+
+    /* look up lcb for this channel */
+    if ((p_lcb = avct_lcb_by_lcid(lcid)) != NULL)
+    {
+        AVCT_TRACE_DEBUG("avct_l2c_connect_cfm_cback lcid:0x%x result: %d ch_state: %d, conflict_lcid:0x%x",
+            lcid, result, p_lcb->ch_state, p_lcb->conflict_lcid);
+        /* if in correct state */
+        if (p_lcb->ch_state == AVCT_CH_CONN)
+        {
+            /* if result successful */
+            if (result == L2CAP_CONN_OK)
+            {
+                /* set channel state */
+                p_lcb->ch_state = AVCT_CH_CFG;
+
+                /* Send L2CAP config req */
+                memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
+                cfg.mtu_present = TRUE;
+                cfg.mtu = avct_cb.mtu;
+                L2CA_ConfigReq(lcid, &cfg);
+                AVCT_TRACE_DEBUG("avct_l2c snd Cfg Req");
+            }
+            /* else failure */
+            else
+            {
+                AVCT_TRACE_DEBUG("avct_l2c_connect_cfm_cback conflict_lcid:0x%x", p_lcb->conflict_lcid);
+                if (p_lcb->conflict_lcid == lcid)
+                    p_lcb->conflict_lcid = 0;
+                else
+                    avct_lcb_event(p_lcb, AVCT_LCB_LL_CLOSE_EVT, (tAVCT_LCB_EVT *) &result);
+            }
+        }
+        else if (p_lcb->conflict_lcid == lcid)
+        {
+            /* we must be in AVCT_CH_CFG state for the ch_lcid channel */
+            AVCT_TRACE_DEBUG("avct_l2c_connect_cfm_cback ch_state: %d, conflict_lcid:0x%x", p_lcb->ch_state, p_lcb->conflict_lcid);
+            if (result == L2CAP_CONN_OK)
+            {
+                /* just in case the peer also accepts our connection - Send L2CAP disconnect req */
+                L2CA_DisconnectReq(lcid);
+            }
+            p_lcb->conflict_lcid = 0;
+        }
+        AVCT_TRACE_DEBUG("ch_state cnc: %d ", p_lcb->ch_state);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         avct_l2c_config_cfm_cback
+**
+** Description      This is the L2CAP config confirm callback function.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void avct_l2c_config_cfm_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg)
+{
+    tAVCT_LCB       *p_lcb;
+
+    /* look up lcb for this channel */
+    if ((p_lcb = avct_lcb_by_lcid(lcid)) != NULL)
+    {
+        AVCT_TRACE_DEBUG("avct_l2c_config_cfm_cback: 0x%x, ch_state: %d, res: %d",
+            lcid, p_lcb->ch_state, p_cfg->result);
+        /* if in correct state */
+        if (p_lcb->ch_state == AVCT_CH_CFG)
+        {
+            /* if result successful */
+            if (p_cfg->result == L2CAP_CFG_OK)
+            {
+                /* update flags */
+                p_lcb->ch_flags |= AVCT_L2C_CFG_CFM_DONE;
+
+                /* if configuration complete */
+                if (p_lcb->ch_flags & AVCT_L2C_CFG_IND_DONE)
+                {
+                    p_lcb->ch_state = AVCT_CH_OPEN;
+                    avct_lcb_event(p_lcb, AVCT_LCB_LL_OPEN_EVT, NULL);
+                }
+            }
+            /* else failure */
+            else
+            {
+                AVCT_TRACE_DEBUG("ERROR avct_l2c_config_cfm_cback L2CA_DisconnectReq %d ", p_lcb->ch_state);
+                /* store result value */
+                p_lcb->ch_result = p_cfg->result;
+
+                /* Send L2CAP disconnect req */
+                L2CA_DisconnectReq(lcid);
+            }
+        }
+        AVCT_TRACE_DEBUG("ch_state cfc: %d ", p_lcb->ch_state);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         avct_l2c_config_ind_cback
+**
+** Description      This is the L2CAP config indication callback function.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void avct_l2c_config_ind_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg)
+{
+    tAVCT_LCB       *p_lcb;
+
+    /* look up lcb for this channel */
+    if ((p_lcb = avct_lcb_by_lcid(lcid)) != NULL)
+    {
+        AVCT_TRACE_DEBUG("avct_l2c_config_ind_cback: 0x%x, ch_state: %d", lcid, p_lcb->ch_state);
+        /* store the mtu in tbl */
+        if (p_cfg->mtu_present)
+        {
+            p_lcb->peer_mtu = p_cfg->mtu;
+        }
+        else
+        {
+            p_lcb->peer_mtu = L2CAP_DEFAULT_MTU;
+        }
+
+        /* 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_lcb->ch_flags & AVCT_L2C_CFG_IND_DONE) == 0)
+        {
+            /* update flags */
+            p_lcb->ch_flags |= AVCT_L2C_CFG_IND_DONE;
+
+            /* if configuration complete */
+            if (p_lcb->ch_flags & AVCT_L2C_CFG_CFM_DONE)
+            {
+                p_lcb->ch_state = AVCT_CH_OPEN;
+                avct_lcb_event(p_lcb, AVCT_LCB_LL_OPEN_EVT, NULL);
+            }
+        }
+        AVCT_TRACE_DEBUG("ch_state cfi: %d ", p_lcb->ch_state);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         avct_l2c_disconnect_ind_cback
+**
+** Description      This is the L2CAP disconnect indication callback function.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void avct_l2c_disconnect_ind_cback(UINT16 lcid, BOOLEAN ack_needed)
+{
+    tAVCT_LCB       *p_lcb;
+    UINT16          result = AVCT_RESULT_FAIL;
+
+    /* look up lcb for this channel */
+    if ((p_lcb = avct_lcb_by_lcid(lcid)) != NULL)
+    {
+        AVCT_TRACE_DEBUG("avct_l2c_disconnect_ind_cback: 0x%x, ch_state: %d", lcid, p_lcb->ch_state);
+        if (ack_needed)
+        {
+            /* send L2CAP disconnect response */
+            L2CA_DisconnectRsp(lcid);
+        }
+
+        avct_lcb_event(p_lcb, AVCT_LCB_LL_CLOSE_EVT, (tAVCT_LCB_EVT *) &result);
+        AVCT_TRACE_DEBUG("ch_state di: %d ", p_lcb->ch_state);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         avct_l2c_disconnect_cfm_cback
+**
+** Description      This is the L2CAP disconnect confirm callback function.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void avct_l2c_disconnect_cfm_cback(UINT16 lcid, UINT16 result)
+{
+    tAVCT_LCB       *p_lcb;
+    UINT16          res;
+
+    /* look up lcb for this channel */
+    if ((p_lcb = avct_lcb_by_lcid(lcid)) != NULL)
+    {
+        AVCT_TRACE_DEBUG("avct_l2c_disconnect_cfm_cback: 0x%x, ch_state: %d, res: %d",
+            lcid, p_lcb->ch_state, result);
+        /* result value may be previously stored */
+        res = (p_lcb->ch_result != 0) ? p_lcb->ch_result : result;
+        p_lcb->ch_result = 0;
+
+        avct_lcb_event(p_lcb, AVCT_LCB_LL_CLOSE_EVT, (tAVCT_LCB_EVT *) &res);
+        AVCT_TRACE_DEBUG("ch_state dc: %d ", p_lcb->ch_state);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         avct_l2c_congestion_ind_cback
+**
+** Description      This is the L2CAP congestion indication callback function.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void avct_l2c_congestion_ind_cback(UINT16 lcid, BOOLEAN is_congested)
+{
+    tAVCT_LCB       *p_lcb;
+
+    AVCT_TRACE_DEBUG("avct_l2c_congestion_ind_cback: 0x%x", lcid);
+    /* look up lcb for this channel */
+    if ((p_lcb = avct_lcb_by_lcid(lcid)) != NULL)
+    {
+        avct_lcb_event(p_lcb, AVCT_LCB_LL_CONG_EVT, (tAVCT_LCB_EVT *) &is_congested);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         avct_l2c_data_ind_cback
+**
+** Description      This is the L2CAP data indication callback function.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void avct_l2c_data_ind_cback(UINT16 lcid, BT_HDR *p_buf)
+{
+    tAVCT_LCB       *p_lcb;
+
+    AVCT_TRACE_DEBUG("avct_l2c_data_ind_cback: 0x%x", lcid);
+    /* look up lcb for this channel */
+    if ((p_lcb = avct_lcb_by_lcid(lcid)) != NULL)
+    {
+        avct_lcb_event(p_lcb, AVCT_LCB_LL_MSG_EVT, (tAVCT_LCB_EVT *) &p_buf);
+    }
+    else /* prevent buffer leak */
+    {
+        AVCT_TRACE_WARNING("ERROR -> avct_l2c_data_ind_cback drop buffer");
+        GKI_freebuf(p_buf);
+    }
+}
+
diff --git a/components/bt/bluedroid/stack/avct/avct_lcb.c b/components/bt/bluedroid/stack/avct/avct_lcb.c
new file mode 100755 (executable)
index 0000000..eabb8aa
--- /dev/null
@@ -0,0 +1,473 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2003-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 link control state machine and functions which
+ *  operate on the link control block.
+ *
+ ******************************************************************************/
+
+#include <string.h>
+#include "bt_types.h"
+#include "bt_target.h"
+#include "bt_utils.h"
+#include "avct_api.h"
+#include "avct_int.h"
+#include "gki.h"
+
+/*****************************************************************************
+** state machine constants and types
+*****************************************************************************/
+
+#if BT_TRACE_VERBOSE == TRUE
+
+/* verbose state strings for trace */
+const char * const avct_lcb_st_str[] = {
+    "LCB_IDLE_ST",
+    "LCB_OPENING_ST",
+    "LCB_OPEN_ST",
+    "LCB_CLOSING_ST"
+};
+
+/* verbose event strings for trace */
+const char * const avct_lcb_evt_str[] = {
+    "UL_BIND_EVT",
+    "UL_UNBIND_EVT",
+    "UL_MSG_EVT",
+    "INT_CLOSE_EVT",
+    "LL_OPEN_EVT",
+    "LL_CLOSE_EVT",
+    "LL_MSG_EVT",
+    "LL_CONG_EVT"
+};
+
+#endif
+
+/* lcb state machine states */
+enum {
+    AVCT_LCB_IDLE_ST,
+    AVCT_LCB_OPENING_ST,
+    AVCT_LCB_OPEN_ST,
+    AVCT_LCB_CLOSING_ST
+};
+
+/* state machine action enumeration list */
+enum {
+    AVCT_LCB_CHNL_OPEN,
+    AVCT_LCB_CHNL_DISC,
+    AVCT_LCB_SEND_MSG,
+    AVCT_LCB_OPEN_IND,
+    AVCT_LCB_OPEN_FAIL,
+    AVCT_LCB_CLOSE_IND,
+    AVCT_LCB_CLOSE_CFM,
+    AVCT_LCB_MSG_IND,
+    AVCT_LCB_CONG_IND,
+    AVCT_LCB_BIND_CONN,
+    AVCT_LCB_BIND_FAIL,
+    AVCT_LCB_UNBIND_DISC,
+    AVCT_LCB_CHK_DISC,
+    AVCT_LCB_DISCARD_MSG,
+    AVCT_LCB_DEALLOC,
+    AVCT_LCB_FREE_MSG_IND,
+    AVCT_LCB_NUM_ACTIONS
+};
+
+#define AVCT_LCB_IGNORE     AVCT_LCB_NUM_ACTIONS
+
+/* type for action functions */
+typedef void (*tAVCT_LCB_ACTION)(tAVCT_LCB *p_ccb, tAVCT_LCB_EVT *p_data);
+
+/* action function list */
+const tAVCT_LCB_ACTION avct_lcb_action[] = {
+    avct_lcb_chnl_open,
+    avct_lcb_chnl_disc,
+    avct_lcb_send_msg,
+    avct_lcb_open_ind,
+    avct_lcb_open_fail,
+    avct_lcb_close_ind,
+    avct_lcb_close_cfm,
+    avct_lcb_msg_ind,
+    avct_lcb_cong_ind,
+    avct_lcb_bind_conn,
+    avct_lcb_bind_fail,
+    avct_lcb_unbind_disc,
+    avct_lcb_chk_disc,
+    avct_lcb_discard_msg,
+    avct_lcb_dealloc,
+    avct_lcb_free_msg_ind
+};
+
+/* state table information */
+#define AVCT_LCB_ACTIONS            2       /* number of actions */
+#define AVCT_LCB_NEXT_STATE         2       /* position of next state */
+#define AVCT_LCB_NUM_COLS           3       /* number of columns in state tables */
+
+/* state table for idle state */
+const UINT8 avct_lcb_st_idle[][AVCT_LCB_NUM_COLS] = {
+/* Event                Action 1                    Action 2                    Next state */
+/* UL_BIND_EVT */       {AVCT_LCB_CHNL_OPEN,        AVCT_LCB_IGNORE,            AVCT_LCB_OPENING_ST},
+/* UL_UNBIND_EVT */     {AVCT_LCB_UNBIND_DISC,      AVCT_LCB_IGNORE,            AVCT_LCB_IDLE_ST},
+/* UL_MSG_EVT */        {AVCT_LCB_DISCARD_MSG,      AVCT_LCB_IGNORE,            AVCT_LCB_IDLE_ST},
+/* INT_CLOSE_EVT */     {AVCT_LCB_IGNORE,           AVCT_LCB_IGNORE,            AVCT_LCB_IDLE_ST},
+/* LL_OPEN_EVT */       {AVCT_LCB_OPEN_IND,         AVCT_LCB_IGNORE,            AVCT_LCB_OPEN_ST},
+/* LL_CLOSE_EVT */      {AVCT_LCB_CLOSE_IND,        AVCT_LCB_DEALLOC,           AVCT_LCB_IDLE_ST},
+/* LL_MSG_EVT */        {AVCT_LCB_FREE_MSG_IND,     AVCT_LCB_IGNORE,            AVCT_LCB_IDLE_ST},
+/* LL_CONG_EVT */       {AVCT_LCB_IGNORE,           AVCT_LCB_IGNORE,            AVCT_LCB_IDLE_ST}
+};
+
+/* state table for opening state */
+const UINT8 avct_lcb_st_opening[][AVCT_LCB_NUM_COLS] = {
+/* Event                Action 1                    Action 2                    Next state */
+/* UL_BIND_EVT */       {AVCT_LCB_IGNORE,           AVCT_LCB_IGNORE,            AVCT_LCB_OPENING_ST},
+/* UL_UNBIND_EVT */     {AVCT_LCB_UNBIND_DISC,      AVCT_LCB_IGNORE,            AVCT_LCB_OPENING_ST},
+/* UL_MSG_EVT */        {AVCT_LCB_DISCARD_MSG,      AVCT_LCB_IGNORE,            AVCT_LCB_OPENING_ST},
+/* INT_CLOSE_EVT */     {AVCT_LCB_CHNL_DISC,        AVCT_LCB_IGNORE,            AVCT_LCB_CLOSING_ST},
+/* LL_OPEN_EVT */       {AVCT_LCB_OPEN_IND,         AVCT_LCB_IGNORE,            AVCT_LCB_OPEN_ST},
+/* LL_CLOSE_EVT */      {AVCT_LCB_OPEN_FAIL,        AVCT_LCB_DEALLOC,           AVCT_LCB_IDLE_ST},
+/* LL_MSG_EVT */        {AVCT_LCB_FREE_MSG_IND,     AVCT_LCB_IGNORE,            AVCT_LCB_OPENING_ST},
+/* LL_CONG_EVT */       {AVCT_LCB_CONG_IND,         AVCT_LCB_IGNORE,            AVCT_LCB_OPENING_ST}
+};
+
+/* state table for open state */
+const UINT8 avct_lcb_st_open[][AVCT_LCB_NUM_COLS] = {
+/* Event                Action 1                    Action 2                    Next state */
+/* UL_BIND_EVT */       {AVCT_LCB_BIND_CONN,        AVCT_LCB_IGNORE,            AVCT_LCB_OPEN_ST},
+/* UL_UNBIND_EVT */     {AVCT_LCB_CHK_DISC,         AVCT_LCB_IGNORE,            AVCT_LCB_OPEN_ST},
+/* UL_MSG_EVT */        {AVCT_LCB_SEND_MSG,         AVCT_LCB_IGNORE,            AVCT_LCB_OPEN_ST},
+/* INT_CLOSE_EVT */     {AVCT_LCB_CHNL_DISC,        AVCT_LCB_IGNORE,            AVCT_LCB_CLOSING_ST},
+/* LL_OPEN_EVT */       {AVCT_LCB_IGNORE,           AVCT_LCB_IGNORE,            AVCT_LCB_OPEN_ST},
+/* LL_CLOSE_EVT */      {AVCT_LCB_CLOSE_IND,        AVCT_LCB_DEALLOC,           AVCT_LCB_IDLE_ST},
+/* LL_MSG_EVT */        {AVCT_LCB_MSG_IND,          AVCT_LCB_IGNORE,            AVCT_LCB_OPEN_ST},
+/* LL_CONG_EVT */       {AVCT_LCB_CONG_IND,         AVCT_LCB_IGNORE,            AVCT_LCB_OPEN_ST}
+};
+
+/* state table for closing state */
+const UINT8 avct_lcb_st_closing[][AVCT_LCB_NUM_COLS] = {
+/* Event                Action 1                    Action 2                    Next state */
+/* UL_BIND_EVT */       {AVCT_LCB_BIND_FAIL,        AVCT_LCB_IGNORE,            AVCT_LCB_CLOSING_ST},
+/* UL_UNBIND_EVT */     {AVCT_LCB_IGNORE,           AVCT_LCB_IGNORE,            AVCT_LCB_CLOSING_ST},
+/* UL_MSG_EVT */        {AVCT_LCB_DISCARD_MSG,      AVCT_LCB_IGNORE,            AVCT_LCB_CLOSING_ST},
+/* INT_CLOSE_EVT */     {AVCT_LCB_IGNORE,           AVCT_LCB_IGNORE,            AVCT_LCB_CLOSING_ST},
+/* LL_OPEN_EVT */       {AVCT_LCB_IGNORE,           AVCT_LCB_IGNORE,            AVCT_LCB_CLOSING_ST},
+/* LL_CLOSE_EVT */      {AVCT_LCB_CLOSE_CFM,        AVCT_LCB_DEALLOC,           AVCT_LCB_IDLE_ST},
+/* LL_MSG_EVT */        {AVCT_LCB_FREE_MSG_IND,     AVCT_LCB_IGNORE,            AVCT_LCB_CLOSING_ST},
+/* LL_CONG_EVT */       {AVCT_LCB_IGNORE,           AVCT_LCB_IGNORE,            AVCT_LCB_CLOSING_ST}
+};
+
+/* type for state table */
+typedef const UINT8 (*tAVCT_LCB_ST_TBL)[AVCT_LCB_NUM_COLS];
+
+/* state table */
+const tAVCT_LCB_ST_TBL avct_lcb_st_tbl[] = {
+    avct_lcb_st_idle,
+    avct_lcb_st_opening,
+    avct_lcb_st_open,
+    avct_lcb_st_closing
+};
+
+/*******************************************************************************
+**
+** Function         avct_lcb_event
+**
+** Description      State machine event handling function for lcb
+**
+**
+** Returns          Nothing.
+**
+*******************************************************************************/
+void avct_lcb_event(tAVCT_LCB *p_lcb, UINT8 event, tAVCT_LCB_EVT *p_data)
+{
+    tAVCT_LCB_ST_TBL    state_table;
+    UINT8               action;
+    int                 i;
+
+#if BT_TRACE_VERBOSE == TRUE
+    AVCT_TRACE_EVENT("LCB lcb=%d event=%s state=%s", p_lcb->allocated, avct_lcb_evt_str[event], avct_lcb_st_str[p_lcb->state]);
+#else
+    AVCT_TRACE_EVENT("LCB lcb=%d event=%d state=%d", p_lcb->allocated, event, p_lcb->state);
+#endif
+
+    /* look up the state table for the current state */
+    state_table = avct_lcb_st_tbl[p_lcb->state];
+
+    /* set next state */
+    p_lcb->state = state_table[event][AVCT_LCB_NEXT_STATE];
+
+    /* execute action functions */
+    for (i = 0; i < AVCT_LCB_ACTIONS; i++)
+    {
+        if ((action = state_table[event][i]) != AVCT_LCB_IGNORE)
+        {
+            (*avct_lcb_action[action])(p_lcb, p_data);
+        }
+        else
+        {
+            break;
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         avct_bcb_event
+**
+** Description      State machine event handling function for lcb
+**
+**
+** Returns          Nothing.
+**
+*******************************************************************************/
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+void avct_bcb_event(tAVCT_BCB *p_bcb, UINT8 event, tAVCT_LCB_EVT *p_data)
+{
+    tAVCT_LCB_ST_TBL    state_table;
+    UINT8               action;
+    int                 i;
+
+#if BT_TRACE_VERBOSE == TRUE
+    AVCT_TRACE_EVENT("BCB lcb=%d event=%s state=%s", p_bcb->allocated, avct_lcb_evt_str[event], avct_lcb_st_str[p_bcb->state]);
+#else
+    AVCT_TRACE_EVENT("BCB lcb=%d event=%d state=%d", p_bcb->allocated, event, p_bcb->state);
+#endif
+
+    /* look up the state table for the current state */
+    state_table = avct_lcb_st_tbl[p_bcb->state];
+
+    /* set next state */
+    p_bcb->state = state_table[event][AVCT_LCB_NEXT_STATE];
+
+    /* execute action functions */
+    for (i = 0; i < AVCT_LCB_ACTIONS; i++)
+    {
+        if ((action = state_table[event][i]) != AVCT_LCB_IGNORE)
+        {
+            (*avct_bcb_action[action])(p_bcb, p_data);
+        }
+        else
+        {
+            break;
+        }
+    }
+}
+#endif
+
+/*******************************************************************************
+**
+** Function         avct_lcb_by_bd
+**
+** Description      This lookup function finds the lcb for a BD address.
+**
+**
+** Returns          pointer to the lcb, or NULL if none found.
+**
+*******************************************************************************/
+tAVCT_LCB *avct_lcb_by_bd(BD_ADDR bd_addr)
+{
+    tAVCT_LCB   *p_lcb = &avct_cb.lcb[0];
+    int         i;
+
+    for (i = 0; i < AVCT_NUM_LINKS; i++, p_lcb++)
+    {
+        /* if allocated lcb has matching lcb */
+        if (p_lcb->allocated && (!memcmp(p_lcb->peer_addr, bd_addr, BD_ADDR_LEN)))
+        {
+            break;
+        }
+    }
+
+    if (i == AVCT_NUM_LINKS)
+    {
+        /* if no lcb found */
+        p_lcb = NULL;
+
+        AVCT_TRACE_DEBUG("No lcb 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_lcb;
+}
+
+/*******************************************************************************
+**
+** Function         avct_lcb_alloc
+**
+** Description      Allocate a link control block.
+**
+**
+** Returns          pointer to the lcb, or NULL if none could be allocated.
+**
+*******************************************************************************/
+tAVCT_LCB *avct_lcb_alloc(BD_ADDR bd_addr)
+{
+    tAVCT_LCB   *p_lcb = &avct_cb.lcb[0];
+    int         i;
+
+    for (i = 0; i < AVCT_NUM_LINKS; i++, p_lcb++)
+    {
+        if (!p_lcb->allocated)
+        {
+            p_lcb->allocated = (UINT8)(i + 1);
+            memcpy(p_lcb->peer_addr, bd_addr, BD_ADDR_LEN);
+            AVCT_TRACE_DEBUG("avct_lcb_alloc %d", p_lcb->allocated);
+            break;
+        }
+    }
+
+    if (i == AVCT_NUM_LINKS)
+    {
+        /* out of lcbs */
+        p_lcb = NULL;
+        AVCT_TRACE_WARNING("Out of lcbs");
+    }
+    return p_lcb;
+}
+
+/*******************************************************************************
+**
+** Function         avct_lcb_dealloc
+**
+** Description      Deallocate a link control block.
+**
+**
+** Returns          void.
+**
+*******************************************************************************/
+void avct_lcb_dealloc(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
+{
+    tAVCT_CCB   *p_ccb = &avct_cb.ccb[0];
+    BOOLEAN     found = FALSE;
+    int         i;
+    UNUSED(p_data);
+
+    AVCT_TRACE_DEBUG("avct_lcb_dealloc %d", p_lcb->allocated);
+
+    for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++)
+    {
+        /* if ccb allocated and */
+        if (p_ccb->allocated)
+        {
+            if (p_ccb->p_lcb == p_lcb)
+            {
+                AVCT_TRACE_DEBUG("avct_lcb_dealloc used by ccb: %d", i);
+                found = TRUE;
+                break;
+            }
+        }
+    }
+
+    if (!found)
+    {
+        AVCT_TRACE_DEBUG("avct_lcb_dealloc now");
+
+        /* clear reassembled msg buffer if in use */
+        if (p_lcb->p_rx_msg != NULL)
+        {
+            GKI_freebuf(p_lcb->p_rx_msg);
+        }
+        memset(p_lcb, 0, sizeof(tAVCT_LCB));
+    }
+}
+
+/*******************************************************************************
+**
+** Function         avct_lcb_by_lcid
+**
+** Description      Find the LCB associated with the L2CAP LCID
+**
+**
+** Returns          pointer to the lcb, or NULL if none found.
+**
+*******************************************************************************/
+tAVCT_LCB *avct_lcb_by_lcid(UINT16 lcid)
+{
+    tAVCT_LCB   *p_lcb = &avct_cb.lcb[0];
+    int         i;
+
+    for (i = 0; i < AVCT_NUM_LINKS; i++, p_lcb++)
+    {
+        if (p_lcb->allocated && ((p_lcb->ch_lcid == lcid) || (p_lcb->conflict_lcid == lcid)))
+        {
+            break;
+        }
+    }
+
+    if (i == AVCT_NUM_LINKS)
+    {
+        /* out of lcbs */
+        p_lcb = NULL;
+        AVCT_TRACE_WARNING("No lcb for lcid %x", lcid);
+    }
+
+    return p_lcb;
+}
+
+/*******************************************************************************
+**
+** Function         avct_lcb_has_pid
+**
+** Description      See if any ccbs on this lcb have a particular pid.
+**
+**
+** Returns          Pointer to CCB if PID found, NULL otherwise.
+**
+*******************************************************************************/
+tAVCT_CCB *avct_lcb_has_pid(tAVCT_LCB *p_lcb, UINT16 pid)
+{
+    tAVCT_CCB   *p_ccb = &avct_cb.ccb[0];
+    int         i;
+
+    for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++)
+    {
+        if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb) && (p_ccb->cc.pid == pid))
+        {
+            return p_ccb;
+        }
+    }
+    return NULL;
+}
+
+/*******************************************************************************
+**
+** Function         avct_lcb_last_ccb
+**
+** Description      See if given ccb is only one on the lcb.
+**
+**
+** Returns          TRUE if ccb is last, FALSE otherwise.
+**
+*******************************************************************************/
+BOOLEAN avct_lcb_last_ccb(tAVCT_LCB *p_lcb, tAVCT_CCB *p_ccb_last)
+{
+    tAVCT_CCB   *p_ccb = &avct_cb.ccb[0];
+    int         i;
+
+    AVCT_TRACE_WARNING("avct_lcb_last_ccb");
+    for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++)
+    {
+        AVCT_TRACE_WARNING("%x: aloc:%d, lcb:0x%x/0x%x, ccb:0x%x/0x%x",
+            i, p_ccb->allocated, p_ccb->p_lcb, p_lcb, p_ccb, p_ccb_last);
+        if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb) && (p_ccb != p_ccb_last))
+        {
+            return FALSE;
+        }
+    }
+    return TRUE;
+}
+
+
+
diff --git a/components/bt/bluedroid/stack/avct/avct_lcb_act.c b/components/bt/bluedroid/stack/avct/avct_lcb_act.c
new file mode 100755 (executable)
index 0000000..589af0b
--- /dev/null
@@ -0,0 +1,734 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2003-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 action functions of the link control state machine.
+ *
+ ******************************************************************************/
+
+#include <string.h>
+#include "bt_types.h"
+#include "bt_target.h"
+#include "bt_utils.h"
+#include "avct_api.h"
+#include "avct_int.h"
+#include "gki.h"
+#include "btm_api.h"
+
+/* packet header length lookup table */
+const UINT8 avct_lcb_pkt_type_len[] = {
+    AVCT_HDR_LEN_SINGLE,
+    AVCT_HDR_LEN_START,
+    AVCT_HDR_LEN_CONT,
+    AVCT_HDR_LEN_END
+};
+
+/*******************************************************************************
+**
+** Function         avct_lcb_msg_asmbl
+**
+** Description      Reassemble incoming message.
+**
+**
+** Returns          Pointer to reassembled message;  NULL if no message
+**                  available.
+**
+*******************************************************************************/
+static BT_HDR *avct_lcb_msg_asmbl(tAVCT_LCB *p_lcb, 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;
+    AVCT_PRS_PKT_TYPE(p, pkt_type);
+
+    /* quick sanity check on length */
+    if (p_buf->len < avct_lcb_pkt_type_len[pkt_type])
+    {
+        GKI_freebuf(p_buf);
+        AVCT_TRACE_WARNING("Bad length during reassembly");
+        p_ret = NULL;
+    }
+    /* single packet */
+    else if (pkt_type == AVCT_PKT_TYPE_SINGLE)
+    {
+        /* if reassembly in progress drop message and process new single */
+        if (p_lcb->p_rx_msg != NULL)
+        {
+            GKI_freebuf(p_lcb->p_rx_msg);
+            p_lcb->p_rx_msg = NULL;
+            AVCT_TRACE_WARNING("Got single during reassembly");
+        }
+        p_ret = p_buf;
+    }
+    /* start packet */
+    else if (pkt_type == AVCT_PKT_TYPE_START)
+    {
+        /* if reassembly in progress drop message and process new start */
+        if (p_lcb->p_rx_msg != NULL)
+        {
+            GKI_freebuf(p_lcb->p_rx_msg);
+            AVCT_TRACE_WARNING("Got start during reassembly");
+        }
+        /* Allocate bigger buffer for reassembly. As lower layers are
+         * not aware of possible packet size after reassembly they
+         * would have allocated smaller buffer.
+         */
+        p_lcb->p_rx_msg = (BT_HDR*)GKI_getbuf(GKI_MAX_BUF_SIZE);
+        if (p_lcb->p_rx_msg == NULL)
+        {
+            AVCT_TRACE_ERROR ("Cannot alloc buffer for reassembly !!");
+            GKI_freebuf(p_buf);
+        }
+        else
+        {
+            memcpy (p_lcb->p_rx_msg, p_buf,
+                sizeof(BT_HDR) + p_buf->offset + p_buf->len);
+            /* Free original buffer */
+            GKI_freebuf(p_buf);
+
+            /* update p to point to new buffer */
+            p = (UINT8 *)(p_lcb->p_rx_msg + 1) + p_lcb->p_rx_msg->offset;
+
+            /* copy first header byte over nosp */
+            *(p + 1) = *p;
+
+            /* set offset to point to where to copy next */
+            p_lcb->p_rx_msg->offset += p_lcb->p_rx_msg->len;
+
+            /* adjust length for packet header */
+            p_lcb->p_rx_msg->len -= 1;
+        }
+        p_ret = NULL;
+    }
+    /* continue or end */
+    else
+    {
+        /* if no reassembly in progress drop message */
+        if (p_lcb->p_rx_msg == NULL)
+        {
+            GKI_freebuf(p_buf);
+            AVCT_TRACE_WARNING("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_lcb->p_rx_msg) - sizeof(BT_HDR);
+
+            /* adjust offset and len of fragment for header byte */
+            p_buf->offset += AVCT_HDR_LEN_CONT;
+            p_buf->len -= AVCT_HDR_LEN_CONT;
+
+            /* verify length */
+            if ((p_lcb->p_rx_msg->offset + p_buf->len) > buf_len)
+            {
+                /* won't fit; free everything */
+                GKI_freebuf(p_lcb->p_rx_msg);
+                p_lcb->p_rx_msg = NULL;
+                GKI_freebuf(p_buf);
+                p_ret = NULL;
+                AVCT_TRACE_WARNING("Fragmented message to big!");
+            }
+            else
+            {
+                /* copy contents of p_buf to p_rx_msg */
+                memcpy((UINT8 *)(p_lcb->p_rx_msg + 1) + p_lcb->p_rx_msg->offset,
+                       (UINT8 *)(p_buf + 1) + p_buf->offset, p_buf->len);
+
+                if (pkt_type == AVCT_PKT_TYPE_END)
+                {
+                    p_lcb->p_rx_msg->offset -= p_lcb->p_rx_msg->len;
+                    p_lcb->p_rx_msg->len += p_buf->len;
+                    p_ret = p_lcb->p_rx_msg;
+                    p_lcb->p_rx_msg = NULL;
+                }
+                else
+                {
+                    p_lcb->p_rx_msg->offset += p_buf->len;
+                    p_lcb->p_rx_msg->len += p_buf->len;
+                    p_ret = NULL;
+                }
+                GKI_freebuf(p_buf);
+            }
+        }
+    }
+    return p_ret;
+}
+
+
+/*******************************************************************************
+**
+** Function         avct_lcb_chnl_open
+**
+** Description      Open L2CAP channel to peer
+**
+**
+** Returns          Nothing.
+**
+*******************************************************************************/
+void avct_lcb_chnl_open(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
+{
+    UINT16 result = AVCT_RESULT_FAIL;
+    UNUSED(p_data);
+
+    BTM_SetOutService(p_lcb->peer_addr, BTM_SEC_SERVICE_AVCTP, 0);
+    /* call l2cap connect req */
+    p_lcb->ch_state = AVCT_CH_CONN;
+    if ((p_lcb->ch_lcid = L2CA_ConnectReq(AVCT_PSM, p_lcb->peer_addr)) == 0)
+    {
+        /* if connect req failed, send ourselves close event */
+        avct_lcb_event(p_lcb, AVCT_LCB_LL_CLOSE_EVT, (tAVCT_LCB_EVT *) &result);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         avct_lcb_unbind_disc
+**
+** Description      Deallocate ccb and call callback with disconnect event.
+**
+**
+** Returns          Nothing.
+**
+*******************************************************************************/
+void avct_lcb_unbind_disc(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
+{
+    UNUSED(p_lcb);
+
+    avct_ccb_dealloc(p_data->p_ccb, AVCT_DISCONNECT_CFM_EVT, 0, NULL);
+}
+
+/*******************************************************************************
+**
+** Function         avct_lcb_open_ind
+**
+** Description      Handle an LL_OPEN event.  For each allocated ccb already
+**                  bound to this lcb, send a connect event.  For each
+**                  unbound ccb with a new PID, bind that ccb to this lcb and
+**                  send a connect event.
+**
+**
+** Returns          Nothing.
+**
+*******************************************************************************/
+void avct_lcb_open_ind(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
+{
+    tAVCT_CCB   *p_ccb = &avct_cb.ccb[0];
+    int         i;
+    BOOLEAN     bind = FALSE;
+
+    for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++)
+    {
+        /* if ccb allocated and */
+        if (p_ccb->allocated)
+        {
+            /* if bound to this lcb send connect confirm event */
+            if (p_ccb->p_lcb == p_lcb)
+            {
+                bind = TRUE;
+                L2CA_SetTxPriority(p_lcb->ch_lcid, L2CAP_CHNL_PRIORITY_HIGH);
+                p_ccb->cc.p_ctrl_cback(avct_ccb_to_idx(p_ccb), AVCT_CONNECT_CFM_EVT,
+                                       0, p_lcb->peer_addr);
+            }
+            /* if unbound acceptor and lcb doesn't already have a ccb for this PID */
+            else if ((p_ccb->p_lcb == NULL) && (p_ccb->cc.role == AVCT_ACP) &&
+                     (avct_lcb_has_pid(p_lcb, p_ccb->cc.pid) == NULL))
+            {
+                /* bind ccb to lcb and send connect ind event */
+                bind = TRUE;
+                p_ccb->p_lcb = p_lcb;
+                L2CA_SetTxPriority(p_lcb->ch_lcid, L2CAP_CHNL_PRIORITY_HIGH);
+                p_ccb->cc.p_ctrl_cback(avct_ccb_to_idx(p_ccb), AVCT_CONNECT_IND_EVT,
+                                    0, p_lcb->peer_addr);
+            }
+        }
+    }
+
+    /* if no ccbs bound to this lcb, disconnect */
+    if (bind == FALSE)
+    {
+        avct_lcb_event(p_lcb, AVCT_LCB_INT_CLOSE_EVT, p_data);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         avct_lcb_open_fail
+**
+** Description      L2CAP channel open attempt failed.  Deallocate any ccbs
+**                  on this lcb and send connect confirm event with failure.
+**
+**
+** Returns          Nothing.
+**
+*******************************************************************************/
+void avct_lcb_open_fail(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
+{
+    tAVCT_CCB           *p_ccb = &avct_cb.ccb[0];
+    int                 i;
+
+    for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++)
+    {
+        if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb))
+        {
+            avct_ccb_dealloc(p_ccb, AVCT_CONNECT_CFM_EVT,
+                             p_data->result, p_lcb->peer_addr);
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         avct_lcb_close_ind
+**
+** Description      L2CAP channel closed by peer.  Deallocate any initiator
+**                  ccbs on this lcb and send disconnect ind event.
+**
+**
+** Returns          Nothing.
+**
+*******************************************************************************/
+void avct_lcb_close_ind(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
+{
+    tAVCT_CCB           *p_ccb = &avct_cb.ccb[0];
+    int                 i;
+    UNUSED(p_data);
+
+    for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++)
+    {
+        if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb))
+        {
+            if (p_ccb->cc.role == AVCT_INT)
+            {
+                avct_ccb_dealloc(p_ccb, AVCT_DISCONNECT_IND_EVT,
+                                 0, p_lcb->peer_addr);
+            }
+            else
+            {
+                p_ccb->p_lcb = NULL;
+                (*p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_ccb), AVCT_DISCONNECT_IND_EVT,
+                                          0, p_lcb->peer_addr);
+            }
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         avct_lcb_close_cfm
+**
+** Description      L2CAP channel closed by us.  Deallocate any initiator
+**                  ccbs on this lcb and send disconnect ind or cfm event.
+**
+**
+** Returns          Nothing.
+**
+*******************************************************************************/
+void avct_lcb_close_cfm(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
+{
+    tAVCT_CCB           *p_ccb = &avct_cb.ccb[0];
+    int                 i;
+    UINT8               event;
+
+    for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++)
+    {
+        if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb))
+        {
+            /* if this ccb initiated close send disconnect cfm otherwise ind */
+            if (p_ccb->ch_close)
+            {
+                p_ccb->ch_close = FALSE;
+                event = AVCT_DISCONNECT_CFM_EVT;
+            }
+            else
+            {
+                event = AVCT_DISCONNECT_IND_EVT;
+            }
+
+            if (p_ccb->cc.role == AVCT_INT)
+            {
+                avct_ccb_dealloc(p_ccb, event, p_data->result, p_lcb->peer_addr);
+            }
+            else
+            {
+                p_ccb->p_lcb = NULL;
+                (*p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_ccb), event,
+                                       p_data->result, p_lcb->peer_addr);
+            }
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         avct_lcb_bind_conn
+**
+** Description      Bind ccb to lcb and send connect cfm event.
+**
+**
+** Returns          Nothing.
+**
+*******************************************************************************/
+void avct_lcb_bind_conn(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
+{
+    p_data->p_ccb->p_lcb = p_lcb;
+    (*p_data->p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_data->p_ccb),
+                                      AVCT_CONNECT_CFM_EVT, 0, p_lcb->peer_addr);
+}
+
+/*******************************************************************************
+**
+** Function         avct_lcb_chk_disc
+**
+** Description      A ccb wants to close; if it is the last ccb on this lcb,
+**                  close channel.  Otherwise just deallocate and call
+**                  callback.
+**
+**
+** Returns          Nothing.
+**
+*******************************************************************************/
+void avct_lcb_chk_disc(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
+{
+    AVCT_TRACE_WARNING("avct_lcb_chk_disc");
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+    avct_close_bcb(p_lcb, p_data);
+#endif
+    if (avct_lcb_last_ccb(p_lcb, p_data->p_ccb))
+    {
+        AVCT_TRACE_WARNING("closing");
+        p_data->p_ccb->ch_close = TRUE;
+        avct_lcb_event(p_lcb, AVCT_LCB_INT_CLOSE_EVT, p_data);
+    }
+    else
+    {
+        AVCT_TRACE_WARNING("dealloc ccb");
+        avct_lcb_unbind_disc(p_lcb, p_data);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         avct_lcb_chnl_disc
+**
+** Description      Disconnect L2CAP channel.
+**
+**
+** Returns          Nothing.
+**
+*******************************************************************************/
+void avct_lcb_chnl_disc(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
+{
+    UNUSED(p_data);
+
+    L2CA_DisconnectReq(p_lcb->ch_lcid);
+}
+
+/*******************************************************************************
+**
+** Function         avct_lcb_bind_fail
+**
+** Description      Deallocate ccb and call callback with connect event
+**                  with failure result.
+**
+**
+** Returns          Nothing.
+**
+*******************************************************************************/
+void avct_lcb_bind_fail(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
+{
+    UNUSED(p_lcb);
+
+    avct_ccb_dealloc(p_data->p_ccb, AVCT_CONNECT_CFM_EVT, AVCT_RESULT_FAIL, NULL);
+}
+
+/*******************************************************************************
+**
+** Function         avct_lcb_cong_ind
+**
+** Description      Handle congestion indication from L2CAP.
+**
+**
+** Returns          Nothing.
+**
+*******************************************************************************/
+void avct_lcb_cong_ind(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
+{
+    tAVCT_CCB           *p_ccb = &avct_cb.ccb[0];
+    int                 i;
+    UINT8               event;
+    BT_HDR          *p_buf;
+
+    /* set event */
+    event = (p_data->cong) ? AVCT_CONG_IND_EVT : AVCT_UNCONG_IND_EVT;
+    p_lcb->cong = p_data->cong;
+    if (p_lcb->cong == FALSE && GKI_getfirst(&p_lcb->tx_q))
+    {
+        while ( !p_lcb->cong  && (p_buf = (BT_HDR *)GKI_dequeue(&p_lcb->tx_q)) != NULL)
+        {
+            if (L2CA_DataWrite(p_lcb->ch_lcid, p_buf) == L2CAP_DW_CONGESTED)
+            {
+                p_lcb->cong = TRUE;
+            }
+        }
+    }
+
+    /* send event to all ccbs on this lcb */
+    for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++)
+    {
+        if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb))
+        {
+            (*p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_ccb), event, 0, p_lcb->peer_addr);
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         avct_lcb_discard_msg
+**
+** Description      Discard a message sent in from the API.
+**
+**
+** Returns          Nothing.
+**
+*******************************************************************************/
+void avct_lcb_discard_msg(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
+{
+    UNUSED(p_lcb);
+
+    AVCT_TRACE_WARNING("Dropping msg");
+
+    GKI_freebuf(p_data->ul_msg.p_buf);
+}
+
+/*******************************************************************************
+**
+** Function         avct_lcb_send_msg
+**
+** Description      Build and send an AVCTP message.
+**
+**
+** Returns          Nothing.
+**
+*******************************************************************************/
+void avct_lcb_send_msg(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
+{
+    UINT16          curr_msg_len;
+    UINT8           pkt_type;
+    UINT8           hdr_len;
+    BT_HDR          *p_buf;
+    UINT8           *p;
+    UINT8           nosp = 0;       /* number of subsequent packets */
+    UINT16          temp;
+    UINT16          buf_size = p_lcb->peer_mtu + L2CAP_MIN_OFFSET + BT_HDR_SIZE;
+
+
+    /* store msg len */
+    curr_msg_len = p_data->ul_msg.p_buf->len;
+
+    /* initialize packet type and other stuff */
+    if (curr_msg_len <= (p_lcb->peer_mtu - AVCT_HDR_LEN_SINGLE))
+    {
+        pkt_type = AVCT_PKT_TYPE_SINGLE;
+    }
+    else
+    {
+        pkt_type = AVCT_PKT_TYPE_START;
+        temp = (curr_msg_len + AVCT_HDR_LEN_START - p_lcb->peer_mtu);
+        nosp = temp / (p_lcb->peer_mtu - 1) + 1;
+        if ( (temp % (p_lcb->peer_mtu - 1)) != 0)
+            nosp++;
+    }
+
+    /* while we haven't sent all packets */
+    while (curr_msg_len != 0)
+    {
+        /* set header len */
+        hdr_len = avct_lcb_pkt_type_len[pkt_type];
+
+        /* if remaining msg must be fragmented */
+        if (p_data->ul_msg.p_buf->len > (p_lcb->peer_mtu - hdr_len))
+        {
+            /* get a new buffer for fragment we are sending */
+            if ((p_buf = (BT_HDR *) GKI_getbuf(buf_size)) == NULL)
+            {
+                /* whoops; free original msg buf and bail */
+                AVCT_TRACE_ERROR ("avct_lcb_send_msg cannot alloc buffer!!");
+                GKI_freebuf(p_data->ul_msg.p_buf);
+                break;
+            }
+
+            /* copy portion of data from current message to new buffer */
+            p_buf->offset = L2CAP_MIN_OFFSET + hdr_len;
+            p_buf->len = p_lcb->peer_mtu - hdr_len;
+
+            memcpy((UINT8 *)(p_buf + 1) + p_buf->offset,
+                   (UINT8 *)(p_data->ul_msg.p_buf + 1) + p_data->ul_msg.p_buf->offset, p_buf->len);
+
+            p_data->ul_msg.p_buf->offset += p_buf->len;
+            p_data->ul_msg.p_buf->len -= p_buf->len;
+        }
+        else
+        {
+            p_buf = p_data->ul_msg.p_buf;
+        }
+
+        curr_msg_len -= 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 */
+        AVCT_BLD_HDR(p, p_data->ul_msg.label, pkt_type, p_data->ul_msg.cr);
+        if (pkt_type == AVCT_PKT_TYPE_START)
+        {
+            UINT8_TO_STREAM(p, nosp);
+        }
+        if ((pkt_type == AVCT_PKT_TYPE_START) || (pkt_type == AVCT_PKT_TYPE_SINGLE))
+        {
+            UINT16_TO_BE_STREAM(p, p_data->ul_msg.p_ccb->cc.pid);
+        }
+
+        if (p_lcb->cong == TRUE)
+        {
+            GKI_enqueue (&p_lcb->tx_q, p_buf);
+        }
+
+        /* send message to L2CAP */
+        else
+        {
+            if (L2CA_DataWrite(p_lcb->ch_lcid, p_buf) == L2CAP_DW_CONGESTED)
+            {
+                p_lcb->cong = TRUE;
+            }
+        }
+
+        /* update pkt type for next packet */
+        if (curr_msg_len > (p_lcb->peer_mtu - AVCT_HDR_LEN_END))
+        {
+            pkt_type = AVCT_PKT_TYPE_CONT;
+        }
+        else
+        {
+            pkt_type = AVCT_PKT_TYPE_END;
+        }
+    }
+    AVCT_TRACE_DEBUG ("avct_lcb_send_msg tx_q_count:%d", GKI_queue_length(&p_lcb->tx_q));
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         avct_lcb_free_msg_ind
+**
+** Description      Discard an incoming AVCTP message.
+**
+**
+** Returns          Nothing.
+**
+*******************************************************************************/
+void avct_lcb_free_msg_ind(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
+{
+    UNUSED(p_lcb);
+
+    if (p_data)
+        GKI_freebuf(p_data->p_buf);
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         avct_lcb_msg_ind
+**
+** Description      Handle an incoming AVCTP message.
+**
+**
+** Returns          Nothing.
+**
+*******************************************************************************/
+void avct_lcb_msg_ind(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
+{
+    UINT8       *p;
+    UINT8       label, type, cr_ipid;
+    UINT16      pid;
+    tAVCT_CCB   *p_ccb;
+    BT_HDR      *p_buf;
+
+    /* this p_buf is to be reported through p_msg_cback. The layer_specific
+     * needs to be set properly to indicate that it is received through
+     * control channel */
+    p_data->p_buf->layer_specific = AVCT_DATA_CTRL;
+
+    /* reassemble message; if no message available (we received a fragment) return */
+    if ((p_data->p_buf = avct_lcb_msg_asmbl(p_lcb, p_data->p_buf)) == NULL)
+    {
+        return;
+    }
+
+    p = (UINT8 *)(p_data->p_buf + 1) + p_data->p_buf->offset;
+
+    /* parse header byte */
+    AVCT_PRS_HDR(p, label, type, cr_ipid);
+    UNUSED(type);
+
+    /* check for invalid cr_ipid */
+    if (cr_ipid == AVCT_CR_IPID_INVALID)
+    {
+        AVCT_TRACE_WARNING("Invalid cr_ipid", cr_ipid);
+        GKI_freebuf(p_data->p_buf);
+        return;
+    }
+
+    /* parse and lookup PID */
+    BE_STREAM_TO_UINT16(pid, p);
+    if ((p_ccb = avct_lcb_has_pid(p_lcb, pid)) != NULL)
+    {
+        /* PID found; send msg up, adjust bt hdr and call msg callback */
+        p_data->p_buf->offset += AVCT_HDR_LEN_SINGLE;
+        p_data->p_buf->len -= AVCT_HDR_LEN_SINGLE;
+        (*p_ccb->cc.p_msg_cback)(avct_ccb_to_idx(p_ccb), label, cr_ipid, p_data->p_buf);
+    }
+    else
+    {
+        /* PID not found; drop message */
+        AVCT_TRACE_WARNING("No ccb for PID=%x", pid);
+        GKI_freebuf(p_data->p_buf);
+
+        /* if command send reject */
+        if (cr_ipid == AVCT_CMD)
+        {
+            if ((p_buf = (BT_HDR *) GKI_getpoolbuf(AVCT_CMD_POOL_ID)) != NULL)
+            {
+                p_buf->len = AVCT_HDR_LEN_SINGLE;
+                p_buf->offset = AVCT_MSG_OFFSET - AVCT_HDR_LEN_SINGLE;
+                p = (UINT8 *)(p_buf + 1) + p_buf->offset;
+                AVCT_BLD_HDR(p, label, AVCT_PKT_TYPE_SINGLE, AVCT_REJ);
+                UINT16_TO_BE_STREAM(p, pid);
+                L2CA_DataWrite(p_lcb->ch_lcid, p_buf);
+            }
+        }
+    }
+}
diff --git a/components/bt/bluedroid/stack/avct/include/avct_defs.h b/components/bt/bluedroid/stack/avct/include/avct_defs.h
new file mode 100755 (executable)
index 0000000..30b8859
--- /dev/null
@@ -0,0 +1,62 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2003-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 AVCTP
+ *  specification.  This file is intended for use internal to AVCT only.
+ *
+ ******************************************************************************/
+#ifndef AVCT_DEFS_H
+#define AVCT_DEFS_H
+
+/*****************************************************************************
+** constants
+*****************************************************************************/
+
+/* packet type */
+#define AVCT_PKT_TYPE_SINGLE        0       /* single packet */
+#define AVCT_PKT_TYPE_START         1       /* start packet */
+#define AVCT_PKT_TYPE_CONT          2       /* continue packet */
+#define AVCT_PKT_TYPE_END           3       /* end packet */
+
+/* header lengths for different packet types */
+#define AVCT_HDR_LEN_SINGLE         3
+#define AVCT_HDR_LEN_START          4
+#define AVCT_HDR_LEN_CONT           1
+#define AVCT_HDR_LEN_END            1
+
+/* invalid cr+ipid value */
+#define AVCT_CR_IPID_INVALID        1
+
+/*****************************************************************************
+** message parsing and building macros
+*****************************************************************************/
+
+#define AVCT_BLD_HDR(p, label, type, cr_ipid) \
+    *(p)++ = ((label) << 4) | ((type) << 2) | (cr_ipid);
+
+#define AVCT_PRS_HDR(p, label, type, cr_ipid) \
+    label = *(p) >> 4; \
+    type = (*(p) >> 2) & 3; \
+    cr_ipid = *(p)++ & 3;
+
+#define AVCT_PRS_PKT_TYPE(p, type) \
+    type = (*(p) >> 2) & 3;
+
+#endif /* AVCT_DEFS_H */
diff --git a/components/bt/bluedroid/stack/avct/include/avct_int.h b/components/bt/bluedroid/stack/avct/include/avct_int.h
new file mode 100755 (executable)
index 0000000..29300a5
--- /dev/null
@@ -0,0 +1,237 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2003-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 AVCTP.
+ *
+ ******************************************************************************/
+#ifndef AVCT_INT_H
+#define AVCT_INT_H
+
+#include "gki.h"
+#include "avct_api.h"
+#include "avct_defs.h"
+#include "l2c_api.h"
+
+/*****************************************************************************
+** constants
+*****************************************************************************/
+
+/* lcb state machine events */
+enum {
+    AVCT_LCB_UL_BIND_EVT,
+    AVCT_LCB_UL_UNBIND_EVT,
+    AVCT_LCB_UL_MSG_EVT,
+    AVCT_LCB_INT_CLOSE_EVT,
+    AVCT_LCB_LL_OPEN_EVT,
+    AVCT_LCB_LL_CLOSE_EVT,
+    AVCT_LCB_LL_MSG_EVT,
+    AVCT_LCB_LL_CONG_EVT
+};
+
+
+/* "states" used for L2CAP channel */
+#define AVCT_CH_IDLE    0       /* No connection */
+#define AVCT_CH_CONN    1       /* Waiting for connection confirm */
+#define AVCT_CH_CFG     2       /* Waiting for configuration complete */
+#define AVCT_CH_OPEN    3       /* Channel opened */
+
+/* "no event" indicator used by ccb dealloc */
+#define AVCT_NO_EVT     0xFF
+
+/*****************************************************************************
+** data types
+*****************************************************************************/
+/* sub control block type - common data members for tAVCT_LCB and tAVCT_BCB */
+typedef struct {
+    UINT16              peer_mtu;          /* peer l2c mtu */
+    UINT16              ch_result;      /* L2CAP connection result value */
+    UINT16              ch_lcid;        /* L2CAP channel LCID */
+    UINT8               allocated;      /* 0, not allocated. index+1, otherwise. */
+    UINT8               state;          /* The state machine state */
+    UINT8               ch_state;       /* L2CAP channel state */
+    UINT8               ch_flags;       /* L2CAP configuration flags */
+} tAVCT_SCB;
+
+/* link control block type */
+typedef struct {
+    UINT16              peer_mtu;          /* peer l2c mtu */
+    UINT16              ch_result;      /* L2CAP connection result value */
+    UINT16              ch_lcid;        /* L2CAP channel LCID */
+    UINT8               allocated;      /* 0, not allocated. index+1, otherwise. */
+    UINT8               state;          /* The state machine state */
+    UINT8               ch_state;       /* L2CAP channel state */
+    UINT8               ch_flags;       /* L2CAP configuration flags */
+    BT_HDR              *p_rx_msg;      /* Message being reassembled */
+    UINT16              conflict_lcid;  /* L2CAP channel LCID */
+    BD_ADDR             peer_addr;      /* BD address of peer */
+    BUFFER_Q            tx_q;           /* Transmit data buffer queue       */
+    BOOLEAN             cong;           /* TRUE, if congested */
+} tAVCT_LCB;
+
+/* browse control block type */
+typedef struct {
+    UINT16              peer_mtu;          /* peer l2c mtu */
+    UINT16              ch_result;      /* L2CAP connection result value */
+    UINT16              ch_lcid;        /* L2CAP channel LCID */
+    UINT8               allocated;      /* 0, not allocated. index+1, otherwise. */
+    UINT8               state;          /* The state machine state */
+    UINT8               ch_state;       /* L2CAP channel state */
+    UINT8               ch_flags;       /* L2CAP configuration flags */
+    BT_HDR              *p_tx_msg;      /* Message to be sent - in case the browsing channel is not open when MsgReg is called */
+    UINT8               ch_close;       /* CCB index+1, if CCB initiated channel close */
+} tAVCT_BCB;
+
+#define AVCT_ALOC_LCB       0x01
+#define AVCT_ALOC_BCB       0x02
+/* connection control block */
+typedef struct {
+    tAVCT_CC            cc;                 /* parameters from connection creation */
+    tAVCT_LCB           *p_lcb;             /* Associated LCB */
+    tAVCT_BCB           *p_bcb;             /* associated BCB */
+    BOOLEAN             ch_close;           /* Whether CCB initiated channel close */
+    UINT8               allocated;          /* Whether LCB/BCB is allocated */
+} tAVCT_CCB;
+
+/* data type associated with UL_MSG_EVT */
+typedef struct {
+    BT_HDR                  *p_buf;
+    tAVCT_CCB               *p_ccb;
+    UINT8                   label;
+    UINT8                   cr;
+} tAVCT_UL_MSG;
+
+/* union associated with lcb state machine events */
+typedef union {
+    tAVCT_UL_MSG            ul_msg;
+    BT_HDR                  *p_buf;
+    tAVCT_CCB               *p_ccb;
+    UINT16                  result;
+    BOOLEAN                 cong;
+    UINT8                   err_code;
+} tAVCT_LCB_EVT;
+
+/* Control block for AVCT */
+typedef struct {
+    tAVCT_LCB       lcb[AVCT_NUM_LINKS];    /* link control blocks */
+    tAVCT_BCB       bcb[AVCT_NUM_LINKS];    /* browse control blocks */
+    tAVCT_CCB       ccb[AVCT_NUM_CONN];     /* connection control blocks */
+    UINT16          mtu;                    /* our L2CAP MTU */
+    UINT16          mtu_br;                 /* our L2CAP MTU for the Browsing channel */
+    UINT8           trace_level;            /* trace level */
+} tAVCT_CB;
+
+/*****************************************************************************
+** function declarations
+*****************************************************************************/
+
+/* LCB function declarations */
+extern void avct_lcb_event(tAVCT_LCB *p_lcb, UINT8 event, tAVCT_LCB_EVT *p_data);
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+extern void avct_bcb_event(tAVCT_BCB *p_bcb, UINT8 event, tAVCT_LCB_EVT *p_data);
+extern void avct_close_bcb(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data);
+extern tAVCT_LCB *avct_lcb_by_bcb(tAVCT_BCB *p_bcb);
+extern tAVCT_BCB *avct_bcb_by_lcb(tAVCT_LCB *p_lcb);
+extern BOOLEAN avct_bcb_last_ccb(tAVCT_BCB *p_bcb, tAVCT_CCB *p_ccb_last);
+extern tAVCT_BCB *avct_bcb_by_lcid(UINT16 lcid);
+#endif
+extern tAVCT_LCB *avct_lcb_by_bd(BD_ADDR bd_addr);
+extern tAVCT_LCB *avct_lcb_alloc(BD_ADDR bd_addr);
+extern void avct_lcb_dealloc(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data);
+extern tAVCT_LCB *avct_lcb_by_lcid(UINT16 lcid);
+extern tAVCT_CCB *avct_lcb_has_pid(tAVCT_LCB *p_lcb, UINT16 pid);
+extern BOOLEAN avct_lcb_last_ccb(tAVCT_LCB *p_lcb, tAVCT_CCB *p_ccb_last);
+
+/* LCB action functions */
+extern void avct_lcb_chnl_open(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data);
+extern void avct_lcb_unbind_disc(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data);
+extern void avct_lcb_open_ind(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data);
+extern void avct_lcb_open_fail(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data);
+extern void avct_lcb_close_ind(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data);
+extern void avct_lcb_close_cfm(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data);
+extern void avct_lcb_bind_conn(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data);
+extern void avct_lcb_chk_disc(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data);
+extern void avct_lcb_chnl_disc(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data);
+extern void avct_lcb_bind_fail(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data);
+extern void avct_lcb_cong_ind(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data);
+extern void avct_lcb_discard_msg(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data);
+extern void avct_lcb_send_msg(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data);
+extern void avct_lcb_msg_ind(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data);
+extern void avct_lcb_free_msg_ind(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data);
+
+/* BCB action functions */
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+typedef void (*tAVCT_BCB_ACTION)(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data);
+extern void avct_bcb_chnl_open(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data);
+extern void avct_bcb_unbind_disc(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data);
+extern void avct_bcb_open_ind(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data);
+extern void avct_bcb_open_fail(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data);
+extern void avct_bcb_close_ind(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data);
+extern void avct_bcb_close_cfm(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data);
+extern void avct_bcb_bind_conn(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data);
+extern void avct_bcb_chk_disc(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data);
+extern void avct_bcb_chnl_disc(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data);
+extern void avct_bcb_bind_fail(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data);
+extern void avct_bcb_cong_ind(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data);
+extern void avct_bcb_discard_msg(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data);
+extern void avct_bcb_send_msg(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data);
+extern void avct_bcb_msg_ind(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data);
+extern void avct_bcb_free_msg_ind(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data);
+
+extern void avct_bcb_dealloc(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data);
+
+extern const tAVCT_BCB_ACTION avct_bcb_action[];
+extern const UINT8 avct_lcb_pkt_type_len[];
+extern const tL2CAP_FCR_OPTS avct_l2c_br_fcr_opts_def;
+#endif
+
+/* CCB function declarations */
+extern tAVCT_CCB *avct_ccb_alloc(tAVCT_CC *p_cc);
+extern void avct_ccb_dealloc(tAVCT_CCB *p_ccb, UINT8 event, UINT16 result, BD_ADDR bd_addr);
+extern UINT8 avct_ccb_to_idx(tAVCT_CCB *p_ccb);
+extern tAVCT_CCB *avct_ccb_by_idx(UINT8 idx);
+
+
+/*****************************************************************************
+** global data
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* Main control block */
+#if AVCT_DYNAMIC_MEMORY == FALSE
+extern tAVCT_CB avct_cb;
+#else
+extern tAVCT_CB *avct_cb_ptr;
+#define avct_cb (*avct_cb_ptr)
+#endif
+
+/* L2CAP callback registration structure */
+extern const tL2CAP_APPL_INFO avct_l2c_appl;
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+extern const tL2CAP_APPL_INFO avct_l2c_br_appl;
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVCT_INT_H */
diff --git a/components/bt/bluedroid/stack/avdt/avdt_ad.c b/components/bt/bluedroid/stack/avdt/avdt_ad.c
new file mode 100755 (executable)
index 0000000..c0f7f15
--- /dev/null
@@ -0,0 +1,641 @@
+/******************************************************************************
+ *
+ *  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 <assert.h>
+#include "bt_trace.h"
+#include <string.h>
+
+#include "bt_types.h"
+#include "bt_target.h"
+#include "bt_utils.h"
+#include "avdt_api.h"
+#include "avdtc_api.h"
+#include "avdt_int.h"
+#include "l2c_api.h"
+#include "l2cdefs.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_DEBUG("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_DEBUG("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;
+        }
+    }
+
+    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 */
+    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_DEBUG("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;
+    UNUSED(reason);
+
+    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_DEBUG("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);
+            AVDT_TRACE_ERROR(" avdt_ad_tc_data_ind buffer freed");
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** 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;
+
+    if((p_tbl = avdt_ad_tc_tbl_alloc(p_ccb)) == NULL)
+    {
+        AVDT_TRACE_ERROR("avdt_ad_open_req: Cannot allocate p_tbl");
+        return;
+    }
+
+
+    p_tbl->tcid = avdt_ad_type_to_tcid(type, p_scb);
+    AVDT_TRACE_DEBUG("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_DEBUG("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_DEBUG("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_DEBUG("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_DEBUG("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/components/bt/bluedroid/stack/avdt/avdt_api.c b/components/bt/bluedroid/stack/avdt/avdt_api.c
new file mode 100755 (executable)
index 0000000..6b91285
--- /dev/null
@@ -0,0 +1,1436 @@
+/******************************************************************************
+ *
+ *  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 "bt_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"
+
+
+/* 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)
+{
+    /* 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();
+
+    /* 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)
+{
+    /* deregister PSM with L2CAP */
+    L2CA_Deregister(AVDT_PSM);
+}
+
+/*******************************************************************************
+**
+** Function         AVDT_SINK_Activate
+**
+** Description      Activate SEP of A2DP Sink. In Use parameter is adjusted.
+**                  In Use will be made false in case of activation. A2DP SRC
+**                  will receive in_use as false and can open A2DP Sink
+**                  connection
+**
+** Returns          void.
+**
+*******************************************************************************/
+void AVDT_SINK_Activate()
+{
+    tAVDT_SCB           *p_scb = &avdt_cb.scb[0];
+    int                 i;
+    AVDT_TRACE_DEBUG("AVDT_SINK_Activate");
+    /* for all allocated scbs */
+    for (i = 0; i < AVDT_NUM_SEPS; i++, p_scb++)
+    {
+        if ((p_scb->allocated) && (p_scb->cs.tsep == AVDT_TSEP_SNK))
+        {
+            AVDT_TRACE_DEBUG("AVDT_SINK_Activate found scb");
+            p_scb->sink_activated = TRUE;
+            /* update in_use */
+            p_scb->in_use = FALSE;
+            break;
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         AVDT_SINK_Deactivate
+**
+** Description      Deactivate SEP of A2DP Sink. In Use parameter is adjusted.
+**                  In Use will be made TRUE in case of activation. A2DP SRC
+**                  will receive in_use as true and will not open A2DP Sink
+**                  connection
+**
+** Returns          void.
+**
+*******************************************************************************/
+void AVDT_SINK_Deactivate()
+{
+    tAVDT_SCB           *p_scb = &avdt_cb.scb[0];
+    int                 i;
+    AVDT_TRACE_DEBUG("AVDT_SINK_Deactivate");
+    /* for all allocated scbs */
+    for (i = 0; i < AVDT_NUM_SEPS; i++, p_scb++)
+    {
+        if ((p_scb->allocated) && (p_scb->cs.tsep == AVDT_TSEP_SNK))
+        {
+            AVDT_TRACE_DEBUG("AVDT_SINK_Deactivate, found scb");
+            p_scb->sink_activated = FALSE;
+            /* update in_use */
+            p_scb->in_use = TRUE;
+            break;
+        }
+    }
+}
+
+void AVDT_AbortReq(UINT8 handle)
+{
+    AVDT_TRACE_ERROR("%s", __func__);
+
+    tAVDT_SCB *p_scb = avdt_scb_by_hdl(handle);
+    if (p_scb != NULL)
+    {
+        avdt_scb_event(p_scb, AVDT_SCB_API_ABORT_REQ_EVT, NULL);
+    } else {
+        AVDT_TRACE_ERROR("%s Improper SCB, can not abort the stream", __func__);
+    }
+}
+
+/*******************************************************************************
+**
+** 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;
+
+    /* 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;
+
+    /* 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;
+
+    /* 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_ERROR("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;
+
+    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;
+
+    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;
+
+    /* 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;
+
+    /* 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;
+
+    /* 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;
+
+    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;
+
+    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;
+
+    /* 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;
+
+    /* 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;
+
+    /* 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;
+
+    /* 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;
+
+    /* 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_WriteReqOpt
+**
+** 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
+**                  (if NO_RTP is specified, L2CAP_MIN_OFFSET can be used).
+**                  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.
+**
+**                  The opt parameter allows passing specific options like:
+**                  - NO_RTP : do not add the RTP header to buffer
+**
+** Returns          AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVDT_WriteReqOpt(UINT8 handle, BT_HDR *p_pkt, UINT32 time_stamp, UINT8 m_pt, tAVDT_DATA_OPT_MASK opt)
+{
+    tAVDT_SCB       *p_scb;
+    tAVDT_SCB_EVT   evt;
+    UINT16          result = AVDT_SUCCESS;
+
+    /* 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;
+        evt.apiwrite.opt = opt;
+#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_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)
+{
+    return AVDT_WriteReqOpt(handle, p_pkt, time_stamp, m_pt, AVDT_DATA_OPT_NONE);
+}
+
+/*******************************************************************************
+**
+** 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;
+
+    /* 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_WARNING("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;
+
+    /* 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;
+    }
+
+    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;
+    }
+
+    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.
+**
+*******************************************************************************/
+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;
+
+    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_WARNING("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_WARNING("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_WARNING("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_WARNING("*** 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.
+**
+*******************************************************************************/
+extern UINT16 AVDT_SetMediaBuf(UINT8 handle, UINT8 *p_buf, UINT32 buf_len)
+{
+    tAVDT_SCB       *p_scb;
+    UINT16          result = AVDT_SUCCESS;
+
+    /* 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=NULL, u;
+#endif
+    UINT32  ssrc;
+    UINT16  len;
+
+    /* 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_API("packet_lost: %d", p_data->rr.packet_lost);
+                p_data->rr.packet_lost &= 0xFFFFFF;
+                AVDT_TRACE_API("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/components/bt/bluedroid/stack/avdt/avdt_ccb.c b/components/bt/bluedroid/stack/avdt/avdt_ccb.c
new file mode 100755 (executable)
index 0000000..09ed39a
--- /dev/null
@@ -0,0 +1,465 @@
+/******************************************************************************
+ *
+ *  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 "bt_types.h"
+#include "bt_target.h"
+#include "bt_utils.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_EVENT("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
+
+    /* 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]) {
+        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)
+        {
+            (*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_DEBUG("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_DEBUG("avdt_ccb_alloc %d", i);
+            break;
+        }
+    }
+
+    if (i == AVDT_NUM_LINKS)
+    {
+        /* out of ccbs */
+        p_ccb = NULL;
+        AVDT_TRACE_WARNING("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)
+{
+    UNUSED(p_data);
+
+    AVDT_TRACE_DEBUG("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_WARNING("No ccb for idx %d", idx);
+    }
+    return p_ccb;
+}
+
diff --git a/components/bt/bluedroid/stack/avdt/avdt_ccb_act.c b/components/bt/bluedroid/stack/avdt/avdt_ccb_act.c
new file mode 100755 (executable)
index 0000000..4dd9b23
--- /dev/null
@@ -0,0 +1,1128 @@
+/******************************************************************************
+ *
+ *  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 "bt_types.h"
+#include "bt_target.h"
+#include "bt_utils.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)
+{
+    UNUSED(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)
+{
+    UNUSED(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];
+    UNUSED(p_data);
+
+    /* 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[p_data->msg.discover_rsp.num_seps].in_use = p_scb->in_use;
+            sep_info[p_data->msg.discover_rsp.num_seps].seid = i + 1;
+            sep_info[p_data->msg.discover_rsp.num_seps].media_type = p_scb->cs.media_type;
+            sep_info[p_data->msg.discover_rsp.num_seps].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   err_code = 0;
+
+    /* verify all streams in the right state */
+    UINT8 seid = avdt_scb_verify(p_ccb, AVDT_VERIFY_START, p_data->msg.multi.seid_list,
+                                 p_data->msg.multi.num_seps, &err_code);
+    if (seid == 0 && 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 = 0;
+
+    /* 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 &&
+                                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;
+    UNUSED(p_data);
+
+    /* 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)
+{
+    UNUSED(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;
+    UNUSED(p_data);
+
+    /* 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;
+    UNUSED(p_data);
+
+    /* 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)
+{
+    UNUSED(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)
+{
+    UNUSED(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;
+    UNUSED(p_data);
+
+    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)
+{
+    UNUSED(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_EVENT("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)
+{
+    UNUSED(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;
+    UNUSED(p_data);
+
+    /* 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/components/bt/bluedroid/stack/avdt/avdt_l2c.c b/components/bt/bluedroid/stack/avdt/avdt_l2c.c
new file mode 100755 (executable)
index 0000000..dbdfc08
--- /dev/null
@@ -0,0 +1,529 @@
+/******************************************************************************
+ *
+ *  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 "bt_types.h"
+#include "bt_target.h"
+#include "bt_utils.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, tBT_TRANSPORT transport,
+                                                 void *p_ref_data, UINT8 res)
+{
+    tAVDT_CCB       *p_ccb = NULL;
+    tL2CAP_CFG_INFO cfg;
+    tAVDT_TC_TBL    *p_tbl;
+    UNUSED(p_ref_data);
+
+    AVDT_TRACE_DEBUG("avdt_sec_check_complete_term res: %d", res);
+    if (!bd_addr)
+    {
+        AVDT_TRACE_WARNING("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, tBT_TRANSPORT trasnport,
+                                                void *p_ref_data, UINT8 res)
+{
+    tAVDT_CCB       *p_ccb = NULL;
+    tL2CAP_CFG_INFO cfg;
+    tAVDT_TC_TBL    *p_tbl;
+    UNUSED(p_ref_data);
+
+    AVDT_TRACE_DEBUG("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;
+    UNUSED(psm);
+
+    /* 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_DEBUG("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)
+    {
+        p_tbl->lcid = lcid;
+
+        /* 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_DEBUG("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_DEBUG("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_DEBUG("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/components/bt/bluedroid/stack/avdt/avdt_msg.c b/components/bt/bluedroid/stack/avdt/avdt_msg.c
new file mode 100755 (executable)
index 0000000..1bf6b7f
--- /dev/null
@@ -0,0 +1,1901 @@
+/******************************************************************************
+ *
+ *  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 "bt_types.h"
+#include "bt_target.h"
+#include "bt_utils.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)
+{
+    UNUSED(p);
+    UNUSED(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_ERROR ("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_DEBUG("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_DEBUG("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_WARNING("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_REPORT) && !(p_cfg->psc_mask & AVDT_PSC_RECOV))
+                    && (elem_len != 5))
+                    || ((!(p_cfg->psc_mask & AVDT_PSC_REPORT) && (p_cfg->psc_mask & AVDT_PSC_RECOV))
+                    && (elem_len != 5))
+                    || (((p_cfg->psc_mask & AVDT_PSC_REPORT) && (p_cfg->psc_mask & AVDT_PSC_RECOV))
+                    && (elem_len != 7)) )
+                {
+                    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_DEBUG("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)
+{
+    UNUSED(p_msg);
+    UNUSED(p);
+    UNUSED(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_DEBUG("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_WARNING("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_DEBUG("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_DEBUG("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_WARNING("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_WARNING("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_WARNING("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_WARNING("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_ERROR("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_DEBUG("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 = 0;
+    AVDT_BLD_LAYERSPEC(p_buf->layer_specific, 0, p_params->hdr.label);
+    AVDT_TRACE_DEBUG("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);
+
+    UNUSED(pkt_type);
+
+    AVDT_TRACE_DEBUG("msg_type=%d, sig=%d", msg_type, sig);
+    /* 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_WARNING("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_WARNING("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_WARNING("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_WARNING("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/components/bt/bluedroid/stack/avdt/avdt_scb.c b/components/bt/bluedroid/stack/avdt/avdt_scb.c
new file mode 100755 (executable)
index 0000000..696fcca
--- /dev/null
@@ -0,0 +1,799 @@
+/******************************************************************************
+ *
+ *  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 "bt_types.h"
+#include "bt_target.h"
+#include "bt_utils.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_HDL_SUSPEND_RSP,      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_EVENT("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
+    /* 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]) {
+        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)
+        {
+            (*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;
+
+            /* initialize sink as activated */
+            if (p_cs->tsep == AVDT_TSEP_SNK)
+            {
+                p_scb->sink_activated = TRUE;
+            }
+
+            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_DEBUG("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_WARNING("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
+    UNUSED(p_data);
+
+    AVDT_TRACE_DEBUG("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_WARNING("scb hdl %d not allocated", hdl);
+        }
+    }
+    else
+    {
+        p_scb = NULL;
+        AVDT_TRACE_WARNING("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       ret = 0;
+
+    AVDT_TRACE_DEBUG("avdt_scb_verify state %d", state);
+    /* set nonsupported command mask */
+    /* translate public state into private state */
+    nsc_mask = 0;
+    if (state == AVDT_VERIFY_SUSPEND)
+      nsc_mask = AVDT_NSC_SUSPEND;
+
+    /* verify every scb */
+    for (i = 0, *p_err_code = 0; (i < num_seid) && (*p_err_code == 0) && (i < AVDT_NUM_SEPS); i++)
+    {
+        if ((p_scb = avdt_scb_by_hdl(p_seid[i])) == NULL)
+            *p_err_code = AVDT_ERR_BAD_STATE;
+        else if (p_scb->p_ccb != p_ccb)
+            *p_err_code = AVDT_ERR_BAD_STATE;
+        else if (p_scb->cs.nsc_mask & nsc_mask)
+            *p_err_code = AVDT_ERR_NSC;
+
+        switch (state) {
+          case AVDT_VERIFY_OPEN:
+          case AVDT_VERIFY_START:
+            if (p_scb->state != AVDT_SCB_OPEN_ST && p_scb->state != AVDT_SCB_STREAM_ST)
+              *p_err_code = AVDT_ERR_BAD_STATE;
+            break;
+
+          case AVDT_VERIFY_SUSPEND:
+          case AVDT_VERIFY_STREAMING:
+            if (p_scb->state != AVDT_SCB_STREAM_ST)
+              *p_err_code = AVDT_ERR_BAD_STATE;
+            break;
+        }
+    }
+
+    if ((i != num_seid) && (i < AVDT_NUM_SEPS))
+    {
+        ret = p_seid[i];
+    }
+
+    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/components/bt/bluedroid/stack/avdt/avdt_scb_act.c b/components/bt/bluedroid/stack/avdt/avdt_scb_act.c
new file mode 100755 (executable)
index 0000000..3ab1c26
--- /dev/null
@@ -0,0 +1,2175 @@
+/******************************************************************************
+ *
+ *  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 "bt_types.h"
+#include "bt_target.h"
+#include "bt_utils.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)
+{
+    UNUSED(p_scb);
+    UNUSED(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)
+{
+    UNUSED(p_scb);
+    UNUSED(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)
+{
+    UNUSED(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;
+    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);
+    p += 4;
+
+    UNUSED(o_v);
+
+    /* 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_WARNING("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;
+    AVDT_REPORT_TYPE    pt;
+    tAVDT_REPORT_DATA   report, *p_rpt;
+
+    AVDT_TRACE_DEBUG( "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++;
+        p += 2;
+        BE_STREAM_TO_UINT32(ssrc, p);
+
+        UNUSED(o_p);
+        UNUSED(o_v);
+
+        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_WARNING( " - 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_ERROR( "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_WARNING("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_WARNING("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_WARNING("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_DEBUG("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_WARNING("bad al_len: %d(<12)", al_len);
+                break;
+            }
+            /* check that data fit into buffer */
+            if (al_len > p_scb->media_buf_len)
+            {
+                AVDT_TRACE_WARNING("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_WARNING("bad al_len: %d(>%d)", al_len, p_scb->media_buf_len);
+                break;
+            }
+        }
+        else
+        {
+            AVDT_TRACE_DEBUG("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_WARNING("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_WARNING("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_WARNING("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_DEBUG("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);
+
+            UNUSED(o_v);
+            UNUSED(ssrc);
+
+            /* 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_WARNING("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_WARNING("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_DEBUG("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_WARNING("*** 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)
+{
+    UNUSED(p_scb);
+
+    GKI_freebuf(p_data->p_pkt);
+    AVDT_TRACE_ERROR(" avdt_scb_drop_pkt 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), /* handle of scb- which is same as sep handle of bta_av_cb.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;
+    UNUSED(p_data);
+
+    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)
+{
+    UNUSED(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)
+{
+    UNUSED(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_DEBUG("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_WARNING("Dropped media packet; congested");
+    }
+
+    /* build a media packet */
+    /* Add RTP header if required */
+    if ( !(p_data->apiwrite.opt & AVDT_DATA_OPT_NO_RTP) )
+    {
+        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_scb->media_seq++;
+        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);
+    }
+
+    /* 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_WARNING("*** 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;
+    UNUSED(p_data);
+
+    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)
+{
+    UNUSED(p_scb);
+
+    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;
+    UNUSED(p_data);
+
+    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_WARNING("avdt_scb_snd_stream_close c:%d, off:%d",
+        GKI_queue_length(&p_scb->frag_q), 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;
+    UNUSED(p_data);
+
+    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;
+    UNUSED(p_data);
+
+    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)
+{
+    UNUSED(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;
+    UNUSED(p_data);
+
+    /* 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)
+{
+    UNUSED(p_scb);
+
+    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)
+{
+    UNUSED(p_scb);
+
+    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)
+{
+    UNUSED(p_scb);
+
+    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)
+{
+    UNUSED(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_WARNING("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
+    UNUSED(p_data);
+
+    /* 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_DEBUG("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_DEBUG("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
+    UNUSED(p_data);
+
+    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_DEBUG("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_DEBUG("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_DEBUG("avdt/l2c congested!!");
+                    break;/* exit loop if channel became congested */
+            }
+            }
+            AVDT_TRACE_DEBUG("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)
+{
+    UNUSED(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)
+{
+    UNUSED(p_data);
+
+    if ((p_scb->cs.tsep == AVDT_TSEP_SNK) && (!p_scb->sink_activated))
+    {
+        p_scb->in_use = TRUE;
+    }
+    else
+    {
+        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_DEBUG("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_DEBUG("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_WARNING("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_DEBUG("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
+
diff --git a/components/bt/bluedroid/stack/avdt/include/avdt_int.h b/components/bt/bluedroid/stack/avdt/include/avdt_int.h
new file mode 100755 (executable)
index 0000000..fb1b313
--- /dev/null
@@ -0,0 +1,742 @@
+/******************************************************************************
+ *
+ *  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
+#define AVDT_DEBUG  FALSE
+#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_DATA_OPT_MASK     opt;
+} 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 */
+    BOOLEAN         sink_activated; /* A2DP Sink activated/de-activated from Application */
+    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
+extern tAVDT_CB  avdt_cb;
+#else
+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 */
similarity index 99%
rename from components/bt/bluedroid/profiles/std/avrc/avrc_api.c
rename to components/bt/bluedroid/stack/avrc/avrc_api.c
index c911de5c19f4967a3c6d6b2767aed0644f7a60a9..e717f9e495da337fffd32f37f781eb4c1c808e14 100755 (executable)
  *  Interface to AVRCP mandatory commands
  *
  ******************************************************************************/
-#include <string.h>
+// #include <assert.h>
 #include "bt_trace.h"
+#include <string.h>
+
 #include "gki.h"
 #include "avrc_api.h"
 #include "avrc_int.h"
similarity index 99%
rename from components/bt/bluedroid/profiles/std/avrc/avrc_bld_tg.c
rename to components/bt/bluedroid/stack/avrc/avrc_bld_tg.c
index 32e513f2a101c8abd9d8f254d12d16ca9ec05eb0..a9b1a2adf5eb5f857dcdf511889609b5d9a68d07 100755 (executable)
@@ -21,6 +21,7 @@
 #include "avrc_api.h"
 #include "avrc_defs.h"
 #include "avrc_int.h"
+#include "bt_utils.h"
 
 /*****************************************************************************
 **  Global data
similarity index 99%
rename from components/bt/bluedroid/profiles/std/avrc/avrc_opt.c
rename to components/bt/bluedroid/stack/avrc/avrc_opt.c
index de1a00cef85ac6003bd9d5292081e7cc04b4b356..9dc9413cfc8be952c94873691936568d0ab2ce05 100755 (executable)
  *  Interface to AVRCP optional commands
  *
  ******************************************************************************/
+// #include <assert.h>
+#include "bt_target.h"
 #include <string.h>
-#include "bt_trace.h"
+
 #include "gki.h"
 #include "avrc_api.h"
 #include "avrc_int.h"
similarity index 99%
rename from components/bt/bluedroid/profiles/std/avrc/avrc_pars_ct.c
rename to components/bt/bluedroid/stack/avrc/avrc_pars_ct.c
index 3db5a8dc98a4bdc52d09f95a962e3a8ac230a7ce..24204eda55fab5c87f7b18178fea6bae51103342 100755 (executable)
@@ -21,6 +21,7 @@
 #include "avrc_api.h"
 #include "avrc_defs.h"
 #include "avrc_int.h"
+#include "bt_utils.h"
 
 /*****************************************************************************
 **  Global data
similarity index 99%
rename from components/bt/bluedroid/profiles/std/avrc/include/avrc_int.h
rename to components/bt/bluedroid/stack/avrc/include/avrc_int.h
index 6bb70144885d3b2d28fcae13dd27837775e41276..36bb0c5fa6affb63d8ac903a8014dba8cc51bd98 100755 (executable)
@@ -26,7 +26,7 @@
 #ifndef AVRC_INT_H
 #define AVRC_INT_H
 
-//#include "avct_defs.h"
+#include "avct_defs.h"
 #include "avrc_api.h"
 
 /*      DEBUG FLAGS
diff --git a/components/bt/bluedroid/stack/include/a2d_api.h b/components/bt/bluedroid/stack/include/a2d_api.h
new file mode 100755 (executable)
index 0000000..f786670
--- /dev/null
@@ -0,0 +1,257 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2000-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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  nterface to A2DP Application Programming Interface
+ *
+ ******************************************************************************/
+#ifndef A2D_API_H
+#define A2D_API_H
+#include "sdp_api.h"
+
+/*****************************************************************************
+**  constants
+*****************************************************************************/
+
+/* Profile supported features */
+#define A2D_SUPF_PLAYER     0x0001
+#define A2D_SUPF_MIC        0x0002
+#define A2D_SUPF_TUNER      0x0004
+#define A2D_SUPF_MIXER      0x0008
+
+#define A2D_SUPF_HEADPHONE  0x0001
+#define A2D_SUPF_SPEAKER    0x0002
+#define A2D_SUPF_RECORDER   0x0004
+#define A2D_SUPF_AMP        0x0008
+
+/* AV Media Types */
+#define A2D_MEDIA_TYPE_AUDIO    0x00    /* audio media type + RFA */
+#define A2D_MEDIA_TYPE_VIDEO    0x10    /* video media type + RFA */
+#define A2D_MEDIA_TYPE_MULTI    0x20    /* multimedia media type + RFA */
+
+/* AV Media Codec Type (Audio Codec ID) */
+#define A2D_MEDIA_CT_SBC        0x00    /* SBC media codec type */
+#define A2D_MEDIA_CT_M12        0x01    /* MPEG-1, 2 Audio media codec type */
+#define A2D_MEDIA_CT_M24        0x02    /* MPEG-2, 4 AAC media codec type */
+#define A2D_MEDIA_CT_ATRAC      0x04    /* ATRAC family media codec type */
+
+#define A2D_SUCCESS           0     /* Success */
+#define A2D_FAIL              0x0A  /* Failed */
+#define A2D_BUSY              0x0B  /* A2D_FindService is already in progress */
+#define A2D_INVALID_PARAMS    0x0C  /* bad parameters */
+#define A2D_WRONG_CODEC       0x0D  /* wrong codec info */
+#define A2D_BAD_CODEC_TYPE    0xC1  /* Media Codec Type is not valid  */
+#define A2D_NS_CODEC_TYPE     0xC2  /* Media Codec Type is not supported */
+#define A2D_BAD_SAMP_FREQ     0xC3  /* Sampling Frequency is not valid or multiple values have been selected  */
+#define A2D_NS_SAMP_FREQ      0xC4  /* Sampling Frequency is not supported  */
+#define A2D_BAD_CH_MODE       0xC5  /* Channel Mode is not valid or multiple values have been selected  */
+#define A2D_NS_CH_MODE        0xC6  /* Channel Mode is not supported */
+#define A2D_BAD_SUBBANDS      0xC7  /* None or multiple values have been selected for Number of Subbands */
+#define A2D_NS_SUBBANDS       0xC8  /* Number of Subbands is not supported */
+#define A2D_BAD_ALLOC_MTHD    0xC9  /* None or multiple values have been selected for Allocation Method */
+#define A2D_NS_ALLOC_MTHD     0xCA  /* Allocation Method is not supported */
+#define A2D_BAD_MIN_BITPOOL   0xCB  /* Minimum Bitpool Value is not valid */
+#define A2D_NS_MIN_BITPOOL    0xCC  /* Minimum Bitpool Value is not supported */
+#define A2D_BAD_MAX_BITPOOL   0xCD  /* Maximum Bitpool Value is not valid */
+#define A2D_NS_MAX_BITPOOL    0xCE  /* Maximum Bitpool Value is not supported */
+#define A2D_BAD_LAYER         0xCF  /* None or multiple values have been selected for Layer */
+#define A2D_NS_LAYER          0xD0  /* Layer is not supported */
+#define A2D_NS_CRC            0xD1  /* CRC is not supported */
+#define A2D_NS_MPF            0xD2  /* MPF-2 is not supported */
+#define A2D_NS_VBR            0xD3  /* VBR is not supported */
+#define A2D_BAD_BIT_RATE      0xD4  /* None or multiple values have been selected for Bit Rate */
+#define A2D_NS_BIT_RATE       0xD5  /* Bit Rate is not supported */
+#define A2D_BAD_OBJ_TYPE      0xD6  /* Either 1) Object type is not valid (b3-b0) or 2) None or multiple values have been selected for Object Type */
+#define A2D_NS_OBJ_TYPE       0xD7  /* Object type is not supported */
+#define A2D_BAD_CHANNEL       0xD8  /* None or multiple values have been selected for Channels */
+#define A2D_NS_CHANNEL        0xD9  /* Channels is not supported */
+#define A2D_BAD_BLOCK_LEN     0xDD  /* None or multiple values have been selected for Block Length */
+#define A2D_BAD_CP_TYPE       0xE0  /* The requested CP Type is not supported. */
+#define A2D_BAD_CP_FORMAT     0xE1  /* The format of Content Protection Service Capability/Content Protection Scheme Dependent Data is not correct. */
+
+typedef UINT8 tA2D_STATUS;
+
+/* the return values from A2D_BitsSet() */
+#define A2D_SET_ONE_BIT         1   /* one and only one bit is set */
+#define A2D_SET_ZERO_BIT        0   /* all bits clear */
+#define A2D_SET_MULTL_BIT       2   /* multiple bits are set */
+
+/*****************************************************************************
+**  type definitions
+*****************************************************************************/
+
+/* This data type is used in A2D_FindService() to initialize the SDP database
+ * to hold the result service search. */
+typedef struct
+{
+    UINT32              db_len;  /* Length, in bytes, of the discovery database */
+    UINT16              num_attr;/* The number of attributes in p_attrs */
+    tSDP_DISCOVERY_DB  *p_db;    /* Pointer to the discovery database */
+    UINT16             *p_attrs; /* The attributes filter. If NULL, A2DP API sets the attribute filter
+                                  * to be ATTR_ID_SERVICE_CLASS_ID_LIST, ATTR_ID_BT_PROFILE_DESC_LIST,
+                                  * ATTR_ID_SUPPORTED_FEATURES, ATTR_ID_SERVICE_NAME and ATTR_ID_PROVIDER_NAME.
+                                  * If not NULL, the input is taken as the filter. */
+} tA2D_SDP_DB_PARAMS;
+
+/* This data type is used in tA2D_FIND_CBACK to report the result of the SDP discovery process. */
+typedef struct
+{
+    UINT16  service_len;    /* Length, in bytes, of the service name */
+    UINT16  provider_len;   /* Length, in bytes, of the provider name */
+    char *  p_service_name; /* Pointer the service name.  This character string may not be null terminated.
+                             * Use the service_len parameter to safely copy this string */
+    char *  p_provider_name;/* Pointer the provider name.  This character string may not be null terminated.
+                             * Use the provider_len parameter to safely copy this string */
+    UINT16  features;       /* Profile supported features */
+    UINT16  avdt_version;   /* AVDTP protocol version */
+} tA2D_Service;
+
+/* This is the callback to notify the result of the SDP discovery process. */
+typedef void (tA2D_FIND_CBACK)(BOOLEAN found, tA2D_Service * p_service);
+
+
+/*****************************************************************************
+**  external function declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/******************************************************************************
+**
+** Function         A2D_AddRecord
+**
+** Description      This function is called by a server application to add
+**                  SRC or SNK information to an SDP record.  Prior to
+**                  calling this function the application must call
+**                  SDP_CreateRecord() to create an SDP record.
+**
+**                  Input Parameters:
+**                      service_uuid:  Indicates SRC or SNK.
+**
+**                      p_service_name:  Pointer to a null-terminated character
+**                      string containing the service name.
+**
+**                      p_provider_name:  Pointer to a null-terminated character
+**                      string containing the provider name.
+**
+**                      features:  Profile supported features.
+**
+**                      sdp_handle:  SDP handle returned by SDP_CreateRecord().
+**
+**                  Output Parameters:
+**                      None.
+**
+** Returns          A2D_SUCCESS if function execution succeeded,
+**                  A2D_INVALID_PARAMS if bad parameters are given.
+**                  A2D_FAIL if function execution failed.
+**
+******************************************************************************/
+extern tA2D_STATUS A2D_AddRecord(UINT16 service_uuid, char *p_service_name, char *p_provider_name,
+        UINT16 features, UINT32 sdp_handle);
+
+/******************************************************************************
+**
+** Function         A2D_FindService
+**
+** Description      This function is called by a client application to
+**                  perform service discovery and retrieve SRC or SNK SDP
+**                  record information from a server.  Information is
+**                  returned for the first service record found on the
+**                  server that matches the service UUID.  The callback
+**                  function will be executed when service discovery is
+**                  complete.  There can only be one outstanding call to
+**                  A2D_FindService() at a time; the application must wait
+**                  for the callback before it makes another call to
+**                  the function.
+**
+**                  Input Parameters:
+**                      service_uuid:  Indicates SRC or SNK.
+**
+**                      bd_addr:  BD address of the peer device.
+**
+**                      p_db:  Pointer to the information to initialize
+**                             the discovery database.
+**
+**                      p_cback:  Pointer to the A2D_FindService()
+**                      callback function.
+**
+**                  Output Parameters:
+**                      None.
+**
+** Returns          A2D_SUCCESS if function execution succeeded,
+**                  A2D_INVALID_PARAMS if bad parameters are given.
+**                  A2D_BUSY if discovery is already in progress.
+**                  A2D_FAIL if function execution failed.
+**
+******************************************************************************/
+extern tA2D_STATUS A2D_FindService(UINT16 service_uuid, BD_ADDR bd_addr,
+                                   tA2D_SDP_DB_PARAMS *p_db, tA2D_FIND_CBACK *p_cback);
+
+/******************************************************************************
+**
+** Function         A2D_SetTraceLevel
+**
+** Description      Sets the trace level for A2D. If 0xff is passed, the
+**                  current trace level is returned.
+**
+**                  Input Parameters:
+**                      new_level:  The level to set the A2D 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.
+**
+******************************************************************************/
+extern UINT8 A2D_SetTraceLevel (UINT8 new_level);
+
+/******************************************************************************
+** Function         A2D_BitsSet
+**
+** Description      Check the given num for the number of bits set
+** Returns          A2D_SET_ONE_BIT, if one and only one bit is set
+**                  A2D_SET_ZERO_BIT, if all bits clear
+**                  A2D_SET_MULTL_BIT, if multiple bits are set
+******************************************************************************/
+extern UINT8 A2D_BitsSet(UINT8 num);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*******************************************************************************
+**
+** Function         A2D_Init
+**
+** Description      This function is called at stack startup to allocate the
+**                  control block (if using dynamic memory), and initializes the
+**                  control block and tracing level.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void A2D_Init(void);
+
+#endif /* A2D_API_H */
diff --git a/components/bt/bluedroid/stack/include/a2d_sbc.h b/components/bt/bluedroid/stack/include/a2d_sbc.h
new file mode 100755 (executable)
index 0000000..a7beb73
--- /dev/null
@@ -0,0 +1,212 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2000-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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  nterface to low complexity subband codec (SBC)
+ *
+ ******************************************************************************/
+#ifndef A2D_SBC_H
+#define A2D_SBC_H
+
+/*****************************************************************************
+**  Constants
+*****************************************************************************/
+/* the length of the SBC Media Payload header. */
+#define A2D_SBC_MPL_HDR_LEN         1
+
+/* the LOSC of SBC media codec capabilitiy */
+#define A2D_SBC_INFO_LEN            6
+
+/* for Codec Specific Information Element */
+#define A2D_SBC_IE_SAMP_FREQ_MSK    0xF0    /* b7-b4 sampling frequency */
+#define A2D_SBC_IE_SAMP_FREQ_16     0x80    /* b7:16  kHz */
+#define A2D_SBC_IE_SAMP_FREQ_32     0x40    /* b6:32  kHz */
+#define A2D_SBC_IE_SAMP_FREQ_44     0x20    /* b5:44.1kHz */
+#define A2D_SBC_IE_SAMP_FREQ_48     0x10    /* b4:48  kHz */
+
+#define A2D_SBC_IE_CH_MD_MSK        0x0F    /* b3-b0 channel mode */
+#define A2D_SBC_IE_CH_MD_MONO       0x08    /* b3: mono */
+#define A2D_SBC_IE_CH_MD_DUAL       0x04    /* b2: dual */
+#define A2D_SBC_IE_CH_MD_STEREO     0x02    /* b1: stereo */
+#define A2D_SBC_IE_CH_MD_JOINT      0x01    /* b0: joint stereo */
+
+#define A2D_SBC_IE_BLOCKS_MSK       0xF0    /* b7-b4 number of blocks */
+#define A2D_SBC_IE_BLOCKS_4         0x80    /* 4 blocks */
+#define A2D_SBC_IE_BLOCKS_8         0x40    /* 8 blocks */
+#define A2D_SBC_IE_BLOCKS_12        0x20    /* 12blocks */
+#define A2D_SBC_IE_BLOCKS_16        0x10    /* 16blocks */
+
+#define A2D_SBC_IE_SUBBAND_MSK      0x0C    /* b3-b2 number of subbands */
+#define A2D_SBC_IE_SUBBAND_4        0x08    /* b3: 4 */
+#define A2D_SBC_IE_SUBBAND_8        0x04    /* b2: 8 */
+
+#define A2D_SBC_IE_ALLOC_MD_MSK     0x03    /* b1-b0 allocation mode */
+#define A2D_SBC_IE_ALLOC_MD_S       0x02    /* b1: SNR */
+#define A2D_SBC_IE_ALLOC_MD_L       0x01    /* b0: loundess */
+
+#define A2D_SBC_IE_MIN_BITPOOL      2
+#define A2D_SBC_IE_MAX_BITPOOL      250
+
+/* for media payload header */
+#define A2D_SBC_HDR_F_MSK           0x80
+#define A2D_SBC_HDR_S_MSK           0x40
+#define A2D_SBC_HDR_L_MSK           0x20
+#define A2D_SBC_HDR_NUM_MSK         0x0F
+
+/*****************************************************************************
+**  Type Definitions
+*****************************************************************************/
+
+/* data type for the SBC Codec Information Element*/
+typedef struct
+{
+    UINT8   samp_freq;      /* Sampling frequency */
+    UINT8   ch_mode;        /* Channel mode */
+    UINT8   block_len;      /* Block length */
+    UINT8   num_subbands;   /* Number of subbands */
+    UINT8   alloc_mthd;     /* Allocation method */
+    UINT8   max_bitpool;    /* Maximum bitpool */
+    UINT8   min_bitpool;    /* Minimum bitpool */
+} tA2D_SBC_CIE;
+
+
+/*****************************************************************************
+**  External Function Declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/******************************************************************************
+**
+** Function         A2D_SbcChkFrInit
+**
+** Description      check if need to init the descramble control block.
+**
+** Returns          nothing.
+******************************************************************************/
+extern void A2D_SbcChkFrInit(UINT8 *p_pkt);
+
+/******************************************************************************
+**
+** Function         A2D_SbcDescramble
+**
+** Description      descramble the packet.
+**
+** Returns          nothing.
+******************************************************************************/
+extern void A2D_SbcDescramble(UINT8 *p_pkt, UINT16 len);
+
+/******************************************************************************
+**
+** Function         A2D_BldSbcInfo
+**
+** Description      This function is called by an application to build
+**                  the SBC Media Codec Capabilities byte sequence
+**                  beginning from the LOSC octet.
+**                  Input Parameters:
+**                      media_type:  Indicates Audio, or Multimedia.
+**
+**                      p_ie:  The SBC Codec Information Element information.
+**
+**                  Output Parameters:
+**                      p_result:  the resulting codec info byte sequence.
+**
+** Returns          A2D_SUCCESS if function execution succeeded.
+**                  Error status code, otherwise.
+******************************************************************************/
+extern tA2D_STATUS A2D_BldSbcInfo(UINT8 media_type, tA2D_SBC_CIE *p_ie,
+                                  UINT8 *p_result);
+
+/******************************************************************************
+**
+** Function         A2D_ParsSbcInfo
+**
+** Description      This function is called by an application to parse
+**                  the SBC Media Codec Capabilities byte sequence
+**                  beginning from the LOSC octet.
+**                  Input Parameters:
+**                      p_info:  the byte sequence to parse.
+**
+**                      for_caps:  TRUE, if the byte sequence is for get capabilities response.
+**
+**                  Output Parameters:
+**                      p_ie:  The SBC Codec Information Element information.
+**
+** Returns          A2D_SUCCESS if function execution succeeded.
+**                  Error status code, otherwise.
+******************************************************************************/
+extern tA2D_STATUS A2D_ParsSbcInfo(tA2D_SBC_CIE *p_ie, UINT8 *p_info,
+                                   BOOLEAN for_caps);
+
+/******************************************************************************
+**
+** Function         A2D_BldSbcMplHdr
+**
+** Description      This function is called by an application to parse
+**                  the SBC Media Payload header.
+**                  Input Parameters:
+**                      frag:  1, if fragmented. 0, otherwise.
+**
+**                      start:  1, if the starting packet of a fragmented frame.
+**
+**                      last:  1, if the last packet of a fragmented frame.
+**
+**                      num:  If frag is 1, this is the number of remaining fragments
+**                            (including this fragment) of this frame.
+**                            If frag is 0, this is the number of frames in this packet.
+**
+**                  Output Parameters:
+**                      p_dst:  the resulting media payload header byte sequence.
+**
+** Returns          void.
+******************************************************************************/
+extern void A2D_BldSbcMplHdr(UINT8 *p_dst, BOOLEAN frag, BOOLEAN start,
+                             BOOLEAN last, UINT8 num);
+
+/******************************************************************************
+**
+** Function         A2D_ParsSbcMplHdr
+**
+** Description      This function is called by an application to parse
+**                  the SBC Media Payload header.
+**                  Input Parameters:
+**                      p_src:  the byte sequence to parse..
+**
+**                  Output Parameters:
+**                      frag:  1, if fragmented. 0, otherwise.
+**
+**                      start:  1, if the starting packet of a fragmented frame.
+**
+**                      last:  1, if the last packet of a fragmented frame.
+**
+**                      num:  If frag is 1, this is the number of remaining fragments
+**                            (including this fragment) of this frame.
+**                            If frag is 0, this is the number of frames in this packet.
+**
+** Returns          void.
+******************************************************************************/
+extern void A2D_ParsSbcMplHdr(UINT8 *p_src, BOOLEAN *p_frag,
+                              BOOLEAN *p_start, BOOLEAN *p_last,
+                              UINT8 *p_num);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* A2D_SBC_H */
diff --git a/components/bt/bluedroid/utils/include/bt_utils.h b/components/bt/bluedroid/utils/include/bt_utils.h
new file mode 100755 (executable)
index 0000000..e77fad8
--- /dev/null
@@ -0,0 +1,46 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2009-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.
+ *
+ ******************************************************************************/
+
+#ifndef BT_UTILS_H
+#define BT_UTILS_H
+
+// static const char BT_UTILS_MODULE[] = "bt_utils_module";
+
+/*******************************************************************************
+**  Type definitions
+********************************************************************************/
+
+typedef enum {
+    TASK_HIGH_MEDIA = 0,
+    TASK_HIGH_GKI_TIMER,
+    TASK_HIGH_BTU,
+    TASK_HIGH_HCI_WORKER,
+    TASK_HIGH_USERIAL_READ,
+    TASK_UIPC_READ,
+    TASK_JAVA_ALARM,
+    TASK_HIGH_MAX
+} tHIGH_PRIORITY_TASK;
+
+/*******************************************************************************
+**  Functions
+********************************************************************************/
+
+// void raise_priority_a2dp(tHIGH_PRIORITY_TASK high_task);
+// void adjust_priority_a2dp(int start);
+#define UNUSED(x) (void)(x)
+#endif /* BT_UTILS_H */
index 1926f857d540816c8017dfc0e189fe927159aba0..fd129359f4530e1c660e3dd3f26627031a34a99e 100644 (file)
@@ -9,10 +9,10 @@ COMPONENT_ADD_INCLUDEDIRS :=  bluedroid/bta/include                   \
                                bluedroid/gki/include                   \
                                bluedroid/hci/include                   \
                                bluedroid/osi/include                   \
+                               bluedroid/utils/include                 \
                                bluedroid/profiles/core/include                 \
                                bluedroid/profiles/esp/blufi/include            \
                                bluedroid/profiles/esp/include          \
-                               bluedroid/profiles/std/avrc/include     \
                                bluedroid/profiles/std/battery/include  \
                                bluedroid/profiles/std/dis/include      \
                                bluedroid/profiles/std/hid/include      \
@@ -26,6 +26,10 @@ COMPONENT_ADD_INCLUDEDIRS := bluedroid/bta/include                   \
                                bluedroid/stack/l2cap/include           \
                                bluedroid/stack/sdp/include             \
                                bluedroid/stack/smp/include             \
+                               bluedroid/stack/avct/include            \
+                               bluedroid/stack/avrc/include            \
+                               bluedroid/stack/avdt/include            \
+                               bluedroid/stack/a2dp/include            \
                                bluedroid/stack/include                 \
                                bluedroid/stack_api/include             \
                                bluedroid/include                       \
@@ -57,7 +61,6 @@ COMPONENT_SRCDIRS :=  bluedroid/bta/dm                        \
                        bluedroid/profiles/esp/ble_button       \
                        bluedroid/profiles/esp/wechat_AirSync   \
                        bluedroid/profiles/esp                  \
-                       bluedroid/profiles/std/avrc             \
                        bluedroid/profiles/std/battery          \
                        bluedroid/profiles/std/dis              \
                        bluedroid/profiles/std/hid              \
@@ -76,6 +79,10 @@ COMPONENT_SRCDIRS :=         bluedroid/bta/dm                        \
                        bluedroid/stack/l2cap                   \
                        bluedroid/stack/sdp                     \
                        bluedroid/stack/smp                     \
+                       bluedroid/stack/avct                    \
+                       bluedroid/stack/avrc                    \
+                       bluedroid/stack/avdt                    \
+                       bluedroid/stack/a2dp                    \
                        bluedroid/stack                         \
                        bluedroid/stack_api                     \
                        bluedroid                               \